blob: 59f65362c2d58207ed73a7a13793b2ec0d4bef53 [file] [log] [blame]
From git-commits-head-owner@vger.kernel.org Wed Apr 25 14:00:42 2007
From: Alexey Kuznetsov <kuznet@ms2.inr.ac.ru>
Date: Wed, 25 Apr 2007 20:59:03 GMT
Subject: NETLINK: Infinite recursion in netlink.
To: git-commits-head@vger.kernel.org
Message-ID: <200704252059.l3PKx3h7031374@hera.kernel.org>
From: Alexey Kuznetsov <kuznet@ms2.inr.ac.ru>
[NETLINK]: Infinite recursion in netlink.
Reply to NETLINK_FIB_LOOKUP messages were misrouted back to kernel,
which resulted in infinite recursion and stack overflow.
The bug is present in all kernel versions since the feature appeared.
The patch also makes some minimal cleanup:
1. Return something consistent (-ENOENT) when fib table is missing
2. Do not crash when queue is empty (does not happen, but yet)
3. Put result of lookup
Signed-off-by: Alexey Kuznetsov <kuznet@ms2.inr.ac.ru>
Signed-off-by: David S. Miller <davem@davemloft.net>
Signed-off-by: Greg Kroah-Hartman <gregkh@suse.de>
---
net/ipv4/fib_frontend.c | 8 +++++++-
1 file changed, 7 insertions(+), 1 deletion(-)
--- a/net/ipv4/fib_frontend.c
+++ b/net/ipv4/fib_frontend.c
@@ -772,6 +772,8 @@ static void nl_fib_lookup(struct fib_res
.nl_u = { .ip4_u = { .daddr = frn->fl_addr,
.tos = frn->fl_tos,
.scope = frn->fl_scope } } };
+
+ frn->err = -ENOENT;
if (tb) {
local_bh_disable();
@@ -783,6 +785,7 @@ static void nl_fib_lookup(struct fib_res
frn->nh_sel = res.nh_sel;
frn->type = res.type;
frn->scope = res.scope;
+ fib_res_put(&res);
}
local_bh_enable();
}
@@ -797,6 +800,9 @@ static void nl_fib_input(struct sock *sk
struct fib_table *tb;
skb = skb_dequeue(&sk->sk_receive_queue);
+ if (skb == NULL)
+ return;
+
nlh = (struct nlmsghdr *)skb->data;
if (skb->len < NLMSG_SPACE(0) || skb->len < nlh->nlmsg_len ||
nlh->nlmsg_len < NLMSG_LENGTH(sizeof(*frn))) {
@@ -809,7 +815,7 @@ static void nl_fib_input(struct sock *sk
nl_fib_lookup(frn, tb);
- pid = nlh->nlmsg_pid; /*pid of sending process */
+ pid = NETLINK_CB(skb).pid; /* pid of sending process */
NETLINK_CB(skb).pid = 0; /* from kernel */
NETLINK_CB(skb).dst_group = 0; /* unicast */
netlink_unicast(sk, skb, pid, MSG_DONTWAIT);