diff --git a/net/netfilter/nf_conntrack_bpf.c b/net/netfilter/nf_conntrack_bpf.c index d2492d050fe601fbb1ce8e3cb598603914712a83..f28b66d2dfc35d2d94616b36457142bad5b53424 100644 --- a/net/netfilter/nf_conntrack_bpf.c +++ b/net/netfilter/nf_conntrack_bpf.c @@ -37,7 +37,7 @@ * -ENONET - No network namespace found for netns_id * -ENOENT - Conntrack lookup could not find entry for tuple * -EAFNOSUPPORT - tuple__sz isn't one of sizeof(tuple->ipv4) - * or sizeof(tuple->ipv6) + * or sizeof(tuple->ipv6) * @l4proto - Layer 4 protocol * Values: * IPPROTO_TCP, IPPROTO_UDP @@ -100,32 +100,38 @@ static int bpf_nf_ct_tuple_parse(struct bpf_sock_tuple *bpf_tuple, static struct nf_conn * __bpf_nf_ct_alloc_entry(struct net *net, struct bpf_sock_tuple *bpf_tuple, - u32 tuple_len, struct bpf_ct_opts *opts, u32 opts_len, - u32 timeout) + u32 tuple_len, struct bpf_ct_opts *opts, u32 opts_len, + u32 timeout) { struct nf_conntrack_tuple otuple, rtuple; struct nf_conn *ct; + s32 netns_id; + u8 l4proto; int err; - if (!opts || !bpf_tuple || opts->reserved[0] || opts->reserved[1] || + if (!opts || !bpf_tuple || READ_ONCE(opts->reserved[0]) || + READ_ONCE(opts->reserved[1]) || opts_len != NF_BPF_CT_OPTS_SZ) return ERR_PTR(-EINVAL); - if (unlikely(opts->netns_id < BPF_F_CURRENT_NETNS)) + netns_id = READ_ONCE(opts->netns_id); + l4proto = READ_ONCE(opts->l4proto); + + if (unlikely(netns_id < BPF_F_CURRENT_NETNS)) return ERR_PTR(-EINVAL); - err = bpf_nf_ct_tuple_parse(bpf_tuple, tuple_len, opts->l4proto, + err = bpf_nf_ct_tuple_parse(bpf_tuple, tuple_len, l4proto, IP_CT_DIR_ORIGINAL, &otuple); if (err < 0) return ERR_PTR(err); - err = bpf_nf_ct_tuple_parse(bpf_tuple, tuple_len, opts->l4proto, + err = bpf_nf_ct_tuple_parse(bpf_tuple, tuple_len, l4proto, IP_CT_DIR_REPLY, &rtuple); if (err < 0) return ERR_PTR(err); - if (opts->netns_id >= 0) { - net = get_net_ns_by_id(net, opts->netns_id); + if (netns_id >= 0) { + net = get_net_ns_by_id(net, netns_id); if (unlikely(!net)) return ERR_PTR(-ENONET); } @@ -139,7 +145,7 @@ __bpf_nf_ct_alloc_entry(struct net *net, struct bpf_sock_tuple *bpf_tuple, __nf_ct_set_timeout(ct, timeout * HZ); out: - if (opts->netns_id >= 0) + if (netns_id >= 0) put_net(net); return ct; @@ -153,29 +159,36 @@ static struct nf_conn *__bpf_nf_ct_lookup(struct net *net, struct nf_conntrack_tuple_hash *hash; struct nf_conntrack_tuple tuple; struct nf_conn *ct; + s32 netns_id; + u8 l4proto; int err; - if (!opts || !bpf_tuple || opts->reserved[0] || opts->reserved[1] || + if (!opts || !bpf_tuple || READ_ONCE(opts->reserved[0]) || + READ_ONCE(opts->reserved[1]) || opts_len != NF_BPF_CT_OPTS_SZ) return ERR_PTR(-EINVAL); - if (unlikely(opts->l4proto != IPPROTO_TCP && opts->l4proto != IPPROTO_UDP)) + + netns_id = READ_ONCE(opts->netns_id); + l4proto = READ_ONCE(opts->l4proto); + + if (unlikely(l4proto != IPPROTO_TCP && l4proto != IPPROTO_UDP)) return ERR_PTR(-EPROTO); - if (unlikely(opts->netns_id < BPF_F_CURRENT_NETNS)) + if (unlikely(netns_id < BPF_F_CURRENT_NETNS)) return ERR_PTR(-EINVAL); - err = bpf_nf_ct_tuple_parse(bpf_tuple, tuple_len, opts->l4proto, + err = bpf_nf_ct_tuple_parse(bpf_tuple, tuple_len, l4proto, IP_CT_DIR_ORIGINAL, &tuple); if (err < 0) return ERR_PTR(err); - if (opts->netns_id >= 0) { - net = get_net_ns_by_id(net, opts->netns_id); + if (netns_id >= 0) { + net = get_net_ns_by_id(net, netns_id); if (unlikely(!net)) return ERR_PTR(-ENONET); } hash = nf_conntrack_find_get(net, &nf_ct_zone_dflt, &tuple); - if (opts->netns_id >= 0) + if (netns_id >= 0) put_net(net); if (!hash) return ERR_PTR(-ENOENT); @@ -236,7 +249,7 @@ __bpf_kfunc_start_defs(); * * Parameters: * @xdp_ctx - Pointer to ctx (xdp_md) in XDP program - * Cannot be NULL + * - Cannot be NULL * @bpf_tuple - Pointer to memory representing the tuple to look up * Cannot be NULL * @tuple__sz - Length of the tuple structure