]> git.ipfire.org Git - thirdparty/kernel/stable.git/commit
macsec: fix refcnt leak in module exit routine
authorTaehee Yoo <ap420073@gmail.com>
Mon, 21 Oct 2019 18:47:55 +0000 (18:47 +0000)
committerGreg Kroah-Hartman <gregkh@linuxfoundation.org>
Tue, 12 Nov 2019 18:27:54 +0000 (19:27 +0100)
commitb0add6db3d5ec4561cab257358871a9d3df7f0a3
tree4d4d9537594e296cc4d48929ef5028f3b0a98d61
parent80688a6fd6f60b679b69a00f538ce4b14fa4e585
macsec: fix refcnt leak in module exit routine

[ Upstream commit 2bce1ebed17da54c65042ec2b962e3234bad5b47 ]

When a macsec interface is created, it increases a refcnt to a lower
device(real device). when macsec interface is deleted, the refcnt is
decreased in macsec_free_netdev(), which is ->priv_destructor() of
macsec interface.

The problem scenario is this.
When nested macsec interfaces are exiting, the exit routine of the
macsec module makes refcnt leaks.

Test commands:
    ip link add dummy0 type dummy
    ip link add macsec0 link dummy0 type macsec
    ip link add macsec1 link macsec0 type macsec
    modprobe -rv macsec

[  208.629433] unregister_netdevice: waiting for macsec0 to become free. Usage count = 1

Steps of exit routine of macsec module are below.
1. Calls ->dellink() in __rtnl_link_unregister().
2. Checks refcnt and wait refcnt to be 0 if refcnt is not 0 in
netdev_run_todo().
3. Calls ->priv_destruvtor() in netdev_run_todo().

Step2 checks refcnt, but step3 decreases refcnt.
So, step2 waits forever.

This patch makes the macsec module do not hold a refcnt of the lower
device because it already holds a refcnt of the lower device with
netdev_upper_dev_link().

Fixes: c09440f7dcb3 ("macsec: introduce IEEE 802.1AE driver")
Signed-off-by: Taehee Yoo <ap420073@gmail.com>
Signed-off-by: David S. Miller <davem@davemloft.net>
Signed-off-by: Sasha Levin <sashal@kernel.org>
drivers/net/macsec.c