summaryrefslogtreecommitdiff
path: root/include/linux
diff options
context:
space:
mode:
authorFlorian Westphal <fw@strlen.de>2026-05-14 14:21:57 +0200
committerFlorian Westphal <fw@strlen.de>2026-05-22 12:28:46 +0200
commit47980b6dbf83961eec1c1363ea986e9c06ff8054 (patch)
tree68590d574ebf8f7f078580998bbf04fb62f37d01 /include/linux
parent92170e6afe927ab2792a3f71902845789c8e31b1 (diff)
netfilter: nf_conntrack_gre: fix gre keymap list corruption
Quoting reporter: A race between GRE keymap insertion and destruction can corrupt the kernel list or use a freed object. `nf_ct_gre_keymap_add()` publishes a new keymap pointer before the embedded `list_head` is linked, while `nf_ct_gre_keymap_destroy()` can concurrently delete and free that same object. An unprivileged user can reach this through the PPTP conntrack helper by racing PPTP control messages or helper teardown, leading to KASAN-detectable list corruption/UAF in kernel context. ## Root Cause Analysis `exp_gre()` installs GRE expectations for a PPTP control flow and then adds two GRE keymap entries [..] The add path publishes `ct_pptp_info->keymap[dir]` before linking the embedded list node [..] Concurrent teardown deletes that partially initialized object. Make add/destroy symmetric: install both, destroy both while under lock. Furthermore, we should refuse to publish a new mapping in case ct is going away, else we may leak the allocation. The "retrans" detection is strange: existing mapping is checked for key equality with the new mapping, then for "is on the list" via list walk. But I can't see how an existing keymap entry can be NOT on list. Change this to only check if we're asked to map same tuple again -- if so, skip re-install, else signal failure. Last, add a bug trap for the keymap list; it has to be empty when namespace is going away. Reported-by: Leo Lin <leo@depthfirst.com> Signed-off-by: Florian Westphal <fw@strlen.de>
Diffstat (limited to 'include/linux')
-rw-r--r--include/linux/netfilter/nf_conntrack_proto_gre.h7
1 files changed, 4 insertions, 3 deletions
diff --git a/include/linux/netfilter/nf_conntrack_proto_gre.h b/include/linux/netfilter/nf_conntrack_proto_gre.h
index 9ee7014400e8..ad5563f0f864 100644
--- a/include/linux/netfilter/nf_conntrack_proto_gre.h
+++ b/include/linux/netfilter/nf_conntrack_proto_gre.h
@@ -18,9 +18,10 @@ struct nf_ct_gre_keymap {
struct rcu_head rcu;
};
-/* add new tuple->key_reply pair to keymap */
-int nf_ct_gre_keymap_add(struct nf_conn *ct, enum ip_conntrack_dir dir,
- struct nf_conntrack_tuple *t);
+/* add tuple->key_reply pairs to keymap */
+bool nf_ct_gre_keymap_add(struct nf_conn *ct,
+ const struct nf_conntrack_tuple *orig,
+ const struct nf_conntrack_tuple *repl);
/* delete keymap entries */
void nf_ct_gre_keymap_destroy(struct nf_conn *ct);