Skip to content

Commit 6d1a3fb

Browse files
kaberdavem330
authored andcommitted
netlink: genl: fix circular locking
genetlink has a circular locking dependency when dumping the registered families: - dump start: genl_rcv() : take genl_mutex genl_rcv_msg() : call netlink_dump_start() while holding genl_mutex netlink_dump_start(), netlink_dump() : take nlk->cb_mutex ctrl_dumpfamily() : try to detect this case and not take genl_mutex a second time - dump continuance: netlink_rcv() : call netlink_dump netlink_dump : take nlk->cb_mutex ctrl_dumpfamily() : take genl_mutex Register genl_lock as callback mutex with netlink to fix this. This slightly widens an already existing module unload race, the genl ops used during the dump might go away when the module is unloaded. Thomas Graf is working on a seperate fix for this. Signed-off-by: Patrick McHardy <[email protected]> Signed-off-by: David S. Miller <[email protected]>
1 parent 3a5be7d commit 6d1a3fb

File tree

1 file changed

+6
-9
lines changed

1 file changed

+6
-9
lines changed

net/netlink/genetlink.c

Lines changed: 6 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -444,8 +444,11 @@ static int genl_rcv_msg(struct sk_buff *skb, struct nlmsghdr *nlh)
444444
if (ops->dumpit == NULL)
445445
return -EOPNOTSUPP;
446446

447-
return netlink_dump_start(genl_sock, skb, nlh,
448-
ops->dumpit, ops->done);
447+
genl_unlock();
448+
err = netlink_dump_start(genl_sock, skb, nlh,
449+
ops->dumpit, ops->done);
450+
genl_lock();
451+
return err;
449452
}
450453

451454
if (ops->doit == NULL)
@@ -603,9 +606,6 @@ static int ctrl_dumpfamily(struct sk_buff *skb, struct netlink_callback *cb)
603606
int chains_to_skip = cb->args[0];
604607
int fams_to_skip = cb->args[1];
605608

606-
if (chains_to_skip != 0)
607-
genl_lock();
608-
609609
for (i = 0; i < GENL_FAM_TAB_SIZE; i++) {
610610
if (i < chains_to_skip)
611611
continue;
@@ -623,9 +623,6 @@ static int ctrl_dumpfamily(struct sk_buff *skb, struct netlink_callback *cb)
623623
}
624624

625625
errout:
626-
if (chains_to_skip != 0)
627-
genl_unlock();
628-
629626
cb->args[0] = i;
630627
cb->args[1] = n;
631628

@@ -770,7 +767,7 @@ static int __init genl_init(void)
770767

771768
/* we'll bump the group number right afterwards */
772769
genl_sock = netlink_kernel_create(&init_net, NETLINK_GENERIC, 0,
773-
genl_rcv, NULL, THIS_MODULE);
770+
genl_rcv, &genl_mutex, THIS_MODULE);
774771
if (genl_sock == NULL)
775772
panic("GENL: Cannot initialize generic netlink\n");
776773

0 commit comments

Comments
 (0)