]> git.ipfire.org Git - thirdparty/linux.git/commitdiff
bpf: Guard conntrack opts error writes
authorYiyang Chen <chenyy23@mails.tsinghua.edu.cn>
Thu, 18 Jun 2026 10:18:43 +0000 (10:18 +0000)
committerAlexei Starovoitov <ast@kernel.org>
Mon, 22 Jun 2026 23:04:34 +0000 (16:04 -0700)
The conntrack lookup and allocation kfuncs take an opts pointer
together with an opts__sz argument. The verifier checks only the memory
range described by opts__sz, but the wrappers unconditionally write
opts->error whenever the internal lookup or allocation helper returns an
error.

For an invalid size smaller than the end of opts->error, that write can
land outside the verifier-checked range. Keep returning NULL for invalid
arguments, but only report the error through opts->error when the
supplied size includes the field.

This preserves error reporting for the supported 12-byte and 16-byte
layouts, and for other invalid sizes that still include opts->error.

Fixes: b4c2b9593a1c ("net/netfilter: Add unstable CT lookup helpers for XDP and TC-BPF")
Fixes: d7e79c97c00c ("net: netfilter: Add kfuncs to allocate and insert CT")
Signed-off-by: Yiyang Chen <chenyy23@mails.tsinghua.edu.cn>
Link: https://lore.kernel.org/r/9535e781fe14449b1d4e9bbc3baa7566a93bf512.1781765747.git.chenyy23@mails.tsinghua.edu.cn
Signed-off-by: Alexei Starovoitov <ast@kernel.org>
net/netfilter/nf_conntrack_bpf.c

index 40c261cd0af3809a714ba96fb35ab51b6c215726..f98d1d4b42c3d6bf6b6e4c39086ab6ac1896b449 100644 (file)
@@ -65,6 +65,15 @@ enum {
        NF_BPF_CT_OPTS_SZ = 16,
 };
 
+static void *bpf_ct_opts_result(struct bpf_ct_opts *opts, u32 opts__sz, void *ret)
+{
+       if (!IS_ERR(ret))
+               return ret;
+       if (opts__sz >= offsetofend(struct bpf_ct_opts, error))
+               opts->error = PTR_ERR(ret);
+       return NULL;
+}
+
 static int bpf_nf_ct_tuple_parse(struct bpf_sock_tuple *bpf_tuple,
                                 u32 tuple_len, u8 protonum, u8 dir,
                                 struct nf_conntrack_tuple *tuple)
@@ -297,12 +306,7 @@ bpf_xdp_ct_alloc(struct xdp_md *xdp_ctx, struct bpf_sock_tuple *bpf_tuple,
 
        nfct = __bpf_nf_ct_alloc_entry(dev_net(ctx->rxq->dev), bpf_tuple, tuple__sz,
                                       opts, opts__sz, 10);
-       if (IS_ERR(nfct)) {
-               opts->error = PTR_ERR(nfct);
-               return NULL;
-       }
-
-       return (struct nf_conn___init *)nfct;
+       return (struct nf_conn___init *)bpf_ct_opts_result(opts, opts__sz, nfct);
 }
 
 /* bpf_xdp_ct_lookup - Lookup CT entry for the given tuple, and acquire a
@@ -331,11 +335,7 @@ bpf_xdp_ct_lookup(struct xdp_md *xdp_ctx, struct bpf_sock_tuple *bpf_tuple,
 
        caller_net = dev_net(ctx->rxq->dev);
        nfct = __bpf_nf_ct_lookup(caller_net, bpf_tuple, tuple__sz, opts, opts__sz);
-       if (IS_ERR(nfct)) {
-               opts->error = PTR_ERR(nfct);
-               return NULL;
-       }
-       return nfct;
+       return bpf_ct_opts_result(opts, opts__sz, nfct);
 }
 
 /* bpf_skb_ct_alloc - Allocate a new CT entry
@@ -363,12 +363,7 @@ bpf_skb_ct_alloc(struct __sk_buff *skb_ctx, struct bpf_sock_tuple *bpf_tuple,
 
        net = skb->dev ? dev_net(skb->dev) : sock_net(skb->sk);
        nfct = __bpf_nf_ct_alloc_entry(net, bpf_tuple, tuple__sz, opts, opts__sz, 10);
-       if (IS_ERR(nfct)) {
-               opts->error = PTR_ERR(nfct);
-               return NULL;
-       }
-
-       return (struct nf_conn___init *)nfct;
+       return (struct nf_conn___init *)bpf_ct_opts_result(opts, opts__sz, nfct);
 }
 
 /* bpf_skb_ct_lookup - Lookup CT entry for the given tuple, and acquire a
@@ -397,11 +392,7 @@ bpf_skb_ct_lookup(struct __sk_buff *skb_ctx, struct bpf_sock_tuple *bpf_tuple,
 
        caller_net = skb->dev ? dev_net(skb->dev) : sock_net(skb->sk);
        nfct = __bpf_nf_ct_lookup(caller_net, bpf_tuple, tuple__sz, opts, opts__sz);
-       if (IS_ERR(nfct)) {
-               opts->error = PTR_ERR(nfct);
-               return NULL;
-       }
-       return nfct;
+       return bpf_ct_opts_result(opts, opts__sz, nfct);
 }
 
 /* bpf_ct_insert_entry - Add the provided entry into a CT map