From 3bd5008544cec65304a4730dab3b277443e4fd69 Mon Sep 17 00:00:00 2001 From: Chris Wright Date: Mon, 27 Feb 2006 12:12:03 -0800 Subject: [PATCH] Fix netlink overrun deadlock from Alexey, fwd from DaveM --- queue/fix-a-severe-bug.patch | 90 ++++++++++++++++++++++++++++++++++++ queue/series | 1 + 2 files changed, 91 insertions(+) create mode 100644 queue/fix-a-severe-bug.patch diff --git a/queue/fix-a-severe-bug.patch b/queue/fix-a-severe-bug.patch new file mode 100644 index 00000000000..509ed258ca5 --- /dev/null +++ b/queue/fix-a-severe-bug.patch @@ -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" +To: stable@kernel.org +Cc: +Subject: [NETLINK]: Fix a severe bug + +From: Alexey Kuznetsov + +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 +Signed-off-by: David S. Miller +Signed-off-by: Chris Wright +--- + + 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) diff --git a/queue/series b/queue/series index 9da3cb58d4d..24fb47f91ba 100644 --- a/queue/series +++ b/queue/series @@ -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 -- 2.47.3