From ec68e97dedacc1c7fb20a4b23b7fa76bee56b5ff Mon Sep 17 00:00:00 2001 From: Patrick McHardy Date: Sun, 4 Mar 2007 15:57:01 -0800 Subject: [NETFILTER]: conntrack: fix {nf,ip}_ct_iterate_cleanup endless loops Fix {nf,ip}_ct_iterate_cleanup unconfirmed list handling: - unconfirmed entries can not be killed manually, they are removed on confirmation or final destruction of the conntrack entry, which means we might iterate forever without making forward progress. This can happen in combination with the conntrack event cache, which holds a reference to the conntrack entry, which is only released when the packet makes it all the way through the stack or a different packet is handled. - taking references to an unconfirmed entry and using it outside the locked section doesn't work, the list entries are not refcounted and another CPU might already be waiting to destroy the entry What the code really wants to do is make sure the references of the hash table to the selected conntrack entries are released, so they will be destroyed once all references from skbs and the event cache are dropped. Since unconfirmed entries haven't even entered the hash yet, simply mark them as dying and skip confirmation based on that. Reported and tested by Chuck Ebbert Signed-off-by: Patrick McHardy Signed-off-by: David S. Miller --- net/ipv4/netfilter/ip_conntrack_core.c | 2 +- net/netfilter/nf_conntrack_core.c | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) (limited to 'net') diff --git a/net/ipv4/netfilter/ip_conntrack_core.c b/net/ipv4/netfilter/ip_conntrack_core.c index 07ba1dd136b5..23b99ae2cc37 100644 --- a/net/ipv4/netfilter/ip_conntrack_core.c +++ b/net/ipv4/netfilter/ip_conntrack_core.c @@ -1254,7 +1254,7 @@ get_next_corpse(int (*iter)(struct ip_conntrack *i, void *data), list_for_each_entry(h, &unconfirmed, list) { ct = tuplehash_to_ctrack(h); if (iter(ct, data)) - goto found; + set_bit(IPS_DYING_BIT, &ct->status); } write_unlock_bh(&ip_conntrack_lock); return NULL; diff --git a/net/netfilter/nf_conntrack_core.c b/net/netfilter/nf_conntrack_core.c index 32891ebc9e68..4fdf4849baf8 100644 --- a/net/netfilter/nf_conntrack_core.c +++ b/net/netfilter/nf_conntrack_core.c @@ -1070,7 +1070,7 @@ get_next_corpse(int (*iter)(struct nf_conn *i, void *data), list_for_each_entry(h, &unconfirmed, list) { ct = nf_ct_tuplehash_to_ctrack(h); if (iter(ct, data)) - goto found; + set_bit(IPS_DYING_BIT, &ct->status); } write_unlock_bh(&nf_conntrack_lock); return NULL; -- cgit v1.2.3-59-g8ed1b From e281db5cdfc3ab077ab3e459d098cb4fde0bc57a Mon Sep 17 00:00:00 2001 From: Patrick McHardy Date: Sun, 4 Mar 2007 15:57:25 -0800 Subject: [NETFILTER]: nf_conntrack/nf_nat: fix incorrect config ifdefs The nf_conntrack_netlink config option is named CONFIG_NF_CT_NETLINK, but multiple files use CONFIG_IP_NF_CONNTRACK_NETLINK or CONFIG_NF_CONNTRACK_NETLINK for ifdefs. Fix this and reformat all CONFIG_NF_CT_NETLINK ifdefs to only use a line. Signed-off-by: Patrick McHardy Signed-off-by: David S. Miller --- net/ipv4/netfilter/nf_conntrack_l3proto_ipv4.c | 6 ++---- net/ipv4/netfilter/nf_conntrack_proto_icmp.c | 6 ++---- net/ipv4/netfilter/nf_nat_core.c | 3 +-- net/ipv4/netfilter/nf_nat_proto_gre.c | 3 +-- net/ipv4/netfilter/nf_nat_proto_icmp.c | 3 +-- net/ipv4/netfilter/nf_nat_proto_tcp.c | 3 +-- net/ipv4/netfilter/nf_nat_proto_udp.c | 3 +-- net/ipv6/netfilter/nf_conntrack_l3proto_ipv6.c | 6 ++---- net/ipv6/netfilter/nf_conntrack_proto_icmpv6.c | 6 ++---- net/netfilter/nf_conntrack_core.c | 3 +-- net/netfilter/nf_conntrack_proto_gre.c | 3 +-- net/netfilter/nf_conntrack_proto_tcp.c | 9 +++------ net/netfilter/nf_conntrack_proto_udp.c | 6 ++---- 13 files changed, 20 insertions(+), 40 deletions(-) (limited to 'net') diff --git a/net/ipv4/netfilter/nf_conntrack_l3proto_ipv4.c b/net/ipv4/netfilter/nf_conntrack_l3proto_ipv4.c index b984db771258..8f3e92d20df8 100644 --- a/net/ipv4/netfilter/nf_conntrack_l3proto_ipv4.c +++ b/net/ipv4/netfilter/nf_conntrack_l3proto_ipv4.c @@ -379,8 +379,7 @@ getorigdst(struct sock *sk, int optval, void __user *user, int *len) return -ENOENT; } -#if defined(CONFIG_NF_CT_NETLINK) || \ - defined(CONFIG_NF_CT_NETLINK_MODULE) +#if defined(CONFIG_NF_CT_NETLINK) || defined(CONFIG_NF_CT_NETLINK_MODULE) #include #include @@ -435,8 +434,7 @@ struct nf_conntrack_l3proto nf_conntrack_l3proto_ipv4 = { .print_conntrack = ipv4_print_conntrack, .prepare = ipv4_prepare, .get_features = ipv4_get_features, -#if defined(CONFIG_NF_CT_NETLINK) || \ - defined(CONFIG_NF_CT_NETLINK_MODULE) +#if defined(CONFIG_NF_CT_NETLINK) || defined(CONFIG_NF_CT_NETLINK_MODULE) .tuple_to_nfattr = ipv4_tuple_to_nfattr, .nfattr_to_tuple = ipv4_nfattr_to_tuple, #endif diff --git a/net/ipv4/netfilter/nf_conntrack_proto_icmp.c b/net/ipv4/netfilter/nf_conntrack_proto_icmp.c index 88cfa6aacfc1..5fd1e5363c1a 100644 --- a/net/ipv4/netfilter/nf_conntrack_proto_icmp.c +++ b/net/ipv4/netfilter/nf_conntrack_proto_icmp.c @@ -268,8 +268,7 @@ icmp_error(struct sk_buff *skb, unsigned int dataoff, return icmp_error_message(skb, ctinfo, hooknum); } -#if defined(CONFIG_NF_CT_NETLINK) || \ - defined(CONFIG_NF_CT_NETLINK_MODULE) +#if defined(CONFIG_NF_CT_NETLINK) || defined(CONFIG_NF_CT_NETLINK_MODULE) #include #include @@ -368,8 +367,7 @@ struct nf_conntrack_l4proto nf_conntrack_l4proto_icmp = .error = icmp_error, .destroy = NULL, .me = NULL, -#if defined(CONFIG_NF_CT_NETLINK) || \ - defined(CONFIG_NF_CT_NETLINK_MODULE) +#if defined(CONFIG_NF_CT_NETLINK) || defined(CONFIG_NF_CT_NETLINK_MODULE) .tuple_to_nfattr = icmp_tuple_to_nfattr, .nfattr_to_tuple = icmp_nfattr_to_tuple, #endif diff --git a/net/ipv4/netfilter/nf_nat_core.c b/net/ipv4/netfilter/nf_nat_core.c index 2c01378d3592..452e9d326684 100644 --- a/net/ipv4/netfilter/nf_nat_core.c +++ b/net/ipv4/netfilter/nf_nat_core.c @@ -546,8 +546,7 @@ void nf_nat_protocol_unregister(struct nf_nat_protocol *proto) } EXPORT_SYMBOL(nf_nat_protocol_unregister); -#if defined(CONFIG_IP_NF_CONNTRACK_NETLINK) || \ - defined(CONFIG_IP_NF_CONNTRACK_NETLINK_MODULE) +#if defined(CONFIG_NF_CT_NETLINK) || defined(CONFIG_NF_CT_NETLINK_MODULE) int nf_nat_port_range_to_nfattr(struct sk_buff *skb, const struct nf_nat_range *range) diff --git a/net/ipv4/netfilter/nf_nat_proto_gre.c b/net/ipv4/netfilter/nf_nat_proto_gre.c index d3de579e09d2..e5a34c17d927 100644 --- a/net/ipv4/netfilter/nf_nat_proto_gre.c +++ b/net/ipv4/netfilter/nf_nat_proto_gre.c @@ -152,8 +152,7 @@ static struct nf_nat_protocol gre __read_mostly = { .manip_pkt = gre_manip_pkt, .in_range = gre_in_range, .unique_tuple = gre_unique_tuple, -#if defined(CONFIG_IP_NF_CONNTRACK_NETLINK) || \ - defined(CONFIG_IP_NF_CONNTRACK_NETLINK_MODULE) +#if defined(CONFIG_NF_CT_NETLINK) || defined(CONFIG_NF_CT_NETLINK_MODULE) .range_to_nfattr = nf_nat_port_range_to_nfattr, .nfattr_to_range = nf_nat_port_nfattr_to_range, #endif diff --git a/net/ipv4/netfilter/nf_nat_proto_icmp.c b/net/ipv4/netfilter/nf_nat_proto_icmp.c index 6bc2f06de055..f71ef9b5f428 100644 --- a/net/ipv4/netfilter/nf_nat_proto_icmp.c +++ b/net/ipv4/netfilter/nf_nat_proto_icmp.c @@ -78,8 +78,7 @@ struct nf_nat_protocol nf_nat_protocol_icmp = { .manip_pkt = icmp_manip_pkt, .in_range = icmp_in_range, .unique_tuple = icmp_unique_tuple, -#if defined(CONFIG_IP_NF_CONNTRACK_NETLINK) || \ - defined(CONFIG_IP_NF_CONNTRACK_NETLINK_MODULE) +#if defined(CONFIG_NF_CT_NETLINK) || defined(CONFIG_NF_CT_NETLINK_MODULE) .range_to_nfattr = nf_nat_port_range_to_nfattr, .nfattr_to_range = nf_nat_port_nfattr_to_range, #endif diff --git a/net/ipv4/netfilter/nf_nat_proto_tcp.c b/net/ipv4/netfilter/nf_nat_proto_tcp.c index 439164c7a626..123c95913f28 100644 --- a/net/ipv4/netfilter/nf_nat_proto_tcp.c +++ b/net/ipv4/netfilter/nf_nat_proto_tcp.c @@ -144,8 +144,7 @@ struct nf_nat_protocol nf_nat_protocol_tcp = { .manip_pkt = tcp_manip_pkt, .in_range = tcp_in_range, .unique_tuple = tcp_unique_tuple, -#if defined(CONFIG_IP_NF_CONNTRACK_NETLINK) || \ - defined(CONFIG_IP_NF_CONNTRACK_NETLINK_MODULE) +#if defined(CONFIG_NF_CT_NETLINK) || defined(CONFIG_NF_CT_NETLINK_MODULE) .range_to_nfattr = nf_nat_port_range_to_nfattr, .nfattr_to_range = nf_nat_port_nfattr_to_range, #endif diff --git a/net/ipv4/netfilter/nf_nat_proto_udp.c b/net/ipv4/netfilter/nf_nat_proto_udp.c index 8cae6e063bb6..1c4c70e25cd4 100644 --- a/net/ipv4/netfilter/nf_nat_proto_udp.c +++ b/net/ipv4/netfilter/nf_nat_proto_udp.c @@ -134,8 +134,7 @@ struct nf_nat_protocol nf_nat_protocol_udp = { .manip_pkt = udp_manip_pkt, .in_range = udp_in_range, .unique_tuple = udp_unique_tuple, -#if defined(CONFIG_IP_NF_CONNTRACK_NETLINK) || \ - defined(CONFIG_IP_NF_CONNTRACK_NETLINK_MODULE) +#if defined(CONFIG_NF_CT_NETLINK) || defined(CONFIG_NF_CT_NETLINK_MODULE) .range_to_nfattr = nf_nat_port_range_to_nfattr, .nfattr_to_range = nf_nat_port_nfattr_to_range, #endif diff --git a/net/ipv6/netfilter/nf_conntrack_l3proto_ipv6.c b/net/ipv6/netfilter/nf_conntrack_l3proto_ipv6.c index 4b7be4bb4d03..6f19c4a49560 100644 --- a/net/ipv6/netfilter/nf_conntrack_l3proto_ipv6.c +++ b/net/ipv6/netfilter/nf_conntrack_l3proto_ipv6.c @@ -353,8 +353,7 @@ static ctl_table nf_ct_ipv6_sysctl_table[] = { }; #endif -#if defined(CONFIG_NF_CT_NETLINK) || \ - defined(CONFIG_NF_CT_NETLINK_MODULE) +#if defined(CONFIG_NF_CT_NETLINK) || defined(CONFIG_NF_CT_NETLINK_MODULE) #include #include @@ -403,8 +402,7 @@ struct nf_conntrack_l3proto nf_conntrack_l3proto_ipv6 = { .print_tuple = ipv6_print_tuple, .print_conntrack = ipv6_print_conntrack, .prepare = ipv6_prepare, -#if defined(CONFIG_NF_CT_NETLINK) || \ - defined(CONFIG_NF_CT_NETLINK_MODULE) +#if defined(CONFIG_NF_CT_NETLINK) || defined(CONFIG_NF_CT_NETLINK_MODULE) .tuple_to_nfattr = ipv6_tuple_to_nfattr, .nfattr_to_tuple = ipv6_nfattr_to_tuple, #endif diff --git a/net/ipv6/netfilter/nf_conntrack_proto_icmpv6.c b/net/ipv6/netfilter/nf_conntrack_proto_icmpv6.c index 21f19cc719f3..075da4f287b8 100644 --- a/net/ipv6/netfilter/nf_conntrack_proto_icmpv6.c +++ b/net/ipv6/netfilter/nf_conntrack_proto_icmpv6.c @@ -244,8 +244,7 @@ icmpv6_error(struct sk_buff *skb, unsigned int dataoff, return icmpv6_error_message(skb, dataoff, ctinfo, hooknum); } -#if defined(CONFIG_NF_CT_NETLINK) || \ - defined(CONFIG_NF_CT_NETLINK_MODULE) +#if defined(CONFIG_NF_CT_NETLINK) || defined(CONFIG_NF_CT_NETLINK_MODULE) #include #include @@ -327,8 +326,7 @@ struct nf_conntrack_l4proto nf_conntrack_l4proto_icmpv6 = .packet = icmpv6_packet, .new = icmpv6_new, .error = icmpv6_error, -#if defined(CONFIG_NF_CT_NETLINK) || \ - defined(CONFIG_NF_CT_NETLINK_MODULE) +#if defined(CONFIG_NF_CT_NETLINK) || defined(CONFIG_NF_CT_NETLINK_MODULE) .tuple_to_nfattr = icmpv6_tuple_to_nfattr, .nfattr_to_tuple = icmpv6_nfattr_to_tuple, #endif diff --git a/net/netfilter/nf_conntrack_core.c b/net/netfilter/nf_conntrack_core.c index 4fdf4849baf8..b3a70eb6d42a 100644 --- a/net/netfilter/nf_conntrack_core.c +++ b/net/netfilter/nf_conntrack_core.c @@ -976,8 +976,7 @@ void __nf_ct_refresh_acct(struct nf_conn *ct, } EXPORT_SYMBOL_GPL(__nf_ct_refresh_acct); -#if defined(CONFIG_NF_CT_NETLINK) || \ - defined(CONFIG_NF_CT_NETLINK_MODULE) +#if defined(CONFIG_NF_CT_NETLINK) || defined(CONFIG_NF_CT_NETLINK_MODULE) #include #include diff --git a/net/netfilter/nf_conntrack_proto_gre.c b/net/netfilter/nf_conntrack_proto_gre.c index ac193ce70249..5434472420fe 100644 --- a/net/netfilter/nf_conntrack_proto_gre.c +++ b/net/netfilter/nf_conntrack_proto_gre.c @@ -281,8 +281,7 @@ static struct nf_conntrack_l4proto nf_conntrack_l4proto_gre4 = { .new = gre_new, .destroy = gre_destroy, .me = THIS_MODULE, -#if defined(CONFIG_NF_CONNTRACK_NETLINK) || \ - defined(CONFIG_NF_CONNTRACK_NETLINK_MODULE) +#if defined(CONFIG_NF_CT_NETLINK) || defined(CONFIG_NF_CT_NETLINK_MODULE) .tuple_to_nfattr = nf_ct_port_tuple_to_nfattr, .nfattr_to_tuple = nf_ct_port_nfattr_to_tuple, #endif diff --git a/net/netfilter/nf_conntrack_proto_tcp.c b/net/netfilter/nf_conntrack_proto_tcp.c index 069b85ca51cd..3b9ad7f6eb5d 100644 --- a/net/netfilter/nf_conntrack_proto_tcp.c +++ b/net/netfilter/nf_conntrack_proto_tcp.c @@ -1099,8 +1099,7 @@ static int tcp_new(struct nf_conn *conntrack, return 1; } -#if defined(CONFIG_NF_CT_NETLINK) || \ - defined(CONFIG_NF_CT_NETLINK_MODULE) +#if defined(CONFIG_NF_CT_NETLINK) || defined(CONFIG_NF_CT_NETLINK_MODULE) #include #include @@ -1378,8 +1377,7 @@ struct nf_conntrack_l4proto nf_conntrack_l4proto_tcp4 = .packet = tcp_packet, .new = tcp_new, .error = tcp_error, -#if defined(CONFIG_NF_CT_NETLINK) || \ - defined(CONFIG_NF_CT_NETLINK_MODULE) +#if defined(CONFIG_NF_CT_NETLINK) || defined(CONFIG_NF_CT_NETLINK_MODULE) .to_nfattr = tcp_to_nfattr, .from_nfattr = nfattr_to_tcp, .tuple_to_nfattr = nf_ct_port_tuple_to_nfattr, @@ -1408,8 +1406,7 @@ struct nf_conntrack_l4proto nf_conntrack_l4proto_tcp6 = .packet = tcp_packet, .new = tcp_new, .error = tcp_error, -#if defined(CONFIG_NF_CT_NETLINK) || \ - defined(CONFIG_NF_CT_NETLINK_MODULE) +#if defined(CONFIG_NF_CT_NETLINK) || defined(CONFIG_NF_CT_NETLINK_MODULE) .to_nfattr = tcp_to_nfattr, .from_nfattr = nfattr_to_tcp, .tuple_to_nfattr = nf_ct_port_tuple_to_nfattr, diff --git a/net/netfilter/nf_conntrack_proto_udp.c b/net/netfilter/nf_conntrack_proto_udp.c index d0a1cee7ee52..a5e5726ec0c7 100644 --- a/net/netfilter/nf_conntrack_proto_udp.c +++ b/net/netfilter/nf_conntrack_proto_udp.c @@ -208,8 +208,7 @@ struct nf_conntrack_l4proto nf_conntrack_l4proto_udp4 = .packet = udp_packet, .new = udp_new, .error = udp_error, -#if defined(CONFIG_NF_CT_NETLINK) || \ - defined(CONFIG_NF_CT_NETLINK_MODULE) +#if defined(CONFIG_NF_CT_NETLINK) || defined(CONFIG_NF_CT_NETLINK_MODULE) .tuple_to_nfattr = nf_ct_port_tuple_to_nfattr, .nfattr_to_tuple = nf_ct_port_nfattr_to_tuple, #endif @@ -236,8 +235,7 @@ struct nf_conntrack_l4proto nf_conntrack_l4proto_udp6 = .packet = udp_packet, .new = udp_new, .error = udp_error, -#if defined(CONFIG_NF_CT_NETLINK) || \ - defined(CONFIG_NF_CT_NETLINK_MODULE) +#if defined(CONFIG_NF_CT_NETLINK) || defined(CONFIG_NF_CT_NETLINK_MODULE) .tuple_to_nfattr = nf_ct_port_tuple_to_nfattr, .nfattr_to_tuple = nf_ct_port_nfattr_to_tuple, #endif -- cgit v1.2.3-59-g8ed1b From d3ab4298aa136d07219664d563d8decf0e75693f Mon Sep 17 00:00:00 2001 From: Patrick McHardy Date: Sun, 4 Mar 2007 15:57:46 -0800 Subject: [NETFILTER]: tcp conntrack: accept SYN|URG as valid Some stacks apparently send packets with SYN|URG set. Linux accepts these packets, so TCP conntrack should to. Pointed out by Martijn Posthuma . Signed-off-by: Patrick McHardy Signed-off-by: David S. Miller --- net/ipv4/netfilter/ip_conntrack_proto_tcp.c | 4 +++- net/netfilter/nf_conntrack_proto_tcp.c | 4 +++- 2 files changed, 6 insertions(+), 2 deletions(-) (limited to 'net') diff --git a/net/ipv4/netfilter/ip_conntrack_proto_tcp.c b/net/ipv4/netfilter/ip_conntrack_proto_tcp.c index 170d625fad67..0a72eab14620 100644 --- a/net/ipv4/netfilter/ip_conntrack_proto_tcp.c +++ b/net/ipv4/netfilter/ip_conntrack_proto_tcp.c @@ -812,8 +812,10 @@ void ip_conntrack_tcp_update(struct sk_buff *skb, static const u8 tcp_valid_flags[(TH_FIN|TH_SYN|TH_RST|TH_PUSH|TH_ACK|TH_URG) + 1] = { [TH_SYN] = 1, - [TH_SYN|TH_ACK] = 1, [TH_SYN|TH_PUSH] = 1, + [TH_SYN|TH_URG] = 1, + [TH_SYN|TH_PUSH|TH_URG] = 1, + [TH_SYN|TH_ACK] = 1, [TH_SYN|TH_ACK|TH_PUSH] = 1, [TH_RST] = 1, [TH_RST|TH_ACK] = 1, diff --git a/net/netfilter/nf_conntrack_proto_tcp.c b/net/netfilter/nf_conntrack_proto_tcp.c index 3b9ad7f6eb5d..153d6619993a 100644 --- a/net/netfilter/nf_conntrack_proto_tcp.c +++ b/net/netfilter/nf_conntrack_proto_tcp.c @@ -769,8 +769,10 @@ EXPORT_SYMBOL_GPL(nf_conntrack_tcp_update); static u8 tcp_valid_flags[(TH_FIN|TH_SYN|TH_RST|TH_PUSH|TH_ACK|TH_URG) + 1] = { [TH_SYN] = 1, - [TH_SYN|TH_ACK] = 1, [TH_SYN|TH_PUSH] = 1, + [TH_SYN|TH_URG] = 1, + [TH_SYN|TH_PUSH|TH_URG] = 1, + [TH_SYN|TH_ACK] = 1, [TH_SYN|TH_ACK|TH_PUSH] = 1, [TH_RST] = 1, [TH_RST|TH_ACK] = 1, -- cgit v1.2.3-59-g8ed1b From ed32abeaf3a3da79b63af6a75f0bd0aa7e7eed9e Mon Sep 17 00:00:00 2001 From: Michal Miroslaw Date: Sun, 4 Mar 2007 15:58:15 -0800 Subject: [NETFILTER]: nfnetlink_log: fix reference leak Stop reference leaking in nfulnl_log_packet(). If we start a timer we are already taking another reference. Signed-off-by: Michal Miroslaw Signed-off-by: Patrick McHardy Signed-off-by: David S. Miller --- net/netfilter/nfnetlink_log.c | 7 ++++--- 1 file changed, 4 insertions(+), 3 deletions(-) (limited to 'net') diff --git a/net/netfilter/nfnetlink_log.c b/net/netfilter/nfnetlink_log.c index b8eab0dbc3dd..62c3f31cdb97 100644 --- a/net/netfilter/nfnetlink_log.c +++ b/net/netfilter/nfnetlink_log.c @@ -711,15 +711,16 @@ nfulnl_log_packet(unsigned int pf, inst->timer.expires = jiffies + (inst->flushtimeout*HZ/100); add_timer(&inst->timer); } - spin_unlock_bh(&inst->lock); +unlock_and_release: + spin_unlock_bh(&inst->lock); + instance_put(inst); return; alloc_failure: - spin_unlock_bh(&inst->lock); - instance_put(inst); UDEBUG("error allocating skb\n"); /* FIXME: statistics */ + goto unlock_and_release; } static int -- cgit v1.2.3-59-g8ed1b From 05f7b7b369e039458a77768619dde123d868c78d Mon Sep 17 00:00:00 2001 From: Michal Miroslaw Date: Sun, 4 Mar 2007 15:58:40 -0800 Subject: [NETFILTER]: nfnetlink_log: fix use after free Paranoia: instance_put() might have freed the inst pointer when we spin_unlock_bh(). Signed-off-by: Michal Miroslaw Signed-off-by: Patrick McHardy Signed-off-by: David S. Miller --- net/netfilter/nfnetlink_log.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'net') diff --git a/net/netfilter/nfnetlink_log.c b/net/netfilter/nfnetlink_log.c index 62c3f31cdb97..27b844a67ec1 100644 --- a/net/netfilter/nfnetlink_log.c +++ b/net/netfilter/nfnetlink_log.c @@ -393,8 +393,8 @@ static void nfulnl_timer(unsigned long data) spin_lock_bh(&inst->lock); __nfulnl_send(inst); - instance_put(inst); spin_unlock_bh(&inst->lock); + instance_put(inst); } /* This is an inline function, we don't really care about a long -- cgit v1.2.3-59-g8ed1b From a497097d35d37b47e885cf15bcaea01f279fe5e6 Mon Sep 17 00:00:00 2001 From: Michal Miroslaw Date: Sun, 4 Mar 2007 15:59:01 -0800 Subject: [NETFILTER]: nfnetlink_log: fix NULL pointer dereference Fix the nasty NULL dereference on multiple packets per netlink message. BUG: unable to handle kernel NULL pointer dereference at virtual address 00000004 printing eip: f8a4b3bf *pde = 00000000 Oops: 0002 [#1] SMP Modules linked in: nfnetlink_log ipt_ttl ipt_REDIRECT xt_tcpudp iptable_nat nf_nat nf_conntrack_ipv4 xt_state ipt_ipp2p xt_NFLOG xt_hashlimit ip6_tables iptable_filter xt_multiport xt_mark ipt_set iptable_raw xt_MARK iptable_mangle ip_tables cls_fw cls_u32 sch_esfq sch_htb ip_set_ipmap ip_set ipt_ULOG x_tables dm_snapshot dm_mirror loop e1000 parport_pc parport e100 floppy ide_cd cdrom CPU: 0 EIP: 0060:[] Not tainted VLI EFLAGS: 00010206 (2.6.20 #5) EIP is at __nfulnl_send+0x24/0x51 [nfnetlink_log] eax: 00000000 ebx: f2b5cbc0 ecx: c03f5f54 edx: c03f4000 esi: f2b5cbc8 edi: c03f5f54 ebp: f8a4b3ec esp: c03f5f30 ds: 007b es: 007b ss: 0068 Process swapper (pid: 0, ti=c03f4000 task=c03bece0 task.ti=c03f4000) Stack: f2b5cbc0 f8a4b401 00000100 c0444080 c012af49 00000000 f6f19100 f6f19000 c1707800 c03f5f54 c03f5f54 00000123 00000021 c03e8d08 c0426380 00000009 c0126932 00000000 00000046 c03e9980 c03e6000 0047b007 c01269bd 00000000 Call Trace: [] nfulnl_timer+0x15/0x25 [nfnetlink_log] [] run_timer_softirq+0x10a/0x164 [] __do_softirq+0x60/0xba [] do_softirq+0x31/0x35 [] do_IRQ+0x62/0x74 [] common_interrupt+0x23/0x28 [] default_idle+0x0/0x3f [] default_idle+0x2d/0x3f [] cpu_idle+0xa0/0xb9 [] start_kernel+0x1a8/0x1ac [] unknown_bootoption+0x0/0x181 ======================= Code: 5e 5f 5b 5e 5f 5d c3 53 89 c3 8d 40 1c 83 7b 1c 00 74 05 e8 2c ee 6d c7 83 7b 14 00 75 04 31 c0 eb 34 83 7b 10 01 76 09 8b 43 18 <66> c7 40 04 03 00 8b 53 34 8b 43 14 b9 40 00 00 00 e8 08 9a 84 EIP: [] __nfulnl_send+0x24/0x51 [nfnetlink_log] SS:ESP 0068:c03f5f30 <0>Kernel panic - not syncing: Fatal exception in interrupt <0>Rebooting in 5 seconds.. Panic no more! Signed-off-by: Micha Mirosaw Signed-off-by: Patrick McHardy Signed-off-by: David S. Miller --- net/netfilter/nfnetlink_log.c | 1 + 1 file changed, 1 insertion(+) (limited to 'net') diff --git a/net/netfilter/nfnetlink_log.c b/net/netfilter/nfnetlink_log.c index 27b844a67ec1..1b940512d87b 100644 --- a/net/netfilter/nfnetlink_log.c +++ b/net/netfilter/nfnetlink_log.c @@ -560,6 +560,7 @@ __build_packet_message(struct nfulnl_instance *inst, } nlh->nlmsg_len = inst->skb->tail - old_tail; + inst->lastnlh = nlh; return 0; nlmsg_failure: -- cgit v1.2.3-59-g8ed1b From dd16704eba171b32ef0cded3a4f562b33b911066 Mon Sep 17 00:00:00 2001 From: Michal Miroslaw Date: Sun, 4 Mar 2007 15:59:20 -0800 Subject: [NETFILTER]: nfnetlink_log: fix possible NULL pointer dereference Eliminate possible NULL pointer dereference in nfulnl_recv_config(). Signed-off-by: Michal Miroslaw Signed-off-by: Patrick McHardy Signed-off-by: David S. Miller --- net/netfilter/nfnetlink_log.c | 4 ++++ 1 file changed, 4 insertions(+) (limited to 'net') diff --git a/net/netfilter/nfnetlink_log.c b/net/netfilter/nfnetlink_log.c index 1b940512d87b..b669db564695 100644 --- a/net/netfilter/nfnetlink_log.c +++ b/net/netfilter/nfnetlink_log.c @@ -858,6 +858,9 @@ nfulnl_recv_config(struct sock *ctnl, struct sk_buff *skb, ret = -EINVAL; break; } + + if (!inst) + goto out; } else { if (!inst) { UDEBUG("no config command, and no instance for " @@ -911,6 +914,7 @@ nfulnl_recv_config(struct sock *ctnl, struct sk_buff *skb, out_put: instance_put(inst); +out: return ret; } -- cgit v1.2.3-59-g8ed1b From 7d90e86d31e8beeb66d6754aece890ac4a579887 Mon Sep 17 00:00:00 2001 From: Patrick McHardy Date: Sun, 4 Mar 2007 15:59:45 -0800 Subject: [NETFILTER]: nfnetlink_log: fix module reference counting Count module references correctly: after instance_destroy() there might be timer pending and holding a reference for this netlink instance. Based on patch by Michal Miroslaw Signed-off-by: Patrick McHardy Signed-off-by: David S. Miller --- net/netfilter/nfnetlink_log.c | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) (limited to 'net') diff --git a/net/netfilter/nfnetlink_log.c b/net/netfilter/nfnetlink_log.c index b669db564695..d0af8bc3eee1 100644 --- a/net/netfilter/nfnetlink_log.c +++ b/net/netfilter/nfnetlink_log.c @@ -133,6 +133,7 @@ instance_put(struct nfulnl_instance *inst) if (inst && atomic_dec_and_test(&inst->use)) { UDEBUG("kfree(inst=%p)\n", inst); kfree(inst); + module_put(THIS_MODULE); } } @@ -228,8 +229,6 @@ _instance_destroy2(struct nfulnl_instance *inst, int lock) /* and finally put the refcount */ instance_put(inst); - - module_put(THIS_MODULE); } static inline void -- cgit v1.2.3-59-g8ed1b From b4d6202b3652f5dbce358b99dee7d7c80b567529 Mon Sep 17 00:00:00 2001 From: Michal Miroslaw Date: Sun, 4 Mar 2007 16:00:04 -0800 Subject: [NETFILTER]: nfnetlink_log: fix reference counting Fix reference counting (memory leak) problem in __nfulnl_send() and callers related to packet queueing. Signed-off-by: Michal Miroslaw Signed-off-by: Patrick McHardy Signed-off-by: David S. Miller --- net/netfilter/nfnetlink_log.c | 9 ++++++--- 1 file changed, 6 insertions(+), 3 deletions(-) (limited to 'net') diff --git a/net/netfilter/nfnetlink_log.c b/net/netfilter/nfnetlink_log.c index d0af8bc3eee1..91a0972ec117 100644 --- a/net/netfilter/nfnetlink_log.c +++ b/net/netfilter/nfnetlink_log.c @@ -218,6 +218,9 @@ _instance_destroy2(struct nfulnl_instance *inst, int lock) spin_lock_bh(&inst->lock); if (inst->skb) { + /* timer "holds" one reference (we have one more) */ + if (del_timer(&inst->timer)) + instance_put(inst); if (inst->qlen) __nfulnl_send(inst); if (inst->skb) { @@ -362,9 +365,6 @@ __nfulnl_send(struct nfulnl_instance *inst) { int status; - if (timer_pending(&inst->timer)) - del_timer(&inst->timer); - if (!inst->skb) return 0; @@ -689,6 +689,9 @@ nfulnl_log_packet(unsigned int pf, * enough room in the skb left. flush to userspace. */ UDEBUG("flushing old skb\n"); + /* timer "holds" one reference (we have another one) */ + if (del_timer(&inst->timer)) + instance_put(inst); __nfulnl_send(inst); if (!(inst->skb = nfulnl_alloc_skb(nlbufsiz, size))) { -- cgit v1.2.3-59-g8ed1b From bc5f77434721a84705601e4d448d331c73900759 Mon Sep 17 00:00:00 2001 From: Yasuyuki Kozakai Date: Sun, 4 Mar 2007 16:00:32 -0800 Subject: [NETFILTER]: ip6_route_me_harder should take into account mark Signed-off-by: Yasuyuki Kozakai Signed-off-by: Patrick McHardy Signed-off-by: David S. Miller --- net/ipv6/netfilter.c | 1 + 1 file changed, 1 insertion(+) (limited to 'net') diff --git a/net/ipv6/netfilter.c b/net/ipv6/netfilter.c index 0b2d265e7da7..1c405dd30c67 100644 --- a/net/ipv6/netfilter.c +++ b/net/ipv6/netfilter.c @@ -15,6 +15,7 @@ int ip6_route_me_harder(struct sk_buff *skb) struct dst_entry *dst; struct flowi fl = { .oif = skb->sk ? skb->sk->sk_bound_dev_if : 0, + .mark = skb->mark, .nl_u = { .ip6_u = { .daddr = iph->daddr, -- cgit v1.2.3-59-g8ed1b From 64a146513f8f12ba204b7bf5cb7e9505594ead42 Mon Sep 17 00:00:00 2001 From: "David S. Miller" Date: Tue, 6 Mar 2007 11:21:05 -0800 Subject: [NET]: Revert incorrect accept queue backlog changes. This reverts two changes: 8488df894d05d6fa41c2bd298c335f944bb0e401 248f06726e866942b3d8ca8f411f9067713b7ff8 A backlog value of N really does mean allow "N + 1" connections to queue to a listening socket. This allows one to specify "0" as the backlog and still get 1 connection. Noticed by Gerrit Renker and Rick Jones. Signed-off-by: David S. Miller --- include/net/sock.h | 2 +- net/unix/af_unix.c | 6 +++--- 2 files changed, 4 insertions(+), 4 deletions(-) (limited to 'net') diff --git a/include/net/sock.h b/include/net/sock.h index 849c7df23181..2c7d60ca3548 100644 --- a/include/net/sock.h +++ b/include/net/sock.h @@ -426,7 +426,7 @@ static inline void sk_acceptq_added(struct sock *sk) static inline int sk_acceptq_is_full(struct sock *sk) { - return sk->sk_ack_backlog >= sk->sk_max_ack_backlog; + return sk->sk_ack_backlog > sk->sk_max_ack_backlog; } /* diff --git a/net/unix/af_unix.c b/net/unix/af_unix.c index 51ca4383c388..606971645b33 100644 --- a/net/unix/af_unix.c +++ b/net/unix/af_unix.c @@ -934,7 +934,7 @@ static long unix_wait_for_peer(struct sock *other, long timeo) sched = !sock_flag(other, SOCK_DEAD) && !(other->sk_shutdown & RCV_SHUTDOWN) && - (skb_queue_len(&other->sk_receive_queue) >= + (skb_queue_len(&other->sk_receive_queue) > other->sk_max_ack_backlog); unix_state_runlock(other); @@ -1008,7 +1008,7 @@ restart: if (other->sk_state != TCP_LISTEN) goto out_unlock; - if (skb_queue_len(&other->sk_receive_queue) >= + if (skb_queue_len(&other->sk_receive_queue) > other->sk_max_ack_backlog) { err = -EAGAIN; if (!timeo) @@ -1381,7 +1381,7 @@ restart: } if (unix_peer(other) != sk && - (skb_queue_len(&other->sk_receive_queue) >= + (skb_queue_len(&other->sk_receive_queue) > other->sk_max_ack_backlog)) { if (!timeo) { err = -EAGAIN; -- cgit v1.2.3-59-g8ed1b From 1e51f9513e6b021abcaefd7c76f9b5d682f83232 Mon Sep 17 00:00:00 2001 From: Johannes Berg Date: Tue, 6 Mar 2007 13:44:06 -0800 Subject: [NET]: Fix compat_sock_common_getsockopt typo. This patch fixes a typo in compat_sock_common_getsockopt. Signed-off-by: Johannes Berg Acked-by: James Morris Signed-off-by: David S. Miller --- net/core/sock.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'net') diff --git a/net/core/sock.c b/net/core/sock.c index e9986acdd0ab..8d65d6478dcd 100644 --- a/net/core/sock.c +++ b/net/core/sock.c @@ -1597,7 +1597,7 @@ int compat_sock_common_getsockopt(struct socket *sock, int level, int optname, { struct sock *sk = sock->sk; - if (sk->sk_prot->compat_setsockopt != NULL) + if (sk->sk_prot->compat_getsockopt != NULL) return sk->sk_prot->compat_getsockopt(sk, level, optname, optval, optlen); return sk->sk_prot->getsockopt(sk, level, optname, optval, optlen); -- cgit v1.2.3-59-g8ed1b From 4d46861be6196d0f1614724590968d8da26af82a Mon Sep 17 00:00:00 2001 From: Gerrit Renker Date: Tue, 6 Mar 2007 14:24:18 -0800 Subject: [DCCP]: Correctly split CCID half connections This fixes a bug caused by a previous patch, which causes DCCP servers in LISTEN state to not receive packets. This patch changes the logic so that * servers in either LISTEN or OPEN state get the RX half connection packets * clients in OPEN state get the TX half connection packets Signed-off-by: Gerrit Renker Signed-off-by: Arnaldo Carvalho de Melo Signed-off-by: David S. Miller --- net/dccp/input.c | 12 ++++++------ 1 file changed, 6 insertions(+), 6 deletions(-) (limited to 'net') diff --git a/net/dccp/input.c b/net/dccp/input.c index 4dee462f00db..287099f7f042 100644 --- a/net/dccp/input.c +++ b/net/dccp/input.c @@ -256,10 +256,10 @@ int dccp_rcv_established(struct sock *sk, struct sk_buff *skb, * (only one is active at a time); when moving to bidirectional * service, this needs to be revised. */ - if (dccp_sk(sk)->dccps_role == DCCP_ROLE_SERVER) - ccid_hc_rx_packet_recv(dp->dccps_hc_rx_ccid, sk, skb); - else + if (dccp_sk(sk)->dccps_role == DCCP_ROLE_CLIENT) ccid_hc_tx_packet_recv(dp->dccps_hc_tx_ccid, sk, skb); + else /* listening or connected server */ + ccid_hc_rx_packet_recv(dp->dccps_hc_rx_ccid, sk, skb); return __dccp_rcv_established(sk, skb, dh, len); discard: @@ -495,10 +495,10 @@ int dccp_rcv_state_process(struct sock *sk, struct sk_buff *skb, goto discard; /* XXX see the comments in dccp_rcv_established about this */ - if (dccp_sk(sk)->dccps_role == DCCP_ROLE_SERVER) - ccid_hc_rx_packet_recv(dp->dccps_hc_rx_ccid, sk, skb); - else + if (dccp_sk(sk)->dccps_role == DCCP_ROLE_CLIENT) ccid_hc_tx_packet_recv(dp->dccps_hc_tx_ccid, sk, skb); + else + ccid_hc_rx_packet_recv(dp->dccps_hc_rx_ccid, sk, skb); } /* -- cgit v1.2.3-59-g8ed1b From 99c72ce091ec85868a0847e598eb7562dc0d8205 Mon Sep 17 00:00:00 2001 From: Gerrit Renker Date: Tue, 6 Mar 2007 14:24:44 -0800 Subject: [DCCP]: Set RTO for newly created child socket This mirrors a recent change in tcp_open_req_child, whereby the icsk_rto of the newly created child socket was not set (but rather on the parent socket). Same fix for DCCP. Signed-off-by: Gerrit Renker Signed-off-by: Arnaldo Carvalho de Melo Signed-off-by: David S. Miller --- net/dccp/minisocks.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'net') diff --git a/net/dccp/minisocks.c b/net/dccp/minisocks.c index 6656bb497c7b..6d235b3013dd 100644 --- a/net/dccp/minisocks.c +++ b/net/dccp/minisocks.c @@ -103,7 +103,7 @@ struct sock *dccp_create_openreq_child(struct sock *sk, if (newsk != NULL) { const struct dccp_request_sock *dreq = dccp_rsk(req); - struct inet_connection_sock *newicsk = inet_csk(sk); + struct inet_connection_sock *newicsk = inet_csk(newsk); struct dccp_sock *newdp = dccp_sk(newsk); struct dccp_minisock *newdmsk = dccp_msk(newsk); -- cgit v1.2.3-59-g8ed1b