- 论坛徽章:
- 0
|
本帖最后由 独孤九贱 于 2012-05-21 10:21 编辑
原贴讨论在
http://bbs.chinaunix.net/thread-3672415-2-1.html
goter 在12楼已经提到过,对于错误长度的报文,tcp_error应该能够处理它。但是问题的关键在于,tcp_error计算的依据是dataoff,而这个值是上层调用传来下的,其计算在ipv4_get_l4proto函数中:- static int ipv4_get_l4proto(const struct sk_buff *skb, unsigned int nhoff,
- unsigned int *dataoff, u_int8_t *protonum)
- {
- const struct iphdr *iph;
- struct iphdr _iph;
- iph = skb_header_pointer(skb, nhoff, sizeof(_iph), &_iph);
- if (iph == NULL)
- return -NF_DROP;
- /* Conntrack defragments packets, we might still see fragments
- * inside ICMP packets though. */
- if (iph->frag_off & htons(IP_OFFSET))
- return -NF_DROP;
- *dataoff = nhoff + (iph->ihl << 2);
- *protonum = iph->protocol;
- return NF_ACCEPT;
- }
复制代码 可以看到,*dataoff = nhoff + (iph->ihl << 2);这个计算,并没有做合法性检验,虽然在ip_rcv函数中:- len = ntohs(iph->tot_len);
- if (skb->len < len) {
- IP_INC_STATS_BH(dev_net(dev), IPSTATS_MIB_INTRUNCATEDPKTS);
- goto drop;
- } else if (len < (iph->ihl*4))
- goto inhdr_error;
复制代码 对于进来的单包是做了检验的,但是对它其它情况呢?从我的遭遇来看,不能依赖于别人,只能相信自己——显然是有另外的情况没有被检测到了,否则这个OOPS是不会被触发的。最先原作者也认为不太可以,不过后来多次沟通后,还是确认了在ipv4_get_l4proto函数中,应该增加对dataoff的检验:- 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 dropping packets with bogus
- ihl value.
- The patch closes netfilter bugzilla id 771.
- Signed-off-by: Jozsef Kadlecsik <kadlec@blackhole.kfki.hu>
- ---
- net/ipv4/netfilter/nf_conntrack_l3proto_ipv4.c | 8 ++++++++
- 1 files changed, 8 insertions(+), 0 deletions(-)
- diff --git a/net/ipv4/netfilter/nf_conntrack_l3proto_ipv4.c \
- b/net/ipv4/netfilter/nf_conntrack_l3proto_ipv4.c index de9da21..6a5f038 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: drop bogus IPv4 packet: "
- + "nhoff %u, ihl %u, skblen %u\n",
- + nhoff, iph->ihl << 2, skb->len);
- + return -NF_DROP;
- + }
- +
- return NF_ACCEPT;
- }
复制代码 |
评分
-
查看全部评分
|