diff mbox series

[net] vxlan: Fix memory leaks in error path

Message ID 20230102065556.3886530-1-idosch@nvidia.com (mailing list archive)
State Accepted
Commit 06bf62944144a92d83dd14fd1378d2a288259561
Delegated to: Netdev Maintainers
Headers show
Series [net] vxlan: Fix memory leaks in error path | expand

Checks

Context Check Description
netdev/tree_selection success Clearly marked for net
netdev/fixes_present success Fixes tag present in non-next series
netdev/subject_prefix success Link
netdev/cover_letter success Single patches do not need cover letters
netdev/patch_count success Link
netdev/header_inline success No static functions without inline keyword in header files
netdev/build_32bit success Errors and warnings before: 1 this patch: 1
netdev/cc_maintainers success CCed 6 of 6 maintainers
netdev/build_clang success Errors and warnings before: 0 this patch: 0
netdev/module_param success Was 0 now: 0
netdev/verify_signedoff success Signed-off-by tag matches author and committer
netdev/check_selftest success No net selftest shell script
netdev/verify_fixes success Fixes tag looks correct
netdev/build_allmodconfig_warn success Errors and warnings before: 1 this patch: 1
netdev/checkpatch success total: 0 errors, 0 warnings, 0 checks, 29 lines checked
netdev/kdoc success Errors and warnings before: 0 this patch: 0
netdev/source_inline success Was 0 now: 0

Commit Message

Ido Schimmel Jan. 2, 2023, 6:55 a.m. UTC
The memory allocated by vxlan_vnigroup_init() is not freed in the error
path, leading to memory leaks [1]. Fix by calling
vxlan_vnigroup_uninit() in the error path.

The leaks can be reproduced by annotating gro_cells_init() with
ALLOW_ERROR_INJECTION() and then running:

 # echo "100" > /sys/kernel/debug/fail_function/probability
 # echo "1" > /sys/kernel/debug/fail_function/times
 # echo "gro_cells_init" > /sys/kernel/debug/fail_function/inject
 # printf %#x -12 > /sys/kernel/debug/fail_function/gro_cells_init/retval
 # ip link add name vxlan0 type vxlan dstport 4789 external vnifilter
 RTNETLINK answers: Cannot allocate memory

[1]
unreferenced object 0xffff88810db84a00 (size 512):
  comm "ip", pid 330, jiffies 4295010045 (age 66.016s)
  hex dump (first 32 bytes):
    f8 d5 76 0e 81 88 ff ff 01 00 00 00 00 00 00 02  ..v.............
    03 00 04 00 48 00 00 00 00 00 00 01 04 00 01 00  ....H...........
  backtrace:
    [<ffffffff81a3097a>] kmalloc_trace+0x2a/0x60
    [<ffffffff82f049fc>] vxlan_vnigroup_init+0x4c/0x160
    [<ffffffff82ecd69e>] vxlan_init+0x1ae/0x280
    [<ffffffff836858ca>] register_netdevice+0x57a/0x16d0
    [<ffffffff82ef67b7>] __vxlan_dev_create+0x7c7/0xa50
    [<ffffffff82ef6ce6>] vxlan_newlink+0xd6/0x130
    [<ffffffff836d02ab>] __rtnl_newlink+0x112b/0x18a0
    [<ffffffff836d0a8c>] rtnl_newlink+0x6c/0xa0
    [<ffffffff836c0ddf>] rtnetlink_rcv_msg+0x43f/0xd40
    [<ffffffff83908ce0>] netlink_rcv_skb+0x170/0x440
    [<ffffffff839066af>] netlink_unicast+0x53f/0x810
    [<ffffffff839072d8>] netlink_sendmsg+0x958/0xe70
    [<ffffffff835c319f>] ____sys_sendmsg+0x78f/0xa90
    [<ffffffff835cd6da>] ___sys_sendmsg+0x13a/0x1e0
    [<ffffffff835cd94c>] __sys_sendmsg+0x11c/0x1f0
    [<ffffffff8424da78>] do_syscall_64+0x38/0x80
unreferenced object 0xffff88810e76d5f8 (size 192):
  comm "ip", pid 330, jiffies 4295010045 (age 66.016s)
  hex dump (first 32 bytes):
    04 00 00 00 00 00 00 00 db e1 4f e7 00 00 00 00  ..........O.....
    08 d6 76 0e 81 88 ff ff 08 d6 76 0e 81 88 ff ff  ..v.......v.....
  backtrace:
    [<ffffffff81a3162e>] __kmalloc_node+0x4e/0x90
    [<ffffffff81a0e166>] kvmalloc_node+0xa6/0x1f0
    [<ffffffff8276e1a3>] bucket_table_alloc.isra.0+0x83/0x460
    [<ffffffff8276f18b>] rhashtable_init+0x43b/0x7c0
    [<ffffffff82f04a1c>] vxlan_vnigroup_init+0x6c/0x160
    [<ffffffff82ecd69e>] vxlan_init+0x1ae/0x280
    [<ffffffff836858ca>] register_netdevice+0x57a/0x16d0
    [<ffffffff82ef67b7>] __vxlan_dev_create+0x7c7/0xa50
    [<ffffffff82ef6ce6>] vxlan_newlink+0xd6/0x130
    [<ffffffff836d02ab>] __rtnl_newlink+0x112b/0x18a0
    [<ffffffff836d0a8c>] rtnl_newlink+0x6c/0xa0
    [<ffffffff836c0ddf>] rtnetlink_rcv_msg+0x43f/0xd40
    [<ffffffff83908ce0>] netlink_rcv_skb+0x170/0x440
    [<ffffffff839066af>] netlink_unicast+0x53f/0x810
    [<ffffffff839072d8>] netlink_sendmsg+0x958/0xe70
    [<ffffffff835c319f>] ____sys_sendmsg+0x78f/0xa90

Fixes: f9c4bb0b245c ("vxlan: vni filtering support on collect metadata device")
Signed-off-by: Ido Schimmel <idosch@nvidia.com>
---
 drivers/net/vxlan/vxlan_core.c | 19 +++++++++++++------
 1 file changed, 13 insertions(+), 6 deletions(-)

Comments

Nikolay Aleksandrov Jan. 2, 2023, 9:41 a.m. UTC | #1
On 02/01/2023 08:55, Ido Schimmel wrote:
> The memory allocated by vxlan_vnigroup_init() is not freed in the error
> path, leading to memory leaks [1]. Fix by calling
> vxlan_vnigroup_uninit() in the error path.
> 
> The leaks can be reproduced by annotating gro_cells_init() with
> ALLOW_ERROR_INJECTION() and then running:
> 
>  # echo "100" > /sys/kernel/debug/fail_function/probability
>  # echo "1" > /sys/kernel/debug/fail_function/times
>  # echo "gro_cells_init" > /sys/kernel/debug/fail_function/inject
>  # printf %#x -12 > /sys/kernel/debug/fail_function/gro_cells_init/retval
>  # ip link add name vxlan0 type vxlan dstport 4789 external vnifilter
>  RTNETLINK answers: Cannot allocate memory
> 
> [1]
> unreferenced object 0xffff88810db84a00 (size 512):
>   comm "ip", pid 330, jiffies 4295010045 (age 66.016s)
>   hex dump (first 32 bytes):
>     f8 d5 76 0e 81 88 ff ff 01 00 00 00 00 00 00 02  ..v.............
>     03 00 04 00 48 00 00 00 00 00 00 01 04 00 01 00  ....H...........
>   backtrace:
>     [<ffffffff81a3097a>] kmalloc_trace+0x2a/0x60
>     [<ffffffff82f049fc>] vxlan_vnigroup_init+0x4c/0x160
>     [<ffffffff82ecd69e>] vxlan_init+0x1ae/0x280
>     [<ffffffff836858ca>] register_netdevice+0x57a/0x16d0
>     [<ffffffff82ef67b7>] __vxlan_dev_create+0x7c7/0xa50
>     [<ffffffff82ef6ce6>] vxlan_newlink+0xd6/0x130
>     [<ffffffff836d02ab>] __rtnl_newlink+0x112b/0x18a0
>     [<ffffffff836d0a8c>] rtnl_newlink+0x6c/0xa0
>     [<ffffffff836c0ddf>] rtnetlink_rcv_msg+0x43f/0xd40
>     [<ffffffff83908ce0>] netlink_rcv_skb+0x170/0x440
>     [<ffffffff839066af>] netlink_unicast+0x53f/0x810
>     [<ffffffff839072d8>] netlink_sendmsg+0x958/0xe70
>     [<ffffffff835c319f>] ____sys_sendmsg+0x78f/0xa90
>     [<ffffffff835cd6da>] ___sys_sendmsg+0x13a/0x1e0
>     [<ffffffff835cd94c>] __sys_sendmsg+0x11c/0x1f0
>     [<ffffffff8424da78>] do_syscall_64+0x38/0x80
> unreferenced object 0xffff88810e76d5f8 (size 192):
>   comm "ip", pid 330, jiffies 4295010045 (age 66.016s)
>   hex dump (first 32 bytes):
>     04 00 00 00 00 00 00 00 db e1 4f e7 00 00 00 00  ..........O.....
>     08 d6 76 0e 81 88 ff ff 08 d6 76 0e 81 88 ff ff  ..v.......v.....
>   backtrace:
>     [<ffffffff81a3162e>] __kmalloc_node+0x4e/0x90
>     [<ffffffff81a0e166>] kvmalloc_node+0xa6/0x1f0
>     [<ffffffff8276e1a3>] bucket_table_alloc.isra.0+0x83/0x460
>     [<ffffffff8276f18b>] rhashtable_init+0x43b/0x7c0
>     [<ffffffff82f04a1c>] vxlan_vnigroup_init+0x6c/0x160
>     [<ffffffff82ecd69e>] vxlan_init+0x1ae/0x280
>     [<ffffffff836858ca>] register_netdevice+0x57a/0x16d0
>     [<ffffffff82ef67b7>] __vxlan_dev_create+0x7c7/0xa50
>     [<ffffffff82ef6ce6>] vxlan_newlink+0xd6/0x130
>     [<ffffffff836d02ab>] __rtnl_newlink+0x112b/0x18a0
>     [<ffffffff836d0a8c>] rtnl_newlink+0x6c/0xa0
>     [<ffffffff836c0ddf>] rtnetlink_rcv_msg+0x43f/0xd40
>     [<ffffffff83908ce0>] netlink_rcv_skb+0x170/0x440
>     [<ffffffff839066af>] netlink_unicast+0x53f/0x810
>     [<ffffffff839072d8>] netlink_sendmsg+0x958/0xe70
>     [<ffffffff835c319f>] ____sys_sendmsg+0x78f/0xa90
> 
> Fixes: f9c4bb0b245c ("vxlan: vni filtering support on collect metadata device")
> Signed-off-by: Ido Schimmel <idosch@nvidia.com>
> ---
>  drivers/net/vxlan/vxlan_core.c | 19 +++++++++++++------
>  1 file changed, 13 insertions(+), 6 deletions(-)
> 
> diff --git a/drivers/net/vxlan/vxlan_core.c b/drivers/net/vxlan/vxlan_core.c
> index 92224b36787a..b1b179effe2a 100644
> --- a/drivers/net/vxlan/vxlan_core.c
> +++ b/drivers/net/vxlan/vxlan_core.c
> @@ -2917,16 +2917,23 @@ static int vxlan_init(struct net_device *dev)
>  		vxlan_vnigroup_init(vxlan);
>  
>  	dev->tstats = netdev_alloc_pcpu_stats(struct pcpu_sw_netstats);
> -	if (!dev->tstats)
> -		return -ENOMEM;
> +	if (!dev->tstats) {
> +		err = -ENOMEM;
> +		goto err_vnigroup_uninit;
> +	}
>  
>  	err = gro_cells_init(&vxlan->gro_cells, dev);
> -	if (err) {
> -		free_percpu(dev->tstats);
> -		return err;
> -	}
> +	if (err)
> +		goto err_free_percpu;
>  
>  	return 0;
> +
> +err_free_percpu:
> +	free_percpu(dev->tstats);
> +err_vnigroup_uninit:
> +	if (vxlan->cfg.flags & VXLAN_F_VNIFILTER)
> +		vxlan_vnigroup_uninit(vxlan);
> +	return err;
>  }
>  
>  static void vxlan_fdb_delete_default(struct vxlan_dev *vxlan, __be32 vni)

Reviewed-by: Nikolay Aleksandrov <razor@blackwall.org>
patchwork-bot+netdevbpf@kernel.org Jan. 2, 2023, 1:40 p.m. UTC | #2
Hello:

This patch was applied to netdev/net.git (master)
by David S. Miller <davem@davemloft.net>:

On Mon,  2 Jan 2023 08:55:56 +0200 you wrote:
> The memory allocated by vxlan_vnigroup_init() is not freed in the error
> path, leading to memory leaks [1]. Fix by calling
> vxlan_vnigroup_uninit() in the error path.
> 
> The leaks can be reproduced by annotating gro_cells_init() with
> ALLOW_ERROR_INJECTION() and then running:
> 
> [...]

Here is the summary with links:
  - [net] vxlan: Fix memory leaks in error path
    https://git.kernel.org/netdev/net/c/06bf62944144

You are awesome, thank you!
diff mbox series

Patch

diff --git a/drivers/net/vxlan/vxlan_core.c b/drivers/net/vxlan/vxlan_core.c
index 92224b36787a..b1b179effe2a 100644
--- a/drivers/net/vxlan/vxlan_core.c
+++ b/drivers/net/vxlan/vxlan_core.c
@@ -2917,16 +2917,23 @@  static int vxlan_init(struct net_device *dev)
 		vxlan_vnigroup_init(vxlan);
 
 	dev->tstats = netdev_alloc_pcpu_stats(struct pcpu_sw_netstats);
-	if (!dev->tstats)
-		return -ENOMEM;
+	if (!dev->tstats) {
+		err = -ENOMEM;
+		goto err_vnigroup_uninit;
+	}
 
 	err = gro_cells_init(&vxlan->gro_cells, dev);
-	if (err) {
-		free_percpu(dev->tstats);
-		return err;
-	}
+	if (err)
+		goto err_free_percpu;
 
 	return 0;
+
+err_free_percpu:
+	free_percpu(dev->tstats);
+err_vnigroup_uninit:
+	if (vxlan->cfg.flags & VXLAN_F_VNIFILTER)
+		vxlan_vnigroup_uninit(vxlan);
+	return err;
 }
 
 static void vxlan_fdb_delete_default(struct vxlan_dev *vxlan, __be32 vni)