[FEISTY]: [PATCH] Denial of Service security fix from stable kernel 2.6.20.8

Phillip Lougher phillip at lougher.demon.co.uk
Thu May 3 12:57:20 UTC 2007


>From d34a455146373a45238053c03b290e984224e0f6 Mon Sep 17 00:00:00 2001
From: Alexey Kuznetsov <kuznet at ms2.inr.ac.ru>
Date: Wed, 25 Apr 2007 20:59:03 +0000
Subject: [PATCH] (Denial of Service security fix from stable kernel 2.6.20.8)

[PATCH] NETLINK: Infinite recursion in netlink.

[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 at ms2.inr.ac.ru>
Signed-off-by: David S. Miller <davem at davemloft.net>
Signed-off-by: Greg Kroah-Hartman <gregkh at suse.de>
(cherry picked from commit 9bc1779885f4ce1a4257c5640c70b75d2ae124ad)
---
 net/ipv4/fib_frontend.c |    8 +++++++-
 1 files changed, 7 insertions(+), 1 deletions(-)

diff --git a/net/ipv4/fib_frontend.c b/net/ipv4/fib_frontend.c
index 91c9bfa..9a811d0 100644
--- a/net/ipv4/fib_frontend.c
+++ b/net/ipv4/fib_frontend.c
@@ -777,6 +777,8 @@ static void nl_fib_lookup(struct fib_result_nl *frn, struct fib_table *tb )
 				       .nl_u = { .ip4_u = { .daddr = frn->fl_addr,
 							    .tos = frn->fl_tos,
 							    .scope = frn->fl_scope } } };
+
+	frn->err = -ENOENT;
 	if (tb) {
 		local_bh_disable();
 
@@ -788,6 +790,7 @@ static void nl_fib_lookup(struct fib_result_nl *frn, struct fib_table *tb )
 			frn->nh_sel = res.nh_sel;
 			frn->type = res.type;
 			frn->scope = res.scope;
+			fib_res_put(&res);
 		}
 		local_bh_enable();
 	}
@@ -802,6 +805,9 @@ static void nl_fib_input(struct sock *sk, int len)
 	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))) {
@@ -814,7 +820,7 @@ static void nl_fib_input(struct sock *sk, int len)
 
 	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);
-- 
1.4.4.2





More information about the kernel-team mailing list