Skip to content

Commit d470e3b

Browse files
committed
[NETLINK]: Fix two socket hashing bugs.
1) netlink_release() should only decrement the hash entry count if the socket was actually hashed. This was causing hash->entries to underflow, which resulting in all kinds of troubles. On 64-bit systems, this would cause the following conditional to erroneously trigger: err = -ENOMEM; if (BITS_PER_LONG > 32 && unlikely(hash->entries >= UINT_MAX)) goto err; 2) netlink_autobind() needs to propagate the error return from netlink_insert(). Otherwise, callers will not see the error as they should and thus try to operate on a socket with a zero pid, which is very bad. However, it should not propagate -EBUSY. If two threads race to autobind the socket, that is fine. This is consistent with the autobind behavior in other protocols. So bug #1 above, combined with this one, resulted in hangs on netlink_sendmsg() calls to the rtnetlink socket. We'd try to do the user sendmsg() with the socket's pid set to zero, later we do a socket lookup using that pid (via the value we stashed away in NETLINK_CB(skb).pid), but that won't give us the user socket, it will give us the rtnetlink socket. So when we try to wake up the receive queue, we dive back into rtnetlink_rcv() which tries to recursively take the rtnetlink semaphore. Thanks to Jakub Jelink for providing backtraces. Also, thanks to Herbert Xu for supplying debugging patches to help track this down, and also finding a mistake in an earlier version of this fix. Signed-off-by: David S. Miller <[email protected]>
1 parent 32e9e25 commit d470e3b

File tree

1 file changed

+8
-3
lines changed

1 file changed

+8
-3
lines changed

net/netlink/af_netlink.c

Lines changed: 8 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -315,8 +315,8 @@ static int netlink_insert(struct sock *sk, u32 pid)
315315
static void netlink_remove(struct sock *sk)
316316
{
317317
netlink_table_grab();
318-
nl_table[sk->sk_protocol].hash.entries--;
319-
sk_del_node_init(sk);
318+
if (sk_del_node_init(sk))
319+
nl_table[sk->sk_protocol].hash.entries--;
320320
if (nlk_sk(sk)->groups)
321321
__sk_del_bind_node(sk);
322322
netlink_table_ungrab();
@@ -429,7 +429,12 @@ static int netlink_autobind(struct socket *sock)
429429
err = netlink_insert(sk, pid);
430430
if (err == -EADDRINUSE)
431431
goto retry;
432-
return 0;
432+
433+
/* If 2 threads race to autobind, that is fine. */
434+
if (err == -EBUSY)
435+
err = 0;
436+
437+
return err;
433438
}
434439

435440
static inline int netlink_capable(struct socket *sock, unsigned int flag)

0 commit comments

Comments
 (0)