net/softnic: fix memory illegal access

Message ID 20180720094439.100562-1-jasvinder.singh@intel.com (mailing list archive)
State Superseded, archived
Headers
Series net/softnic: fix memory illegal access |

Checks

Context Check Description
ci/checkpatch success coding style OK
ci/Intel-compilation success Compilation OK

Commit Message

Jasvinder Singh July 20, 2018, 9:44 a.m. UTC
  While deleting the elements from the linked list, TAILQ_FOREACH causes
read from the freed pointer. Fixes the issue by using for loop instead
of TAILQ_FOREACH.

Coverity issue: 302867
Fixes: bef50bcb1c47 ("net/softnic: implement start and stop")

Signed-off-by: Jasvinder Singh <jasvinder.singh@intel.com>
Acked-by: Cristian Dumitrescu <cristian.dumitrescu@intel.com>
---
 drivers/net/softnic/rte_eth_softnic_swq.c | 6 ++++--
 1 file changed, 4 insertions(+), 2 deletions(-)
  

Comments

Bruce Richardson July 20, 2018, 10:29 a.m. UTC | #1
On Fri, Jul 20, 2018 at 10:44:39AM +0100, Jasvinder Singh wrote:
> While deleting the elements from the linked list, TAILQ_FOREACH causes
> read from the freed pointer. Fixes the issue by using for loop instead
> of TAILQ_FOREACH.
> 
> Coverity issue: 302867
> Fixes: bef50bcb1c47 ("net/softnic: implement start and stop")
> 
> Signed-off-by: Jasvinder Singh <jasvinder.singh@intel.com>
> Acked-by: Cristian Dumitrescu <cristian.dumitrescu@intel.com>
> ---
>  drivers/net/softnic/rte_eth_softnic_swq.c | 6 ++++--
>  1 file changed, 4 insertions(+), 2 deletions(-)
> 
> diff --git a/drivers/net/softnic/rte_eth_softnic_swq.c b/drivers/net/softnic/rte_eth_softnic_swq.c
> index 1944fbb..a1f1899 100644
> --- a/drivers/net/softnic/rte_eth_softnic_swq.c
> +++ b/drivers/net/softnic/rte_eth_softnic_swq.c
> @@ -36,9 +36,11 @@ softnic_swq_free(struct pmd_internals *p)
>  void
>  softnic_softnic_swq_free_keep_rxq_txq(struct pmd_internals *p)
>  {
> -	struct softnic_swq *swq;
> +	struct softnic_swq *swq, *swq_next;
> +
> +	for (swq = TAILQ_FIRST(&p->swq_list); swq != NULL; swq = swq_next) {
> +		swq_next = TAILQ_NEXT(swq, node);
>  
> -	TAILQ_FOREACH(swq, &p->swq_list, node) {
>  		if ((strncmp(swq->name, "RXQ", strlen("RXQ")) == 0) ||
>  			(strncmp(swq->name, "TXQ", strlen("TXQ")) == 0))

TAILQ_FOREACH_SAFE is probably what you want to use here.

From man page:

     The macros TAILQ_FOREACH, TAILQ_FOREACH_REVERSE, TAILQ_FOREACH_SAFE, and
     TAILQ_FOREACH_REVERSE_SAFE traverse the tail queue referenced by head in
     the forward or reverse direction direction, assigning each element in
     turn to var.

     The SAFE versions use tmp to hold the next element, so var may be freed
     or removed from the list.
  
Van Haaren, Harry July 20, 2018, 10:31 a.m. UTC | #2
> -----Original Message-----
> From: dev [mailto:dev-bounces@dpdk.org] On Behalf Of Jasvinder Singh
> Sent: Friday, July 20, 2018 10:45 AM
> To: dev@dpdk.org
> Cc: Dumitrescu, Cristian <cristian.dumitrescu@intel.com>
> Subject: [dpdk-dev] [PATCH] net/softnic: fix memory illegal access
> 
> While deleting the elements from the linked list, TAILQ_FOREACH causes
> read from the freed pointer. Fixes the issue by using for loop instead
> of TAILQ_FOREACH.
> 
> Coverity issue: 302867
> Fixes: bef50bcb1c47 ("net/softnic: implement start and stop")
> 
> Signed-off-by: Jasvinder Singh <jasvinder.singh@intel.com>
> Acked-by: Cristian Dumitrescu <cristian.dumitrescu@intel.com>
> ---
>  drivers/net/softnic/rte_eth_softnic_swq.c | 6 ++++--
>  1 file changed, 4 insertions(+), 2 deletions(-)
> 
> diff --git a/drivers/net/softnic/rte_eth_softnic_swq.c
> b/drivers/net/softnic/rte_eth_softnic_swq.c
> index 1944fbb..a1f1899 100644
> --- a/drivers/net/softnic/rte_eth_softnic_swq.c
> +++ b/drivers/net/softnic/rte_eth_softnic_swq.c
> @@ -36,9 +36,11 @@ softnic_swq_free(struct pmd_internals *p)
>  void
>  softnic_softnic_swq_free_keep_rxq_txq(struct pmd_internals *p)
>  {
> -	struct softnic_swq *swq;
> +	struct softnic_swq *swq, *swq_next;
> +
> +	for (swq = TAILQ_FIRST(&p->swq_list); swq != NULL; swq = swq_next) {
> +		swq_next = TAILQ_NEXT(swq, node);
> 
> -	TAILQ_FOREACH(swq, &p->swq_list, node) {
>  		if ((strncmp(swq->name, "RXQ", strlen("RXQ")) == 0) ||
>  			(strncmp(swq->name, "TXQ", strlen("TXQ")) == 0))
>  			continue;


The TAILQ_FOREACH_SAFE() macro handles exactly this case. Although it is not
in the linux TAILQ header, DPDK provides it in rte_tailq.h:

http://git.dpdk.org/dpdk/tree/lib/librte_eal/common/include/rte_tailq.h#n130

I think it is cleaner to use the MACRO instead of manually doing the loop,
linked-list iter + delete is error prone enough already :)
  
Jasvinder Singh July 20, 2018, 10:49 a.m. UTC | #3
> -----Original Message-----
> From: Van Haaren, Harry
> Sent: Friday, July 20, 2018 11:32 AM
> To: Singh, Jasvinder <jasvinder.singh@intel.com>; dev@dpdk.org
> Cc: Dumitrescu, Cristian <cristian.dumitrescu@intel.com>
> Subject: RE: [dpdk-dev] [PATCH] net/softnic: fix memory illegal access
> 
> > -----Original Message-----
> > From: dev [mailto:dev-bounces@dpdk.org] On Behalf Of Jasvinder Singh
> > Sent: Friday, July 20, 2018 10:45 AM
> > To: dev@dpdk.org
> > Cc: Dumitrescu, Cristian <cristian.dumitrescu@intel.com>
> > Subject: [dpdk-dev] [PATCH] net/softnic: fix memory illegal access
> >
> > While deleting the elements from the linked list, TAILQ_FOREACH causes
> > read from the freed pointer. Fixes the issue by using for loop instead
> > of TAILQ_FOREACH.
> >
> > Coverity issue: 302867
> > Fixes: bef50bcb1c47 ("net/softnic: implement start and stop")
> >
> > Signed-off-by: Jasvinder Singh <jasvinder.singh@intel.com>
> > Acked-by: Cristian Dumitrescu <cristian.dumitrescu@intel.com>
> > ---
> >  drivers/net/softnic/rte_eth_softnic_swq.c | 6 ++++--
> >  1 file changed, 4 insertions(+), 2 deletions(-)
> >
> > diff --git a/drivers/net/softnic/rte_eth_softnic_swq.c
> > b/drivers/net/softnic/rte_eth_softnic_swq.c
> > index 1944fbb..a1f1899 100644
> > --- a/drivers/net/softnic/rte_eth_softnic_swq.c
> > +++ b/drivers/net/softnic/rte_eth_softnic_swq.c
> > @@ -36,9 +36,11 @@ softnic_swq_free(struct pmd_internals *p)  void
> > softnic_softnic_swq_free_keep_rxq_txq(struct pmd_internals *p)  {
> > -	struct softnic_swq *swq;
> > +	struct softnic_swq *swq, *swq_next;
> > +
> > +	for (swq = TAILQ_FIRST(&p->swq_list); swq != NULL; swq = swq_next) {
> > +		swq_next = TAILQ_NEXT(swq, node);
> >
> > -	TAILQ_FOREACH(swq, &p->swq_list, node) {
> >  		if ((strncmp(swq->name, "RXQ", strlen("RXQ")) == 0) ||
> >  			(strncmp(swq->name, "TXQ", strlen("TXQ")) == 0))
> >  			continue;
> 
> 
> The TAILQ_FOREACH_SAFE() macro handles exactly this case. Although it is not
> in the linux TAILQ header, DPDK provides it in rte_tailq.h:
> 
> http://git.dpdk.org/dpdk/tree/lib/librte_eal/common/include/rte_tailq.h#n13
> 0
> 
> I think it is cleaner to use the MACRO instead of manually doing the loop,
> linked-list iter + delete is error prone enough already :)

Macro lessens the confusion as well  :)  thanks, Harry!
  

Patch

diff --git a/drivers/net/softnic/rte_eth_softnic_swq.c b/drivers/net/softnic/rte_eth_softnic_swq.c
index 1944fbb..a1f1899 100644
--- a/drivers/net/softnic/rte_eth_softnic_swq.c
+++ b/drivers/net/softnic/rte_eth_softnic_swq.c
@@ -36,9 +36,11 @@  softnic_swq_free(struct pmd_internals *p)
 void
 softnic_softnic_swq_free_keep_rxq_txq(struct pmd_internals *p)
 {
-	struct softnic_swq *swq;
+	struct softnic_swq *swq, *swq_next;
+
+	for (swq = TAILQ_FIRST(&p->swq_list); swq != NULL; swq = swq_next) {
+		swq_next = TAILQ_NEXT(swq, node);
 
-	TAILQ_FOREACH(swq, &p->swq_list, node) {
 		if ((strncmp(swq->name, "RXQ", strlen("RXQ")) == 0) ||
 			(strncmp(swq->name, "TXQ", strlen("TXQ")) == 0))
 			continue;