linux/net/netfilter
Sven Wegener aea9d711f3 ipvs: Add missing locking during connection table hashing and unhashing
The code that hashes and unhashes connections from the connection table
is missing locking of the connection being modified, which opens up a
race condition and results in memory corruption when this race condition
is hit.

Here is what happens in pretty verbose form:

CPU 0					CPU 1
------------				------------
An active connection is terminated and
we schedule ip_vs_conn_expire() on this
CPU to expire this connection.

					IRQ assignment is changed to this CPU,
					but the expire timer stays scheduled on
					the other CPU.

					New connection from same ip:port comes
					in right before the timer expires, we
					find the inactive connection in our
					connection table and get a reference to
					it. We proper lock the connection in
					tcp_state_transition() and read the
					connection flags in set_tcp_state().

ip_vs_conn_expire() gets called, we
unhash the connection from our
connection table and remove the hashed
flag in ip_vs_conn_unhash(), without
proper locking!

					While still holding proper locks we
					write the connection flags in
					set_tcp_state() and this sets the hashed
					flag again.

ip_vs_conn_expire() fails to expire the
connection, because the other CPU has
incremented the reference count. We try
to re-insert the connection into our
connection table, but this fails in
ip_vs_conn_hash(), because the hashed
flag has been set by the other CPU. We
re-schedule execution of
ip_vs_conn_expire(). Now this connection
has the hashed flag set, but isn't
actually hashed in our connection table
and has a dangling list_head.

					We drop the reference we held on the
					connection and schedule the expire timer
					for timeouting the connection on this
					CPU. Further packets won't be able to
					find this connection in our connection
					table.

					ip_vs_conn_expire() gets called again,
					we think it's already hashed, but the
					list_head is dangling and while removing
					the connection from our connection table
					we write to the memory location where
					this list_head points to.

The result will probably be a kernel oops at some other point in time.

This race condition is pretty subtle, but it can be triggered remotely.
It needs the IRQ assignment change or another circumstance where packets
coming from the same ip:port for the same service are being processed on
different CPUs. And it involves hitting the exact time at which
ip_vs_conn_expire() gets called. It can be avoided by making sure that
all packets from one connection are always processed on the same CPU and
can be made harder to exploit by changing the connection timeouts to
some custom values.

Signed-off-by: Sven Wegener <sven.wegener@stealer.net>
Cc: stable@kernel.org
Acked-by: Simon Horman <horms@verge.net.au>
Signed-off-by: Patrick McHardy <kaber@trash.net>
2010-06-09 16:10:57 +02:00
..
ipvs ipvs: Add missing locking during connection table hashing and unhashing 2010-06-09 16:10:57 +02:00
core.c include cleanup: Update gfp.h and slab.h includes to prepare for breaking implicit slab.h inclusion from percpu.h 2010-03-30 22:02:32 +09:00
Kconfig netfilter: xt_TEE depends on NF_CONNTRACK 2010-05-14 13:52:30 -07:00
Makefile netfilter: xtables: inclusion of xt_TEE 2010-04-19 14:17:47 +02:00
nf_conntrack_acct.c include cleanup: Update gfp.h and slab.h includes to prepare for breaking implicit slab.h inclusion from percpu.h 2010-03-30 22:02:32 +09:00
nf_conntrack_amanda.c netfilter: cleanup printk messages 2010-05-13 15:02:08 +02:00
nf_conntrack_core.c netfilter: nf_conntrack: fix a race in __nf_conntrack_confirm against nf_ct_get_next_corpse() 2010-05-20 15:55:30 +02:00
nf_conntrack_ecache.c netfilter: use rcu_dereference_protected() 2010-05-10 18:47:57 +02:00
nf_conntrack_expect.c
nf_conntrack_extend.c
nf_conntrack_ftp.c netfilter: cleanup printk messages 2010-05-13 15:02:08 +02:00
nf_conntrack_h323_asn1.c
nf_conntrack_h323_main.c netfilter: cleanup printk messages 2010-05-13 15:02:08 +02:00
nf_conntrack_h323_types.c
nf_conntrack_helper.c include cleanup: Update gfp.h and slab.h includes to prepare for breaking implicit slab.h inclusion from percpu.h 2010-03-30 22:02:32 +09:00
nf_conntrack_irc.c netfilter: cleanup printk messages 2010-05-13 15:02:08 +02:00
nf_conntrack_l3proto_generic.c
nf_conntrack_netbios_ns.c
nf_conntrack_netlink.c netfilter: remove unnecessary returns from void function()s 2010-05-13 15:16:27 +02:00
nf_conntrack_pptp.c
nf_conntrack_proto_dccp.c include cleanup: Update gfp.h and slab.h includes to prepare for breaking implicit slab.h inclusion from percpu.h 2010-03-30 22:02:32 +09:00
nf_conntrack_proto_generic.c
nf_conntrack_proto_gre.c include cleanup: Update gfp.h and slab.h includes to prepare for breaking implicit slab.h inclusion from percpu.h 2010-03-30 22:02:32 +09:00
nf_conntrack_proto_sctp.c netfilter: cleanup printk messages 2010-05-13 15:02:08 +02:00
nf_conntrack_proto_tcp.c
nf_conntrack_proto_udp.c
nf_conntrack_proto_udplite.c
nf_conntrack_proto.c netfilter: nf_conntrack_proto: fix warning with CONFIG_PROVE_RCU 2010-05-10 17:45:56 +02:00
nf_conntrack_sane.c include cleanup: Update gfp.h and slab.h includes to prepare for breaking implicit slab.h inclusion from percpu.h 2010-03-30 22:02:32 +09:00
nf_conntrack_sip.c netfilter: nf_ct_sip: handle non-linear skbs 2010-05-14 21:18:17 +02:00
nf_conntrack_standalone.c netfilter: cleanup printk messages 2010-05-13 15:02:08 +02:00
nf_conntrack_tftp.c netfilter: cleanup printk messages 2010-05-13 15:02:08 +02:00
nf_internals.h netfilter: cleanup printk messages 2010-05-13 15:02:08 +02:00
nf_log.c netfilter: use rcu_dereference_protected() 2010-05-10 18:47:57 +02:00
nf_queue.c net: add a noref bit on skb dst 2010-05-17 17:18:50 -07:00
nf_sockopt.c
nf_tproxy_core.c
nfnetlink_log.c netfilter: cleanup printk messages 2010-05-13 15:02:08 +02:00
nfnetlink_queue.c Merge branch 'master' of /repos/git/net-next-2.6 2010-04-20 16:02:01 +02:00
nfnetlink.c netfilter: cleanup printk messages 2010-05-13 15:02:08 +02:00
x_tables.c netfilter: xtables: stackptr should be percpu 2010-05-31 16:41:35 +02:00
xt_CLASSIFY.c netfilter: xtables: substitute temporary defines by final name 2010-05-11 18:31:17 +02:00
xt_cluster.c netfilter: xtables: deconstify struct xt_action_param for matches 2010-05-11 18:33:37 +02:00
xt_comment.c netfilter: xtables: deconstify struct xt_action_param for matches 2010-05-11 18:33:37 +02:00
xt_connbytes.c netfilter: xtables: deconstify struct xt_action_param for matches 2010-05-11 18:33:37 +02:00
xt_connlimit.c netfilter: xtables: change hotdrop pointer to direct modification 2010-05-11 18:35:27 +02:00
xt_connmark.c netfilter: xtables: deconstify struct xt_action_param for matches 2010-05-11 18:33:37 +02:00
xt_CONNSECMARK.c netfilter: xtables: substitute temporary defines by final name 2010-05-11 18:31:17 +02:00
xt_conntrack.c netfilter: xtables: deconstify struct xt_action_param for matches 2010-05-11 18:33:37 +02:00
xt_CT.c netfilter: xtables: substitute temporary defines by final name 2010-05-11 18:31:17 +02:00
xt_dccp.c netfilter: xtables: change hotdrop pointer to direct modification 2010-05-11 18:35:27 +02:00
xt_dscp.c netfilter: xtables: deconstify struct xt_action_param for matches 2010-05-11 18:33:37 +02:00
xt_DSCP.c netfilter: xtables: substitute temporary defines by final name 2010-05-11 18:31:17 +02:00
xt_esp.c netfilter: xtables: change hotdrop pointer to direct modification 2010-05-11 18:35:27 +02:00
xt_hashlimit.c netfilter: xtables: change hotdrop pointer to direct modification 2010-05-11 18:35:27 +02:00
xt_helper.c netfilter: xtables: deconstify struct xt_action_param for matches 2010-05-11 18:33:37 +02:00
xt_hl.c netfilter: xtables: deconstify struct xt_action_param for matches 2010-05-11 18:33:37 +02:00
xt_HL.c netfilter: xtables: substitute temporary defines by final name 2010-05-11 18:31:17 +02:00
xt_iprange.c netfilter: xtables: deconstify struct xt_action_param for matches 2010-05-11 18:33:37 +02:00
xt_LED.c netfilter: xtables: substitute temporary defines by final name 2010-05-11 18:31:17 +02:00
xt_length.c netfilter: xtables: deconstify struct xt_action_param for matches 2010-05-11 18:33:37 +02:00
xt_limit.c netfilter: xtables: deconstify struct xt_action_param for matches 2010-05-11 18:33:37 +02:00
xt_mac.c netfilter: xtables: deconstify struct xt_action_param for matches 2010-05-11 18:33:37 +02:00
xt_mark.c netfilter: xtables: deconstify struct xt_action_param for matches 2010-05-11 18:33:37 +02:00
xt_multiport.c netfilter: xtables: change hotdrop pointer to direct modification 2010-05-11 18:35:27 +02:00
xt_NFLOG.c netfilter: xtables: substitute temporary defines by final name 2010-05-11 18:31:17 +02:00
xt_NFQUEUE.c netfilter: xtables: substitute temporary defines by final name 2010-05-11 18:31:17 +02:00
xt_NOTRACK.c netfilter: xtables: substitute temporary defines by final name 2010-05-11 18:31:17 +02:00
xt_osf.c netfilter: xtables: deconstify struct xt_action_param for matches 2010-05-11 18:33:37 +02:00
xt_owner.c netfilter: xtables: deconstify struct xt_action_param for matches 2010-05-11 18:33:37 +02:00
xt_physdev.c netfilter: xtables: deconstify struct xt_action_param for matches 2010-05-11 18:33:37 +02:00
xt_pkttype.c netfilter: xtables: deconstify struct xt_action_param for matches 2010-05-11 18:33:37 +02:00
xt_policy.c netfilter: xtables: deconstify struct xt_action_param for matches 2010-05-11 18:33:37 +02:00
xt_quota.c netfilter: xtables: deconstify struct xt_action_param for matches 2010-05-11 18:33:37 +02:00
xt_rateest.c netfilter: xtables: deconstify struct xt_action_param for matches 2010-05-11 18:33:37 +02:00
xt_RATEEST.c netfilter: xtables: substitute temporary defines by final name 2010-05-11 18:31:17 +02:00
xt_realm.c netfilter: xtables: deconstify struct xt_action_param for matches 2010-05-11 18:33:37 +02:00
xt_recent.c netfilter: xtables: change hotdrop pointer to direct modification 2010-05-11 18:35:27 +02:00
xt_repldata.h
xt_sctp.c netfilter: xtables: change hotdrop pointer to direct modification 2010-05-11 18:35:27 +02:00
xt_SECMARK.c netfilter: xtables: substitute temporary defines by final name 2010-05-11 18:31:17 +02:00
xt_socket.c netfilter: xtables: deconstify struct xt_action_param for matches 2010-05-11 18:33:37 +02:00
xt_state.c netfilter: xtables: deconstify struct xt_action_param for matches 2010-05-11 18:33:37 +02:00
xt_statistic.c netfilter: xtables: deconstify struct xt_action_param for matches 2010-05-11 18:33:37 +02:00
xt_string.c netfilter: xtables: deconstify struct xt_action_param for matches 2010-05-11 18:33:37 +02:00
xt_tcpmss.c netfilter: xtables: change hotdrop pointer to direct modification 2010-05-11 18:35:27 +02:00
xt_TCPMSS.c netfilter: xtables: substitute temporary defines by final name 2010-05-11 18:31:17 +02:00
xt_TCPOPTSTRIP.c netfilter: xtables: substitute temporary defines by final name 2010-05-11 18:31:17 +02:00
xt_tcpudp.c netfilter: xtables: change hotdrop pointer to direct modification 2010-05-11 18:35:27 +02:00
xt_TEE.c xt_tee: use skb_dst_drop() 2010-05-28 03:41:17 -07:00
xt_time.c netfilter: remove unnecessary returns from void function()s 2010-05-13 15:16:27 +02:00
xt_TPROXY.c netfilter: xtables: substitute temporary defines by final name 2010-05-11 18:31:17 +02:00
xt_TRACE.c netfilter: xtables: substitute temporary defines by final name 2010-05-11 18:31:17 +02:00
xt_u32.c netfilter: xtables: deconstify struct xt_action_param for matches 2010-05-11 18:33:37 +02:00