Don't attach callback to a going-away netlink socket
Subsystems (2)
PATCH 1/1 Don't attach callback to a going-away netlink socket
From: Denis Lunev <[email protected]>
There is a race between netlink_dump_start() and netlink_release() that can lead to the situation when a netlink socket with non-zero callback is freed.
net/netlink/af_netlink.c +3 -3
@@ -255,6 +255,7 @@ static int netlink_release(struct socketreturn 0 ;netlink_remove (sk); +sock_orphan (sk); nlk =nlk_sk (sk);spin_lock (&nlk->cb_lock);
@@ -269,7 +270,6 @@ static int netlink_release(struct socket/* OK. Socket is unlinked, and, therefore, no new packets will arrive */ -sock_orphan (sk); sock->sk =NULL ;wake_up_interruptible_all (&nlk->wait);
@@ -942,9 +942,9 @@ int netlink_dump_start(struct sock *ssk,return -ECONNREFUSED ; } nlk =nlk_sk (sk); -/* A dump is in progress... */ +/* A dump or destruction is in progress... */ spin_lock (&nlk->cb_lock); -if (nlk->cb) { +if (nlk->cb ||sock_flag (sk,SOCK_DEAD )) {spin_unlock (&nlk->cb_lock);netlink_destroy_callback (cb);sock_put (sk);
Quoted 5 lines · Pavel Emelianov
From: Denis Lunev <[email protected]>
There is a race between
netlink_dump_start()andnetlink_release()that can lead to the situation when a netlink socket with non-zero callback is freed.
Can you describe the race in more detail please?
Quoted 11 lines · Patrick McHardy
Quoted 5 lines · Pavel Emelianov
From: Denis Lunev <[email protected]>
There is a race between
netlink_dump_start()andnetlink_release()that can lead to the situation when a netlink socket with non-zero callback is freed.Can you describe the race in more detail please?
Here it is:
CPU1: CPU2 netlink_release(): netlink_dump_start():
sk = netlink_lookup(); /* OK */
netlink_remove();
spin_lock(&nlk->cb_lock);
if (nlk->cb) { /* false */
...
}spin_unlock(&nlk->cb_lock);
spin_lock(&nlk->cb_lock);
if (nlk->cb) { /* false */
...
}
nlk->cb = cb;
spin_unlock(&nlk->cb_lock);
...sock_orphan(sk);
/*
* proceed with releasing
* the socket
*/
The proposal it to make sock_orphan before detaching the callback in netlink_release() and to check for the sock to be SOCK_DEAD in netlink_dump_start() before setting a new callback.
Patrick McHardy
Acked-byQuoted 10 lines · Pavel Emelianov
Quoted 7 lines · Patrick McHardy
Quoted 3 lines
There is a race between
netlink_dump_start()andnetlink_release()that can lead to the situation when a netlink socket with non-zero callback is freed.Can you describe the race in more detail please?
Quoted 6 lines
Here it is:
[...]
The proposal it to makesock_orphanbefore detaching the callback innetlink_release()and to check for the sock to beSOCK_DEADinnetlink_dump_start()before setting a new callback.
Thanks, good catch. Your patch also looks good.
Please post networking patches to the networking developer list:
http://vger.kernel.org/vger-lists.html#netdev
- James
Signature · 2 lines
James Morris <[email protected]>