Skip to content

Commit f12b69d

Browse files
ecsvsimonwunderlich
authored andcommitted
batman-adv: Release references to inactive interfaces
Trying to dump the originators or the neighbors via netlink for a meshif with an inactive primary interface is not allowed. The dump functions were checking this correctly but they didn't handle non-existing primary interfaces and existing _inactive_ interfaces differently. (Primary) batadv_hard_ifaces hold a references to a net_device. And accessing them is only allowed when either being in a RCU/spinlock protected section or when holding a valid reference to them. The netlink dump functions use the latter. But because the missing specific error handling for inactive primary interfaces, the reference was never dropped. This reference counting error was only detected when the interface should have been removed from the system: unregister_netdevice: waiting for batadv_slave_0 to become free. Usage count = 2 Cc: stable@vger.kernel.org Fixes: 6ecc4fd ("batman-adv: netlink: reduce duplicate code by returning interfaces") Reported-by: syzbot+881d65229ca4f9ae8c84@syzkaller.appspotmail.com Reported-by: Tetsuo Handa <penguin-kernel@i-love.sakura.ne.jp> Signed-off-by: Sven Eckelmann <sven@narfation.org> Signed-off-by: Simon Wunderlich <sw@simonwunderlich.de>
1 parent d69eb20 commit f12b69d

1 file changed

Lines changed: 12 additions & 2 deletions

File tree

net/batman-adv/originator.c

Lines changed: 12 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -764,11 +764,16 @@ int batadv_hardif_neigh_dump(struct sk_buff *msg, struct netlink_callback *cb)
764764
bat_priv = netdev_priv(mesh_iface);
765765

766766
primary_if = batadv_primary_if_get_selected(bat_priv);
767-
if (!primary_if || primary_if->if_status != BATADV_IF_ACTIVE) {
767+
if (!primary_if) {
768768
ret = -ENOENT;
769769
goto out_put_mesh_iface;
770770
}
771771

772+
if (primary_if->if_status != BATADV_IF_ACTIVE) {
773+
ret = -ENOENT;
774+
goto out_put_primary_if;
775+
}
776+
772777
hard_iface = batadv_netlink_get_hardif(bat_priv, cb);
773778
if (IS_ERR(hard_iface) && PTR_ERR(hard_iface) != -ENONET) {
774779
ret = PTR_ERR(hard_iface);
@@ -1333,11 +1338,16 @@ int batadv_orig_dump(struct sk_buff *msg, struct netlink_callback *cb)
13331338
bat_priv = netdev_priv(mesh_iface);
13341339

13351340
primary_if = batadv_primary_if_get_selected(bat_priv);
1336-
if (!primary_if || primary_if->if_status != BATADV_IF_ACTIVE) {
1341+
if (!primary_if) {
13371342
ret = -ENOENT;
13381343
goto out_put_mesh_iface;
13391344
}
13401345

1346+
if (primary_if->if_status != BATADV_IF_ACTIVE) {
1347+
ret = -ENOENT;
1348+
goto out_put_primary_if;
1349+
}
1350+
13411351
hard_iface = batadv_netlink_get_hardif(bat_priv, cb);
13421352
if (IS_ERR(hard_iface) && PTR_ERR(hard_iface) != -ENONET) {
13431353
ret = PTR_ERR(hard_iface);

0 commit comments

Comments
 (0)