netfilter: ctnetlink: force null nat binding on insert
authorPablo Neira Ayuso <pablo@netfilter.org>
Sun, 16 Feb 2014 11:15:43 +0000 (12:15 +0100)
committerPablo Neira Ayuso <pablo@netfilter.org>
Mon, 17 Feb 2014 23:13:51 +0000 (00:13 +0100)
commit0eba801b64cc8284d9024c7ece30415a2b981a72
treea2d1b4f667231451a801b8099d54bc322b8f3ce7
parentf627ed91d85ed7a189ec8b3b045a0d831e1655e2
netfilter: ctnetlink: force null nat binding on insert

Quoting Andrey Vagin:
  When a conntrack is created  by kernel, it is initialized (sets
  IPS_{DST,SRC}_NAT_DONE_BIT bits in nf_nat_setup_info) and only then it
  is added in hashes (__nf_conntrack_hash_insert), so one conntract
  can't be initialized from a few threads concurrently.

  ctnetlink can add an uninitialized conntrack (w/o
  IPS_{DST,SRC}_NAT_DONE_BIT) in hashes, then a few threads can look up
  this conntrack and start initialize it concurrently. It's dangerous,
  because BUG can be triggered from nf_nat_setup_info.

Fix this race by always setting up nat, even if no CTA_NAT_ attribute
was requested before inserting the ct into the hash table. In absence
of CTA_NAT_ attribute, a null binding is created.

This alters current behaviour: Before this patch, the first packet
matching the newly injected conntrack would be run through the nat
table since nf_nat_initialized() returns false.  IOW, this forces
ctnetlink users to specify the desired nat transformation on ct
creation time.

Thanks for Florian Westphal, this patch is based on his original
patch to address this problem, including this patch description.

Reported-By: Andrey Vagin <avagin@gmail.com>
Signed-off-by: Pablo Neira Ayuso <pablo@netfilter.org>
Acked-by: Florian Westphal <fw@strlen.de>
net/netfilter/nf_conntrack_netlink.c
net/netfilter/nf_nat_core.c