When inserting a rbnode and we find a matching node in the tree, but that node is already dead, we will replace that node in that tree with a new one. This means the newly inserted node should have the same parent of the current node we are about to replace. Before we were incorrectly setting the parent to be the node that was being replaced. If the node being replaced was the first node in the tree then at nf_conncount_destroy() time we would erase the first node with the incorrect parent pointer. Since the parent pointer was incorrect, the root would not get updated to point to the next node and instead would remain pointing to the node we just erased. This would then cause nf_conncount_desrtoy() to attempt to rb_erase the same node a second time and crash with the following. RIP: 0010:rb_erase+0xae/0x360 Code: 4d 89 50 08 4d 85 c9 74 5b 48 83 c8 01 48 89 0a 49 89 01 c3 48 8b 0f 48 89 ca 48 83 e2 fc 48 85 d2 48 89 d0 0f 84 41 02 00 00 <48> 3b 7a 10 0f 84 3f 02 00 00 4c 89 42 08 4d 85 c0 0f 84 1b 02 00 RSP: 0018:ffffb5bec0af7d18 EFLAGS: 00010206 RAX: 6e3319b62019e1d4 RBX: ffff8ebe30766630 RCX: 6e3319b62019e1d5 RDX: 6e3319b62019e1d4 RSI: ffff8ebe38c8e348 RDI: ffff8ebe38dadde0 RBP: ffff8ebe38dade00 R08: 0000000000000000 R09: ffffffffc04ef301 R10: ffff8ebe38dadde0 R11: 0000000000000001 R12: ffff8ebe38dadde0 R13: ffff8ebe38c8e348 R14: ffff8ebe38c8e808 R15: ffff8ebe38c8e000 FS: 00007ff81d373700(0000) GS:ffff8ebe3c440000(0000) knlGS:0000000000000000 CS: 0010 DS: 0000 ES: 0000 CR0: 0000000080050033 CR2: 000055968cc0d008 CR3: 0000000138f52002 CR4: 00000000003606e0 Call Trace: nf_conncount_destroy+0x59/0xc0 [nf_conncount] cleanup_match+0x45/0x70 [ip_tables] ? next_arg+0x92/0x110 cleanup_entry+0x3e/0xc0 [ip_tables] __do_replace+0x1a4/0x240 [ip_tables] do_ipt_set_ctl+0x150/0x1b0 [ip_tables] nf_setsockopt+0x44/0x70 __sys_setsockopt+0x82/0xe0 __x64_sys_setsockopt+0x20/0x30 do_syscall_64+0x48/0xf0 entry_SYSCALL_64_after_hwframe+0x44/0xa9 Fixes: 5c789e131cbb9 ("netfilter: nf_conncount: Add list lock and gc worker, and RCU for init tree search") Signed-off-by: Shawn Bohrer <sbohrer@xxxxxxxxxxxxxx> --- net/netfilter/nf_conncount.c | 1 + 1 file changed, 1 insertion(+) diff --git a/net/netfilter/nf_conncount.c b/net/netfilter/nf_conncount.c index 9cd180bda092..372015e3f18d 100644 --- a/net/netfilter/nf_conncount.c +++ b/net/netfilter/nf_conncount.c @@ -380,6 +380,7 @@ insert_tree(struct net *net, * reclaimed by gc, insert a new tree node */ node_found = false; + parent = rb_parent(*rbnode); } break; } -- 2.20.1