1 // SPDX-License-Identifier: GPL-2.0
3 #include <linux/filter.h>
4 #include <linux/netfilter.h>
6 #include <net/netfilter/nf_bpf_link.h>
7 #include <uapi/linux/netfilter_ipv4.h>
9 static unsigned int nf_hook_run_bpf(void *bpf_prog
, struct sk_buff
*skb
,
10 const struct nf_hook_state
*s
)
12 const struct bpf_prog
*prog
= bpf_prog
;
13 struct bpf_nf_ctx ctx
= {
18 return bpf_prog_run(prog
, &ctx
);
23 struct nf_hook_ops hook_ops
;
28 static void bpf_nf_link_release(struct bpf_link
*link
)
30 struct bpf_nf_link
*nf_link
= container_of(link
, struct bpf_nf_link
, link
);
35 /* prevent hook-not-found warning splat from netfilter core when
36 * .detach was already called
38 if (!cmpxchg(&nf_link
->dead
, 0, 1))
39 nf_unregister_net_hook(nf_link
->net
, &nf_link
->hook_ops
);
42 static void bpf_nf_link_dealloc(struct bpf_link
*link
)
44 struct bpf_nf_link
*nf_link
= container_of(link
, struct bpf_nf_link
, link
);
49 static int bpf_nf_link_detach(struct bpf_link
*link
)
51 bpf_nf_link_release(link
);
55 static void bpf_nf_link_show_info(const struct bpf_link
*link
,
58 struct bpf_nf_link
*nf_link
= container_of(link
, struct bpf_nf_link
, link
);
60 seq_printf(seq
, "pf:\t%u\thooknum:\t%u\tprio:\t%d\n",
61 nf_link
->hook_ops
.pf
, nf_link
->hook_ops
.hooknum
,
62 nf_link
->hook_ops
.priority
);
65 static int bpf_nf_link_fill_link_info(const struct bpf_link
*link
,
66 struct bpf_link_info
*info
)
68 struct bpf_nf_link
*nf_link
= container_of(link
, struct bpf_nf_link
, link
);
70 info
->netfilter
.pf
= nf_link
->hook_ops
.pf
;
71 info
->netfilter
.hooknum
= nf_link
->hook_ops
.hooknum
;
72 info
->netfilter
.priority
= nf_link
->hook_ops
.priority
;
73 info
->netfilter
.flags
= 0;
78 static int bpf_nf_link_update(struct bpf_link
*link
, struct bpf_prog
*new_prog
,
79 struct bpf_prog
*old_prog
)
84 static const struct bpf_link_ops bpf_nf_link_lops
= {
85 .release
= bpf_nf_link_release
,
86 .dealloc
= bpf_nf_link_dealloc
,
87 .detach
= bpf_nf_link_detach
,
88 .show_fdinfo
= bpf_nf_link_show_info
,
89 .fill_link_info
= bpf_nf_link_fill_link_info
,
90 .update_prog
= bpf_nf_link_update
,
93 static int bpf_nf_check_pf_and_hooks(const union bpf_attr
*attr
)
95 switch (attr
->link_create
.netfilter
.pf
) {
98 if (attr
->link_create
.netfilter
.hooknum
>= NF_INET_NUMHOOKS
)
102 return -EAFNOSUPPORT
;
105 if (attr
->link_create
.netfilter
.flags
)
108 /* make sure conntrack confirm is always last.
110 * In the future, if userspace can e.g. request defrag, then
111 * "defrag_requested && prio before NF_IP_PRI_CONNTRACK_DEFRAG"
114 switch (attr
->link_create
.netfilter
.priority
) {
115 case NF_IP_PRI_FIRST
: return -ERANGE
; /* sabotage_in and other warts */
116 case NF_IP_PRI_LAST
: return -ERANGE
; /* e.g. conntrack confirm */
122 int bpf_nf_link_attach(const union bpf_attr
*attr
, struct bpf_prog
*prog
)
124 struct net
*net
= current
->nsproxy
->net_ns
;
125 struct bpf_link_primer link_primer
;
126 struct bpf_nf_link
*link
;
129 if (attr
->link_create
.flags
)
132 err
= bpf_nf_check_pf_and_hooks(attr
);
136 link
= kzalloc(sizeof(*link
), GFP_USER
);
140 bpf_link_init(&link
->link
, BPF_LINK_TYPE_NETFILTER
, &bpf_nf_link_lops
, prog
);
142 link
->hook_ops
.hook
= nf_hook_run_bpf
;
143 link
->hook_ops
.hook_ops_type
= NF_HOOK_OP_BPF
;
144 link
->hook_ops
.priv
= prog
;
146 link
->hook_ops
.pf
= attr
->link_create
.netfilter
.pf
;
147 link
->hook_ops
.priority
= attr
->link_create
.netfilter
.priority
;
148 link
->hook_ops
.hooknum
= attr
->link_create
.netfilter
.hooknum
;
153 err
= bpf_link_prime(&link
->link
, &link_primer
);
159 err
= nf_register_net_hook(net
, &link
->hook_ops
);
161 bpf_link_cleanup(&link_primer
);
165 return bpf_link_settle(&link_primer
);
168 const struct bpf_prog_ops netfilter_prog_ops
= {
169 .test_run
= bpf_prog_test_run_nf
,
172 static bool nf_ptr_to_btf_id(struct bpf_insn_access_aux
*info
, const char *name
)
177 btf
= bpf_get_btf_vmlinux();
178 if (IS_ERR_OR_NULL(btf
))
181 type_id
= btf_find_by_name_kind(btf
, name
, BTF_KIND_STRUCT
);
182 if (WARN_ON_ONCE(type_id
< 0))
186 info
->btf_id
= type_id
;
187 info
->reg_type
= PTR_TO_BTF_ID
| PTR_TRUSTED
;
191 static bool nf_is_valid_access(int off
, int size
, enum bpf_access_type type
,
192 const struct bpf_prog
*prog
,
193 struct bpf_insn_access_aux
*info
)
195 if (off
< 0 || off
>= sizeof(struct bpf_nf_ctx
))
198 if (type
== BPF_WRITE
)
202 case bpf_ctx_range(struct bpf_nf_ctx
, skb
):
203 if (size
!= sizeof_field(struct bpf_nf_ctx
, skb
))
206 return nf_ptr_to_btf_id(info
, "sk_buff");
207 case bpf_ctx_range(struct bpf_nf_ctx
, state
):
208 if (size
!= sizeof_field(struct bpf_nf_ctx
, state
))
211 return nf_ptr_to_btf_id(info
, "nf_hook_state");
219 static const struct bpf_func_proto
*
220 bpf_nf_func_proto(enum bpf_func_id func_id
, const struct bpf_prog
*prog
)
222 return bpf_base_func_proto(func_id
);
225 const struct bpf_verifier_ops netfilter_verifier_ops
= {
226 .is_valid_access
= nf_is_valid_access
,
227 .get_func_proto
= bpf_nf_func_proto
,