免费注册 查看新帖 |

Chinaunix

  平台 论坛 博客 文库
最近访问板块 发新帖
查看: 2412 | 回复: 8
打印 上一主题 下一主题

[网络子系统] 一个Netfilter 处理畸形包导致内核OOPS的Bug [复制链接]

论坛徽章:
0
跳转到指定楼层
1 [收藏(0)] [报告]
发表于 2012-05-21 10:20 |只看该作者 |倒序浏览
本帖最后由 独孤九贱 于 2012-05-21 10:21 编辑

原贴讨论在
http://bbs.chinaunix.net/thread-3672415-2-1.html

goter 在12楼已经提到过,对于错误长度的报文,tcp_error应该能够处理它。但是问题的关键在于,tcp_error计算的依据是dataoff,而这个值是上层调用传来下的,其计算在ipv4_get_l4proto函数中:
  1. static int ipv4_get_l4proto(const struct sk_buff *skb, unsigned int nhoff,
  2.                             unsigned int *dataoff, u_int8_t *protonum)
  3. {
  4.         const struct iphdr *iph;
  5.         struct iphdr _iph;

  6.         iph = skb_header_pointer(skb, nhoff, sizeof(_iph), &_iph);
  7.         if (iph == NULL)
  8.                 return -NF_DROP;

  9.         /* Conntrack defragments packets, we might still see fragments
  10.          * inside ICMP packets though. */
  11.         if (iph->frag_off & htons(IP_OFFSET))
  12.                 return -NF_DROP;

  13.         *dataoff = nhoff + (iph->ihl << 2);
  14.         *protonum = iph->protocol;

  15.         return NF_ACCEPT;
  16. }
复制代码
可以看到,*dataoff = nhoff + (iph->ihl << 2);这个计算,并没有做合法性检验,虽然在ip_rcv函数中:
  1.         len = ntohs(iph->tot_len);
  2.         if (skb->len < len) {
  3.                 IP_INC_STATS_BH(dev_net(dev), IPSTATS_MIB_INTRUNCATEDPKTS);
  4.                 goto drop;
  5.         } else if (len < (iph->ihl*4))
  6.                 goto inhdr_error;
复制代码
对于进来的单包是做了检验的,但是对它其它情况呢?从我的遭遇来看,不能依赖于别人,只能相信自己——显然是有另外的情况没有被检测到了,否则这个OOPS是不会被触发的。最先原作者也认为不太可以,不过后来多次沟通后,还是确认了在ipv4_get_l4proto函数中,应该增加对dataoff的检验:
  1. ipv4_get_l4proto() in nf_conntrack_l3proto_ipv4.c and tcp_error() in
  2. nf_conntrack_proto_tcp.c should catch malformed packets, so the errors
  3. at the indicated lines - TCP options parsing - should not happen.
  4. However, tcp_error() relies on the "dataoff" offset to the TCP header,
  5. calculated by ipv4_get_l4proto().  But ipv4_get_l4proto() does not check
  6. bogus ihl values in IPv4 packets, which then can slip through tcp_error()
  7. and get caught at the TCP options parsing routines.
复制代码
这是作者发布的补丁,好像最新的内核也还没有应用它。如果遇到和我一样问题的同学,可以打这个补丁:
  1. The patch fixes ipv4_get_l4proto() by dropping packets with bogus
  2. ihl value.

  3. The patch closes netfilter bugzilla id 771.

  4. Signed-off-by: Jozsef Kadlecsik <kadlec@blackhole.kfki.hu>
  5. ---
  6. net/ipv4/netfilter/nf_conntrack_l3proto_ipv4.c |    8 ++++++++
  7. 1 files changed, 8 insertions(+), 0 deletions(-)

  8. diff --git a/net/ipv4/netfilter/nf_conntrack_l3proto_ipv4.c \
  9. b/net/ipv4/netfilter/nf_conntrack_l3proto_ipv4.c index de9da21..6a5f038 100644
  10. --- a/net/ipv4/netfilter/nf_conntrack_l3proto_ipv4.c
  11. +++ b/net/ipv4/netfilter/nf_conntrack_l3proto_ipv4.c
  12. @@ -84,6 +84,14 @@ static int ipv4_get_l4proto(const struct sk_buff *skb, unsigned \
  13.                 int nhoff,
  14.         *dataoff = nhoff + (iph->ihl << 2);
  15.         *protonum = iph->protocol;

  16. +        /* Check bogus IP headers */
  17. +        if (*dataoff > skb->len) {
  18. +                pr_debug("nf_conntrack_ipv4: drop bogus IPv4 packet: "
  19. +                         "nhoff %u, ihl %u, skblen %u\n",
  20. +                         nhoff, iph->ihl << 2, skb->len);
  21. +                return -NF_DROP;
  22. +        }
  23. +
  24.         return NF_ACCEPT;
  25. }
复制代码

评分

参与人数 2可用积分 +16 收起 理由
瀚海书香 + 8 很给力!
Godbach + 8 赞一个!

查看全部评分

论坛徽章:
36
IT运维版块每日发帖之星
日期:2016-04-10 06:20:00IT运维版块每日发帖之星
日期:2016-04-16 06:20:0015-16赛季CBA联赛之广东
日期:2016-04-16 19:59:32IT运维版块每日发帖之星
日期:2016-04-18 06:20:00IT运维版块每日发帖之星
日期:2016-04-19 06:20:00每日论坛发贴之星
日期:2016-04-19 06:20:00IT运维版块每日发帖之星
日期:2016-04-25 06:20:00IT运维版块每日发帖之星
日期:2016-05-06 06:20:00IT运维版块每日发帖之星
日期:2016-05-08 06:20:00IT运维版块每日发帖之星
日期:2016-05-13 06:20:00IT运维版块每日发帖之星
日期:2016-05-28 06:20:00每日论坛发贴之星
日期:2016-05-28 06:20:00
2 [报告]
发表于 2012-05-21 14:15 |只看该作者
回复 1# 独孤九贱
感谢九贱兄的分享啊


   

论坛徽章:
36
IT运维版块每日发帖之星
日期:2016-04-10 06:20:00IT运维版块每日发帖之星
日期:2016-04-16 06:20:0015-16赛季CBA联赛之广东
日期:2016-04-16 19:59:32IT运维版块每日发帖之星
日期:2016-04-18 06:20:00IT运维版块每日发帖之星
日期:2016-04-19 06:20:00每日论坛发贴之星
日期:2016-04-19 06:20:00IT运维版块每日发帖之星
日期:2016-04-25 06:20:00IT运维版块每日发帖之星
日期:2016-05-06 06:20:00IT运维版块每日发帖之星
日期:2016-05-08 06:20:00IT运维版块每日发帖之星
日期:2016-05-13 06:20:00IT运维版块每日发帖之星
日期:2016-05-28 06:20:00每日论坛发贴之星
日期:2016-05-28 06:20:00
3 [报告]
发表于 2012-05-22 12:32 |只看该作者
回复 1# 独孤九贱
九贱兄,这个 BUG 是你发现的吧,其实你也可以自己提交 patch 吧


   

论坛徽章:
2
申猴
日期:2013-12-26 22:11:31天秤座
日期:2014-12-23 10:23:19
4 [报告]
发表于 2012-05-22 13:16 |只看该作者
居然没有加上Reported-by:
官方patch改动了点

commit 07153c6ec074257ade76a461429b567cff2b3a1e
Author: Jozsef Kadlecsik <kadlec@blackhole.kfki.hu>
Date:   Tue Apr 3 22:02:01 2012 +0200

    netfilter: nf_ct_ipv4: packets with wrong ihl are invalid
   
    It was reported that the Linux kernel sometimes logs:
   
    klogd: [2629147.402413] kernel BUG at net / netfilter /
    nf_conntrack_proto_tcp.c: 447!
    klogd: [1072212.887368] kernel BUG at net / netfilter /
    nf_conntrack_proto_tcp.c: 392
   
    ipv4_get_l4proto() in nf_conntrack_l3proto_ipv4.c and tcp_error() in
    nf_conntrack_proto_tcp.c should catch malformed packets, so the errors
    at the indicated lines - TCP options parsing - should not happen.
    However, tcp_error() relies on the "dataoff" offset to the TCP header,
    calculated by ipv4_get_l4proto().  But ipv4_get_l4proto() does not check
    bogus ihl values in IPv4 packets, which then can slip through tcp_error()
    and get caught at the TCP options parsing routines.
   
    The patch fixes ipv4_get_l4proto() by invalidating packets with bogus
    ihl value.
   
    The patch closes netfilter bugzilla id 771.
   
    Signed-off-by: Jozsef Kadlecsik <kadlec@blackhole.kfki.hu>
    Signed-off-by: Pablo Neira Ayuso <pablo@netfilter.org>

diff --git a/net/ipv4/netfilter/nf_conntrack_l3proto_ipv4.c b/net/ipv4/netfilter/nf_conntrack_l3proto_ipv4.c
index 750b06a..cf73cc7 100644
--- a/net/ipv4/netfilter/nf_conntrack_l3proto_ipv4.c
+++ b/net/ipv4/netfilter/nf_conntrack_l3proto_ipv4.c
@@ -84,6 +84,14 @@ static int ipv4_get_l4proto(const struct sk_buff *skb, unsigned int nhoff,
        *dataoff = nhoff + (iph->ihl << 2);
        *protonum = iph->protocol;

+       /* Check bogus IP headers */
+       if (*dataoff > skb->len) {
+               pr_debug("nf_conntrack_ipv4: bogus IPv4 packet: "
+                        "nhoff %u, ihl %u, skblen %u\n",
+                        nhoff, iph->ihl << 2, skb->len);
+               return -NF_ACCEPT;

+       }
+
        return NF_ACCEPT;
}

论坛徽章:
36
IT运维版块每日发帖之星
日期:2016-04-10 06:20:00IT运维版块每日发帖之星
日期:2016-04-16 06:20:0015-16赛季CBA联赛之广东
日期:2016-04-16 19:59:32IT运维版块每日发帖之星
日期:2016-04-18 06:20:00IT运维版块每日发帖之星
日期:2016-04-19 06:20:00每日论坛发贴之星
日期:2016-04-19 06:20:00IT运维版块每日发帖之星
日期:2016-04-25 06:20:00IT运维版块每日发帖之星
日期:2016-05-06 06:20:00IT运维版块每日发帖之星
日期:2016-05-08 06:20:00IT运维版块每日发帖之星
日期:2016-05-13 06:20:00IT运维版块每日发帖之星
日期:2016-05-28 06:20:00每日论坛发贴之星
日期:2016-05-28 06:20:00
5 [报告]
发表于 2012-05-22 14:12 |只看该作者
回复 4# goter

是啊,如果是九贱兄最先报出的,应该记录一下。

   

论坛徽章:
0
6 [报告]
发表于 2012-05-22 15:43 |只看该作者
goter 发表于 2012-05-22 13:16
居然没有加上Reported-by:
官方patch改动了点


你这个在哪儿搜到的,能否发个URL过来呢?我对比一下,谢谢。

论坛徽章:
0
7 [报告]
发表于 2012-05-22 15:50 |只看该作者
回复 2# Godbach

原来类似问题提交过几回,没得啥回应,后来发现都是些老Bug,别个早就修复了 。所以现在一般都是找到问题,和作者邮件交流,把问题沟通清楚了,我想原作者写个补丁是很简单的事情。这个补丁事实上并没有能真正解决问题,问题的核心在于,这样的报文是如何产生的?我到现在还没有想明白,主要是对新内核的一些新特性还没有掌握呀。


   

论坛徽章:
2
申猴
日期:2013-12-26 22:11:31天秤座
日期:2014-12-23 10:23:19
8 [报告]
发表于 2012-05-24 08:37 |只看该作者
独孤九贱 发表于 2012-05-22 15:43
你这个在哪儿搜到的,能否发个URL过来呢?我对比一下,谢谢。


http://git.kernel.org/?p=linux/k ... 490e2ab8bb50d59077a

论坛徽章:
2
申猴
日期:2013-12-26 22:11:31天秤座
日期:2014-12-23 10:23:19
9 [报告]
发表于 2012-05-24 08:41 |只看该作者
您需要登录后才可以回帖 登录 | 注册

本版积分规则 发表回复

  

北京盛拓优讯信息技术有限公司. 版权所有 京ICP备16024965号-6 北京市公安局海淀分局网监中心备案编号:11010802020122 niuxiaotong@pcpop.com 17352615567
未成年举报专区
中国互联网协会会员  联系我们:huangweiwei@itpub.net
感谢所有关心和支持过ChinaUnix的朋友们 转载本站内容请注明原作者名及出处

清除 Cookies - ChinaUnix - Archiver - WAP - TOP