| 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); |