linux/net
Patrick McHardy b0cdb1d9a9 netfilter: nf_nat: fix oops when unloading protocol modules
When unloading a protocol module nf_ct_iterate_cleanup() is used to
remove all conntracks using the protocol from the bysource hash and
clean their NAT sections. Since the conntrack isn't actually killed,
the NAT callback is invoked twice, once for each direction, which
causes an oops when trying to delete it from the bysource hash for
the second time.

The same oops can also happen when removing both an L3 and L4 protocol
since the cleanup function doesn't check whether the conntrack has
already been cleaned up.

Pid: 4052, comm: modprobe Not tainted 3.6.0-rc3-test-nat-unload-fix+ #32 Red Hat KVM
RIP: 0010:[<ffffffffa002c303>]  [<ffffffffa002c303>] nf_nat_proto_clean+0x73/0xd0 [nf_nat]
RSP: 0018:ffff88007808fe18  EFLAGS: 00010246
RAX: 0000000000000000 RBX: ffff8800728550c0 RCX: ffff8800756288b0
RDX: dead000000200200 RSI: ffff88007808fe88 RDI: ffffffffa002f208
RBP: ffff88007808fe28 R08: ffff88007808e000 R09: 0000000000000000
R10: dead000000200200 R11: dead000000100100 R12: ffffffff81c6dc00
R13: ffff8800787582b8 R14: ffff880078758278 R15: ffff88007808fe88
FS:  00007f515985d700(0000) GS:ffff88007cd00000(0000) knlGS:0000000000000000
CS:  0010 DS: 0000 ES: 0000 CR0: 000000008005003b
CR2: 00007f515986a000 CR3: 000000007867a000 CR4: 00000000000006e0
DR0: 0000000000000000 DR1: 0000000000000000 DR2: 0000000000000000
DR3: 0000000000000000 DR6: 00000000ffff0ff0 DR7: 0000000000000400
Process modprobe (pid: 4052, threadinfo ffff88007808e000, task ffff8800756288b0)
Stack:
 ffff88007808fe68 ffffffffa002c290 ffff88007808fe78 ffffffff815614e3
 ffffffff00000000 00000aeb00000246 ffff88007808fe68 ffffffff81c6dc00
 ffff88007808fe88 ffffffffa00358a0 0000000000000000 000000000040f5b0
Call Trace:
 [<ffffffffa002c290>] ? nf_nat_net_exit+0x50/0x50 [nf_nat]
 [<ffffffff815614e3>] nf_ct_iterate_cleanup+0xc3/0x170
 [<ffffffffa002c55a>] nf_nat_l3proto_unregister+0x8a/0x100 [nf_nat]
 [<ffffffff812a0303>] ? compat_prepare_timeout+0x13/0xb0
 [<ffffffffa0035848>] nf_nat_l3proto_ipv4_exit+0x10/0x23 [nf_nat_ipv4]
 ...

To fix this,

- check whether the conntrack has already been cleaned up in
  nf_nat_proto_clean

- change nf_ct_iterate_cleanup() to only invoke the callback function
  once for each conntrack (IP_CT_DIR_ORIGINAL).

The second change doesn't affect other callers since when conntracks are
actually killed, both directions are removed from the hash immediately
and the callback is already only invoked once. If it is not killed, the
second callback invocation will always return the same decision not to
kill it.

Reported-by: Jesper Dangaard Brouer <brouer@redhat.com>
Signed-off-by: Patrick McHardy <kaber@trash.net>
Acked-by: Jesper Dangaard Brouer <brouer@redhat.com>
Signed-off-by: Pablo Neira Ayuso <pablo@netfilter.org>
2012-09-21 11:35:18 +02:00
..
9p net: Fix (nearly-)kernel-doc comments for various functions 2012-07-10 23:13:45 -07:00
802 tokenring: delete all remaining driver support 2012-05-15 20:23:16 -04:00
8021q vlan: add helper which can be called to see if device is used by vlan 2012-08-24 13:46:39 -04:00
appletalk userns: Print out socket uids in a user namespace aware fashion. 2012-08-14 21:48:06 -07:00
atm net🏧fix up ENOIOCTLCMD error handling 2012-08-31 16:14:33 -04:00
ax25 userns: Convert net/ax25 to use kuid_t where appropriate 2012-08-14 21:49:42 -07:00
batman-adv batman-adv: Start new development cycle 2012-08-23 14:20:23 +02:00
bluetooth Merge git://git.kernel.org/pub/scm/linux/kernel/git/davem/net 2012-09-15 11:43:53 -04:00
bridge netdev: make address const in device address management 2012-09-19 16:35:22 -04:00
caif caif: move the dereference below the NULL test 2012-09-10 16:13:31 -04:00
can netlink: Rename pid to portid to avoid confusion 2012-09-10 15:30:41 -04:00
ceph libceph: avoid truncation due to racing banners 2012-08-21 15:55:27 -07:00
core netpoll: call ->ndo_select_queue() in tx path 2012-09-19 17:19:09 -04:00
dcb netlink: Rename pid to portid to avoid confusion 2012-09-10 15:30:41 -04:00
dccp dccp: fix info leak via getsockopt(DCCP_SOCKOPT_CCID_TX_INFO) 2012-08-15 21:36:31 -07:00
decnet netlink: Rename pid to portid to avoid confusion 2012-09-10 15:30:41 -04:00
dns_resolver Merge branch 'next' of git://git.kernel.org/pub/scm/linux/kernel/git/jmorris/linux-security 2012-05-21 20:27:36 -07:00
dsa dsa: Convert compare_ether_addr to ether_addr_equal 2012-05-09 20:49:19 -04:00
ethernet ipx: move peII functions 2012-07-19 10:48:00 -07:00
ieee802154 net/ieee802154/6lowpan.c: Remove unecessary semicolon 2012-09-18 16:08:19 -04:00
ipv4 tcp: Document use of undefined variable. 2012-09-20 17:29:36 -04:00
ipv6 netfilter: fix IPv6 NAT dependencies in Kconfig 2012-09-21 11:33:19 +02:00
ipx userns: Print out socket uids in a user namespace aware fashion. 2012-08-14 21:48:06 -07:00
irda netlink: Rename pid to portid to avoid confusion 2012-09-10 15:30:41 -04:00
iucv net: remove skb_orphan_try() 2012-06-15 15:30:15 -07:00
key netlink: Rename pid to portid to avoid confusion 2012-09-10 15:30:41 -04:00
l2tp Merge git://git.kernel.org/pub/scm/linux/kernel/git/davem/net 2012-09-15 11:43:53 -04:00
lapb lapb: Neaten debugging 2012-05-17 18:45:20 -04:00
llc llc: Remove stray reference to sysctl_llc_station_ack_timeout. 2012-09-17 13:13:24 -04:00
mac80211 Merge git://git.kernel.org/pub/scm/linux/kernel/git/davem/net 2012-09-15 11:43:53 -04:00
mac802154 mac802154: sparse warnings: make symbols static 2012-07-12 07:54:45 -07:00
netfilter netfilter: nf_nat: fix oops when unloading protocol modules 2012-09-21 11:35:18 +02:00
netlabel netlink: Rename pid to portid to avoid confusion 2012-09-10 15:30:41 -04:00
netlink netlink: Rename pid to portid to avoid confusion 2012-09-10 15:30:41 -04:00
netrom netrom: copy_datagram_iovec can fail 2012-09-04 12:57:35 -04:00
nfc netlink: Rename pid to portid to avoid confusion 2012-09-10 15:30:41 -04:00
openvswitch net/openvswitch/vport.c: Remove unecessary semicolon 2012-09-18 16:08:19 -04:00
packet netlink: Rename pid to portid to avoid confusion 2012-09-10 15:30:41 -04:00
phonet netlink: Rename pid to portid to avoid confusion 2012-09-10 15:30:41 -04:00
rds rds: Don't disable BH on BH context 2012-08-22 22:52:04 -07:00
rfkill Revert "rfkill: remove dead code" 2012-08-21 20:50:25 +02:00
rose net: Convert all sysctl registrations to register_net_sysctl 2012-04-20 21:22:30 -04:00
rxrpc Merge git://git.kernel.org/pub/scm/linux/kernel/git/davem/net 2012-07-10 23:56:33 -07:00
sched Merge git://git.kernel.org/pub/scm/linux/kernel/git/davem/net 2012-09-15 11:43:53 -04:00
sctp Merge git://git.kernel.org/pub/scm/linux/kernel/git/davem/net 2012-09-15 11:43:53 -04:00
sunrpc NFS client bugfixes for Linux 3.6 2012-09-13 09:04:13 +08:00
tipc net/tipc/name_table.c: Remove unecessary semicolon 2012-09-18 16:08:19 -04:00
unix af_unix: old_cred is surplus 2012-09-17 13:00:13 -04:00
wanrouter wanmain: comparing array with NULL 2012-07-24 13:55:21 -07:00
wimax net: cleanup unsigned to unsigned int 2012-04-15 12:44:40 -04:00
wireless Merge git://git.kernel.org/pub/scm/linux/kernel/git/davem/net 2012-09-15 11:43:53 -04:00
x25 net: Fix (nearly-)kernel-doc comments for various functions 2012-07-10 23:13:45 -07:00
xfrm Merge git://git.kernel.org/pub/scm/linux/kernel/git/davem/net 2012-09-15 11:43:53 -04:00
compat.c net: Fix references to out-of-scope variables in put_cmsg_compat() 2012-07-22 17:50:49 -07:00
Kconfig net: Add INET dependency on aes crypto for the sake of TCP fastopen. 2012-09-04 14:20:14 -04:00
Makefile econet: remove ancient bug ridden protocol 2012-05-18 01:35:08 -04:00
nonet.c
socket.c Merge git://git.kernel.org/pub/scm/linux/kernel/git/davem/net 2012-09-15 11:43:53 -04:00
sysctl_net.c net: delete all instances of special processing for token ring 2012-05-15 20:14:35 -04:00