diff mbox series

[net-next] net: vxlan: Free a leaked vetoed multicast rdst

Message ID f0b53ffcc4ca130436a8f2799f85bd90695f6d45.1549540888.git.petrm@mellanox.com
State Accepted
Delegated to: David Miller
Headers show
Series [net-next] net: vxlan: Free a leaked vetoed multicast rdst | expand

Commit Message

Petr Machata Feb. 7, 2019, 12:18 p.m. UTC
When an rdst is rejected by a driver, the current code removes it from
the remote list, but neglects to free it. This is triggered by
tools/testing/selftests/drivers/net/mlxsw/vxlan_fdb_veto.sh and shows as
the following kmemleak trace:

unreferenced object 0xffff88817fa3d888 (size 96):
  comm "softirq", pid 0, jiffies 4372702718 (age 165.252s)
  hex dump (first 32 bytes):
    02 00 00 00 c6 33 64 03 80 f5 a2 61 81 88 ff ff  .....3d....a....
    06 df 71 ae ff ff ff ff 0c 00 00 00 04 d2 6a 6b  ..q...........jk
  backtrace:
    [<00000000296b27ac>] kmem_cache_alloc_trace+0x1ae/0x370
    [<0000000075c86dc6>] vxlan_fdb_append.part.12+0x62/0x3b0 [vxlan]
    [<00000000e0414b63>] vxlan_fdb_update+0xc61/0x1020 [vxlan]
    [<00000000f330c4bd>] vxlan_fdb_add+0x2e8/0x3d0 [vxlan]
    [<0000000008f81c2c>] rtnl_fdb_add+0x4c2/0xa10
    [<00000000bdc4b270>] rtnetlink_rcv_msg+0x6dd/0x970
    [<000000006701f2ce>] netlink_rcv_skb+0x290/0x410
    [<00000000c08a5487>] rtnetlink_rcv+0x15/0x20
    [<00000000d5f54b1e>] netlink_unicast+0x43f/0x5e0
    [<00000000db4336bb>] netlink_sendmsg+0x789/0xcd0
    [<00000000e1ee26b6>] sock_sendmsg+0xba/0x100
    [<00000000ba409802>] ___sys_sendmsg+0x631/0x960
    [<000000003c332113>] __sys_sendmsg+0xea/0x180
    [<00000000f4139144>] __x64_sys_sendmsg+0x78/0xb0
    [<000000006d1ddc59>] do_syscall_64+0x94/0x410
    [<00000000c8defa9a>] entry_SYSCALL_64_after_hwframe+0x49/0xbe

Move vxlan_dst_free() up and schedule a call thereof to plug this leak.

Fixes: 61f46fe8c646 ("vxlan: Allow vetoing of FDB notifications")
Signed-off-by: Petr Machata <petrm@mellanox.com>
Acked-by: Jiri Pirko <jiri@mellanox.com>
---
 drivers/net/vxlan.c | 20 +++++++++++---------
 1 file changed, 11 insertions(+), 9 deletions(-)

Comments

David Miller Feb. 7, 2019, 7:18 p.m. UTC | #1
From: Petr Machata <petrm@mellanox.com>
Date: Thu, 7 Feb 2019 12:18:02 +0000

> When an rdst is rejected by a driver, the current code removes it from
> the remote list, but neglects to free it. This is triggered by
> tools/testing/selftests/drivers/net/mlxsw/vxlan_fdb_veto.sh and shows as
> the following kmemleak trace:
> 
> unreferenced object 0xffff88817fa3d888 (size 96):
>   comm "softirq", pid 0, jiffies 4372702718 (age 165.252s)
>   hex dump (first 32 bytes):
>     02 00 00 00 c6 33 64 03 80 f5 a2 61 81 88 ff ff  .....3d....a....
>     06 df 71 ae ff ff ff ff 0c 00 00 00 04 d2 6a 6b  ..q...........jk
>   backtrace:
>     [<00000000296b27ac>] kmem_cache_alloc_trace+0x1ae/0x370
>     [<0000000075c86dc6>] vxlan_fdb_append.part.12+0x62/0x3b0 [vxlan]
>     [<00000000e0414b63>] vxlan_fdb_update+0xc61/0x1020 [vxlan]
>     [<00000000f330c4bd>] vxlan_fdb_add+0x2e8/0x3d0 [vxlan]
>     [<0000000008f81c2c>] rtnl_fdb_add+0x4c2/0xa10
>     [<00000000bdc4b270>] rtnetlink_rcv_msg+0x6dd/0x970
>     [<000000006701f2ce>] netlink_rcv_skb+0x290/0x410
>     [<00000000c08a5487>] rtnetlink_rcv+0x15/0x20
>     [<00000000d5f54b1e>] netlink_unicast+0x43f/0x5e0
>     [<00000000db4336bb>] netlink_sendmsg+0x789/0xcd0
>     [<00000000e1ee26b6>] sock_sendmsg+0xba/0x100
>     [<00000000ba409802>] ___sys_sendmsg+0x631/0x960
>     [<000000003c332113>] __sys_sendmsg+0xea/0x180
>     [<00000000f4139144>] __x64_sys_sendmsg+0x78/0xb0
>     [<000000006d1ddc59>] do_syscall_64+0x94/0x410
>     [<00000000c8defa9a>] entry_SYSCALL_64_after_hwframe+0x49/0xbe
> 
> Move vxlan_dst_free() up and schedule a call thereof to plug this leak.
> 
> Fixes: 61f46fe8c646 ("vxlan: Allow vetoing of FDB notifications")
> Signed-off-by: Petr Machata <petrm@mellanox.com>
> Acked-by: Jiri Pirko <jiri@mellanox.com>

Applied, thanks.
diff mbox series

Patch

diff --git a/drivers/net/vxlan.c b/drivers/net/vxlan.c
index ef45c3c925be..c0cd1c022e77 100644
--- a/drivers/net/vxlan.c
+++ b/drivers/net/vxlan.c
@@ -869,6 +869,14 @@  static void vxlan_fdb_destroy(struct vxlan_dev *vxlan, struct vxlan_fdb *f,
 	call_rcu(&f->rcu, vxlan_fdb_free);
 }
 
+static void vxlan_dst_free(struct rcu_head *head)
+{
+	struct vxlan_rdst *rd = container_of(head, struct vxlan_rdst, rcu);
+
+	dst_cache_destroy(&rd->dst_cache);
+	kfree(rd);
+}
+
 static int vxlan_fdb_update_existing(struct vxlan_dev *vxlan,
 				     union vxlan_addr *ip,
 				     __u16 state, __u16 flags,
@@ -941,8 +949,10 @@  static int vxlan_fdb_update_existing(struct vxlan_dev *vxlan,
 err_notify:
 	if ((flags & NLM_F_REPLACE) && rc)
 		*rd = oldrd;
-	else if ((flags & NLM_F_APPEND) && rc)
+	else if ((flags & NLM_F_APPEND) && rc) {
 		list_del_rcu(&rd->list);
+		call_rcu(&rd->rcu, vxlan_dst_free);
+	}
 	return err;
 }
 
@@ -1013,14 +1023,6 @@  static int vxlan_fdb_update(struct vxlan_dev *vxlan,
 	}
 }
 
-static void vxlan_dst_free(struct rcu_head *head)
-{
-	struct vxlan_rdst *rd = container_of(head, struct vxlan_rdst, rcu);
-
-	dst_cache_destroy(&rd->dst_cache);
-	kfree(rd);
-}
-
 static void vxlan_fdb_dst_destroy(struct vxlan_dev *vxlan, struct vxlan_fdb *f,
 				  struct vxlan_rdst *rd, bool swdev_notify)
 {