]> git.ipfire.org Git - thirdparty/kernel/stable-queue.git/commitdiff
Fix netlink overrun deadlock from Alexey, fwd from DaveM
authorChris Wright <chrisw@sous-sol.org>
Mon, 27 Feb 2006 20:12:03 +0000 (12:12 -0800)
committerChris Wright <chrisw@sous-sol.org>
Mon, 27 Feb 2006 20:12:03 +0000 (12:12 -0800)
queue/fix-a-severe-bug.patch [new file with mode: 0644]
queue/series

diff --git a/queue/fix-a-severe-bug.patch b/queue/fix-a-severe-bug.patch
new file mode 100644 (file)
index 0000000..509ed25
--- /dev/null
@@ -0,0 +1,90 @@
+From stable-bounces@linux.kernel.org  Mon Feb 27 00:32:15 2006
+Date: Mon, 27 Feb 2006 00:28:32 -0800 (PST)
+From: "David S. Miller" <davem@davemloft.net>
+To: stable@kernel.org
+Cc: 
+Subject: [NETLINK]: Fix a severe bug
+
+From: Alexey Kuznetsov <kuznet@ms2.inr.ac.ru>
+
+netlink overrun was broken while improvement of netlink.
+Destination socket is used in the place where it was meant to be source socket,
+so that now overrun is never sent to user netlink sockets, when it should be,
+and it even can be set on kernel socket, which results in complete deadlock
+of rtnetlink.
+
+Suggested fix is to restore status quo passing source socket as additional
+argument to netlink_attachskb().
+
+A little explanation: overrun is set on a socket, when it failed
+to receive some message and sender of this messages does not or even
+have no way to handle this error. This happens in two cases:
+1. when kernel sends something. Kernel never retransmits and cannot
+   wait for buffer space.
+2. when user sends a broadcast and the message was not delivered
+   to some recipients.
+
+Signed-off-by: Alexey Kuznetsov <kuznet@ms2.inr.ac.ru>
+Signed-off-by: David S. Miller <davem@davemloft.net>
+Signed-off-by: Chris Wright <chrisw@sous-sol.org>
+---
+
+ include/linux/netlink.h  |    3 ++-
+ ipc/mqueue.c             |    3 ++-
+ net/netlink/af_netlink.c |    7 ++++---
+ 3 files changed, 8 insertions(+), 5 deletions(-)
+
+--- linux-2.6.15.4.orig/include/linux/netlink.h
++++ linux-2.6.15.4/include/linux/netlink.h
+@@ -160,7 +160,8 @@ extern int netlink_unregister_notifier(s
+ /* finegrained unicast helpers: */
+ struct sock *netlink_getsockbyfilp(struct file *filp);
+-int netlink_attachskb(struct sock *sk, struct sk_buff *skb, int nonblock, long timeo);
++int netlink_attachskb(struct sock *sk, struct sk_buff *skb, int nonblock,
++              long timeo, struct sock *ssk);
+ void netlink_detachskb(struct sock *sk, struct sk_buff *skb);
+ int netlink_sendskb(struct sock *sk, struct sk_buff *skb, int protocol);
+--- linux-2.6.15.4.orig/ipc/mqueue.c
++++ linux-2.6.15.4/ipc/mqueue.c
+@@ -1017,7 +1017,8 @@ retry:
+                               goto out;
+                       }
+-                      ret = netlink_attachskb(sock, nc, 0, MAX_SCHEDULE_TIMEOUT);
++                      ret = netlink_attachskb(sock, nc, 0,
++                                      MAX_SCHEDULE_TIMEOUT, NULL);
+                       if (ret == 1)
+                               goto retry;
+                       if (ret) {
+--- linux-2.6.15.4.orig/net/netlink/af_netlink.c
++++ linux-2.6.15.4/net/netlink/af_netlink.c
+@@ -701,7 +701,8 @@ struct sock *netlink_getsockbyfilp(struc
+  * 0: continue
+  * 1: repeat lookup - reference dropped while waiting for socket memory.
+  */
+-int netlink_attachskb(struct sock *sk, struct sk_buff *skb, int nonblock, long timeo)
++int netlink_attachskb(struct sock *sk, struct sk_buff *skb, int nonblock,
++              long timeo, struct sock *ssk)
+ {
+       struct netlink_sock *nlk;
+@@ -711,7 +712,7 @@ int netlink_attachskb(struct sock *sk, s
+           test_bit(0, &nlk->state)) {
+               DECLARE_WAITQUEUE(wait, current);
+               if (!timeo) {
+-                      if (!nlk->pid)
++                      if (!ssk || nlk_sk(ssk)->pid == 0)
+                               netlink_overrun(sk);
+                       sock_put(sk);
+                       kfree_skb(skb);
+@@ -796,7 +797,7 @@ retry:
+               kfree_skb(skb);
+               return PTR_ERR(sk);
+       }
+-      err = netlink_attachskb(sk, skb, nonblock, timeo);
++      err = netlink_attachskb(sk, skb, nonblock, timeo, ssk);
+       if (err == 1)
+               goto retry;
+       if (err)
index 9da3cb58d4d41e9a0469d6070b7fd9bea4350118..24fb47f91ba950e794dbebe05cb68a3e3f1e6593 100644 (file)
@@ -31,3 +31,4 @@ skge-fix-napi-irq-race.patch
 skge-genesis-phy-initialization-fix.patch
 skge-fix-smp-race.patch
 x86_64-check-for-bad-elf-entry-address.patch
+fix-a-severe-bug.patch