diff options
author | David S. Miller <davem@davemloft.net> | 2009-12-03 16:23:12 -0500 |
---|---|---|
committer | David S. Miller <davem@davemloft.net> | 2009-12-03 16:23:12 -0500 |
commit | 424eff975192553a9ea8bfd51bf65039ffb356ef (patch) | |
tree | 5fa7b15715b3ce904f7250c50d09bc921d9f28bf | |
parent | 55dbabee63462a455d8fb57caf08b69db256b012 (diff) | |
parent | 3666ed1c4837fd6906da0224c5373d7a2186a193 (diff) |
Merge branch 'master' of git://git.kernel.org/pub/scm/linux/kernel/git/kaber/nf-next-2.6
32 files changed, 253 insertions, 257 deletions
diff --git a/include/linux/netfilter/nf_conntrack_tcp.h b/include/linux/netfilter/nf_conntrack_tcp.h index f6d97f64d7a0..6e135f97e59a 100644 --- a/include/linux/netfilter/nf_conntrack_tcp.h +++ b/include/linux/netfilter/nf_conntrack_tcp.h | |||
@@ -66,6 +66,9 @@ struct ip_ct_tcp { | |||
66 | u_int32_t last_ack; /* Last sequence number seen in opposite dir */ | 66 | u_int32_t last_ack; /* Last sequence number seen in opposite dir */ |
67 | u_int32_t last_end; /* Last seq + len */ | 67 | u_int32_t last_end; /* Last seq + len */ |
68 | u_int16_t last_win; /* Last window advertisement seen in dir */ | 68 | u_int16_t last_win; /* Last window advertisement seen in dir */ |
69 | /* For SYN packets while we may be out-of-sync */ | ||
70 | u_int8_t last_wscale; /* Last window scaling factor seen */ | ||
71 | u_int8_t last_flags; /* Last flags set */ | ||
69 | }; | 72 | }; |
70 | 73 | ||
71 | #endif /* __KERNEL__ */ | 74 | #endif /* __KERNEL__ */ |
diff --git a/net/ipv4/netfilter/arp_tables.c b/net/ipv4/netfilter/arp_tables.c index 27774c99d888..06632762ba5f 100644 --- a/net/ipv4/netfilter/arp_tables.c +++ b/net/ipv4/netfilter/arp_tables.c | |||
@@ -384,11 +384,11 @@ static int mark_source_chains(struct xt_table_info *newinfo, | |||
384 | |= ((1 << hook) | (1 << NF_ARP_NUMHOOKS)); | 384 | |= ((1 << hook) | (1 << NF_ARP_NUMHOOKS)); |
385 | 385 | ||
386 | /* Unconditional return/END. */ | 386 | /* Unconditional return/END. */ |
387 | if ((e->target_offset == sizeof(struct arpt_entry) | 387 | if ((e->target_offset == sizeof(struct arpt_entry) && |
388 | && (strcmp(t->target.u.user.name, | 388 | (strcmp(t->target.u.user.name, |
389 | ARPT_STANDARD_TARGET) == 0) | 389 | ARPT_STANDARD_TARGET) == 0) && |
390 | && t->verdict < 0 | 390 | t->verdict < 0 && unconditional(&e->arp)) || |
391 | && unconditional(&e->arp)) || visited) { | 391 | visited) { |
392 | unsigned int oldpos, size; | 392 | unsigned int oldpos, size; |
393 | 393 | ||
394 | if ((strcmp(t->target.u.user.name, | 394 | if ((strcmp(t->target.u.user.name, |
@@ -427,8 +427,8 @@ static int mark_source_chains(struct xt_table_info *newinfo, | |||
427 | int newpos = t->verdict; | 427 | int newpos = t->verdict; |
428 | 428 | ||
429 | if (strcmp(t->target.u.user.name, | 429 | if (strcmp(t->target.u.user.name, |
430 | ARPT_STANDARD_TARGET) == 0 | 430 | ARPT_STANDARD_TARGET) == 0 && |
431 | && newpos >= 0) { | 431 | newpos >= 0) { |
432 | if (newpos > newinfo->size - | 432 | if (newpos > newinfo->size - |
433 | sizeof(struct arpt_entry)) { | 433 | sizeof(struct arpt_entry)) { |
434 | duprintf("mark_source_chains: " | 434 | duprintf("mark_source_chains: " |
@@ -559,8 +559,8 @@ static inline int check_entry_size_and_hooks(struct arpt_entry *e, | |||
559 | { | 559 | { |
560 | unsigned int h; | 560 | unsigned int h; |
561 | 561 | ||
562 | if ((unsigned long)e % __alignof__(struct arpt_entry) != 0 | 562 | if ((unsigned long)e % __alignof__(struct arpt_entry) != 0 || |
563 | || (unsigned char *)e + sizeof(struct arpt_entry) >= limit) { | 563 | (unsigned char *)e + sizeof(struct arpt_entry) >= limit) { |
564 | duprintf("Bad offset %p\n", e); | 564 | duprintf("Bad offset %p\n", e); |
565 | return -EINVAL; | 565 | return -EINVAL; |
566 | } | 566 | } |
@@ -1251,8 +1251,8 @@ check_compat_entry_size_and_hooks(struct compat_arpt_entry *e, | |||
1251 | int ret, off, h; | 1251 | int ret, off, h; |
1252 | 1252 | ||
1253 | duprintf("check_compat_entry_size_and_hooks %p\n", e); | 1253 | duprintf("check_compat_entry_size_and_hooks %p\n", e); |
1254 | if ((unsigned long)e % __alignof__(struct compat_arpt_entry) != 0 | 1254 | if ((unsigned long)e % __alignof__(struct compat_arpt_entry) != 0 || |
1255 | || (unsigned char *)e + sizeof(struct compat_arpt_entry) >= limit) { | 1255 | (unsigned char *)e + sizeof(struct compat_arpt_entry) >= limit) { |
1256 | duprintf("Bad offset %p, limit = %p\n", e, limit); | 1256 | duprintf("Bad offset %p, limit = %p\n", e, limit); |
1257 | return -EINVAL; | 1257 | return -EINVAL; |
1258 | } | 1258 | } |
diff --git a/net/ipv4/netfilter/ip_queue.c b/net/ipv4/netfilter/ip_queue.c index 884f0859cb3b..49ad44712f46 100644 --- a/net/ipv4/netfilter/ip_queue.c +++ b/net/ipv4/netfilter/ip_queue.c | |||
@@ -497,8 +497,7 @@ ipq_rcv_nl_event(struct notifier_block *this, | |||
497 | { | 497 | { |
498 | struct netlink_notify *n = ptr; | 498 | struct netlink_notify *n = ptr; |
499 | 499 | ||
500 | if (event == NETLINK_URELEASE && | 500 | if (event == NETLINK_URELEASE && n->protocol == NETLINK_FIREWALL) { |
501 | n->protocol == NETLINK_FIREWALL && n->pid) { | ||
502 | write_lock_bh(&queue_lock); | 501 | write_lock_bh(&queue_lock); |
503 | if ((net_eq(n->net, &init_net)) && (n->pid == peer_pid)) | 502 | if ((net_eq(n->net, &init_net)) && (n->pid == peer_pid)) |
504 | __ipq_reset(); | 503 | __ipq_reset(); |
@@ -622,7 +621,7 @@ cleanup_netlink_notifier: | |||
622 | static void __exit ip_queue_fini(void) | 621 | static void __exit ip_queue_fini(void) |
623 | { | 622 | { |
624 | nf_unregister_queue_handlers(&nfqh); | 623 | nf_unregister_queue_handlers(&nfqh); |
625 | synchronize_net(); | 624 | |
626 | ipq_flush(NULL, 0); | 625 | ipq_flush(NULL, 0); |
627 | 626 | ||
628 | #ifdef CONFIG_SYSCTL | 627 | #ifdef CONFIG_SYSCTL |
diff --git a/net/ipv4/netfilter/ip_tables.c b/net/ipv4/netfilter/ip_tables.c index cde755d5eeab..572330a552ef 100644 --- a/net/ipv4/netfilter/ip_tables.c +++ b/net/ipv4/netfilter/ip_tables.c | |||
@@ -89,9 +89,9 @@ ip_packet_match(const struct iphdr *ip, | |||
89 | #define FWINV(bool, invflg) ((bool) ^ !!(ipinfo->invflags & (invflg))) | 89 | #define FWINV(bool, invflg) ((bool) ^ !!(ipinfo->invflags & (invflg))) |
90 | 90 | ||
91 | if (FWINV((ip->saddr&ipinfo->smsk.s_addr) != ipinfo->src.s_addr, | 91 | if (FWINV((ip->saddr&ipinfo->smsk.s_addr) != ipinfo->src.s_addr, |
92 | IPT_INV_SRCIP) | 92 | IPT_INV_SRCIP) || |
93 | || FWINV((ip->daddr&ipinfo->dmsk.s_addr) != ipinfo->dst.s_addr, | 93 | FWINV((ip->daddr&ipinfo->dmsk.s_addr) != ipinfo->dst.s_addr, |
94 | IPT_INV_DSTIP)) { | 94 | IPT_INV_DSTIP)) { |
95 | dprintf("Source or dest mismatch.\n"); | 95 | dprintf("Source or dest mismatch.\n"); |
96 | 96 | ||
97 | dprintf("SRC: %pI4. Mask: %pI4. Target: %pI4.%s\n", | 97 | dprintf("SRC: %pI4. Mask: %pI4. Target: %pI4.%s\n", |
@@ -122,8 +122,8 @@ ip_packet_match(const struct iphdr *ip, | |||
122 | } | 122 | } |
123 | 123 | ||
124 | /* Check specific protocol */ | 124 | /* Check specific protocol */ |
125 | if (ipinfo->proto | 125 | if (ipinfo->proto && |
126 | && FWINV(ip->protocol != ipinfo->proto, IPT_INV_PROTO)) { | 126 | FWINV(ip->protocol != ipinfo->proto, IPT_INV_PROTO)) { |
127 | dprintf("Packet protocol %hi does not match %hi.%s\n", | 127 | dprintf("Packet protocol %hi does not match %hi.%s\n", |
128 | ip->protocol, ipinfo->proto, | 128 | ip->protocol, ipinfo->proto, |
129 | ipinfo->invflags&IPT_INV_PROTO ? " (INV)":""); | 129 | ipinfo->invflags&IPT_INV_PROTO ? " (INV)":""); |
@@ -246,11 +246,11 @@ get_chainname_rulenum(struct ipt_entry *s, struct ipt_entry *e, | |||
246 | } else if (s == e) { | 246 | } else if (s == e) { |
247 | (*rulenum)++; | 247 | (*rulenum)++; |
248 | 248 | ||
249 | if (s->target_offset == sizeof(struct ipt_entry) | 249 | if (s->target_offset == sizeof(struct ipt_entry) && |
250 | && strcmp(t->target.u.kernel.target->name, | 250 | strcmp(t->target.u.kernel.target->name, |
251 | IPT_STANDARD_TARGET) == 0 | 251 | IPT_STANDARD_TARGET) == 0 && |
252 | && t->verdict < 0 | 252 | t->verdict < 0 && |
253 | && unconditional(&s->ip)) { | 253 | unconditional(&s->ip)) { |
254 | /* Tail of chains: STANDARD target (return/policy) */ | 254 | /* Tail of chains: STANDARD target (return/policy) */ |
255 | *comment = *chainname == hookname | 255 | *comment = *chainname == hookname |
256 | ? comments[NF_IP_TRACE_COMMENT_POLICY] | 256 | ? comments[NF_IP_TRACE_COMMENT_POLICY] |
@@ -388,8 +388,8 @@ ipt_do_table(struct sk_buff *skb, | |||
388 | back = get_entry(table_base, back->comefrom); | 388 | back = get_entry(table_base, back->comefrom); |
389 | continue; | 389 | continue; |
390 | } | 390 | } |
391 | if (table_base + v != ipt_next_entry(e) | 391 | if (table_base + v != ipt_next_entry(e) && |
392 | && !(e->ip.flags & IPT_F_GOTO)) { | 392 | !(e->ip.flags & IPT_F_GOTO)) { |
393 | /* Save old back ptr in next entry */ | 393 | /* Save old back ptr in next entry */ |
394 | struct ipt_entry *next = ipt_next_entry(e); | 394 | struct ipt_entry *next = ipt_next_entry(e); |
395 | next->comefrom = (void *)back - table_base; | 395 | next->comefrom = (void *)back - table_base; |
@@ -473,11 +473,11 @@ mark_source_chains(struct xt_table_info *newinfo, | |||
473 | e->comefrom |= ((1 << hook) | (1 << NF_INET_NUMHOOKS)); | 473 | e->comefrom |= ((1 << hook) | (1 << NF_INET_NUMHOOKS)); |
474 | 474 | ||
475 | /* Unconditional return/END. */ | 475 | /* Unconditional return/END. */ |
476 | if ((e->target_offset == sizeof(struct ipt_entry) | 476 | if ((e->target_offset == sizeof(struct ipt_entry) && |
477 | && (strcmp(t->target.u.user.name, | 477 | (strcmp(t->target.u.user.name, |
478 | IPT_STANDARD_TARGET) == 0) | 478 | IPT_STANDARD_TARGET) == 0) && |
479 | && t->verdict < 0 | 479 | t->verdict < 0 && unconditional(&e->ip)) || |
480 | && unconditional(&e->ip)) || visited) { | 480 | visited) { |
481 | unsigned int oldpos, size; | 481 | unsigned int oldpos, size; |
482 | 482 | ||
483 | if ((strcmp(t->target.u.user.name, | 483 | if ((strcmp(t->target.u.user.name, |
@@ -524,8 +524,8 @@ mark_source_chains(struct xt_table_info *newinfo, | |||
524 | int newpos = t->verdict; | 524 | int newpos = t->verdict; |
525 | 525 | ||
526 | if (strcmp(t->target.u.user.name, | 526 | if (strcmp(t->target.u.user.name, |
527 | IPT_STANDARD_TARGET) == 0 | 527 | IPT_STANDARD_TARGET) == 0 && |
528 | && newpos >= 0) { | 528 | newpos >= 0) { |
529 | if (newpos > newinfo->size - | 529 | if (newpos > newinfo->size - |
530 | sizeof(struct ipt_entry)) { | 530 | sizeof(struct ipt_entry)) { |
531 | duprintf("mark_source_chains: " | 531 | duprintf("mark_source_chains: " |
@@ -735,8 +735,8 @@ check_entry_size_and_hooks(struct ipt_entry *e, | |||
735 | { | 735 | { |
736 | unsigned int h; | 736 | unsigned int h; |
737 | 737 | ||
738 | if ((unsigned long)e % __alignof__(struct ipt_entry) != 0 | 738 | if ((unsigned long)e % __alignof__(struct ipt_entry) != 0 || |
739 | || (unsigned char *)e + sizeof(struct ipt_entry) >= limit) { | 739 | (unsigned char *)e + sizeof(struct ipt_entry) >= limit) { |
740 | duprintf("Bad offset %p\n", e); | 740 | duprintf("Bad offset %p\n", e); |
741 | return -EINVAL; | 741 | return -EINVAL; |
742 | } | 742 | } |
@@ -1548,8 +1548,8 @@ check_compat_entry_size_and_hooks(struct compat_ipt_entry *e, | |||
1548 | int ret, off, h; | 1548 | int ret, off, h; |
1549 | 1549 | ||
1550 | duprintf("check_compat_entry_size_and_hooks %p\n", e); | 1550 | duprintf("check_compat_entry_size_and_hooks %p\n", e); |
1551 | if ((unsigned long)e % __alignof__(struct compat_ipt_entry) != 0 | 1551 | if ((unsigned long)e % __alignof__(struct compat_ipt_entry) != 0 || |
1552 | || (unsigned char *)e + sizeof(struct compat_ipt_entry) >= limit) { | 1552 | (unsigned char *)e + sizeof(struct compat_ipt_entry) >= limit) { |
1553 | duprintf("Bad offset %p, limit = %p\n", e, limit); | 1553 | duprintf("Bad offset %p, limit = %p\n", e, limit); |
1554 | return -EINVAL; | 1554 | return -EINVAL; |
1555 | } | 1555 | } |
diff --git a/net/ipv4/netfilter/ipt_CLUSTERIP.c b/net/ipv4/netfilter/ipt_CLUSTERIP.c index 2e4f98b85524..40ca2d240abb 100644 --- a/net/ipv4/netfilter/ipt_CLUSTERIP.c +++ b/net/ipv4/netfilter/ipt_CLUSTERIP.c | |||
@@ -303,9 +303,9 @@ clusterip_tg(struct sk_buff *skb, const struct xt_target_param *par) | |||
303 | 303 | ||
304 | /* special case: ICMP error handling. conntrack distinguishes between | 304 | /* special case: ICMP error handling. conntrack distinguishes between |
305 | * error messages (RELATED) and information requests (see below) */ | 305 | * error messages (RELATED) and information requests (see below) */ |
306 | if (ip_hdr(skb)->protocol == IPPROTO_ICMP | 306 | if (ip_hdr(skb)->protocol == IPPROTO_ICMP && |
307 | && (ctinfo == IP_CT_RELATED | 307 | (ctinfo == IP_CT_RELATED || |
308 | || ctinfo == IP_CT_RELATED+IP_CT_IS_REPLY)) | 308 | ctinfo == IP_CT_RELATED + IP_CT_IS_REPLY)) |
309 | return XT_CONTINUE; | 309 | return XT_CONTINUE; |
310 | 310 | ||
311 | /* ip_conntrack_icmp guarantees us that we only have ICMP_ECHO, | 311 | /* ip_conntrack_icmp guarantees us that we only have ICMP_ECHO, |
@@ -362,8 +362,8 @@ static bool clusterip_tg_check(const struct xt_tgchk_param *par) | |||
362 | return false; | 362 | return false; |
363 | 363 | ||
364 | } | 364 | } |
365 | if (e->ip.dmsk.s_addr != htonl(0xffffffff) | 365 | if (e->ip.dmsk.s_addr != htonl(0xffffffff) || |
366 | || e->ip.dst.s_addr == 0) { | 366 | e->ip.dst.s_addr == 0) { |
367 | printk(KERN_ERR "CLUSTERIP: Please specify destination IP\n"); | 367 | printk(KERN_ERR "CLUSTERIP: Please specify destination IP\n"); |
368 | return false; | 368 | return false; |
369 | } | 369 | } |
@@ -495,14 +495,14 @@ arp_mangle(unsigned int hook, | |||
495 | struct clusterip_config *c; | 495 | struct clusterip_config *c; |
496 | 496 | ||
497 | /* we don't care about non-ethernet and non-ipv4 ARP */ | 497 | /* we don't care about non-ethernet and non-ipv4 ARP */ |
498 | if (arp->ar_hrd != htons(ARPHRD_ETHER) | 498 | if (arp->ar_hrd != htons(ARPHRD_ETHER) || |
499 | || arp->ar_pro != htons(ETH_P_IP) | 499 | arp->ar_pro != htons(ETH_P_IP) || |
500 | || arp->ar_pln != 4 || arp->ar_hln != ETH_ALEN) | 500 | arp->ar_pln != 4 || arp->ar_hln != ETH_ALEN) |
501 | return NF_ACCEPT; | 501 | return NF_ACCEPT; |
502 | 502 | ||
503 | /* we only want to mangle arp requests and replies */ | 503 | /* we only want to mangle arp requests and replies */ |
504 | if (arp->ar_op != htons(ARPOP_REPLY) | 504 | if (arp->ar_op != htons(ARPOP_REPLY) && |
505 | && arp->ar_op != htons(ARPOP_REQUEST)) | 505 | arp->ar_op != htons(ARPOP_REQUEST)) |
506 | return NF_ACCEPT; | 506 | return NF_ACCEPT; |
507 | 507 | ||
508 | payload = (void *)(arp+1); | 508 | payload = (void *)(arp+1); |
diff --git a/net/ipv4/netfilter/ipt_ECN.c b/net/ipv4/netfilter/ipt_ECN.c index f7e2fa0974dc..549e206cdd42 100644 --- a/net/ipv4/netfilter/ipt_ECN.c +++ b/net/ipv4/netfilter/ipt_ECN.c | |||
@@ -85,8 +85,8 @@ ecn_tg(struct sk_buff *skb, const struct xt_target_param *par) | |||
85 | if (!set_ect_ip(skb, einfo)) | 85 | if (!set_ect_ip(skb, einfo)) |
86 | return NF_DROP; | 86 | return NF_DROP; |
87 | 87 | ||
88 | if (einfo->operation & (IPT_ECN_OP_SET_ECE | IPT_ECN_OP_SET_CWR) | 88 | if (einfo->operation & (IPT_ECN_OP_SET_ECE | IPT_ECN_OP_SET_CWR) && |
89 | && ip_hdr(skb)->protocol == IPPROTO_TCP) | 89 | ip_hdr(skb)->protocol == IPPROTO_TCP) |
90 | if (!set_ect_tcp(skb, einfo)) | 90 | if (!set_ect_tcp(skb, einfo)) |
91 | return NF_DROP; | 91 | return NF_DROP; |
92 | 92 | ||
@@ -108,8 +108,8 @@ static bool ecn_tg_check(const struct xt_tgchk_param *par) | |||
108 | einfo->ip_ect); | 108 | einfo->ip_ect); |
109 | return false; | 109 | return false; |
110 | } | 110 | } |
111 | if ((einfo->operation & (IPT_ECN_OP_SET_ECE|IPT_ECN_OP_SET_CWR)) | 111 | if ((einfo->operation & (IPT_ECN_OP_SET_ECE|IPT_ECN_OP_SET_CWR)) && |
112 | && (e->ip.proto != IPPROTO_TCP || (e->ip.invflags & XT_INV_PROTO))) { | 112 | (e->ip.proto != IPPROTO_TCP || (e->ip.invflags & XT_INV_PROTO))) { |
113 | printk(KERN_WARNING "ECN: cannot use TCP operations on a " | 113 | printk(KERN_WARNING "ECN: cannot use TCP operations on a " |
114 | "non-tcp rule\n"); | 114 | "non-tcp rule\n"); |
115 | return false; | 115 | return false; |
diff --git a/net/ipv4/netfilter/ipt_LOG.c b/net/ipv4/netfilter/ipt_LOG.c index acc44c69eb68..ee128efa1c8d 100644 --- a/net/ipv4/netfilter/ipt_LOG.c +++ b/net/ipv4/netfilter/ipt_LOG.c | |||
@@ -74,8 +74,8 @@ static void dump_packet(const struct nf_loginfo *info, | |||
74 | if (ntohs(ih->frag_off) & IP_OFFSET) | 74 | if (ntohs(ih->frag_off) & IP_OFFSET) |
75 | printk("FRAG:%u ", ntohs(ih->frag_off) & IP_OFFSET); | 75 | printk("FRAG:%u ", ntohs(ih->frag_off) & IP_OFFSET); |
76 | 76 | ||
77 | if ((logflags & IPT_LOG_IPOPT) | 77 | if ((logflags & IPT_LOG_IPOPT) && |
78 | && ih->ihl * 4 > sizeof(struct iphdr)) { | 78 | ih->ihl * 4 > sizeof(struct iphdr)) { |
79 | const unsigned char *op; | 79 | const unsigned char *op; |
80 | unsigned char _opt[4 * 15 - sizeof(struct iphdr)]; | 80 | unsigned char _opt[4 * 15 - sizeof(struct iphdr)]; |
81 | unsigned int i, optsize; | 81 | unsigned int i, optsize; |
@@ -146,8 +146,8 @@ static void dump_packet(const struct nf_loginfo *info, | |||
146 | /* Max length: 11 "URGP=65535 " */ | 146 | /* Max length: 11 "URGP=65535 " */ |
147 | printk("URGP=%u ", ntohs(th->urg_ptr)); | 147 | printk("URGP=%u ", ntohs(th->urg_ptr)); |
148 | 148 | ||
149 | if ((logflags & IPT_LOG_TCPOPT) | 149 | if ((logflags & IPT_LOG_TCPOPT) && |
150 | && th->doff * 4 > sizeof(struct tcphdr)) { | 150 | th->doff * 4 > sizeof(struct tcphdr)) { |
151 | unsigned char _opt[4 * 15 - sizeof(struct tcphdr)]; | 151 | unsigned char _opt[4 * 15 - sizeof(struct tcphdr)]; |
152 | const unsigned char *op; | 152 | const unsigned char *op; |
153 | unsigned int i, optsize; | 153 | unsigned int i, optsize; |
@@ -238,9 +238,9 @@ static void dump_packet(const struct nf_loginfo *info, | |||
238 | printk("TYPE=%u CODE=%u ", ich->type, ich->code); | 238 | printk("TYPE=%u CODE=%u ", ich->type, ich->code); |
239 | 239 | ||
240 | /* Max length: 25 "INCOMPLETE [65535 bytes] " */ | 240 | /* Max length: 25 "INCOMPLETE [65535 bytes] " */ |
241 | if (ich->type <= NR_ICMP_TYPES | 241 | if (ich->type <= NR_ICMP_TYPES && |
242 | && required_len[ich->type] | 242 | required_len[ich->type] && |
243 | && skb->len-iphoff-ih->ihl*4 < required_len[ich->type]) { | 243 | skb->len-iphoff-ih->ihl*4 < required_len[ich->type]) { |
244 | printk("INCOMPLETE [%u bytes] ", | 244 | printk("INCOMPLETE [%u bytes] ", |
245 | skb->len - iphoff - ih->ihl*4); | 245 | skb->len - iphoff - ih->ihl*4); |
246 | break; | 246 | break; |
@@ -276,8 +276,8 @@ static void dump_packet(const struct nf_loginfo *info, | |||
276 | } | 276 | } |
277 | 277 | ||
278 | /* Max length: 10 "MTU=65535 " */ | 278 | /* Max length: 10 "MTU=65535 " */ |
279 | if (ich->type == ICMP_DEST_UNREACH | 279 | if (ich->type == ICMP_DEST_UNREACH && |
280 | && ich->code == ICMP_FRAG_NEEDED) | 280 | ich->code == ICMP_FRAG_NEEDED) |
281 | printk("MTU=%u ", ntohs(ich->un.frag.mtu)); | 281 | printk("MTU=%u ", ntohs(ich->un.frag.mtu)); |
282 | } | 282 | } |
283 | break; | 283 | break; |
@@ -407,8 +407,8 @@ ipt_log_packet(u_int8_t pf, | |||
407 | if (in && !out) { | 407 | if (in && !out) { |
408 | /* MAC logging for input chain only. */ | 408 | /* MAC logging for input chain only. */ |
409 | printk("MAC="); | 409 | printk("MAC="); |
410 | if (skb->dev && skb->dev->hard_header_len | 410 | if (skb->dev && skb->dev->hard_header_len && |
411 | && skb->mac_header != skb->network_header) { | 411 | skb->mac_header != skb->network_header) { |
412 | int i; | 412 | int i; |
413 | const unsigned char *p = skb_mac_header(skb); | 413 | const unsigned char *p = skb_mac_header(skb); |
414 | for (i = 0; i < skb->dev->hard_header_len; i++,p++) | 414 | for (i = 0; i < skb->dev->hard_header_len; i++,p++) |
diff --git a/net/ipv4/netfilter/ipt_MASQUERADE.c b/net/ipv4/netfilter/ipt_MASQUERADE.c index dada0863946d..650b54042b01 100644 --- a/net/ipv4/netfilter/ipt_MASQUERADE.c +++ b/net/ipv4/netfilter/ipt_MASQUERADE.c | |||
@@ -59,8 +59,8 @@ masquerade_tg(struct sk_buff *skb, const struct xt_target_param *par) | |||
59 | ct = nf_ct_get(skb, &ctinfo); | 59 | ct = nf_ct_get(skb, &ctinfo); |
60 | nat = nfct_nat(ct); | 60 | nat = nfct_nat(ct); |
61 | 61 | ||
62 | NF_CT_ASSERT(ct && (ctinfo == IP_CT_NEW || ctinfo == IP_CT_RELATED | 62 | NF_CT_ASSERT(ct && (ctinfo == IP_CT_NEW || ctinfo == IP_CT_RELATED || |
63 | || ctinfo == IP_CT_RELATED + IP_CT_IS_REPLY)); | 63 | ctinfo == IP_CT_RELATED + IP_CT_IS_REPLY)); |
64 | 64 | ||
65 | /* Source address is 0.0.0.0 - locally generated packet that is | 65 | /* Source address is 0.0.0.0 - locally generated packet that is |
66 | * probably not supposed to be masqueraded. | 66 | * probably not supposed to be masqueraded. |
diff --git a/net/ipv4/netfilter/ipt_REJECT.c b/net/ipv4/netfilter/ipt_REJECT.c index c93ae44bff2a..5113b8f1a379 100644 --- a/net/ipv4/netfilter/ipt_REJECT.c +++ b/net/ipv4/netfilter/ipt_REJECT.c | |||
@@ -184,8 +184,8 @@ static bool reject_tg_check(const struct xt_tgchk_param *par) | |||
184 | return false; | 184 | return false; |
185 | } else if (rejinfo->with == IPT_TCP_RESET) { | 185 | } else if (rejinfo->with == IPT_TCP_RESET) { |
186 | /* Must specify that it's a TCP packet */ | 186 | /* Must specify that it's a TCP packet */ |
187 | if (e->ip.proto != IPPROTO_TCP | 187 | if (e->ip.proto != IPPROTO_TCP || |
188 | || (e->ip.invflags & XT_INV_PROTO)) { | 188 | (e->ip.invflags & XT_INV_PROTO)) { |
189 | printk("ipt_REJECT: TCP_RESET invalid for non-tcp\n"); | 189 | printk("ipt_REJECT: TCP_RESET invalid for non-tcp\n"); |
190 | return false; | 190 | return false; |
191 | } | 191 | } |
diff --git a/net/ipv4/netfilter/ipt_ULOG.c b/net/ipv4/netfilter/ipt_ULOG.c index d32cc4bb328a..399061c3fd7d 100644 --- a/net/ipv4/netfilter/ipt_ULOG.c +++ b/net/ipv4/netfilter/ipt_ULOG.c | |||
@@ -226,9 +226,9 @@ static void ipt_ulog_packet(unsigned int hooknum, | |||
226 | else | 226 | else |
227 | *(pm->prefix) = '\0'; | 227 | *(pm->prefix) = '\0'; |
228 | 228 | ||
229 | if (in && in->hard_header_len > 0 | 229 | if (in && in->hard_header_len > 0 && |
230 | && skb->mac_header != skb->network_header | 230 | skb->mac_header != skb->network_header && |
231 | && in->hard_header_len <= ULOG_MAC_LEN) { | 231 | in->hard_header_len <= ULOG_MAC_LEN) { |
232 | memcpy(pm->mac, skb_mac_header(skb), in->hard_header_len); | 232 | memcpy(pm->mac, skb_mac_header(skb), in->hard_header_len); |
233 | pm->mac_len = in->hard_header_len; | 233 | pm->mac_len = in->hard_header_len; |
234 | } else | 234 | } else |
diff --git a/net/ipv4/netfilter/ipt_ecn.c b/net/ipv4/netfilter/ipt_ecn.c index 6289b64144c6..2a1e56b71908 100644 --- a/net/ipv4/netfilter/ipt_ecn.c +++ b/net/ipv4/netfilter/ipt_ecn.c | |||
@@ -96,8 +96,8 @@ static bool ecn_mt_check(const struct xt_mtchk_param *par) | |||
96 | if (info->invert & IPT_ECN_OP_MATCH_MASK) | 96 | if (info->invert & IPT_ECN_OP_MATCH_MASK) |
97 | return false; | 97 | return false; |
98 | 98 | ||
99 | if (info->operation & (IPT_ECN_OP_MATCH_ECE|IPT_ECN_OP_MATCH_CWR) | 99 | if (info->operation & (IPT_ECN_OP_MATCH_ECE|IPT_ECN_OP_MATCH_CWR) && |
100 | && ip->proto != IPPROTO_TCP) { | 100 | ip->proto != IPPROTO_TCP) { |
101 | printk(KERN_WARNING "ipt_ecn: can't match TCP bits in rule for" | 101 | printk(KERN_WARNING "ipt_ecn: can't match TCP bits in rule for" |
102 | " non-tcp packets\n"); | 102 | " non-tcp packets\n"); |
103 | return false; | 103 | return false; |
diff --git a/net/ipv4/netfilter/iptable_mangle.c b/net/ipv4/netfilter/iptable_mangle.c index 036047f9b0f2..fae78c3076c4 100644 --- a/net/ipv4/netfilter/iptable_mangle.c +++ b/net/ipv4/netfilter/iptable_mangle.c | |||
@@ -130,8 +130,8 @@ ipt_local_hook(unsigned int hook, | |||
130 | u_int32_t mark; | 130 | u_int32_t mark; |
131 | 131 | ||
132 | /* root is playing with raw sockets. */ | 132 | /* root is playing with raw sockets. */ |
133 | if (skb->len < sizeof(struct iphdr) | 133 | if (skb->len < sizeof(struct iphdr) || |
134 | || ip_hdrlen(skb) < sizeof(struct iphdr)) | 134 | ip_hdrlen(skb) < sizeof(struct iphdr)) |
135 | return NF_ACCEPT; | 135 | return NF_ACCEPT; |
136 | 136 | ||
137 | /* Save things which could affect route */ | 137 | /* Save things which could affect route */ |
diff --git a/net/ipv4/netfilter/iptable_security.c b/net/ipv4/netfilter/iptable_security.c index 99eb76c65d25..3bd3d6388da5 100644 --- a/net/ipv4/netfilter/iptable_security.c +++ b/net/ipv4/netfilter/iptable_security.c | |||
@@ -94,8 +94,8 @@ ipt_local_out_hook(unsigned int hook, | |||
94 | int (*okfn)(struct sk_buff *)) | 94 | int (*okfn)(struct sk_buff *)) |
95 | { | 95 | { |
96 | /* Somebody is playing with raw sockets. */ | 96 | /* Somebody is playing with raw sockets. */ |
97 | if (skb->len < sizeof(struct iphdr) | 97 | if (skb->len < sizeof(struct iphdr) || |
98 | || ip_hdrlen(skb) < sizeof(struct iphdr)) | 98 | ip_hdrlen(skb) < sizeof(struct iphdr)) |
99 | return NF_ACCEPT; | 99 | return NF_ACCEPT; |
100 | return ipt_do_table(skb, hook, in, out, | 100 | return ipt_do_table(skb, hook, in, out, |
101 | dev_net(out)->ipv4.iptable_security); | 101 | dev_net(out)->ipv4.iptable_security); |
diff --git a/net/ipv4/netfilter/nf_conntrack_proto_icmp.c b/net/ipv4/netfilter/nf_conntrack_proto_icmp.c index d71ba7677344..e3dd93623df8 100644 --- a/net/ipv4/netfilter/nf_conntrack_proto_icmp.c +++ b/net/ipv4/netfilter/nf_conntrack_proto_icmp.c | |||
@@ -54,8 +54,8 @@ static const u_int8_t invmap[] = { | |||
54 | static bool icmp_invert_tuple(struct nf_conntrack_tuple *tuple, | 54 | static bool icmp_invert_tuple(struct nf_conntrack_tuple *tuple, |
55 | const struct nf_conntrack_tuple *orig) | 55 | const struct nf_conntrack_tuple *orig) |
56 | { | 56 | { |
57 | if (orig->dst.u.icmp.type >= sizeof(invmap) | 57 | if (orig->dst.u.icmp.type >= sizeof(invmap) || |
58 | || !invmap[orig->dst.u.icmp.type]) | 58 | !invmap[orig->dst.u.icmp.type]) |
59 | return false; | 59 | return false; |
60 | 60 | ||
61 | tuple->src.u.icmp.id = orig->src.u.icmp.id; | 61 | tuple->src.u.icmp.id = orig->src.u.icmp.id; |
@@ -101,8 +101,8 @@ static bool icmp_new(struct nf_conn *ct, const struct sk_buff *skb, | |||
101 | [ICMP_ADDRESS] = 1 | 101 | [ICMP_ADDRESS] = 1 |
102 | }; | 102 | }; |
103 | 103 | ||
104 | if (ct->tuplehash[0].tuple.dst.u.icmp.type >= sizeof(valid_new) | 104 | if (ct->tuplehash[0].tuple.dst.u.icmp.type >= sizeof(valid_new) || |
105 | || !valid_new[ct->tuplehash[0].tuple.dst.u.icmp.type]) { | 105 | !valid_new[ct->tuplehash[0].tuple.dst.u.icmp.type]) { |
106 | /* Can't create a new ICMP `conn' with this. */ | 106 | /* Can't create a new ICMP `conn' with this. */ |
107 | pr_debug("icmp: can't create new conn with type %u\n", | 107 | pr_debug("icmp: can't create new conn with type %u\n", |
108 | ct->tuplehash[0].tuple.dst.u.icmp.type); | 108 | ct->tuplehash[0].tuple.dst.u.icmp.type); |
@@ -201,11 +201,11 @@ icmp_error(struct net *net, struct sk_buff *skb, unsigned int dataoff, | |||
201 | } | 201 | } |
202 | 202 | ||
203 | /* Need to track icmp error message? */ | 203 | /* Need to track icmp error message? */ |
204 | if (icmph->type != ICMP_DEST_UNREACH | 204 | if (icmph->type != ICMP_DEST_UNREACH && |
205 | && icmph->type != ICMP_SOURCE_QUENCH | 205 | icmph->type != ICMP_SOURCE_QUENCH && |
206 | && icmph->type != ICMP_TIME_EXCEEDED | 206 | icmph->type != ICMP_TIME_EXCEEDED && |
207 | && icmph->type != ICMP_PARAMETERPROB | 207 | icmph->type != ICMP_PARAMETERPROB && |
208 | && icmph->type != ICMP_REDIRECT) | 208 | icmph->type != ICMP_REDIRECT) |
209 | return NF_ACCEPT; | 209 | return NF_ACCEPT; |
210 | 210 | ||
211 | return icmp_error_message(net, skb, ctinfo, hooknum); | 211 | return icmp_error_message(net, skb, ctinfo, hooknum); |
@@ -238,17 +238,17 @@ static const struct nla_policy icmp_nla_policy[CTA_PROTO_MAX+1] = { | |||
238 | static int icmp_nlattr_to_tuple(struct nlattr *tb[], | 238 | static int icmp_nlattr_to_tuple(struct nlattr *tb[], |
239 | struct nf_conntrack_tuple *tuple) | 239 | struct nf_conntrack_tuple *tuple) |
240 | { | 240 | { |
241 | if (!tb[CTA_PROTO_ICMP_TYPE] | 241 | if (!tb[CTA_PROTO_ICMP_TYPE] || |
242 | || !tb[CTA_PROTO_ICMP_CODE] | 242 | !tb[CTA_PROTO_ICMP_CODE] || |
243 | || !tb[CTA_PROTO_ICMP_ID]) | 243 | !tb[CTA_PROTO_ICMP_ID]) |
244 | return -EINVAL; | 244 | return -EINVAL; |
245 | 245 | ||
246 | tuple->dst.u.icmp.type = nla_get_u8(tb[CTA_PROTO_ICMP_TYPE]); | 246 | tuple->dst.u.icmp.type = nla_get_u8(tb[CTA_PROTO_ICMP_TYPE]); |
247 | tuple->dst.u.icmp.code = nla_get_u8(tb[CTA_PROTO_ICMP_CODE]); | 247 | tuple->dst.u.icmp.code = nla_get_u8(tb[CTA_PROTO_ICMP_CODE]); |
248 | tuple->src.u.icmp.id = nla_get_be16(tb[CTA_PROTO_ICMP_ID]); | 248 | tuple->src.u.icmp.id = nla_get_be16(tb[CTA_PROTO_ICMP_ID]); |
249 | 249 | ||
250 | if (tuple->dst.u.icmp.type >= sizeof(invmap) | 250 | if (tuple->dst.u.icmp.type >= sizeof(invmap) || |
251 | || !invmap[tuple->dst.u.icmp.type]) | 251 | !invmap[tuple->dst.u.icmp.type]) |
252 | return -EINVAL; | 252 | return -EINVAL; |
253 | 253 | ||
254 | return 0; | 254 | return 0; |
diff --git a/net/ipv4/netfilter/nf_nat_helper.c b/net/ipv4/netfilter/nf_nat_helper.c index f9520fa3aba9..7f10a6be0191 100644 --- a/net/ipv4/netfilter/nf_nat_helper.c +++ b/net/ipv4/netfilter/nf_nat_helper.c | |||
@@ -41,18 +41,14 @@ adjust_tcp_sequence(u32 seq, | |||
41 | struct nf_conn *ct, | 41 | struct nf_conn *ct, |
42 | enum ip_conntrack_info ctinfo) | 42 | enum ip_conntrack_info ctinfo) |
43 | { | 43 | { |
44 | int dir; | 44 | enum ip_conntrack_dir dir = CTINFO2DIR(ctinfo); |
45 | struct nf_nat_seq *this_way, *other_way; | ||
46 | struct nf_conn_nat *nat = nfct_nat(ct); | 45 | struct nf_conn_nat *nat = nfct_nat(ct); |
46 | struct nf_nat_seq *this_way = &nat->seq[dir]; | ||
47 | 47 | ||
48 | pr_debug("adjust_tcp_sequence: seq = %u, sizediff = %d\n", seq, seq); | 48 | pr_debug("adjust_tcp_sequence: seq = %u, sizediff = %d\n", |
49 | 49 | seq, sizediff); | |
50 | dir = CTINFO2DIR(ctinfo); | ||
51 | |||
52 | this_way = &nat->seq[dir]; | ||
53 | other_way = &nat->seq[!dir]; | ||
54 | 50 | ||
55 | pr_debug("nf_nat_resize_packet: Seq_offset before: "); | 51 | pr_debug("adjust_tcp_sequence: Seq_offset before: "); |
56 | DUMP_OFFSET(this_way); | 52 | DUMP_OFFSET(this_way); |
57 | 53 | ||
58 | spin_lock_bh(&nf_nat_seqofs_lock); | 54 | spin_lock_bh(&nf_nat_seqofs_lock); |
@@ -63,13 +59,13 @@ adjust_tcp_sequence(u32 seq, | |||
63 | * retransmit */ | 59 | * retransmit */ |
64 | if (this_way->offset_before == this_way->offset_after || | 60 | if (this_way->offset_before == this_way->offset_after || |
65 | before(this_way->correction_pos, seq)) { | 61 | before(this_way->correction_pos, seq)) { |
66 | this_way->correction_pos = seq; | 62 | this_way->correction_pos = seq; |
67 | this_way->offset_before = this_way->offset_after; | 63 | this_way->offset_before = this_way->offset_after; |
68 | this_way->offset_after += sizediff; | 64 | this_way->offset_after += sizediff; |
69 | } | 65 | } |
70 | spin_unlock_bh(&nf_nat_seqofs_lock); | 66 | spin_unlock_bh(&nf_nat_seqofs_lock); |
71 | 67 | ||
72 | pr_debug("nf_nat_resize_packet: Seq_offset after: "); | 68 | pr_debug("adjust_tcp_sequence: Seq_offset after: "); |
73 | DUMP_OFFSET(this_way); | 69 | DUMP_OFFSET(this_way); |
74 | } | 70 | } |
75 | 71 | ||
diff --git a/net/ipv4/netfilter/nf_nat_standalone.c b/net/ipv4/netfilter/nf_nat_standalone.c index 5f41d017ddd8..5678e9562c15 100644 --- a/net/ipv4/netfilter/nf_nat_standalone.c +++ b/net/ipv4/netfilter/nf_nat_standalone.c | |||
@@ -197,11 +197,11 @@ nf_nat_out(unsigned int hooknum, | |||
197 | (ct = nf_ct_get(skb, &ctinfo)) != NULL) { | 197 | (ct = nf_ct_get(skb, &ctinfo)) != NULL) { |
198 | enum ip_conntrack_dir dir = CTINFO2DIR(ctinfo); | 198 | enum ip_conntrack_dir dir = CTINFO2DIR(ctinfo); |
199 | 199 | ||
200 | if (ct->tuplehash[dir].tuple.src.u3.ip != | 200 | if ((ct->tuplehash[dir].tuple.src.u3.ip != |
201 | ct->tuplehash[!dir].tuple.dst.u3.ip | 201 | ct->tuplehash[!dir].tuple.dst.u3.ip) || |
202 | || ct->tuplehash[dir].tuple.src.u.all != | 202 | (ct->tuplehash[dir].tuple.src.u.all != |
203 | ct->tuplehash[!dir].tuple.dst.u.all | 203 | ct->tuplehash[!dir].tuple.dst.u.all) |
204 | ) | 204 | ) |
205 | return ip_xfrm_me_harder(skb) == 0 ? ret : NF_DROP; | 205 | return ip_xfrm_me_harder(skb) == 0 ? ret : NF_DROP; |
206 | } | 206 | } |
207 | #endif | 207 | #endif |
diff --git a/net/ipv6/netfilter/ip6_queue.c b/net/ipv6/netfilter/ip6_queue.c index 4c7a18abcaff..db4d5725cce8 100644 --- a/net/ipv6/netfilter/ip6_queue.c +++ b/net/ipv6/netfilter/ip6_queue.c | |||
@@ -499,8 +499,7 @@ ipq_rcv_nl_event(struct notifier_block *this, | |||
499 | { | 499 | { |
500 | struct netlink_notify *n = ptr; | 500 | struct netlink_notify *n = ptr; |
501 | 501 | ||
502 | if (event == NETLINK_URELEASE && | 502 | if (event == NETLINK_URELEASE && n->protocol == NETLINK_IP6_FW) { |
503 | n->protocol == NETLINK_IP6_FW && n->pid) { | ||
504 | write_lock_bh(&queue_lock); | 503 | write_lock_bh(&queue_lock); |
505 | if ((net_eq(n->net, &init_net)) && (n->pid == peer_pid)) | 504 | if ((net_eq(n->net, &init_net)) && (n->pid == peer_pid)) |
506 | __ipq_reset(); | 505 | __ipq_reset(); |
@@ -625,7 +624,7 @@ cleanup_netlink_notifier: | |||
625 | static void __exit ip6_queue_fini(void) | 624 | static void __exit ip6_queue_fini(void) |
626 | { | 625 | { |
627 | nf_unregister_queue_handlers(&nfqh); | 626 | nf_unregister_queue_handlers(&nfqh); |
628 | synchronize_net(); | 627 | |
629 | ipq_flush(NULL, 0); | 628 | ipq_flush(NULL, 0); |
630 | 629 | ||
631 | #ifdef CONFIG_SYSCTL | 630 | #ifdef CONFIG_SYSCTL |
diff --git a/net/ipv6/netfilter/ip6_tables.c b/net/ipv6/netfilter/ip6_tables.c index cc9f8ef303fd..480d7f8c9802 100644 --- a/net/ipv6/netfilter/ip6_tables.c +++ b/net/ipv6/netfilter/ip6_tables.c | |||
@@ -105,9 +105,9 @@ ip6_packet_match(const struct sk_buff *skb, | |||
105 | #define FWINV(bool, invflg) ((bool) ^ !!(ip6info->invflags & (invflg))) | 105 | #define FWINV(bool, invflg) ((bool) ^ !!(ip6info->invflags & (invflg))) |
106 | 106 | ||
107 | if (FWINV(ipv6_masked_addr_cmp(&ipv6->saddr, &ip6info->smsk, | 107 | if (FWINV(ipv6_masked_addr_cmp(&ipv6->saddr, &ip6info->smsk, |
108 | &ip6info->src), IP6T_INV_SRCIP) | 108 | &ip6info->src), IP6T_INV_SRCIP) || |
109 | || FWINV(ipv6_masked_addr_cmp(&ipv6->daddr, &ip6info->dmsk, | 109 | FWINV(ipv6_masked_addr_cmp(&ipv6->daddr, &ip6info->dmsk, |
110 | &ip6info->dst), IP6T_INV_DSTIP)) { | 110 | &ip6info->dst), IP6T_INV_DSTIP)) { |
111 | dprintf("Source or dest mismatch.\n"); | 111 | dprintf("Source or dest mismatch.\n"); |
112 | /* | 112 | /* |
113 | dprintf("SRC: %u. Mask: %u. Target: %u.%s\n", ip->saddr, | 113 | dprintf("SRC: %u. Mask: %u. Target: %u.%s\n", ip->saddr, |
@@ -277,11 +277,11 @@ get_chainname_rulenum(struct ip6t_entry *s, struct ip6t_entry *e, | |||
277 | } else if (s == e) { | 277 | } else if (s == e) { |
278 | (*rulenum)++; | 278 | (*rulenum)++; |
279 | 279 | ||
280 | if (s->target_offset == sizeof(struct ip6t_entry) | 280 | if (s->target_offset == sizeof(struct ip6t_entry) && |
281 | && strcmp(t->target.u.kernel.target->name, | 281 | strcmp(t->target.u.kernel.target->name, |
282 | IP6T_STANDARD_TARGET) == 0 | 282 | IP6T_STANDARD_TARGET) == 0 && |
283 | && t->verdict < 0 | 283 | t->verdict < 0 && |
284 | && unconditional(&s->ipv6)) { | 284 | unconditional(&s->ipv6)) { |
285 | /* Tail of chains: STANDARD target (return/policy) */ | 285 | /* Tail of chains: STANDARD target (return/policy) */ |
286 | *comment = *chainname == hookname | 286 | *comment = *chainname == hookname |
287 | ? comments[NF_IP6_TRACE_COMMENT_POLICY] | 287 | ? comments[NF_IP6_TRACE_COMMENT_POLICY] |
@@ -418,8 +418,8 @@ ip6t_do_table(struct sk_buff *skb, | |||
418 | back = get_entry(table_base, back->comefrom); | 418 | back = get_entry(table_base, back->comefrom); |
419 | continue; | 419 | continue; |
420 | } | 420 | } |
421 | if (table_base + v != ip6t_next_entry(e) | 421 | if (table_base + v != ip6t_next_entry(e) && |
422 | && !(e->ipv6.flags & IP6T_F_GOTO)) { | 422 | !(e->ipv6.flags & IP6T_F_GOTO)) { |
423 | /* Save old back ptr in next entry */ | 423 | /* Save old back ptr in next entry */ |
424 | struct ip6t_entry *next = ip6t_next_entry(e); | 424 | struct ip6t_entry *next = ip6t_next_entry(e); |
425 | next->comefrom = (void *)back - table_base; | 425 | next->comefrom = (void *)back - table_base; |
@@ -505,11 +505,11 @@ mark_source_chains(struct xt_table_info *newinfo, | |||
505 | e->comefrom |= ((1 << hook) | (1 << NF_INET_NUMHOOKS)); | 505 | e->comefrom |= ((1 << hook) | (1 << NF_INET_NUMHOOKS)); |
506 | 506 | ||
507 | /* Unconditional return/END. */ | 507 | /* Unconditional return/END. */ |
508 | if ((e->target_offset == sizeof(struct ip6t_entry) | 508 | if ((e->target_offset == sizeof(struct ip6t_entry) && |
509 | && (strcmp(t->target.u.user.name, | 509 | (strcmp(t->target.u.user.name, |
510 | IP6T_STANDARD_TARGET) == 0) | 510 | IP6T_STANDARD_TARGET) == 0) && |
511 | && t->verdict < 0 | 511 | t->verdict < 0 && |
512 | && unconditional(&e->ipv6)) || visited) { | 512 | unconditional(&e->ipv6)) || visited) { |
513 | unsigned int oldpos, size; | 513 | unsigned int oldpos, size; |
514 | 514 | ||
515 | if ((strcmp(t->target.u.user.name, | 515 | if ((strcmp(t->target.u.user.name, |
@@ -556,8 +556,8 @@ mark_source_chains(struct xt_table_info *newinfo, | |||
556 | int newpos = t->verdict; | 556 | int newpos = t->verdict; |
557 | 557 | ||
558 | if (strcmp(t->target.u.user.name, | 558 | if (strcmp(t->target.u.user.name, |
559 | IP6T_STANDARD_TARGET) == 0 | 559 | IP6T_STANDARD_TARGET) == 0 && |
560 | && newpos >= 0) { | 560 | newpos >= 0) { |
561 | if (newpos > newinfo->size - | 561 | if (newpos > newinfo->size - |
562 | sizeof(struct ip6t_entry)) { | 562 | sizeof(struct ip6t_entry)) { |
563 | duprintf("mark_source_chains: " | 563 | duprintf("mark_source_chains: " |
@@ -767,8 +767,8 @@ check_entry_size_and_hooks(struct ip6t_entry *e, | |||
767 | { | 767 | { |
768 | unsigned int h; | 768 | unsigned int h; |
769 | 769 | ||
770 | if ((unsigned long)e % __alignof__(struct ip6t_entry) != 0 | 770 | if ((unsigned long)e % __alignof__(struct ip6t_entry) != 0 || |
771 | || (unsigned char *)e + sizeof(struct ip6t_entry) >= limit) { | 771 | (unsigned char *)e + sizeof(struct ip6t_entry) >= limit) { |
772 | duprintf("Bad offset %p\n", e); | 772 | duprintf("Bad offset %p\n", e); |
773 | return -EINVAL; | 773 | return -EINVAL; |
774 | } | 774 | } |
@@ -1584,8 +1584,8 @@ check_compat_entry_size_and_hooks(struct compat_ip6t_entry *e, | |||
1584 | int ret, off, h; | 1584 | int ret, off, h; |
1585 | 1585 | ||
1586 | duprintf("check_compat_entry_size_and_hooks %p\n", e); | 1586 | duprintf("check_compat_entry_size_and_hooks %p\n", e); |
1587 | if ((unsigned long)e % __alignof__(struct compat_ip6t_entry) != 0 | 1587 | if ((unsigned long)e % __alignof__(struct compat_ip6t_entry) != 0 || |
1588 | || (unsigned char *)e + sizeof(struct compat_ip6t_entry) >= limit) { | 1588 | (unsigned char *)e + sizeof(struct compat_ip6t_entry) >= limit) { |
1589 | duprintf("Bad offset %p, limit = %p\n", e, limit); | 1589 | duprintf("Bad offset %p, limit = %p\n", e, limit); |
1590 | return -EINVAL; | 1590 | return -EINVAL; |
1591 | } | 1591 | } |
diff --git a/net/ipv6/netfilter/ip6t_LOG.c b/net/ipv6/netfilter/ip6t_LOG.c index 7018cac4fddc..b285fdf19050 100644 --- a/net/ipv6/netfilter/ip6t_LOG.c +++ b/net/ipv6/netfilter/ip6t_LOG.c | |||
@@ -249,8 +249,8 @@ static void dump_packet(const struct nf_loginfo *info, | |||
249 | /* Max length: 11 "URGP=65535 " */ | 249 | /* Max length: 11 "URGP=65535 " */ |
250 | printk("URGP=%u ", ntohs(th->urg_ptr)); | 250 | printk("URGP=%u ", ntohs(th->urg_ptr)); |
251 | 251 | ||
252 | if ((logflags & IP6T_LOG_TCPOPT) | 252 | if ((logflags & IP6T_LOG_TCPOPT) && |
253 | && th->doff * 4 > sizeof(struct tcphdr)) { | 253 | th->doff * 4 > sizeof(struct tcphdr)) { |
254 | u_int8_t _opt[60 - sizeof(struct tcphdr)]; | 254 | u_int8_t _opt[60 - sizeof(struct tcphdr)]; |
255 | const u_int8_t *op; | 255 | const u_int8_t *op; |
256 | unsigned int i; | 256 | unsigned int i; |
diff --git a/net/ipv6/netfilter/ip6t_REJECT.c b/net/ipv6/netfilter/ip6t_REJECT.c index 5a7f00cd15ce..8311ca31816a 100644 --- a/net/ipv6/netfilter/ip6t_REJECT.c +++ b/net/ipv6/netfilter/ip6t_REJECT.c | |||
@@ -223,8 +223,8 @@ static bool reject_tg6_check(const struct xt_tgchk_param *par) | |||
223 | return false; | 223 | return false; |
224 | } else if (rejinfo->with == IP6T_TCP_RESET) { | 224 | } else if (rejinfo->with == IP6T_TCP_RESET) { |
225 | /* Must specify that it's a TCP packet */ | 225 | /* Must specify that it's a TCP packet */ |
226 | if (e->ipv6.proto != IPPROTO_TCP | 226 | if (e->ipv6.proto != IPPROTO_TCP || |
227 | || (e->ipv6.invflags & XT_INV_PROTO)) { | 227 | (e->ipv6.invflags & XT_INV_PROTO)) { |
228 | printk("ip6t_REJECT: TCP_RESET illegal for non-tcp\n"); | 228 | printk("ip6t_REJECT: TCP_RESET illegal for non-tcp\n"); |
229 | return false; | 229 | return false; |
230 | } | 230 | } |
diff --git a/net/ipv6/netfilter/ip6t_ah.c b/net/ipv6/netfilter/ip6t_ah.c index 3a82f24746b9..ac0b7c629d78 100644 --- a/net/ipv6/netfilter/ip6t_ah.c +++ b/net/ipv6/netfilter/ip6t_ah.c | |||
@@ -77,17 +77,14 @@ static bool ah_mt6(const struct sk_buff *skb, const struct xt_match_param *par) | |||
77 | ahinfo->hdrres, ah->reserved, | 77 | ahinfo->hdrres, ah->reserved, |
78 | !(ahinfo->hdrres && ah->reserved)); | 78 | !(ahinfo->hdrres && ah->reserved)); |
79 | 79 | ||
80 | return (ah != NULL) | 80 | return (ah != NULL) && |
81 | && | 81 | spi_match(ahinfo->spis[0], ahinfo->spis[1], |
82 | spi_match(ahinfo->spis[0], ahinfo->spis[1], | 82 | ntohl(ah->spi), |
83 | ntohl(ah->spi), | 83 | !!(ahinfo->invflags & IP6T_AH_INV_SPI)) && |
84 | !!(ahinfo->invflags & IP6T_AH_INV_SPI)) | 84 | (!ahinfo->hdrlen || |
85 | && | 85 | (ahinfo->hdrlen == hdrlen) ^ |
86 | (!ahinfo->hdrlen || | 86 | !!(ahinfo->invflags & IP6T_AH_INV_LEN)) && |
87 | (ahinfo->hdrlen == hdrlen) ^ | 87 | !(ahinfo->hdrres && ah->reserved); |
88 | !!(ahinfo->invflags & IP6T_AH_INV_LEN)) | ||
89 | && | ||
90 | !(ahinfo->hdrres && ah->reserved); | ||
91 | } | 88 | } |
92 | 89 | ||
93 | static bool ah_mt6_check(const struct xt_mtchk_param *par) | 90 | static bool ah_mt6_check(const struct xt_mtchk_param *par) |
diff --git a/net/ipv6/netfilter/ip6t_frag.c b/net/ipv6/netfilter/ip6t_frag.c index 673aa0a5084e..7b91c2598ed5 100644 --- a/net/ipv6/netfilter/ip6t_frag.c +++ b/net/ipv6/netfilter/ip6t_frag.c | |||
@@ -70,41 +70,36 @@ frag_mt6(const struct sk_buff *skb, const struct xt_match_param *par) | |||
70 | pr_debug("res %02X %02X%04X %02X ", | 70 | pr_debug("res %02X %02X%04X %02X ", |
71 | fraginfo->flags & IP6T_FRAG_RES, fh->reserved, | 71 | fraginfo->flags & IP6T_FRAG_RES, fh->reserved, |
72 | ntohs(fh->frag_off) & 0x6, | 72 | ntohs(fh->frag_off) & 0x6, |
73 | !((fraginfo->flags & IP6T_FRAG_RES) | 73 | !((fraginfo->flags & IP6T_FRAG_RES) && |
74 | && (fh->reserved || (ntohs(fh->frag_off) & 0x06)))); | 74 | (fh->reserved || (ntohs(fh->frag_off) & 0x06)))); |
75 | pr_debug("first %02X %02X %02X ", | 75 | pr_debug("first %02X %02X %02X ", |
76 | fraginfo->flags & IP6T_FRAG_FST, | 76 | fraginfo->flags & IP6T_FRAG_FST, |
77 | ntohs(fh->frag_off) & ~0x7, | 77 | ntohs(fh->frag_off) & ~0x7, |
78 | !((fraginfo->flags & IP6T_FRAG_FST) | 78 | !((fraginfo->flags & IP6T_FRAG_FST) && |
79 | && (ntohs(fh->frag_off) & ~0x7))); | 79 | (ntohs(fh->frag_off) & ~0x7))); |
80 | pr_debug("mf %02X %02X %02X ", | 80 | pr_debug("mf %02X %02X %02X ", |
81 | fraginfo->flags & IP6T_FRAG_MF, | 81 | fraginfo->flags & IP6T_FRAG_MF, |
82 | ntohs(fh->frag_off) & IP6_MF, | 82 | ntohs(fh->frag_off) & IP6_MF, |
83 | !((fraginfo->flags & IP6T_FRAG_MF) | 83 | !((fraginfo->flags & IP6T_FRAG_MF) && |
84 | && !((ntohs(fh->frag_off) & IP6_MF)))); | 84 | !((ntohs(fh->frag_off) & IP6_MF)))); |
85 | pr_debug("last %02X %02X %02X\n", | 85 | pr_debug("last %02X %02X %02X\n", |
86 | fraginfo->flags & IP6T_FRAG_NMF, | 86 | fraginfo->flags & IP6T_FRAG_NMF, |
87 | ntohs(fh->frag_off) & IP6_MF, | 87 | ntohs(fh->frag_off) & IP6_MF, |
88 | !((fraginfo->flags & IP6T_FRAG_NMF) | 88 | !((fraginfo->flags & IP6T_FRAG_NMF) && |
89 | && (ntohs(fh->frag_off) & IP6_MF))); | 89 | (ntohs(fh->frag_off) & IP6_MF))); |
90 | 90 | ||
91 | return (fh != NULL) | 91 | return (fh != NULL) && |
92 | && | 92 | id_match(fraginfo->ids[0], fraginfo->ids[1], |
93 | id_match(fraginfo->ids[0], fraginfo->ids[1], | 93 | ntohl(fh->identification), |
94 | ntohl(fh->identification), | 94 | !!(fraginfo->invflags & IP6T_FRAG_INV_IDS)) && |
95 | !!(fraginfo->invflags & IP6T_FRAG_INV_IDS)) | 95 | !((fraginfo->flags & IP6T_FRAG_RES) && |
96 | && | 96 | (fh->reserved || (ntohs(fh->frag_off) & 0x6))) && |
97 | !((fraginfo->flags & IP6T_FRAG_RES) | 97 | !((fraginfo->flags & IP6T_FRAG_FST) && |
98 | && (fh->reserved || (ntohs(fh->frag_off) & 0x6))) | 98 | (ntohs(fh->frag_off) & ~0x7)) && |
99 | && | 99 | !((fraginfo->flags & IP6T_FRAG_MF) && |
100 | !((fraginfo->flags & IP6T_FRAG_FST) | 100 | !(ntohs(fh->frag_off) & IP6_MF)) && |
101 | && (ntohs(fh->frag_off) & ~0x7)) | 101 | !((fraginfo->flags & IP6T_FRAG_NMF) && |
102 | && | 102 | (ntohs(fh->frag_off) & IP6_MF)); |
103 | !((fraginfo->flags & IP6T_FRAG_MF) | ||
104 | && !(ntohs(fh->frag_off) & IP6_MF)) | ||
105 | && | ||
106 | !((fraginfo->flags & IP6T_FRAG_NMF) | ||
107 | && (ntohs(fh->frag_off) & IP6_MF)); | ||
108 | } | 103 | } |
109 | 104 | ||
110 | static bool frag_mt6_check(const struct xt_mtchk_param *par) | 105 | static bool frag_mt6_check(const struct xt_mtchk_param *par) |
diff --git a/net/ipv6/netfilter/ip6t_rt.c b/net/ipv6/netfilter/ip6t_rt.c index 356b8d6f6baa..b77307fc8743 100644 --- a/net/ipv6/netfilter/ip6t_rt.c +++ b/net/ipv6/netfilter/ip6t_rt.c | |||
@@ -92,16 +92,13 @@ static bool rt_mt6(const struct sk_buff *skb, const struct xt_match_param *par) | |||
92 | !((rtinfo->flags & IP6T_RT_RES) && | 92 | !((rtinfo->flags & IP6T_RT_RES) && |
93 | (((const struct rt0_hdr *)rh)->reserved))); | 93 | (((const struct rt0_hdr *)rh)->reserved))); |
94 | 94 | ||
95 | ret = (rh != NULL) | 95 | ret = (rh != NULL) && |
96 | && | ||
97 | (segsleft_match(rtinfo->segsleft[0], rtinfo->segsleft[1], | 96 | (segsleft_match(rtinfo->segsleft[0], rtinfo->segsleft[1], |
98 | rh->segments_left, | 97 | rh->segments_left, |
99 | !!(rtinfo->invflags & IP6T_RT_INV_SGS))) | 98 | !!(rtinfo->invflags & IP6T_RT_INV_SGS))) && |
100 | && | ||
101 | (!(rtinfo->flags & IP6T_RT_LEN) || | 99 | (!(rtinfo->flags & IP6T_RT_LEN) || |
102 | ((rtinfo->hdrlen == hdrlen) ^ | 100 | ((rtinfo->hdrlen == hdrlen) ^ |
103 | !!(rtinfo->invflags & IP6T_RT_INV_LEN))) | 101 | !!(rtinfo->invflags & IP6T_RT_INV_LEN))) && |
104 | && | ||
105 | (!(rtinfo->flags & IP6T_RT_TYP) || | 102 | (!(rtinfo->flags & IP6T_RT_TYP) || |
106 | ((rtinfo->rt_type == rh->type) ^ | 103 | ((rtinfo->rt_type == rh->type) ^ |
107 | !!(rtinfo->invflags & IP6T_RT_INV_TYP))); | 104 | !!(rtinfo->invflags & IP6T_RT_INV_TYP))); |
diff --git a/net/ipv6/netfilter/ip6table_filter.c b/net/ipv6/netfilter/ip6table_filter.c index 6f4383ad86f9..ad378efd0eb8 100644 --- a/net/ipv6/netfilter/ip6table_filter.c +++ b/net/ipv6/netfilter/ip6table_filter.c | |||
@@ -79,8 +79,8 @@ ip6t_local_out_hook(unsigned int hook, | |||
79 | { | 79 | { |
80 | #if 0 | 80 | #if 0 |
81 | /* root is playing with raw sockets. */ | 81 | /* root is playing with raw sockets. */ |
82 | if (skb->len < sizeof(struct iphdr) | 82 | if (skb->len < sizeof(struct iphdr) || |
83 | || ip_hdrlen(skb) < sizeof(struct iphdr)) { | 83 | ip_hdrlen(skb) < sizeof(struct iphdr)) { |
84 | if (net_ratelimit()) | 84 | if (net_ratelimit()) |
85 | printk("ip6t_hook: happy cracking.\n"); | 85 | printk("ip6t_hook: happy cracking.\n"); |
86 | return NF_ACCEPT; | 86 | return NF_ACCEPT; |
diff --git a/net/ipv6/netfilter/ip6table_mangle.c b/net/ipv6/netfilter/ip6table_mangle.c index 0ad91433ed61..a929c19d30e3 100644 --- a/net/ipv6/netfilter/ip6table_mangle.c +++ b/net/ipv6/netfilter/ip6table_mangle.c | |||
@@ -102,8 +102,8 @@ ip6t_local_out_hook(unsigned int hook, | |||
102 | 102 | ||
103 | #if 0 | 103 | #if 0 |
104 | /* root is playing with raw sockets. */ | 104 | /* root is playing with raw sockets. */ |
105 | if (skb->len < sizeof(struct iphdr) | 105 | if (skb->len < sizeof(struct iphdr) || |
106 | || ip_hdrlen(skb) < sizeof(struct iphdr)) { | 106 | ip_hdrlen(skb) < sizeof(struct iphdr)) { |
107 | if (net_ratelimit()) | 107 | if (net_ratelimit()) |
108 | printk("ip6t_hook: happy cracking.\n"); | 108 | printk("ip6t_hook: happy cracking.\n"); |
109 | return NF_ACCEPT; | 109 | return NF_ACCEPT; |
@@ -122,11 +122,11 @@ ip6t_local_out_hook(unsigned int hook, | |||
122 | ret = ip6t_do_table(skb, hook, in, out, | 122 | ret = ip6t_do_table(skb, hook, in, out, |
123 | dev_net(out)->ipv6.ip6table_mangle); | 123 | dev_net(out)->ipv6.ip6table_mangle); |
124 | 124 | ||
125 | if (ret != NF_DROP && ret != NF_STOLEN | 125 | if (ret != NF_DROP && ret != NF_STOLEN && |
126 | && (memcmp(&ipv6_hdr(skb)->saddr, &saddr, sizeof(saddr)) | 126 | (memcmp(&ipv6_hdr(skb)->saddr, &saddr, sizeof(saddr)) || |
127 | || memcmp(&ipv6_hdr(skb)->daddr, &daddr, sizeof(daddr)) | 127 | memcmp(&ipv6_hdr(skb)->daddr, &daddr, sizeof(daddr)) || |
128 | || skb->mark != mark | 128 | skb->mark != mark || |
129 | || ipv6_hdr(skb)->hop_limit != hop_limit)) | 129 | ipv6_hdr(skb)->hop_limit != hop_limit)) |
130 | return ip6_route_me_harder(skb) == 0 ? ret : NF_DROP; | 130 | return ip6_route_me_harder(skb) == 0 ? ret : NF_DROP; |
131 | 131 | ||
132 | return ret; | 132 | return ret; |
diff --git a/net/ipv6/netfilter/nf_conntrack_proto_icmpv6.c b/net/ipv6/netfilter/nf_conntrack_proto_icmpv6.c index 642dcb127bab..0f3df45718ac 100644 --- a/net/ipv6/netfilter/nf_conntrack_proto_icmpv6.c +++ b/net/ipv6/netfilter/nf_conntrack_proto_icmpv6.c | |||
@@ -244,18 +244,18 @@ static const struct nla_policy icmpv6_nla_policy[CTA_PROTO_MAX+1] = { | |||
244 | static int icmpv6_nlattr_to_tuple(struct nlattr *tb[], | 244 | static int icmpv6_nlattr_to_tuple(struct nlattr *tb[], |
245 | struct nf_conntrack_tuple *tuple) | 245 | struct nf_conntrack_tuple *tuple) |
246 | { | 246 | { |
247 | if (!tb[CTA_PROTO_ICMPV6_TYPE] | 247 | if (!tb[CTA_PROTO_ICMPV6_TYPE] || |
248 | || !tb[CTA_PROTO_ICMPV6_CODE] | 248 | !tb[CTA_PROTO_ICMPV6_CODE] || |
249 | || !tb[CTA_PROTO_ICMPV6_ID]) | 249 | !tb[CTA_PROTO_ICMPV6_ID]) |
250 | return -EINVAL; | 250 | return -EINVAL; |
251 | 251 | ||
252 | tuple->dst.u.icmp.type = nla_get_u8(tb[CTA_PROTO_ICMPV6_TYPE]); | 252 | tuple->dst.u.icmp.type = nla_get_u8(tb[CTA_PROTO_ICMPV6_TYPE]); |
253 | tuple->dst.u.icmp.code = nla_get_u8(tb[CTA_PROTO_ICMPV6_CODE]); | 253 | tuple->dst.u.icmp.code = nla_get_u8(tb[CTA_PROTO_ICMPV6_CODE]); |
254 | tuple->src.u.icmp.id = nla_get_be16(tb[CTA_PROTO_ICMPV6_ID]); | 254 | tuple->src.u.icmp.id = nla_get_be16(tb[CTA_PROTO_ICMPV6_ID]); |
255 | 255 | ||
256 | if (tuple->dst.u.icmp.type < 128 | 256 | if (tuple->dst.u.icmp.type < 128 || |
257 | || tuple->dst.u.icmp.type - 128 >= sizeof(invmap) | 257 | tuple->dst.u.icmp.type - 128 >= sizeof(invmap) || |
258 | || !invmap[tuple->dst.u.icmp.type - 128]) | 258 | !invmap[tuple->dst.u.icmp.type - 128]) |
259 | return -EINVAL; | 259 | return -EINVAL; |
260 | 260 | ||
261 | return 0; | 261 | return 0; |
diff --git a/net/netfilter/nf_conntrack_core.c b/net/netfilter/nf_conntrack_core.c index b9168c1864ca..0e98c3282d42 100644 --- a/net/netfilter/nf_conntrack_core.c +++ b/net/netfilter/nf_conntrack_core.c | |||
@@ -512,11 +512,17 @@ static noinline int early_drop(struct net *net, unsigned int hash) | |||
512 | cnt++; | 512 | cnt++; |
513 | } | 513 | } |
514 | 514 | ||
515 | if (ct && unlikely(nf_ct_is_dying(ct) || | 515 | if (ct != NULL) { |
516 | !atomic_inc_not_zero(&ct->ct_general.use))) | 516 | if (likely(!nf_ct_is_dying(ct) && |
517 | ct = NULL; | 517 | atomic_inc_not_zero(&ct->ct_general.use))) |
518 | if (ct || cnt >= NF_CT_EVICTION_RANGE) | 518 | break; |
519 | else | ||
520 | ct = NULL; | ||
521 | } | ||
522 | |||
523 | if (cnt >= NF_CT_EVICTION_RANGE) | ||
519 | break; | 524 | break; |
525 | |||
520 | hash = (hash + 1) % nf_conntrack_htable_size; | 526 | hash = (hash + 1) % nf_conntrack_htable_size; |
521 | } | 527 | } |
522 | rcu_read_unlock(); | 528 | rcu_read_unlock(); |
diff --git a/net/netfilter/nf_conntrack_proto_tcp.c b/net/netfilter/nf_conntrack_proto_tcp.c index ba2b76937283..37a8c74be619 100644 --- a/net/netfilter/nf_conntrack_proto_tcp.c +++ b/net/netfilter/nf_conntrack_proto_tcp.c | |||
@@ -896,23 +896,54 @@ static int tcp_packet(struct nf_conn *ct, | |||
896 | /* b) This SYN/ACK acknowledges a SYN that we earlier | 896 | /* b) This SYN/ACK acknowledges a SYN that we earlier |
897 | * ignored as invalid. This means that the client and | 897 | * ignored as invalid. This means that the client and |
898 | * the server are both in sync, while the firewall is | 898 | * the server are both in sync, while the firewall is |
899 | * not. We kill this session and block the SYN/ACK so | 899 | * not. We get in sync from the previously annotated |
900 | * that the client cannot but retransmit its SYN and | 900 | * values. |
901 | * thus initiate a clean new session. | ||
902 | */ | 901 | */ |
903 | spin_unlock_bh(&ct->lock); | 902 | old_state = TCP_CONNTRACK_SYN_SENT; |
904 | if (LOG_INVALID(net, IPPROTO_TCP)) | 903 | new_state = TCP_CONNTRACK_SYN_RECV; |
905 | nf_log_packet(pf, 0, skb, NULL, NULL, NULL, | 904 | ct->proto.tcp.seen[ct->proto.tcp.last_dir].td_end = |
906 | "nf_ct_tcp: killing out of sync session "); | 905 | ct->proto.tcp.last_end; |
907 | nf_ct_kill(ct); | 906 | ct->proto.tcp.seen[ct->proto.tcp.last_dir].td_maxend = |
908 | return NF_DROP; | 907 | ct->proto.tcp.last_end; |
908 | ct->proto.tcp.seen[ct->proto.tcp.last_dir].td_maxwin = | ||
909 | ct->proto.tcp.last_win == 0 ? | ||
910 | 1 : ct->proto.tcp.last_win; | ||
911 | ct->proto.tcp.seen[ct->proto.tcp.last_dir].td_scale = | ||
912 | ct->proto.tcp.last_wscale; | ||
913 | ct->proto.tcp.seen[ct->proto.tcp.last_dir].flags = | ||
914 | ct->proto.tcp.last_flags; | ||
915 | memset(&ct->proto.tcp.seen[dir], 0, | ||
916 | sizeof(struct ip_ct_tcp_state)); | ||
917 | break; | ||
909 | } | 918 | } |
910 | ct->proto.tcp.last_index = index; | 919 | ct->proto.tcp.last_index = index; |
911 | ct->proto.tcp.last_dir = dir; | 920 | ct->proto.tcp.last_dir = dir; |
912 | ct->proto.tcp.last_seq = ntohl(th->seq); | 921 | ct->proto.tcp.last_seq = ntohl(th->seq); |
913 | ct->proto.tcp.last_end = | 922 | ct->proto.tcp.last_end = |
914 | segment_seq_plus_len(ntohl(th->seq), skb->len, dataoff, th); | 923 | segment_seq_plus_len(ntohl(th->seq), skb->len, dataoff, th); |
915 | 924 | ct->proto.tcp.last_win = ntohs(th->window); | |
925 | |||
926 | /* a) This is a SYN in ORIGINAL. The client and the server | ||
927 | * may be in sync but we are not. In that case, we annotate | ||
928 | * the TCP options and let the packet go through. If it is a | ||
929 | * valid SYN packet, the server will reply with a SYN/ACK, and | ||
930 | * then we'll get in sync. Otherwise, the server ignores it. */ | ||
931 | if (index == TCP_SYN_SET && dir == IP_CT_DIR_ORIGINAL) { | ||
932 | struct ip_ct_tcp_state seen = {}; | ||
933 | |||
934 | ct->proto.tcp.last_flags = | ||
935 | ct->proto.tcp.last_wscale = 0; | ||
936 | tcp_options(skb, dataoff, th, &seen); | ||
937 | if (seen.flags & IP_CT_TCP_FLAG_WINDOW_SCALE) { | ||
938 | ct->proto.tcp.last_flags |= | ||
939 | IP_CT_TCP_FLAG_WINDOW_SCALE; | ||
940 | ct->proto.tcp.last_wscale = seen.td_scale; | ||
941 | } | ||
942 | if (seen.flags & IP_CT_TCP_FLAG_SACK_PERM) { | ||
943 | ct->proto.tcp.last_flags |= | ||
944 | IP_CT_TCP_FLAG_SACK_PERM; | ||
945 | } | ||
946 | } | ||
916 | spin_unlock_bh(&ct->lock); | 947 | spin_unlock_bh(&ct->lock); |
917 | if (LOG_INVALID(net, IPPROTO_TCP)) | 948 | if (LOG_INVALID(net, IPPROTO_TCP)) |
918 | nf_log_packet(pf, 0, skb, NULL, NULL, NULL, | 949 | nf_log_packet(pf, 0, skb, NULL, NULL, NULL, |
diff --git a/net/netfilter/nfnetlink_log.c b/net/netfilter/nfnetlink_log.c index 49005482e39a..9de0470d557e 100644 --- a/net/netfilter/nfnetlink_log.c +++ b/net/netfilter/nfnetlink_log.c | |||
@@ -666,8 +666,7 @@ nfulnl_rcv_nl_event(struct notifier_block *this, | |||
666 | { | 666 | { |
667 | struct netlink_notify *n = ptr; | 667 | struct netlink_notify *n = ptr; |
668 | 668 | ||
669 | if (event == NETLINK_URELEASE && | 669 | if (event == NETLINK_URELEASE && n->protocol == NETLINK_NETFILTER) { |
670 | n->protocol == NETLINK_NETFILTER && n->pid) { | ||
671 | int i; | 670 | int i; |
672 | 671 | ||
673 | /* destroy all instances for this pid */ | 672 | /* destroy all instances for this pid */ |
diff --git a/net/netfilter/nfnetlink_queue.c b/net/netfilter/nfnetlink_queue.c index 7a9dec9fb822..7e3fa410641e 100644 --- a/net/netfilter/nfnetlink_queue.c +++ b/net/netfilter/nfnetlink_queue.c | |||
@@ -574,8 +574,7 @@ nfqnl_rcv_nl_event(struct notifier_block *this, | |||
574 | { | 574 | { |
575 | struct netlink_notify *n = ptr; | 575 | struct netlink_notify *n = ptr; |
576 | 576 | ||
577 | if (event == NETLINK_URELEASE && | 577 | if (event == NETLINK_URELEASE && n->protocol == NETLINK_NETFILTER) { |
578 | n->protocol == NETLINK_NETFILTER && n->pid) { | ||
579 | int i; | 578 | int i; |
580 | 579 | ||
581 | /* destroy all instances for this pid */ | 580 | /* destroy all instances for this pid */ |
diff --git a/net/netfilter/xt_conntrack.c b/net/netfilter/xt_conntrack.c index 6dc4652f2fe8..ae66305f0fe5 100644 --- a/net/netfilter/xt_conntrack.c +++ b/net/netfilter/xt_conntrack.c | |||
@@ -113,7 +113,8 @@ ct_proto_port_check(const struct xt_conntrack_mtinfo2 *info, | |||
113 | } | 113 | } |
114 | 114 | ||
115 | static bool | 115 | static bool |
116 | conntrack_mt(const struct sk_buff *skb, const struct xt_match_param *par) | 116 | conntrack_mt(const struct sk_buff *skb, const struct xt_match_param *par, |
117 | u16 state_mask, u16 status_mask) | ||
117 | { | 118 | { |
118 | const struct xt_conntrack_mtinfo2 *info = par->matchinfo; | 119 | const struct xt_conntrack_mtinfo2 *info = par->matchinfo; |
119 | enum ip_conntrack_info ctinfo; | 120 | enum ip_conntrack_info ctinfo; |
@@ -136,7 +137,7 @@ conntrack_mt(const struct sk_buff *skb, const struct xt_match_param *par) | |||
136 | if (test_bit(IPS_DST_NAT_BIT, &ct->status)) | 137 | if (test_bit(IPS_DST_NAT_BIT, &ct->status)) |
137 | statebit |= XT_CONNTRACK_STATE_DNAT; | 138 | statebit |= XT_CONNTRACK_STATE_DNAT; |
138 | } | 139 | } |
139 | if (!!(info->state_mask & statebit) ^ | 140 | if (!!(state_mask & statebit) ^ |
140 | !(info->invert_flags & XT_CONNTRACK_STATE)) | 141 | !(info->invert_flags & XT_CONNTRACK_STATE)) |
141 | return false; | 142 | return false; |
142 | } | 143 | } |
@@ -172,7 +173,7 @@ conntrack_mt(const struct sk_buff *skb, const struct xt_match_param *par) | |||
172 | return false; | 173 | return false; |
173 | 174 | ||
174 | if ((info->match_flags & XT_CONNTRACK_STATUS) && | 175 | if ((info->match_flags & XT_CONNTRACK_STATUS) && |
175 | (!!(info->status_mask & ct->status) ^ | 176 | (!!(status_mask & ct->status) ^ |
176 | !(info->invert_flags & XT_CONNTRACK_STATUS))) | 177 | !(info->invert_flags & XT_CONNTRACK_STATUS))) |
177 | return false; | 178 | return false; |
178 | 179 | ||
@@ -192,11 +193,17 @@ conntrack_mt(const struct sk_buff *skb, const struct xt_match_param *par) | |||
192 | static bool | 193 | static bool |
193 | conntrack_mt_v1(const struct sk_buff *skb, const struct xt_match_param *par) | 194 | conntrack_mt_v1(const struct sk_buff *skb, const struct xt_match_param *par) |
194 | { | 195 | { |
195 | const struct xt_conntrack_mtinfo2 *const *info = par->matchinfo; | 196 | const struct xt_conntrack_mtinfo1 *info = par->matchinfo; |
196 | struct xt_match_param newpar = *par; | ||
197 | 197 | ||
198 | newpar.matchinfo = *info; | 198 | return conntrack_mt(skb, par, info->state_mask, info->status_mask); |
199 | return conntrack_mt(skb, &newpar); | 199 | } |
200 | |||
201 | static bool | ||
202 | conntrack_mt_v2(const struct sk_buff *skb, const struct xt_match_param *par) | ||
203 | { | ||
204 | const struct xt_conntrack_mtinfo2 *info = par->matchinfo; | ||
205 | |||
206 | return conntrack_mt(skb, par, info->state_mask, info->status_mask); | ||
200 | } | 207 | } |
201 | 208 | ||
202 | static bool conntrack_mt_check(const struct xt_mtchk_param *par) | 209 | static bool conntrack_mt_check(const struct xt_mtchk_param *par) |
@@ -209,45 +216,11 @@ static bool conntrack_mt_check(const struct xt_mtchk_param *par) | |||
209 | return true; | 216 | return true; |
210 | } | 217 | } |
211 | 218 | ||
212 | static bool conntrack_mt_check_v1(const struct xt_mtchk_param *par) | ||
213 | { | ||
214 | struct xt_conntrack_mtinfo1 *info = par->matchinfo; | ||
215 | struct xt_conntrack_mtinfo2 *up; | ||
216 | int ret = conntrack_mt_check(par); | ||
217 | |||
218 | if (ret < 0) | ||
219 | return ret; | ||
220 | |||
221 | up = kmalloc(sizeof(*up), GFP_KERNEL); | ||
222 | if (up == NULL) { | ||
223 | nf_ct_l3proto_module_put(par->family); | ||
224 | return -ENOMEM; | ||
225 | } | ||
226 | |||
227 | /* | ||
228 | * The strategy here is to minimize the overhead of v1 matching, | ||
229 | * by prebuilding a v2 struct and putting the pointer into the | ||
230 | * v1 dataspace. | ||
231 | */ | ||
232 | memcpy(up, info, offsetof(typeof(*info), state_mask)); | ||
233 | up->state_mask = info->state_mask; | ||
234 | up->status_mask = info->status_mask; | ||
235 | *(void **)info = up; | ||
236 | return true; | ||
237 | } | ||
238 | |||
239 | static void conntrack_mt_destroy(const struct xt_mtdtor_param *par) | 219 | static void conntrack_mt_destroy(const struct xt_mtdtor_param *par) |
240 | { | 220 | { |
241 | nf_ct_l3proto_module_put(par->family); | 221 | nf_ct_l3proto_module_put(par->family); |
242 | } | 222 | } |
243 | 223 | ||
244 | static void conntrack_mt_destroy_v1(const struct xt_mtdtor_param *par) | ||
245 | { | ||
246 | struct xt_conntrack_mtinfo2 **info = par->matchinfo; | ||
247 | kfree(*info); | ||
248 | conntrack_mt_destroy(par); | ||
249 | } | ||
250 | |||
251 | static struct xt_match conntrack_mt_reg[] __read_mostly = { | 224 | static struct xt_match conntrack_mt_reg[] __read_mostly = { |
252 | { | 225 | { |
253 | .name = "conntrack", | 226 | .name = "conntrack", |
@@ -255,8 +228,8 @@ static struct xt_match conntrack_mt_reg[] __read_mostly = { | |||
255 | .family = NFPROTO_UNSPEC, | 228 | .family = NFPROTO_UNSPEC, |
256 | .matchsize = sizeof(struct xt_conntrack_mtinfo1), | 229 | .matchsize = sizeof(struct xt_conntrack_mtinfo1), |
257 | .match = conntrack_mt_v1, | 230 | .match = conntrack_mt_v1, |
258 | .checkentry = conntrack_mt_check_v1, | 231 | .checkentry = conntrack_mt_check, |
259 | .destroy = conntrack_mt_destroy_v1, | 232 | .destroy = conntrack_mt_destroy, |
260 | .me = THIS_MODULE, | 233 | .me = THIS_MODULE, |
261 | }, | 234 | }, |
262 | { | 235 | { |
@@ -264,7 +237,7 @@ static struct xt_match conntrack_mt_reg[] __read_mostly = { | |||
264 | .revision = 2, | 237 | .revision = 2, |
265 | .family = NFPROTO_UNSPEC, | 238 | .family = NFPROTO_UNSPEC, |
266 | .matchsize = sizeof(struct xt_conntrack_mtinfo2), | 239 | .matchsize = sizeof(struct xt_conntrack_mtinfo2), |
267 | .match = conntrack_mt, | 240 | .match = conntrack_mt_v2, |
268 | .checkentry = conntrack_mt_check, | 241 | .checkentry = conntrack_mt_check, |
269 | .destroy = conntrack_mt_destroy, | 242 | .destroy = conntrack_mt_destroy, |
270 | .me = THIS_MODULE, | 243 | .me = THIS_MODULE, |
diff --git a/net/netfilter/xt_socket.c b/net/netfilter/xt_socket.c index 362afbd60a96..6a902564d24f 100644 --- a/net/netfilter/xt_socket.c +++ b/net/netfilter/xt_socket.c | |||
@@ -192,7 +192,8 @@ static struct xt_match socket_mt_reg[] __read_mostly = { | |||
192 | .revision = 0, | 192 | .revision = 0, |
193 | .family = NFPROTO_IPV4, | 193 | .family = NFPROTO_IPV4, |
194 | .match = socket_mt_v0, | 194 | .match = socket_mt_v0, |
195 | .hooks = 1 << NF_INET_PRE_ROUTING, | 195 | .hooks = (1 << NF_INET_PRE_ROUTING) | |
196 | (1 << NF_INET_LOCAL_IN), | ||
196 | .me = THIS_MODULE, | 197 | .me = THIS_MODULE, |
197 | }, | 198 | }, |
198 | { | 199 | { |
@@ -201,7 +202,8 @@ static struct xt_match socket_mt_reg[] __read_mostly = { | |||
201 | .family = NFPROTO_IPV4, | 202 | .family = NFPROTO_IPV4, |
202 | .match = socket_mt_v1, | 203 | .match = socket_mt_v1, |
203 | .matchsize = sizeof(struct xt_socket_mtinfo1), | 204 | .matchsize = sizeof(struct xt_socket_mtinfo1), |
204 | .hooks = 1 << NF_INET_PRE_ROUTING, | 205 | .hooks = (1 << NF_INET_PRE_ROUTING) | |
206 | (1 << NF_INET_LOCAL_IN), | ||
205 | .me = THIS_MODULE, | 207 | .me = THIS_MODULE, |
206 | }, | 208 | }, |
207 | }; | 209 | }; |