aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorGirish Moodalbail <girish.moodalbail@oracle.com>2017-10-25 03:23:04 -0400
committerDavid S. Miller <davem@davemloft.net>2017-10-26 04:57:39 -0400
commit78e0ea6791d7baafb8a0ca82b1bd0c7b3453c919 (patch)
tree6be52d342cd4ea32359a90ec7aabc96d9b08dd40
parent5889e2c0e441d84060e66211ed5c4517ca591167 (diff)
tap: double-free in error path in tap_open()
Double free of skb_array in tap module is causing kernel panic. When tap_set_queue() fails we free skb_array right away by calling skb_array_cleanup(). However, later on skb_array_cleanup() is called again by tap_sock_destruct through sock_put(). This patch fixes that issue. Fixes: 362899b8725b35e3 (macvtap: switch to use skb array) Signed-off-by: Girish Moodalbail <girish.moodalbail@oracle.com> Acked-by: Jason Wang <jasowang@redhat.com> Signed-off-by: David S. Miller <davem@davemloft.net>
-rw-r--r--drivers/net/tap.c18
1 files changed, 9 insertions, 9 deletions
diff --git a/drivers/net/tap.c b/drivers/net/tap.c
index 21b71ae947fd..98ee6cc2875d 100644
--- a/drivers/net/tap.c
+++ b/drivers/net/tap.c
@@ -517,6 +517,10 @@ static int tap_open(struct inode *inode, struct file *file)
517 &tap_proto, 0); 517 &tap_proto, 0);
518 if (!q) 518 if (!q)
519 goto err; 519 goto err;
520 if (skb_array_init(&q->skb_array, tap->dev->tx_queue_len, GFP_KERNEL)) {
521 sk_free(&q->sk);
522 goto err;
523 }
520 524
521 RCU_INIT_POINTER(q->sock.wq, &q->wq); 525 RCU_INIT_POINTER(q->sock.wq, &q->wq);
522 init_waitqueue_head(&q->wq.wait); 526 init_waitqueue_head(&q->wq.wait);
@@ -540,22 +544,18 @@ static int tap_open(struct inode *inode, struct file *file)
540 if ((tap->dev->features & NETIF_F_HIGHDMA) && (tap->dev->features & NETIF_F_SG)) 544 if ((tap->dev->features & NETIF_F_HIGHDMA) && (tap->dev->features & NETIF_F_SG))
541 sock_set_flag(&q->sk, SOCK_ZEROCOPY); 545 sock_set_flag(&q->sk, SOCK_ZEROCOPY);
542 546
543 err = -ENOMEM;
544 if (skb_array_init(&q->skb_array, tap->dev->tx_queue_len, GFP_KERNEL))
545 goto err_array;
546
547 err = tap_set_queue(tap, file, q); 547 err = tap_set_queue(tap, file, q);
548 if (err) 548 if (err) {
549 goto err_queue; 549 /* tap_sock_destruct() will take care of freeing skb_array */
550 goto err_put;
551 }
550 552
551 dev_put(tap->dev); 553 dev_put(tap->dev);
552 554
553 rtnl_unlock(); 555 rtnl_unlock();
554 return err; 556 return err;
555 557
556err_queue: 558err_put:
557 skb_array_cleanup(&q->skb_array);
558err_array:
559 sock_put(&q->sk); 559 sock_put(&q->sk);
560err: 560err:
561 if (tap) 561 if (tap)