• R/O
  • HTTP
  • SSH

linux-2.4.36: Commit

2.4.36-stable kernel tree

Commit MetaInfo

Revision2bd6c95c3a00dadee6378e13c699006830d7e8e0 (tree)
Zeit2005-07-27 05:26:44
AutorDavid S. Miller <davem@dave...>
CommiterDavid S. Miller

Log Message

[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 <davem@davemloft.net>

Ändern Zusammenfassung


--- a/net/netlink/af_netlink.c
+++ b/net/netlink/af_netlink.c
@@ -330,9 +330,9 @@ static void netlink_remove(struct sock *sk)
330330 u32 pid = nlk_sk(sk)->pid;
332332 netlink_table_grab();
333- hash->entries--;
334333 for (skp = nl_pid_hashfn(hash, pid); *skp; skp = &((*skp)->next)) {
335334 if (*skp == sk) {
335+ hash->entries--;
336336 *skp = sk->next;
337337 __sock_put(sk);
338338 break;
@@ -450,7 +450,12 @@ retry:
450450 err = netlink_insert(sk, pid);
451451 if (err == -EADDRINUSE)
452452 goto retry;
453- return 0;
454+ /* If 2 threads race to autobind, that is fine. */
455+ if (err == -EBUSY)
456+ err = 0;
458+ return err;
454459 }
456461 static inline int netlink_capable(struct socket *sock, unsigned int flag)
Show on old repository browser