Re: [Patch net] vlan: fix a use-after-free in vlan_device_event()

2017-11-11 Thread David Miller
From: Cong Wang 
Date: Thu,  9 Nov 2017 16:43:13 -0800

> After refcnt reaches zero, vlan_vid_del() could free
> dev->vlan_info via RCU:
> 
>   RCU_INIT_POINTER(dev->vlan_info, NULL);
>   call_rcu(&vlan_info->rcu, vlan_info_rcu_free);
> 
> However, the pointer 'grp' still points to that memory
> since it is set before vlan_vid_del():
> 
> vlan_info = rtnl_dereference(dev->vlan_info);
> if (!vlan_info)
> goto out;
> grp = &vlan_info->grp;
> 
> Depends on when that RCU callback is scheduled, we could
> trigger a use-after-free in vlan_group_for_each_dev()
> right following this vlan_vid_del().
> 
> Fix it by moving vlan_vid_del() before setting grp. This
> is also symmetric to the vlan_vid_add() we call in
> vlan_device_event().
> 
> Reported-by: Fengguang Wu 
> Fixes: efc73f4bbc23 ("net: Fix memory leak - vlan_info struct")
> Cc: Alexander Duyck 
> Cc: Linus Torvalds 
> Cc: Girish Moodalbail 
> Signed-off-by: Cong Wang 

Applied and queued up for -stable, thanks Cong!


Re: [Patch net] vlan: fix a use-after-free in vlan_device_event()

2017-11-10 Thread Linus Torvalds
On Fri, Nov 10, 2017 at 3:50 AM, Fengguang Wu  wrote:
> It works, thank you for fixing this ancient bug!
>
> Tested-by: Fengguang Wu 

Thanks for all the 0day work to make people finally figure this out.

 Linus


Re: [Patch net] vlan: fix a use-after-free in vlan_device_event()

2017-11-10 Thread Fengguang Wu

It works, thank you for fixing this ancient bug!

Tested-by: Fengguang Wu 


Re: [Patch net] vlan: fix a use-after-free in vlan_device_event()

2017-11-09 Thread Girish Moodalbail

On 11/9/17 4:43 PM, Cong Wang wrote:

After refcnt reaches zero, vlan_vid_del() could free
dev->vlan_info via RCU:

RCU_INIT_POINTER(dev->vlan_info, NULL);
call_rcu(&vlan_info->rcu, vlan_info_rcu_free);

However, the pointer 'grp' still points to that memory
since it is set before vlan_vid_del():

 vlan_info = rtnl_dereference(dev->vlan_info);
 if (!vlan_info)
 goto out;
 grp = &vlan_info->grp;

Depends on when that RCU callback is scheduled, we could
trigger a use-after-free in vlan_group_for_each_dev()
right following this vlan_vid_del().

Fix it by moving vlan_vid_del() before setting grp. This
is also symmetric to the vlan_vid_add() we call in
vlan_device_event().

Reported-by: Fengguang Wu 
Fixes: efc73f4bbc23 ("net: Fix memory leak - vlan_info struct")
Cc: Alexander Duyck 
Cc: Linus Torvalds 
Cc: Girish Moodalbail 
Signed-off-by: Cong Wang 


LGTM.

Reviewed-by: Girish Moodalbail 

Thanks,
~Girish



---
  net/8021q/vlan.c | 6 +++---
  1 file changed, 3 insertions(+), 3 deletions(-)

diff --git a/net/8021q/vlan.c b/net/8021q/vlan.c
index 9649579b5b9f..4a72ee4e2ae9 100644
--- a/net/8021q/vlan.c
+++ b/net/8021q/vlan.c
@@ -376,6 +376,9 @@ static int vlan_device_event(struct notifier_block *unused, 
unsigned long event,
dev->name);
vlan_vid_add(dev, htons(ETH_P_8021Q), 0);
}
+   if (event == NETDEV_DOWN &&
+   (dev->features & NETIF_F_HW_VLAN_CTAG_FILTER))
+   vlan_vid_del(dev, htons(ETH_P_8021Q), 0);
  
  	vlan_info = rtnl_dereference(dev->vlan_info);

if (!vlan_info)
@@ -423,9 +426,6 @@ static int vlan_device_event(struct notifier_block *unused, 
unsigned long event,
struct net_device *tmp;
LIST_HEAD(close_list);
  
-		if (dev->features & NETIF_F_HW_VLAN_CTAG_FILTER)

-   vlan_vid_del(dev, htons(ETH_P_8021Q), 0);
-
/* Put all VLANs for this dev in the down state too.  */
vlan_group_for_each_dev(grp, i, vlandev) {
flgs = vlandev->flags;





[Patch net] vlan: fix a use-after-free in vlan_device_event()

2017-11-09 Thread Cong Wang
After refcnt reaches zero, vlan_vid_del() could free
dev->vlan_info via RCU:

RCU_INIT_POINTER(dev->vlan_info, NULL);
call_rcu(&vlan_info->rcu, vlan_info_rcu_free);

However, the pointer 'grp' still points to that memory
since it is set before vlan_vid_del():

vlan_info = rtnl_dereference(dev->vlan_info);
if (!vlan_info)
goto out;
grp = &vlan_info->grp;

Depends on when that RCU callback is scheduled, we could
trigger a use-after-free in vlan_group_for_each_dev()
right following this vlan_vid_del().

Fix it by moving vlan_vid_del() before setting grp. This
is also symmetric to the vlan_vid_add() we call in
vlan_device_event().

Reported-by: Fengguang Wu 
Fixes: efc73f4bbc23 ("net: Fix memory leak - vlan_info struct")
Cc: Alexander Duyck 
Cc: Linus Torvalds 
Cc: Girish Moodalbail 
Signed-off-by: Cong Wang 
---
 net/8021q/vlan.c | 6 +++---
 1 file changed, 3 insertions(+), 3 deletions(-)

diff --git a/net/8021q/vlan.c b/net/8021q/vlan.c
index 9649579b5b9f..4a72ee4e2ae9 100644
--- a/net/8021q/vlan.c
+++ b/net/8021q/vlan.c
@@ -376,6 +376,9 @@ static int vlan_device_event(struct notifier_block *unused, 
unsigned long event,
dev->name);
vlan_vid_add(dev, htons(ETH_P_8021Q), 0);
}
+   if (event == NETDEV_DOWN &&
+   (dev->features & NETIF_F_HW_VLAN_CTAG_FILTER))
+   vlan_vid_del(dev, htons(ETH_P_8021Q), 0);
 
vlan_info = rtnl_dereference(dev->vlan_info);
if (!vlan_info)
@@ -423,9 +426,6 @@ static int vlan_device_event(struct notifier_block *unused, 
unsigned long event,
struct net_device *tmp;
LIST_HEAD(close_list);
 
-   if (dev->features & NETIF_F_HW_VLAN_CTAG_FILTER)
-   vlan_vid_del(dev, htons(ETH_P_8021Q), 0);
-
/* Put all VLANs for this dev in the down state too.  */
vlan_group_for_each_dev(grp, i, vlandev) {
flgs = vlandev->flags;
-- 
2.13.0