• R/O
  • HTTP
  • SSH

linux-2.4.36: Commit

2.4.36-stable kernel tree

Commit MetaInfo

Revisionaedc33f490e5c89cbfce462255fdfc9fbb5beaad (tree)
Zeit2005-06-26 16:20:15
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.
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, and Herbert Xu for
debugging patches to help track this down.

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,7 @@ retry:
450450 err = netlink_insert(sk, pid);
451451 if (err == -EADDRINUSE)
452452 goto retry;
453- return 0;
453+ return err;
454454 }
456456 static inline int netlink_capable(struct socket *sock, unsigned int flag)
Show on old repository browser