Branch data Line data Source code
1 : : // SPDX-License-Identifier: GPL-2.0-or-later
2 : : /*
3 : : * Linux Socket Filter - Kernel level socket filtering
4 : : *
5 : : * Based on the design of the Berkeley Packet Filter. The new
6 : : * internal format has been designed by PLUMgrid:
7 : : *
8 : : * Copyright (c) 2011 - 2014 PLUMgrid, http://plumgrid.com
9 : : *
10 : : * Authors:
11 : : *
12 : : * Jay Schulist <jschlst@samba.org>
13 : : * Alexei Starovoitov <ast@plumgrid.com>
14 : : * Daniel Borkmann <dborkman@redhat.com>
15 : : *
16 : : * Andi Kleen - Fix a few bad bugs and races.
17 : : * Kris Katterjohn - Added many additional checks in bpf_check_classic()
18 : : */
19 : :
20 : : #include <linux/module.h>
21 : : #include <linux/types.h>
22 : : #include <linux/mm.h>
23 : : #include <linux/fcntl.h>
24 : : #include <linux/socket.h>
25 : : #include <linux/sock_diag.h>
26 : : #include <linux/in.h>
27 : : #include <linux/inet.h>
28 : : #include <linux/netdevice.h>
29 : : #include <linux/if_packet.h>
30 : : #include <linux/if_arp.h>
31 : : #include <linux/gfp.h>
32 : : #include <net/inet_common.h>
33 : : #include <net/ip.h>
34 : : #include <net/protocol.h>
35 : : #include <net/netlink.h>
36 : : #include <linux/skbuff.h>
37 : : #include <linux/skmsg.h>
38 : : #include <net/sock.h>
39 : : #include <net/flow_dissector.h>
40 : : #include <linux/errno.h>
41 : : #include <linux/timer.h>
42 : : #include <linux/uaccess.h>
43 : : #include <asm/unaligned.h>
44 : : #include <asm/cmpxchg.h>
45 : : #include <linux/filter.h>
46 : : #include <linux/ratelimit.h>
47 : : #include <linux/seccomp.h>
48 : : #include <linux/if_vlan.h>
49 : : #include <linux/bpf.h>
50 : : #include <net/sch_generic.h>
51 : : #include <net/cls_cgroup.h>
52 : : #include <net/dst_metadata.h>
53 : : #include <net/dst.h>
54 : : #include <net/sock_reuseport.h>
55 : : #include <net/busy_poll.h>
56 : : #include <net/tcp.h>
57 : : #include <net/xfrm.h>
58 : : #include <net/udp.h>
59 : : #include <linux/bpf_trace.h>
60 : : #include <net/xdp_sock.h>
61 : : #include <linux/inetdevice.h>
62 : : #include <net/inet_hashtables.h>
63 : : #include <net/inet6_hashtables.h>
64 : : #include <net/ip_fib.h>
65 : : #include <net/nexthop.h>
66 : : #include <net/flow.h>
67 : : #include <net/arp.h>
68 : : #include <net/ipv6.h>
69 : : #include <net/net_namespace.h>
70 : : #include <linux/seg6_local.h>
71 : : #include <net/seg6.h>
72 : : #include <net/seg6_local.h>
73 : : #include <net/lwtunnel.h>
74 : : #include <net/ipv6_stubs.h>
75 : : #include <net/bpf_sk_storage.h>
76 : :
77 : : /**
78 : : * sk_filter_trim_cap - run a packet through a socket filter
79 : : * @sk: sock associated with &sk_buff
80 : : * @skb: buffer to filter
81 : : * @cap: limit on how short the eBPF program may trim the packet
82 : : *
83 : : * Run the eBPF program and then cut skb->data to correct size returned by
84 : : * the program. If pkt_len is 0 we toss packet. If skb->len is smaller
85 : : * than pkt_len we keep whole skb->data. This is the socket level
86 : : * wrapper to BPF_PROG_RUN. It returns 0 if the packet should
87 : : * be accepted or -EPERM if the packet should be tossed.
88 : : *
89 : : */
90 : 739442 : int sk_filter_trim_cap(struct sock *sk, struct sk_buff *skb, unsigned int cap)
91 : : {
92 : : int err;
93 : : struct sk_filter *filter;
94 : :
95 : : /*
96 : : * If the skb was allocated from pfmemalloc reserves, only
97 : : * allow SOCK_MEMALLOC sockets to use it as this socket is
98 : : * helping free memory
99 : : */
100 [ - + # # ]: 739442 : if (skb_pfmemalloc(skb) && !sock_flag(sk, SOCK_MEMALLOC)) {
101 : 0 : NET_INC_STATS(sock_net(sk), LINUX_MIB_PFMEMALLOCDROP);
102 : 0 : return -ENOMEM;
103 : : }
104 [ + + ]: 740236 : err = BPF_CGROUP_RUN_PROG_INET_INGRESS(sk, skb);
105 [ + - ]: 739471 : if (err)
106 : : return err;
107 : :
108 : 739471 : err = security_sock_rcv_skb(sk, skb);
109 [ + + ]: 739464 : if (err)
110 : : return err;
111 : :
112 : : rcu_read_lock();
113 : 733353 : filter = rcu_dereference(sk->sk_filter);
114 [ + + ]: 733353 : if (filter) {
115 : 232849 : struct sock *save_sk = skb->sk;
116 : : unsigned int pkt_len;
117 : :
118 : 232849 : skb->sk = sk;
119 : 232849 : pkt_len = bpf_prog_run_save_cb(filter->prog, skb);
120 : 237153 : skb->sk = save_sk;
121 [ + + ]: 237153 : err = pkt_len ? pskb_trim(skb, max(cap, pkt_len)) : -EPERM;
122 : : }
123 : : rcu_read_unlock();
124 : :
125 : 737493 : return err;
126 : : }
127 : : EXPORT_SYMBOL(sk_filter_trim_cap);
128 : :
129 : 0 : BPF_CALL_1(bpf_skb_get_pay_offset, struct sk_buff *, skb)
130 : : {
131 : 0 : return skb_get_poff(skb);
132 : : }
133 : :
134 : 0 : BPF_CALL_3(bpf_skb_get_nlattr, struct sk_buff *, skb, u32, a, u32, x)
135 : : {
136 : : struct nlattr *nla;
137 : :
138 [ # # ]: 0 : if (skb_is_nonlinear(skb))
139 : : return 0;
140 : :
141 [ # # ]: 0 : if (skb->len < sizeof(struct nlattr))
142 : : return 0;
143 : :
144 [ # # ]: 0 : if (a > skb->len - sizeof(struct nlattr))
145 : : return 0;
146 : :
147 : 0 : nla = nla_find((struct nlattr *) &skb->data[a], skb->len - a, x);
148 [ # # ]: 0 : if (nla)
149 : 0 : return (void *) nla - (void *) skb->data;
150 : :
151 : : return 0;
152 : : }
153 : :
154 : 0 : BPF_CALL_3(bpf_skb_get_nlattr_nest, struct sk_buff *, skb, u32, a, u32, x)
155 : : {
156 : : struct nlattr *nla;
157 : :
158 [ # # ]: 0 : if (skb_is_nonlinear(skb))
159 : : return 0;
160 : :
161 [ # # ]: 0 : if (skb->len < sizeof(struct nlattr))
162 : : return 0;
163 : :
164 [ # # ]: 0 : if (a > skb->len - sizeof(struct nlattr))
165 : : return 0;
166 : :
167 : 0 : nla = (struct nlattr *) &skb->data[a];
168 [ # # ]: 0 : if (nla->nla_len > skb->len - a)
169 : : return 0;
170 : :
171 : 0 : nla = nla_find_nested(nla, x);
172 [ # # ]: 0 : if (nla)
173 : 0 : return (void *) nla - (void *) skb->data;
174 : :
175 : : return 0;
176 : : }
177 : :
178 : 28766 : BPF_CALL_4(bpf_skb_load_helper_8, const struct sk_buff *, skb, const void *,
179 : : data, int, headlen, int, offset)
180 : : {
181 : : u8 tmp, *ptr;
182 : : const int len = sizeof(tmp);
183 : :
184 [ # # + - ]: 14383 : if (offset >= 0) {
185 [ # # + - ]: 14383 : if (headlen - offset >= len)
186 : 14383 : return *(u8 *)(data + offset);
187 [ # # # # ]: 0 : if (!skb_copy_bits(skb, offset, &tmp, sizeof(tmp)))
188 : 0 : return tmp;
189 : : } else {
190 : 0 : ptr = bpf_internal_load_pointer_neg_helper(skb, offset, len);
191 [ # # # # ]: 0 : if (likely(ptr))
192 : 0 : return *(u8 *)ptr;
193 : : }
194 : :
195 : : return -EFAULT;
196 : : }
197 : :
198 : 0 : BPF_CALL_2(bpf_skb_load_helper_8_no_cache, const struct sk_buff *, skb,
199 : : int, offset)
200 : : {
201 : 0 : return ____bpf_skb_load_helper_8(skb, skb->data, skb->len - skb->data_len,
202 : : offset);
203 : : }
204 : :
205 : 40730 : BPF_CALL_4(bpf_skb_load_helper_16, const struct sk_buff *, skb, const void *,
206 : : data, int, headlen, int, offset)
207 : : {
208 : : u16 tmp, *ptr;
209 : : const int len = sizeof(tmp);
210 : :
211 [ # # + - ]: 20365 : if (offset >= 0) {
212 [ # # + - ]: 20365 : if (headlen - offset >= len)
213 : 20365 : return get_unaligned_be16(data + offset);
214 [ # # # # ]: 0 : if (!skb_copy_bits(skb, offset, &tmp, sizeof(tmp)))
215 : 0 : return be16_to_cpu(tmp);
216 : : } else {
217 : 0 : ptr = bpf_internal_load_pointer_neg_helper(skb, offset, len);
218 [ # # # # ]: 0 : if (likely(ptr))
219 : 0 : return get_unaligned_be16(ptr);
220 : : }
221 : :
222 : : return -EFAULT;
223 : : }
224 : :
225 : 0 : BPF_CALL_2(bpf_skb_load_helper_16_no_cache, const struct sk_buff *, skb,
226 : : int, offset)
227 : : {
228 : 0 : return ____bpf_skb_load_helper_16(skb, skb->data, skb->len - skb->data_len,
229 : : offset);
230 : : }
231 : :
232 : 19180 : BPF_CALL_4(bpf_skb_load_helper_32, const struct sk_buff *, skb, const void *,
233 : : data, int, headlen, int, offset)
234 : : {
235 : : u32 tmp, *ptr;
236 : : const int len = sizeof(tmp);
237 : :
238 [ # # + - ]: 9590 : if (likely(offset >= 0)) {
239 [ # # + - ]: 9590 : if (headlen - offset >= len)
240 : 9590 : return get_unaligned_be32(data + offset);
241 [ # # # # ]: 0 : if (!skb_copy_bits(skb, offset, &tmp, sizeof(tmp)))
242 : 0 : return be32_to_cpu(tmp);
243 : : } else {
244 : 0 : ptr = bpf_internal_load_pointer_neg_helper(skb, offset, len);
245 [ # # # # ]: 0 : if (likely(ptr))
246 : 0 : return get_unaligned_be32(ptr);
247 : : }
248 : :
249 : : return -EFAULT;
250 : : }
251 : :
252 : 0 : BPF_CALL_2(bpf_skb_load_helper_32_no_cache, const struct sk_buff *, skb,
253 : : int, offset)
254 : : {
255 : 0 : return ____bpf_skb_load_helper_32(skb, skb->data, skb->len - skb->data_len,
256 : : offset);
257 : : }
258 : :
259 : 0 : BPF_CALL_0(bpf_get_raw_cpu_id)
260 : : {
261 : 0 : return raw_smp_processor_id();
262 : : }
263 : :
264 : : static const struct bpf_func_proto bpf_get_raw_smp_processor_id_proto = {
265 : : .func = bpf_get_raw_cpu_id,
266 : : .gpl_only = false,
267 : : .ret_type = RET_INTEGER,
268 : : };
269 : :
270 : 0 : static u32 convert_skb_access(int skb_field, int dst_reg, int src_reg,
271 : : struct bpf_insn *insn_buf)
272 : : {
273 : : struct bpf_insn *insn = insn_buf;
274 : :
275 [ # # # # : 0 : switch (skb_field) {
# # ]
276 : : case SKF_AD_MARK:
277 : : BUILD_BUG_ON(FIELD_SIZEOF(struct sk_buff, mark) != 4);
278 : :
279 : 0 : *insn++ = BPF_LDX_MEM(BPF_W, dst_reg, src_reg,
280 : : offsetof(struct sk_buff, mark));
281 : 0 : break;
282 : :
283 : : case SKF_AD_PKTTYPE:
284 : 0 : *insn++ = BPF_LDX_MEM(BPF_B, dst_reg, src_reg, PKT_TYPE_OFFSET());
285 : 0 : *insn++ = BPF_ALU32_IMM(BPF_AND, dst_reg, PKT_TYPE_MAX);
286 : : #ifdef __BIG_ENDIAN_BITFIELD
287 : : *insn++ = BPF_ALU32_IMM(BPF_RSH, dst_reg, 5);
288 : : #endif
289 : 0 : break;
290 : :
291 : : case SKF_AD_QUEUE:
292 : : BUILD_BUG_ON(FIELD_SIZEOF(struct sk_buff, queue_mapping) != 2);
293 : :
294 : 0 : *insn++ = BPF_LDX_MEM(BPF_H, dst_reg, src_reg,
295 : : offsetof(struct sk_buff, queue_mapping));
296 : 0 : break;
297 : :
298 : : case SKF_AD_VLAN_TAG:
299 : : BUILD_BUG_ON(FIELD_SIZEOF(struct sk_buff, vlan_tci) != 2);
300 : :
301 : : /* dst_reg = *(u16 *) (src_reg + offsetof(vlan_tci)) */
302 : 0 : *insn++ = BPF_LDX_MEM(BPF_H, dst_reg, src_reg,
303 : : offsetof(struct sk_buff, vlan_tci));
304 : 0 : break;
305 : : case SKF_AD_VLAN_TAG_PRESENT:
306 : 0 : *insn++ = BPF_LDX_MEM(BPF_B, dst_reg, src_reg, PKT_VLAN_PRESENT_OFFSET());
307 : : if (PKT_VLAN_PRESENT_BIT)
308 : : *insn++ = BPF_ALU32_IMM(BPF_RSH, dst_reg, PKT_VLAN_PRESENT_BIT);
309 : : if (PKT_VLAN_PRESENT_BIT < 7)
310 : 0 : *insn++ = BPF_ALU32_IMM(BPF_AND, dst_reg, 1);
311 : : break;
312 : : }
313 : :
314 : 0 : return insn - insn_buf;
315 : : }
316 : :
317 : 27324 : static bool convert_bpf_extensions(struct sock_filter *fp,
318 : : struct bpf_insn **insnp)
319 : : {
320 : 27324 : struct bpf_insn *insn = *insnp;
321 : : u32 cnt;
322 : :
323 [ - - - - : 27324 : switch (fp->k) {
- - - - -
- - + ]
324 : : case SKF_AD_OFF + SKF_AD_PROTOCOL:
325 : : BUILD_BUG_ON(FIELD_SIZEOF(struct sk_buff, protocol) != 2);
326 : :
327 : : /* A = *(u16 *) (CTX + offsetof(protocol)) */
328 : 0 : *insn++ = BPF_LDX_MEM(BPF_H, BPF_REG_A, BPF_REG_CTX,
329 : : offsetof(struct sk_buff, protocol));
330 : : /* A = ntohs(A) [emitting a nop or swap16] */
331 : 0 : *insn = BPF_ENDIAN(BPF_FROM_BE, BPF_REG_A, 16);
332 : 0 : break;
333 : :
334 : : case SKF_AD_OFF + SKF_AD_PKTTYPE:
335 : 0 : cnt = convert_skb_access(SKF_AD_PKTTYPE, BPF_REG_A, BPF_REG_CTX, insn);
336 : 0 : insn += cnt - 1;
337 : 0 : break;
338 : :
339 : : case SKF_AD_OFF + SKF_AD_IFINDEX:
340 : : case SKF_AD_OFF + SKF_AD_HATYPE:
341 : : BUILD_BUG_ON(FIELD_SIZEOF(struct net_device, ifindex) != 4);
342 : : BUILD_BUG_ON(FIELD_SIZEOF(struct net_device, type) != 2);
343 : :
344 : 0 : *insn++ = BPF_LDX_MEM(BPF_FIELD_SIZEOF(struct sk_buff, dev),
345 : : BPF_REG_TMP, BPF_REG_CTX,
346 : : offsetof(struct sk_buff, dev));
347 : : /* if (tmp != 0) goto pc + 1 */
348 : 0 : *insn++ = BPF_JMP_IMM(BPF_JNE, BPF_REG_TMP, 0, 1);
349 : 0 : *insn++ = BPF_EXIT_INSN();
350 [ # # ]: 0 : if (fp->k == SKF_AD_OFF + SKF_AD_IFINDEX)
351 : 0 : *insn = BPF_LDX_MEM(BPF_W, BPF_REG_A, BPF_REG_TMP,
352 : : offsetof(struct net_device, ifindex));
353 : : else
354 : 0 : *insn = BPF_LDX_MEM(BPF_H, BPF_REG_A, BPF_REG_TMP,
355 : : offsetof(struct net_device, type));
356 : : break;
357 : :
358 : : case SKF_AD_OFF + SKF_AD_MARK:
359 : 0 : cnt = convert_skb_access(SKF_AD_MARK, BPF_REG_A, BPF_REG_CTX, insn);
360 : 0 : insn += cnt - 1;
361 : 0 : break;
362 : :
363 : : case SKF_AD_OFF + SKF_AD_RXHASH:
364 : : BUILD_BUG_ON(FIELD_SIZEOF(struct sk_buff, hash) != 4);
365 : :
366 : 0 : *insn = BPF_LDX_MEM(BPF_W, BPF_REG_A, BPF_REG_CTX,
367 : : offsetof(struct sk_buff, hash));
368 : 0 : break;
369 : :
370 : : case SKF_AD_OFF + SKF_AD_QUEUE:
371 : 0 : cnt = convert_skb_access(SKF_AD_QUEUE, BPF_REG_A, BPF_REG_CTX, insn);
372 : 0 : insn += cnt - 1;
373 : 0 : break;
374 : :
375 : : case SKF_AD_OFF + SKF_AD_VLAN_TAG:
376 : 0 : cnt = convert_skb_access(SKF_AD_VLAN_TAG,
377 : : BPF_REG_A, BPF_REG_CTX, insn);
378 : 0 : insn += cnt - 1;
379 : 0 : break;
380 : :
381 : : case SKF_AD_OFF + SKF_AD_VLAN_TAG_PRESENT:
382 : 0 : cnt = convert_skb_access(SKF_AD_VLAN_TAG_PRESENT,
383 : : BPF_REG_A, BPF_REG_CTX, insn);
384 : 0 : insn += cnt - 1;
385 : 0 : break;
386 : :
387 : : case SKF_AD_OFF + SKF_AD_VLAN_TPID:
388 : : BUILD_BUG_ON(FIELD_SIZEOF(struct sk_buff, vlan_proto) != 2);
389 : :
390 : : /* A = *(u16 *) (CTX + offsetof(vlan_proto)) */
391 : 0 : *insn++ = BPF_LDX_MEM(BPF_H, BPF_REG_A, BPF_REG_CTX,
392 : : offsetof(struct sk_buff, vlan_proto));
393 : : /* A = ntohs(A) [emitting a nop or swap16] */
394 : 0 : *insn = BPF_ENDIAN(BPF_FROM_BE, BPF_REG_A, 16);
395 : 0 : break;
396 : :
397 : : case SKF_AD_OFF + SKF_AD_PAY_OFFSET:
398 : : case SKF_AD_OFF + SKF_AD_NLATTR:
399 : : case SKF_AD_OFF + SKF_AD_NLATTR_NEST:
400 : : case SKF_AD_OFF + SKF_AD_CPU:
401 : : case SKF_AD_OFF + SKF_AD_RANDOM:
402 : : /* arg1 = CTX */
403 : 0 : *insn++ = BPF_MOV64_REG(BPF_REG_ARG1, BPF_REG_CTX);
404 : : /* arg2 = A */
405 : 0 : *insn++ = BPF_MOV64_REG(BPF_REG_ARG2, BPF_REG_A);
406 : : /* arg3 = X */
407 : 0 : *insn++ = BPF_MOV64_REG(BPF_REG_ARG3, BPF_REG_X);
408 : : /* Emit call(arg1=CTX, arg2=A, arg3=X) */
409 [ # # # # : 0 : switch (fp->k) {
# # ]
410 : : case SKF_AD_OFF + SKF_AD_PAY_OFFSET:
411 : 0 : *insn = BPF_EMIT_CALL(bpf_skb_get_pay_offset);
412 : 0 : break;
413 : : case SKF_AD_OFF + SKF_AD_NLATTR:
414 : 0 : *insn = BPF_EMIT_CALL(bpf_skb_get_nlattr);
415 : 0 : break;
416 : : case SKF_AD_OFF + SKF_AD_NLATTR_NEST:
417 : 0 : *insn = BPF_EMIT_CALL(bpf_skb_get_nlattr_nest);
418 : 0 : break;
419 : : case SKF_AD_OFF + SKF_AD_CPU:
420 : 0 : *insn = BPF_EMIT_CALL(bpf_get_raw_cpu_id);
421 : 0 : break;
422 : : case SKF_AD_OFF + SKF_AD_RANDOM:
423 : 0 : *insn = BPF_EMIT_CALL(bpf_user_rnd_u32);
424 : 0 : bpf_user_rnd_init_once();
425 : 0 : break;
426 : : }
427 : : break;
428 : :
429 : : case SKF_AD_OFF + SKF_AD_ALU_XOR_X:
430 : : /* A ^= X */
431 : 0 : *insn = BPF_ALU32_REG(BPF_XOR, BPF_REG_A, BPF_REG_X);
432 : 0 : break;
433 : :
434 : : default:
435 : : /* This is just a dummy call to avoid letting the compiler
436 : : * evict __bpf_call_base() as an optimization. Placed here
437 : : * where no-one bothers.
438 : : */
439 [ - + ]: 27324 : BUG_ON(__bpf_call_base(0, 0, 0, 0, 0) != 0);
440 : : return false;
441 : : }
442 : :
443 : 0 : *insnp = insn;
444 : 0 : return true;
445 : : }
446 : :
447 : 41606 : static bool convert_bpf_ld_abs(struct sock_filter *fp, struct bpf_insn **insnp)
448 : : {
449 : : const bool unaligned_ok = IS_BUILTIN(CONFIG_HAVE_EFFICIENT_UNALIGNED_ACCESS);
450 [ + + + + : 41606 : int size = bpf_size_to_bytes(BPF_SIZE(fp->code));
- + # # ]
451 : 41606 : bool endian = BPF_SIZE(fp->code) == BPF_H ||
452 : : BPF_SIZE(fp->code) == BPF_W;
453 : 41606 : bool indirect = BPF_MODE(fp->code) == BPF_IND;
454 : : const int ip_align = NET_IP_ALIGN;
455 : 41606 : struct bpf_insn *insn = *insnp;
456 : 41606 : int offset = fp->k;
457 : :
458 [ + + ]: 41606 : if (!indirect &&
459 : 41606 : ((unaligned_ok && offset >= 0) ||
460 : : (!unaligned_ok && offset >= 0 &&
461 : : offset + ip_align >= 0 &&
462 : : offset + ip_align % size == 0))) {
463 : 27323 : bool ldx_off_ok = offset <= S16_MAX;
464 : :
465 : 27323 : *insn++ = BPF_MOV64_REG(BPF_REG_TMP, BPF_REG_H);
466 [ + - ]: 27323 : if (offset)
467 : 27323 : *insn++ = BPF_ALU64_IMM(BPF_SUB, BPF_REG_TMP, offset);
468 : 27323 : *insn++ = BPF_JMP_IMM(BPF_JSLT, BPF_REG_TMP,
469 : : size, 2 + endian + (!ldx_off_ok * 2));
470 [ + - ]: 27323 : if (ldx_off_ok) {
471 : 27323 : *insn++ = BPF_LDX_MEM(BPF_SIZE(fp->code), BPF_REG_A,
472 : : BPF_REG_D, offset);
473 : : } else {
474 : 0 : *insn++ = BPF_MOV64_REG(BPF_REG_TMP, BPF_REG_D);
475 : 0 : *insn++ = BPF_ALU64_IMM(BPF_ADD, BPF_REG_TMP, offset);
476 : 0 : *insn++ = BPF_LDX_MEM(BPF_SIZE(fp->code), BPF_REG_A,
477 : : BPF_REG_TMP, 0);
478 : : }
479 [ + - ]: 27323 : if (endian)
480 : 27323 : *insn++ = BPF_ENDIAN(BPF_FROM_BE, BPF_REG_A, size * 8);
481 : 27323 : *insn++ = BPF_JMP_A(8);
482 : : }
483 : :
484 : 41606 : *insn++ = BPF_MOV64_REG(BPF_REG_ARG1, BPF_REG_CTX);
485 : 41606 : *insn++ = BPF_MOV64_REG(BPF_REG_ARG2, BPF_REG_D);
486 : 41606 : *insn++ = BPF_MOV64_REG(BPF_REG_ARG3, BPF_REG_H);
487 [ + + ]: 41606 : if (!indirect) {
488 : 27323 : *insn++ = BPF_MOV64_IMM(BPF_REG_ARG4, offset);
489 : : } else {
490 : 14283 : *insn++ = BPF_MOV64_REG(BPF_REG_ARG4, BPF_REG_X);
491 [ + + ]: 14283 : if (fp->k)
492 : 11178 : *insn++ = BPF_ALU64_IMM(BPF_ADD, BPF_REG_ARG4, offset);
493 : : }
494 : :
495 [ + + + - ]: 41606 : switch (BPF_SIZE(fp->code)) {
496 : : case BPF_B:
497 : 4347 : *insn++ = BPF_EMIT_CALL(bpf_skb_load_helper_8);
498 : 4347 : break;
499 : : case BPF_H:
500 : 7452 : *insn++ = BPF_EMIT_CALL(bpf_skb_load_helper_16);
501 : 7452 : break;
502 : : case BPF_W:
503 : 29807 : *insn++ = BPF_EMIT_CALL(bpf_skb_load_helper_32);
504 : 29807 : break;
505 : : default:
506 : : return false;
507 : : }
508 : :
509 : 41606 : *insn++ = BPF_JMP_IMM(BPF_JSGE, BPF_REG_A, 0, 2);
510 : 41606 : *insn++ = BPF_ALU32_REG(BPF_XOR, BPF_REG_A, BPF_REG_A);
511 : 41606 : *insn = BPF_EXIT_INSN();
512 : :
513 : 41606 : *insnp = insn;
514 : 41606 : return true;
515 : : }
516 : :
517 : : /**
518 : : * bpf_convert_filter - convert filter program
519 : : * @prog: the user passed filter program
520 : : * @len: the length of the user passed filter program
521 : : * @new_prog: allocated 'struct bpf_prog' or NULL
522 : : * @new_len: pointer to store length of converted program
523 : : * @seen_ld_abs: bool whether we've seen ld_abs/ind
524 : : *
525 : : * Remap 'sock_filter' style classic BPF (cBPF) instruction set to 'bpf_insn'
526 : : * style extended BPF (eBPF).
527 : : * Conversion workflow:
528 : : *
529 : : * 1) First pass for calculating the new program length:
530 : : * bpf_convert_filter(old_prog, old_len, NULL, &new_len, &seen_ld_abs)
531 : : *
532 : : * 2) 2nd pass to remap in two passes: 1st pass finds new
533 : : * jump offsets, 2nd pass remapping:
534 : : * bpf_convert_filter(old_prog, old_len, new_prog, &new_len, &seen_ld_abs)
535 : : */
536 : 18640 : static int bpf_convert_filter(struct sock_filter *prog, int len,
537 : : struct bpf_prog *new_prog, int *new_len,
538 : : bool *seen_ld_abs)
539 : : {
540 : : int new_flen = 0, pass = 0, target, i, stack_off;
541 : : struct bpf_insn *new_insn, *first_insn = NULL;
542 : : struct sock_filter *fp;
543 : : int *addrs = NULL;
544 : : u8 bpf_src;
545 : :
546 : : BUILD_BUG_ON(BPF_MEMWORDS * sizeof(u32) > MAX_BPF_STACK);
547 : : BUILD_BUG_ON(BPF_REG_FP + 1 != MAX_BPF_REG);
548 : :
549 [ + - ]: 18640 : if (len <= 0 || len > BPF_MAXINSNS)
550 : : return -EINVAL;
551 : :
552 [ + + ]: 18641 : if (new_prog) {
553 : 9320 : first_insn = new_prog->insnsi;
554 : : addrs = kcalloc(len, sizeof(*addrs),
555 : : GFP_KERNEL | __GFP_NOWARN);
556 [ + + ]: 9321 : if (!addrs)
557 : : return -ENOMEM;
558 : : }
559 : :
560 : : do_pass:
561 : : new_insn = first_insn;
562 : : fp = prog;
563 : :
564 : : /* Classic BPF related prologue emission. */
565 [ + + ]: 27969 : if (new_prog) {
566 : : /* Classic BPF expects A and X to be reset first. These need
567 : : * to be guaranteed to be the first two instructions.
568 : : */
569 : 18648 : *new_insn++ = BPF_ALU32_REG(BPF_XOR, BPF_REG_A, BPF_REG_A);
570 : 18648 : *new_insn++ = BPF_ALU32_REG(BPF_XOR, BPF_REG_X, BPF_REG_X);
571 : :
572 : : /* All programs must keep CTX in callee saved BPF_REG_CTX.
573 : : * In eBPF case it's done by the compiler, here we need to
574 : : * do this ourself. Initial CTX is present in BPF_REG_ARG1.
575 : : */
576 : 18648 : *new_insn++ = BPF_MOV64_REG(BPF_REG_CTX, BPF_REG_ARG1);
577 [ + + ]: 18648 : if (*seen_ld_abs) {
578 : : /* For packet access in classic BPF, cache skb->data
579 : : * in callee-saved BPF R8 and skb->len - skb->data_len
580 : : * (headlen) in BPF R9. Since classic BPF is read-only
581 : : * on CTX, we only need to cache it once.
582 : : */
583 : 6624 : *new_insn++ = BPF_LDX_MEM(BPF_FIELD_SIZEOF(struct sk_buff, data),
584 : : BPF_REG_D, BPF_REG_CTX,
585 : : offsetof(struct sk_buff, data));
586 : 6624 : *new_insn++ = BPF_LDX_MEM(BPF_W, BPF_REG_H, BPF_REG_CTX,
587 : : offsetof(struct sk_buff, len));
588 : 6624 : *new_insn++ = BPF_LDX_MEM(BPF_W, BPF_REG_TMP, BPF_REG_CTX,
589 : : offsetof(struct sk_buff, data_len));
590 : 6624 : *new_insn++ = BPF_ALU32_REG(BPF_SUB, BPF_REG_H, BPF_REG_TMP);
591 : : }
592 : : } else {
593 : 9321 : new_insn += 3;
594 : : }
595 : :
596 [ + + ]: 1032879 : for (i = 0; i < len; fp++, i++) {
597 : 1032885 : struct bpf_insn tmp_insns[32] = { };
598 : 1032885 : struct bpf_insn *insn = tmp_insns;
599 : :
600 [ + + ]: 1032885 : if (addrs)
601 : 688589 : addrs[i] = new_insn - first_insn;
602 : :
603 [ + - + + : 1032885 : switch (fp->code) {
+ - - + +
- - + + ]
604 : : /* All arithmetic insns and skb loads map as-is. */
605 : : case BPF_ALU | BPF_ADD | BPF_X:
606 : : case BPF_ALU | BPF_ADD | BPF_K:
607 : : case BPF_ALU | BPF_SUB | BPF_X:
608 : : case BPF_ALU | BPF_SUB | BPF_K:
609 : : case BPF_ALU | BPF_AND | BPF_X:
610 : : case BPF_ALU | BPF_AND | BPF_K:
611 : : case BPF_ALU | BPF_OR | BPF_X:
612 : : case BPF_ALU | BPF_OR | BPF_K:
613 : : case BPF_ALU | BPF_LSH | BPF_X:
614 : : case BPF_ALU | BPF_LSH | BPF_K:
615 : : case BPF_ALU | BPF_RSH | BPF_X:
616 : : case BPF_ALU | BPF_RSH | BPF_K:
617 : : case BPF_ALU | BPF_XOR | BPF_X:
618 : : case BPF_ALU | BPF_XOR | BPF_K:
619 : : case BPF_ALU | BPF_MUL | BPF_X:
620 : : case BPF_ALU | BPF_MUL | BPF_K:
621 : : case BPF_ALU | BPF_DIV | BPF_X:
622 : : case BPF_ALU | BPF_DIV | BPF_K:
623 : : case BPF_ALU | BPF_MOD | BPF_X:
624 : : case BPF_ALU | BPF_MOD | BPF_K:
625 : : case BPF_ALU | BPF_NEG:
626 : : case BPF_LD | BPF_ABS | BPF_W:
627 : : case BPF_LD | BPF_ABS | BPF_H:
628 : : case BPF_LD | BPF_ABS | BPF_B:
629 : : case BPF_LD | BPF_IND | BPF_W:
630 : : case BPF_LD | BPF_IND | BPF_H:
631 : : case BPF_LD | BPF_IND | BPF_B:
632 : : /* Check for overloaded BPF extension and
633 : : * directly convert it if found, otherwise
634 : : * just move on with mapping.
635 : : */
636 [ + + ]: 70793 : if (BPF_CLASS(fp->code) == BPF_LD &&
637 [ + + ]: 27324 : BPF_MODE(fp->code) == BPF_ABS &&
638 : 27323 : convert_bpf_extensions(fp, &insn))
639 : : break;
640 [ + + + + ]: 112399 : if (BPF_CLASS(fp->code) == BPF_LD &&
641 : 41606 : convert_bpf_ld_abs(fp, &insn)) {
642 : 41606 : *seen_ld_abs = true;
643 : 41606 : break;
644 : : }
645 : :
646 [ - + ]: 29187 : if (fp->code == (BPF_ALU | BPF_DIV | BPF_X) ||
647 : : fp->code == (BPF_ALU | BPF_MOD | BPF_X)) {
648 : 0 : *insn++ = BPF_MOV32_REG(BPF_REG_X, BPF_REG_X);
649 : : /* Error with exception code on div/mod by 0.
650 : : * For cBPF programs, this was always return 0.
651 : : */
652 : 0 : *insn++ = BPF_JMP_IMM(BPF_JNE, BPF_REG_X, 0, 2);
653 : 0 : *insn++ = BPF_ALU32_REG(BPF_XOR, BPF_REG_A, BPF_REG_A);
654 : 0 : *insn++ = BPF_EXIT_INSN();
655 : : }
656 : :
657 : 29187 : *insn = BPF_RAW_INSN(fp->code, BPF_REG_A, BPF_REG_X, 0, fp->k);
658 : 29187 : break;
659 : :
660 : : /* Jump transformation cannot use BPF block macros
661 : : * everywhere as offset calculation and target updates
662 : : * require a bit more work than the rest, i.e. jump
663 : : * opcodes map as-is, but offsets need adjustment.
664 : : */
665 : :
666 : : #define BPF_EMIT_JMP \
667 : : do { \
668 : : const s32 off_min = S16_MIN, off_max = S16_MAX; \
669 : : s32 off; \
670 : : \
671 : : if (target >= len || target < 0) \
672 : : goto err; \
673 : : off = addrs ? addrs[target] - addrs[i] - 1 : 0; \
674 : : /* Adjust pc relative offset for 2nd or 3rd insn. */ \
675 : : off -= insn - tmp_insns; \
676 : : /* Reject anything not fitting into insn->off. */ \
677 : : if (off < off_min || off > off_max) \
678 : : goto err; \
679 : : insn->off = off; \
680 : : } while (0)
681 : :
682 : : case BPF_JMP | BPF_JA:
683 : 0 : target = i + fp->k + 1;
684 : 0 : insn->code = fp->code;
685 [ # # # # : 0 : BPF_EMIT_JMP;
# # ]
686 : 0 : break;
687 : :
688 : : case BPF_JMP | BPF_JEQ | BPF_K:
689 : : case BPF_JMP | BPF_JEQ | BPF_X:
690 : : case BPF_JMP | BPF_JSET | BPF_K:
691 : : case BPF_JMP | BPF_JSET | BPF_X:
692 : : case BPF_JMP | BPF_JGT | BPF_K:
693 : : case BPF_JMP | BPF_JGT | BPF_X:
694 : : case BPF_JMP | BPF_JGE | BPF_K:
695 : : case BPF_JMP | BPF_JGE | BPF_X:
696 [ + - + + ]: 806762 : if (BPF_SRC(fp->code) == BPF_K && (int) fp->k < 0) {
697 : : /* BPF immediates are signed, zero extend
698 : : * immediate into tmp register and use it
699 : : * in compare insn.
700 : : */
701 : 17387 : *insn++ = BPF_MOV32_IMM(BPF_REG_TMP, fp->k);
702 : :
703 : 17387 : insn->dst_reg = BPF_REG_A;
704 : 17387 : insn->src_reg = BPF_REG_TMP;
705 : 17387 : bpf_src = BPF_X;
706 : : } else {
707 : 789375 : insn->dst_reg = BPF_REG_A;
708 : 789375 : insn->imm = fp->k;
709 : 789375 : bpf_src = BPF_SRC(fp->code);
710 [ + - ]: 789375 : insn->src_reg = bpf_src == BPF_X ? BPF_REG_X : 0;
711 : : }
712 : :
713 : : /* Common case where 'jump_false' is next insn. */
714 [ + + ]: 806762 : if (fp->jf == 0) {
715 : 736547 : insn->code = BPF_JMP | BPF_OP(fp->code) | bpf_src;
716 : 736547 : target = i + fp->jt + 1;
717 [ + - + + : 736547 : BPF_EMIT_JMP;
+ - ]
718 : 736548 : break;
719 : : }
720 : :
721 : : /* Convert some jumps when 'jump_true' is next insn. */
722 [ + + ]: 70215 : if (fp->jt == 0) {
723 [ + - - + ]: 65247 : switch (BPF_OP(fp->code)) {
724 : : case BPF_JEQ:
725 : 64626 : insn->code = BPF_JMP | BPF_JNE | bpf_src;
726 : 64626 : break;
727 : : case BPF_JGT:
728 : 0 : insn->code = BPF_JMP | BPF_JLE | bpf_src;
729 : 0 : break;
730 : : case BPF_JGE:
731 : 0 : insn->code = BPF_JMP | BPF_JLT | bpf_src;
732 : 0 : break;
733 : : default:
734 : : goto jmp_rest;
735 : : }
736 : :
737 : 64626 : target = i + fp->jf + 1;
738 [ + + + + : 64626 : BPF_EMIT_JMP;
+ - ]
739 : 64626 : break;
740 : : }
741 : : jmp_rest:
742 : : /* Other jumps are mapped into two insns: Jxx and JA. */
743 : 5589 : target = i + fp->jt + 1;
744 : 5589 : insn->code = BPF_JMP | BPF_OP(fp->code) | bpf_src;
745 [ + - + + : 5589 : BPF_EMIT_JMP;
+ - ]
746 : 5589 : insn++;
747 : :
748 : 5589 : insn->code = BPF_JMP | BPF_JA;
749 : 5589 : target = i + fp->jf + 1;
750 [ + - + + : 5589 : BPF_EMIT_JMP;
+ - ]
751 : 5589 : break;
752 : :
753 : : /* ldxb 4 * ([14] & 0xf) is remaped into 6 insns. */
754 : : case BPF_LDX | BPF_MSH | BPF_B: {
755 : 16 : struct sock_filter tmp = {
756 : : .code = BPF_LD | BPF_ABS | BPF_B,
757 : 8 : .k = fp->k,
758 : : };
759 : :
760 : 8 : *seen_ld_abs = true;
761 : :
762 : : /* X = A */
763 : 8 : *insn++ = BPF_MOV64_REG(BPF_REG_X, BPF_REG_A);
764 : : /* A = BPF_R0 = *(u8 *) (skb->data + K) */
765 : 8 : convert_bpf_ld_abs(&tmp, &insn);
766 : 0 : insn++;
767 : : /* A &= 0xf */
768 : 0 : *insn++ = BPF_ALU32_IMM(BPF_AND, BPF_REG_A, 0xf);
769 : : /* A <<= 2 */
770 : 0 : *insn++ = BPF_ALU32_IMM(BPF_LSH, BPF_REG_A, 2);
771 : : /* tmp = X */
772 : 0 : *insn++ = BPF_MOV64_REG(BPF_REG_TMP, BPF_REG_X);
773 : : /* X = A */
774 : 0 : *insn++ = BPF_MOV64_REG(BPF_REG_X, BPF_REG_A);
775 : : /* A = tmp */
776 : 0 : *insn = BPF_MOV64_REG(BPF_REG_A, BPF_REG_TMP);
777 : : break;
778 : : }
779 : : /* RET_K is remaped into 2 insns. RET_A case doesn't need an
780 : : * extra mov as BPF_REG_0 is already mapped into BPF_REG_A.
781 : : */
782 : : case BPF_RET | BPF_A:
783 : : case BPF_RET | BPF_K:
784 [ + - ]: 91322 : if (BPF_RVAL(fp->code) == BPF_K)
785 : 91323 : *insn++ = BPF_MOV32_RAW(BPF_K, BPF_REG_0,
786 : : 0, fp->k);
787 : 91322 : *insn = BPF_EXIT_INSN();
788 : 91322 : break;
789 : :
790 : : /* Store to stack. */
791 : : case BPF_ST:
792 : : case BPF_STX:
793 : 0 : stack_off = fp->k * 4 + 4;
794 [ - - ]: 0 : *insn = BPF_STX_MEM(BPF_W, BPF_REG_FP, BPF_CLASS(fp->code) ==
795 : : BPF_ST ? BPF_REG_A : BPF_REG_X,
796 : : -stack_off);
797 : : /* check_load_and_stores() verifies that classic BPF can
798 : : * load from stack only after write, so tracking
799 : : * stack_depth for ST|STX insns is enough
800 : : */
801 [ # # - - : 0 : if (new_prog && new_prog->aux->stack_depth < stack_off)
# # ]
802 : 0 : new_prog->aux->stack_depth = stack_off;
803 : : break;
804 : :
805 : : /* Load from stack. */
806 : : case BPF_LD | BPF_MEM:
807 : : case BPF_LDX | BPF_MEM:
808 : 0 : stack_off = fp->k * 4 + 4;
809 [ # # ]: 0 : *insn = BPF_LDX_MEM(BPF_W, BPF_CLASS(fp->code) == BPF_LD ?
810 : : BPF_REG_A : BPF_REG_X, BPF_REG_FP,
811 : : -stack_off);
812 : 0 : break;
813 : :
814 : : /* A = K or X = K */
815 : : case BPF_LD | BPF_IMM:
816 : : case BPF_LDX | BPF_IMM:
817 [ + - ]: 1863 : *insn = BPF_MOV32_IMM(BPF_CLASS(fp->code) == BPF_LD ?
818 : : BPF_REG_A : BPF_REG_X, fp->k);
819 : 1863 : break;
820 : :
821 : : /* X = A */
822 : : case BPF_MISC | BPF_TAX:
823 : 621 : *insn = BPF_MOV64_REG(BPF_REG_X, BPF_REG_A);
824 : 621 : break;
825 : :
826 : : /* A = X */
827 : : case BPF_MISC | BPF_TXA:
828 : 0 : *insn = BPF_MOV64_REG(BPF_REG_A, BPF_REG_X);
829 : 0 : break;
830 : :
831 : : /* A = skb->len or X = skb->len */
832 : : case BPF_LD | BPF_W | BPF_LEN:
833 : : case BPF_LDX | BPF_W | BPF_LEN:
834 [ # # ]: 0 : *insn = BPF_LDX_MEM(BPF_W, BPF_CLASS(fp->code) == BPF_LD ?
835 : : BPF_REG_A : BPF_REG_X, BPF_REG_CTX,
836 : : offsetof(struct sk_buff, len));
837 : 0 : break;
838 : :
839 : : /* Access seccomp_data fields. */
840 : : case BPF_LDX | BPF_ABS | BPF_W:
841 : : /* A = *(u32 *) (ctx + K) */
842 : 61521 : *insn = BPF_LDX_MEM(BPF_W, BPF_REG_A, BPF_REG_CTX, fp->k);
843 : 61521 : break;
844 : :
845 : : /* Unknown instruction. */
846 : : default:
847 : : goto err;
848 : : }
849 : :
850 : 1032879 : insn++;
851 [ + + ]: 1032879 : if (new_prog)
852 : 688589 : memcpy(new_insn, tmp_insns,
853 : 688589 : sizeof(*insn) * (insn - tmp_insns));
854 : 1032879 : new_insn += insn - tmp_insns;
855 : : }
856 : :
857 [ + + ]: 27963 : if (!new_prog) {
858 : : /* Only calculating new length. */
859 : 9321 : *new_len = new_insn - first_insn;
860 [ + + ]: 9321 : if (*seen_ld_abs)
861 : 3312 : *new_len += 4; /* Prologue bits. */
862 : : return 0;
863 : : }
864 : :
865 : 18642 : pass++;
866 [ + + ]: 18642 : if (new_flen != new_insn - first_insn) {
867 : : new_flen = new_insn - first_insn;
868 [ + - ]: 9321 : if (pass > 2)
869 : : goto err;
870 : : goto do_pass;
871 : : }
872 : :
873 : 9321 : kfree(addrs);
874 [ - + ]: 9321 : BUG_ON(*new_len != new_flen);
875 : : return 0;
876 : : err:
877 : 0 : kfree(addrs);
878 : 0 : return -EINVAL;
879 : : }
880 : :
881 : : /* Security:
882 : : *
883 : : * As we dont want to clear mem[] array for each packet going through
884 : : * __bpf_prog_run(), we check that filter loaded by user never try to read
885 : : * a cell if not previously written, and we check all branches to be sure
886 : : * a malicious user doesn't try to abuse us.
887 : : */
888 : 9321 : static int check_load_and_stores(const struct sock_filter *filter, int flen)
889 : : {
890 : : u16 *masks, memvalid = 0; /* One bit per cell, 16 cells */
891 : : int pc, ret = 0;
892 : :
893 : : BUILD_BUG_ON(BPF_MEMWORDS > 16);
894 : :
895 : 9321 : masks = kmalloc_array(flen, sizeof(*masks), GFP_KERNEL);
896 [ + - ]: 9321 : if (!masks)
897 : : return -ENOMEM;
898 : :
899 : 9321 : memset(masks, 0xff, flen * sizeof(*masks));
900 : :
901 [ + + ]: 353616 : for (pc = 0; pc < flen; pc++) {
902 : 344295 : memvalid &= masks[pc];
903 : :
904 [ - - - + : 344295 : switch (filter[pc].code) {
+ ]
905 : : case BPF_ST:
906 : : case BPF_STX:
907 : 0 : memvalid |= (1 << filter[pc].k);
908 : 0 : break;
909 : : case BPF_LD | BPF_MEM:
910 : : case BPF_LDX | BPF_MEM:
911 [ # # ]: 0 : if (!(memvalid & (1 << filter[pc].k))) {
912 : : ret = -EINVAL;
913 : : goto error;
914 : : }
915 : : break;
916 : : case BPF_JMP | BPF_JA:
917 : : /* A jump must set masks on target */
918 : 0 : masks[pc + 1 + filter[pc].k] &= memvalid;
919 : : memvalid = ~0;
920 : 0 : break;
921 : : case BPF_JMP | BPF_JEQ | BPF_K:
922 : : case BPF_JMP | BPF_JEQ | BPF_X:
923 : : case BPF_JMP | BPF_JGE | BPF_K:
924 : : case BPF_JMP | BPF_JGE | BPF_X:
925 : : case BPF_JMP | BPF_JGT | BPF_K:
926 : : case BPF_JMP | BPF_JGT | BPF_X:
927 : : case BPF_JMP | BPF_JSET | BPF_K:
928 : : case BPF_JMP | BPF_JSET | BPF_X:
929 : : /* A jump must set masks on targets */
930 : 268921 : masks[pc + 1 + filter[pc].jt] &= memvalid;
931 : 268921 : masks[pc + 1 + filter[pc].jf] &= memvalid;
932 : : memvalid = ~0;
933 : 268921 : break;
934 : : }
935 : : }
936 : : error:
937 : 9321 : kfree(masks);
938 : 9321 : return ret;
939 : : }
940 : :
941 : : static bool chk_code_allowed(u16 code_to_probe)
942 : : {
943 : : static const bool codes[] = {
944 : : /* 32 bit ALU operations */
945 : : [BPF_ALU | BPF_ADD | BPF_K] = true,
946 : : [BPF_ALU | BPF_ADD | BPF_X] = true,
947 : : [BPF_ALU | BPF_SUB | BPF_K] = true,
948 : : [BPF_ALU | BPF_SUB | BPF_X] = true,
949 : : [BPF_ALU | BPF_MUL | BPF_K] = true,
950 : : [BPF_ALU | BPF_MUL | BPF_X] = true,
951 : : [BPF_ALU | BPF_DIV | BPF_K] = true,
952 : : [BPF_ALU | BPF_DIV | BPF_X] = true,
953 : : [BPF_ALU | BPF_MOD | BPF_K] = true,
954 : : [BPF_ALU | BPF_MOD | BPF_X] = true,
955 : : [BPF_ALU | BPF_AND | BPF_K] = true,
956 : : [BPF_ALU | BPF_AND | BPF_X] = true,
957 : : [BPF_ALU | BPF_OR | BPF_K] = true,
958 : : [BPF_ALU | BPF_OR | BPF_X] = true,
959 : : [BPF_ALU | BPF_XOR | BPF_K] = true,
960 : : [BPF_ALU | BPF_XOR | BPF_X] = true,
961 : : [BPF_ALU | BPF_LSH | BPF_K] = true,
962 : : [BPF_ALU | BPF_LSH | BPF_X] = true,
963 : : [BPF_ALU | BPF_RSH | BPF_K] = true,
964 : : [BPF_ALU | BPF_RSH | BPF_X] = true,
965 : : [BPF_ALU | BPF_NEG] = true,
966 : : /* Load instructions */
967 : : [BPF_LD | BPF_W | BPF_ABS] = true,
968 : : [BPF_LD | BPF_H | BPF_ABS] = true,
969 : : [BPF_LD | BPF_B | BPF_ABS] = true,
970 : : [BPF_LD | BPF_W | BPF_LEN] = true,
971 : : [BPF_LD | BPF_W | BPF_IND] = true,
972 : : [BPF_LD | BPF_H | BPF_IND] = true,
973 : : [BPF_LD | BPF_B | BPF_IND] = true,
974 : : [BPF_LD | BPF_IMM] = true,
975 : : [BPF_LD | BPF_MEM] = true,
976 : : [BPF_LDX | BPF_W | BPF_LEN] = true,
977 : : [BPF_LDX | BPF_B | BPF_MSH] = true,
978 : : [BPF_LDX | BPF_IMM] = true,
979 : : [BPF_LDX | BPF_MEM] = true,
980 : : /* Store instructions */
981 : : [BPF_ST] = true,
982 : : [BPF_STX] = true,
983 : : /* Misc instructions */
984 : : [BPF_MISC | BPF_TAX] = true,
985 : : [BPF_MISC | BPF_TXA] = true,
986 : : /* Return instructions */
987 : : [BPF_RET | BPF_K] = true,
988 : : [BPF_RET | BPF_A] = true,
989 : : /* Jump instructions */
990 : : [BPF_JMP | BPF_JA] = true,
991 : : [BPF_JMP | BPF_JEQ | BPF_K] = true,
992 : : [BPF_JMP | BPF_JEQ | BPF_X] = true,
993 : : [BPF_JMP | BPF_JGE | BPF_K] = true,
994 : : [BPF_JMP | BPF_JGE | BPF_X] = true,
995 : : [BPF_JMP | BPF_JGT | BPF_K] = true,
996 : : [BPF_JMP | BPF_JGT | BPF_X] = true,
997 : : [BPF_JMP | BPF_JSET | BPF_K] = true,
998 : : [BPF_JMP | BPF_JSET | BPF_X] = true,
999 : : };
1000 : :
1001 [ + - ]: 344295 : if (code_to_probe >= ARRAY_SIZE(codes))
1002 : : return false;
1003 : :
1004 : 344295 : return codes[code_to_probe];
1005 : : }
1006 : :
1007 : : static bool bpf_check_basics_ok(const struct sock_filter *filter,
1008 : : unsigned int flen)
1009 : : {
1010 [ + - + - : 9321 : if (filter == NULL)
# # ]
1011 : : return false;
1012 [ + - + - : 9321 : if (flen == 0 || flen > BPF_MAXINSNS)
# # ]
1013 : : return false;
1014 : :
1015 : : return true;
1016 : : }
1017 : :
1018 : : /**
1019 : : * bpf_check_classic - verify socket filter code
1020 : : * @filter: filter to verify
1021 : : * @flen: length of filter
1022 : : *
1023 : : * Check the user's filter code. If we let some ugly
1024 : : * filter code slip through kaboom! The filter must contain
1025 : : * no references or jumps that are out of range, no illegal
1026 : : * instructions, and must end with a RET instruction.
1027 : : *
1028 : : * All jumps are forward as they are not signed.
1029 : : *
1030 : : * Returns 0 if the rule set is legal or -EINVAL if not.
1031 : : */
1032 : 9321 : static int bpf_check_classic(const struct sock_filter *filter,
1033 : : unsigned int flen)
1034 : : {
1035 : : bool anc_found;
1036 : : int pc;
1037 : :
1038 : : /* Check the filter code now */
1039 [ + + ]: 353616 : for (pc = 0; pc < flen; pc++) {
1040 : 344295 : const struct sock_filter *ftest = &filter[pc];
1041 : :
1042 : : /* May we actually operate on this code? */
1043 [ + - ]: 688590 : if (!chk_code_allowed(ftest->code))
1044 : : return -EINVAL;
1045 : :
1046 : : /* Some instructions need special checks */
1047 [ - - - - : 344295 : switch (ftest->code) {
+ + + ]
1048 : : case BPF_ALU | BPF_DIV | BPF_K:
1049 : : case BPF_ALU | BPF_MOD | BPF_K:
1050 : : /* Check for division by zero */
1051 [ # # ]: 0 : if (ftest->k == 0)
1052 : : return -EINVAL;
1053 : : break;
1054 : : case BPF_ALU | BPF_LSH | BPF_K:
1055 : : case BPF_ALU | BPF_RSH | BPF_K:
1056 [ # # ]: 0 : if (ftest->k >= 32)
1057 : : return -EINVAL;
1058 : : break;
1059 : : case BPF_LD | BPF_MEM:
1060 : : case BPF_LDX | BPF_MEM:
1061 : : case BPF_ST:
1062 : : case BPF_STX:
1063 : : /* Check for invalid memory addresses */
1064 [ # # ]: 0 : if (ftest->k >= BPF_MEMWORDS)
1065 : : return -EINVAL;
1066 : : break;
1067 : : case BPF_JMP | BPF_JA:
1068 : : /* Note, the large ftest->k might cause loops.
1069 : : * Compare this with conditional jumps below,
1070 : : * where offsets are limited. --ANK (981016)
1071 : : */
1072 [ # # ]: 0 : if (ftest->k >= (unsigned int)(flen - pc - 1))
1073 : : return -EINVAL;
1074 : : break;
1075 : : case BPF_JMP | BPF_JEQ | BPF_K:
1076 : : case BPF_JMP | BPF_JEQ | BPF_X:
1077 : : case BPF_JMP | BPF_JGE | BPF_K:
1078 : : case BPF_JMP | BPF_JGE | BPF_X:
1079 : : case BPF_JMP | BPF_JGT | BPF_K:
1080 : : case BPF_JMP | BPF_JGT | BPF_X:
1081 : : case BPF_JMP | BPF_JSET | BPF_K:
1082 : : case BPF_JMP | BPF_JSET | BPF_X:
1083 : : /* Both conditionals must be safe */
1084 [ + - + - ]: 537842 : if (pc + ftest->jt + 1 >= flen ||
1085 : 268921 : pc + ftest->jf + 1 >= flen)
1086 : : return -EINVAL;
1087 : : break;
1088 : : case BPF_LD | BPF_W | BPF_ABS:
1089 : : case BPF_LD | BPF_H | BPF_ABS:
1090 : : case BPF_LD | BPF_B | BPF_ABS:
1091 : : anc_found = false;
1092 [ - + ]: 29615 : if (bpf_anc_helper(ftest) & BPF_ANC)
1093 : : anc_found = true;
1094 : : /* Ancillary operation unknown or unsupported */
1095 [ + - + - ]: 29615 : if (anc_found == false && ftest->k >= SKF_AD_OFF)
1096 : : return -EINVAL;
1097 : : }
1098 : : }
1099 : :
1100 : : /* Last instruction must be a RET code */
1101 [ + - ]: 9321 : switch (filter[flen - 1].code) {
1102 : : case BPF_RET | BPF_K:
1103 : : case BPF_RET | BPF_A:
1104 : 9321 : return check_load_and_stores(filter, flen);
1105 : : }
1106 : :
1107 : : return -EINVAL;
1108 : : }
1109 : :
1110 : 3312 : static int bpf_prog_store_orig_filter(struct bpf_prog *fp,
1111 : : const struct sock_fprog *fprog)
1112 : : {
1113 : 3312 : unsigned int fsize = bpf_classic_proglen(fprog);
1114 : : struct sock_fprog_kern *fkprog;
1115 : :
1116 : 3312 : fp->orig_prog = kmalloc(sizeof(*fkprog), GFP_KERNEL);
1117 [ + - ]: 3312 : if (!fp->orig_prog)
1118 : : return -ENOMEM;
1119 : :
1120 : : fkprog = fp->orig_prog;
1121 : 3312 : fkprog->len = fprog->len;
1122 : :
1123 : 3312 : fkprog->filter = kmemdup(fp->insns, fsize,
1124 : : GFP_KERNEL | __GFP_NOWARN);
1125 [ - + ]: 3312 : if (!fkprog->filter) {
1126 : 0 : kfree(fp->orig_prog);
1127 : 0 : return -ENOMEM;
1128 : : }
1129 : :
1130 : : return 0;
1131 : : }
1132 : :
1133 : 834 : static void bpf_release_orig_filter(struct bpf_prog *fp)
1134 : : {
1135 : 834 : struct sock_fprog_kern *fprog = fp->orig_prog;
1136 : :
1137 [ + + ]: 834 : if (fprog) {
1138 : 828 : kfree(fprog->filter);
1139 : 828 : kfree(fprog);
1140 : : }
1141 : 834 : }
1142 : :
1143 : 834 : static void __bpf_prog_release(struct bpf_prog *prog)
1144 : : {
1145 [ - + ]: 834 : if (prog->type == BPF_PROG_TYPE_SOCKET_FILTER) {
1146 : 0 : bpf_prog_put(prog);
1147 : : } else {
1148 : 834 : bpf_release_orig_filter(prog);
1149 : 834 : bpf_prog_free(prog);
1150 : : }
1151 : 834 : }
1152 : :
1153 : : static void __sk_filter_release(struct sk_filter *fp)
1154 : : {
1155 : 828 : __bpf_prog_release(fp->prog);
1156 : 828 : kfree(fp);
1157 : : }
1158 : :
1159 : : /**
1160 : : * sk_filter_release_rcu - Release a socket filter by rcu_head
1161 : : * @rcu: rcu_head that contains the sk_filter to free
1162 : : */
1163 : 828 : static void sk_filter_release_rcu(struct rcu_head *rcu)
1164 : : {
1165 : 828 : struct sk_filter *fp = container_of(rcu, struct sk_filter, rcu);
1166 : :
1167 : : __sk_filter_release(fp);
1168 : 828 : }
1169 : :
1170 : : /**
1171 : : * sk_filter_release - release a socket filter
1172 : : * @fp: filter to remove
1173 : : *
1174 : : * Remove a filter from a socket and release its resources.
1175 : : */
1176 : 828 : static void sk_filter_release(struct sk_filter *fp)
1177 : : {
1178 [ + - ]: 828 : if (refcount_dec_and_test(&fp->refcnt))
1179 : 828 : call_rcu(&fp->rcu, sk_filter_release_rcu);
1180 : 828 : }
1181 : :
1182 : 828 : void sk_filter_uncharge(struct sock *sk, struct sk_filter *fp)
1183 : : {
1184 : 828 : u32 filter_size = bpf_prog_size(fp->prog->len);
1185 : :
1186 : 828 : atomic_sub(filter_size, &sk->sk_omem_alloc);
1187 : 828 : sk_filter_release(fp);
1188 : 828 : }
1189 : :
1190 : : /* try to charge the socket memory if there is space available
1191 : : * return true on success
1192 : : */
1193 : 3311 : static bool __sk_filter_charge(struct sock *sk, struct sk_filter *fp)
1194 : : {
1195 : 3311 : u32 filter_size = bpf_prog_size(fp->prog->len);
1196 : :
1197 : : /* same check as in sock_kmalloc() */
1198 [ + - + + ]: 6623 : if (filter_size <= sysctl_optmem_max &&
1199 : 3312 : atomic_read(&sk->sk_omem_alloc) + filter_size < sysctl_optmem_max) {
1200 : 3311 : atomic_add(filter_size, &sk->sk_omem_alloc);
1201 : 3311 : return true;
1202 : : }
1203 : : return false;
1204 : : }
1205 : :
1206 : 0 : bool sk_filter_charge(struct sock *sk, struct sk_filter *fp)
1207 : : {
1208 [ # # ]: 0 : if (!refcount_inc_not_zero(&fp->refcnt))
1209 : : return false;
1210 : :
1211 [ # # ]: 0 : if (!__sk_filter_charge(sk, fp)) {
1212 : 0 : sk_filter_release(fp);
1213 : 0 : return false;
1214 : : }
1215 : : return true;
1216 : : }
1217 : :
1218 : 9320 : static struct bpf_prog *bpf_migrate_filter(struct bpf_prog *fp)
1219 : : {
1220 : : struct sock_filter *old_prog;
1221 : : struct bpf_prog *old_fp;
1222 : 9320 : int err, new_len, old_len = fp->len;
1223 : 9320 : bool seen_ld_abs = false;
1224 : :
1225 : : /* We are free to overwrite insns et al right here as it
1226 : : * won't be used at this point in time anymore internally
1227 : : * after the migration to the internal BPF instruction
1228 : : * representation.
1229 : : */
1230 : : BUILD_BUG_ON(sizeof(struct sock_filter) !=
1231 : : sizeof(struct bpf_insn));
1232 : :
1233 : : /* Conversion cannot happen on overlapping memory areas,
1234 : : * so we need to keep the user BPF around until the 2nd
1235 : : * pass. At this time, the user BPF is stored in fp->insns.
1236 : : */
1237 : 9320 : old_prog = kmemdup(fp->insns, old_len * sizeof(struct sock_filter),
1238 : : GFP_KERNEL | __GFP_NOWARN);
1239 [ - + ]: 9321 : if (!old_prog) {
1240 : 0 : err = -ENOMEM;
1241 : 0 : goto out_err;
1242 : : }
1243 : :
1244 : : /* 1st pass: calculate the new program length. */
1245 : 9321 : err = bpf_convert_filter(old_prog, old_len, NULL, &new_len,
1246 : : &seen_ld_abs);
1247 [ + - ]: 9321 : if (err)
1248 : : goto out_err_free;
1249 : :
1250 : : /* Expand fp for appending the new filter representation. */
1251 : : old_fp = fp;
1252 : 18642 : fp = bpf_prog_realloc(old_fp, bpf_prog_size(new_len), 0);
1253 [ - + ]: 9320 : if (!fp) {
1254 : : /* The old_fp is still around in case we couldn't
1255 : : * allocate new memory, so uncharge on that one.
1256 : : */
1257 : : fp = old_fp;
1258 : 0 : err = -ENOMEM;
1259 : 0 : goto out_err_free;
1260 : : }
1261 : :
1262 : 9320 : fp->len = new_len;
1263 : :
1264 : : /* 2nd pass: remap sock_filter insns into bpf_insn insns. */
1265 : 9320 : err = bpf_convert_filter(old_prog, old_len, fp, &new_len,
1266 : : &seen_ld_abs);
1267 [ + - ]: 9321 : if (err)
1268 : : /* 2nd bpf_convert_filter() can fail only if it fails
1269 : : * to allocate memory, remapping must succeed. Note,
1270 : : * that at this time old_fp has already been released
1271 : : * by krealloc().
1272 : : */
1273 : : goto out_err_free;
1274 : :
1275 : 9321 : fp = bpf_prog_select_runtime(fp, &err);
1276 [ + - ]: 9320 : if (err)
1277 : : goto out_err_free;
1278 : :
1279 : 9321 : kfree(old_prog);
1280 : 9321 : return fp;
1281 : :
1282 : : out_err_free:
1283 : 0 : kfree(old_prog);
1284 : : out_err:
1285 : 0 : __bpf_prog_release(fp);
1286 : 0 : return ERR_PTR(err);
1287 : : }
1288 : :
1289 : 9321 : static struct bpf_prog *bpf_prepare_filter(struct bpf_prog *fp,
1290 : : bpf_aux_classic_check_t trans)
1291 : : {
1292 : : int err;
1293 : :
1294 : 9321 : fp->bpf_func = NULL;
1295 : 9321 : fp->jited = 0;
1296 : :
1297 : 9321 : err = bpf_check_classic(fp->insns, fp->len);
1298 [ - + ]: 9321 : if (err) {
1299 : 0 : __bpf_prog_release(fp);
1300 : 0 : return ERR_PTR(err);
1301 : : }
1302 : :
1303 : : /* There might be additional checks and transformations
1304 : : * needed on classic filters, f.e. in case of seccomp.
1305 : : */
1306 [ + + ]: 9321 : if (trans) {
1307 : 6009 : err = trans(fp->insns, fp->len);
1308 [ - + ]: 6009 : if (err) {
1309 : 0 : __bpf_prog_release(fp);
1310 : 0 : return ERR_PTR(err);
1311 : : }
1312 : : }
1313 : :
1314 : : /* Probe if we can JIT compile the filter and if so, do
1315 : : * the compilation of the filter.
1316 : : */
1317 : 9321 : bpf_jit_compile(fp);
1318 : :
1319 : : /* JIT compiler couldn't process this filter, so do the
1320 : : * internal BPF translation for the optimized interpreter.
1321 : : */
1322 [ + - ]: 9321 : if (!fp->jited)
1323 : 9321 : fp = bpf_migrate_filter(fp);
1324 : :
1325 : 9321 : return fp;
1326 : : }
1327 : :
1328 : : /**
1329 : : * bpf_prog_create - create an unattached filter
1330 : : * @pfp: the unattached filter that is created
1331 : : * @fprog: the filter program
1332 : : *
1333 : : * Create a filter independent of any socket. We first run some
1334 : : * sanity checks on it to make sure it does not explode on us later.
1335 : : * If an error occurs or there is insufficient memory for the filter
1336 : : * a negative errno code is returned. On success the return is zero.
1337 : : */
1338 : 0 : int bpf_prog_create(struct bpf_prog **pfp, struct sock_fprog_kern *fprog)
1339 : : {
1340 : 0 : unsigned int fsize = bpf_classic_proglen(fprog);
1341 : : struct bpf_prog *fp;
1342 : :
1343 : : /* Make sure new filter is there and in the right amounts. */
1344 [ # # ]: 0 : if (!bpf_check_basics_ok(fprog->filter, fprog->len))
1345 : : return -EINVAL;
1346 : :
1347 : 0 : fp = bpf_prog_alloc(bpf_prog_size(fprog->len), 0);
1348 [ # # ]: 0 : if (!fp)
1349 : : return -ENOMEM;
1350 : :
1351 : 0 : memcpy(fp->insns, fprog->filter, fsize);
1352 : :
1353 : 0 : fp->len = fprog->len;
1354 : : /* Since unattached filters are not copied back to user
1355 : : * space through sk_get_filter(), we do not need to hold
1356 : : * a copy here, and can spare us the work.
1357 : : */
1358 : 0 : fp->orig_prog = NULL;
1359 : :
1360 : : /* bpf_prepare_filter() already takes care of freeing
1361 : : * memory in case something goes wrong.
1362 : : */
1363 : 0 : fp = bpf_prepare_filter(fp, NULL);
1364 [ # # ]: 0 : if (IS_ERR(fp))
1365 : 0 : return PTR_ERR(fp);
1366 : :
1367 : 0 : *pfp = fp;
1368 : 0 : return 0;
1369 : : }
1370 : : EXPORT_SYMBOL_GPL(bpf_prog_create);
1371 : :
1372 : : /**
1373 : : * bpf_prog_create_from_user - create an unattached filter from user buffer
1374 : : * @pfp: the unattached filter that is created
1375 : : * @fprog: the filter program
1376 : : * @trans: post-classic verifier transformation handler
1377 : : * @save_orig: save classic BPF program
1378 : : *
1379 : : * This function effectively does the same as bpf_prog_create(), only
1380 : : * that it builds up its insns buffer from user space provided buffer.
1381 : : * It also allows for passing a bpf_aux_classic_check_t handler.
1382 : : */
1383 : 6009 : int bpf_prog_create_from_user(struct bpf_prog **pfp, struct sock_fprog *fprog,
1384 : : bpf_aux_classic_check_t trans, bool save_orig)
1385 : : {
1386 : 6009 : unsigned int fsize = bpf_classic_proglen(fprog);
1387 : : struct bpf_prog *fp;
1388 : : int err;
1389 : :
1390 : : /* Make sure new filter is there and in the right amounts. */
1391 [ + - ]: 12018 : if (!bpf_check_basics_ok(fprog->filter, fprog->len))
1392 : : return -EINVAL;
1393 : :
1394 : 6009 : fp = bpf_prog_alloc(bpf_prog_size(fprog->len), 0);
1395 [ + - ]: 6009 : if (!fp)
1396 : : return -ENOMEM;
1397 : :
1398 [ - + ]: 12018 : if (copy_from_user(fp->insns, fprog->filter, fsize)) {
1399 : 0 : __bpf_prog_free(fp);
1400 : 0 : return -EFAULT;
1401 : : }
1402 : :
1403 : 6009 : fp->len = fprog->len;
1404 : 6009 : fp->orig_prog = NULL;
1405 : :
1406 [ - + ]: 6009 : if (save_orig) {
1407 : 0 : err = bpf_prog_store_orig_filter(fp, fprog);
1408 [ # # ]: 0 : if (err) {
1409 : 0 : __bpf_prog_free(fp);
1410 : 0 : return -ENOMEM;
1411 : : }
1412 : : }
1413 : :
1414 : : /* bpf_prepare_filter() already takes care of freeing
1415 : : * memory in case something goes wrong.
1416 : : */
1417 : 6009 : fp = bpf_prepare_filter(fp, trans);
1418 [ - + ]: 6009 : if (IS_ERR(fp))
1419 : 0 : return PTR_ERR(fp);
1420 : :
1421 : 6009 : *pfp = fp;
1422 : 6009 : return 0;
1423 : : }
1424 : : EXPORT_SYMBOL_GPL(bpf_prog_create_from_user);
1425 : :
1426 : 6 : void bpf_prog_destroy(struct bpf_prog *fp)
1427 : : {
1428 : 6 : __bpf_prog_release(fp);
1429 : 6 : }
1430 : : EXPORT_SYMBOL_GPL(bpf_prog_destroy);
1431 : :
1432 : 3312 : static int __sk_attach_prog(struct bpf_prog *prog, struct sock *sk)
1433 : : {
1434 : : struct sk_filter *fp, *old_fp;
1435 : :
1436 : : fp = kmalloc(sizeof(*fp), GFP_KERNEL);
1437 [ + - ]: 3312 : if (!fp)
1438 : : return -ENOMEM;
1439 : :
1440 : 3312 : fp->prog = prog;
1441 : :
1442 [ - + ]: 3312 : if (!__sk_filter_charge(sk, fp)) {
1443 : 0 : kfree(fp);
1444 : 0 : return -ENOMEM;
1445 : : }
1446 : : refcount_set(&fp->refcnt, 1);
1447 : :
1448 : 3311 : old_fp = rcu_dereference_protected(sk->sk_filter,
1449 : : lockdep_sock_is_held(sk));
1450 : 3311 : rcu_assign_pointer(sk->sk_filter, fp);
1451 : :
1452 [ + + ]: 3312 : if (old_fp)
1453 : 207 : sk_filter_uncharge(sk, old_fp);
1454 : :
1455 : : return 0;
1456 : : }
1457 : :
1458 : : static
1459 : 3312 : struct bpf_prog *__get_filter(struct sock_fprog *fprog, struct sock *sk)
1460 : : {
1461 : 3312 : unsigned int fsize = bpf_classic_proglen(fprog);
1462 : : struct bpf_prog *prog;
1463 : : int err;
1464 : :
1465 [ + - ]: 3312 : if (sock_flag(sk, SOCK_FILTER_LOCKED))
1466 : : return ERR_PTR(-EPERM);
1467 : :
1468 : : /* Make sure new filter is there and in the right amounts. */
1469 [ + - ]: 6624 : if (!bpf_check_basics_ok(fprog->filter, fprog->len))
1470 : : return ERR_PTR(-EINVAL);
1471 : :
1472 : 3312 : prog = bpf_prog_alloc(bpf_prog_size(fprog->len), 0);
1473 [ + - ]: 3312 : if (!prog)
1474 : : return ERR_PTR(-ENOMEM);
1475 : :
1476 [ - + ]: 6624 : if (copy_from_user(prog->insns, fprog->filter, fsize)) {
1477 : 0 : __bpf_prog_free(prog);
1478 : 0 : return ERR_PTR(-EFAULT);
1479 : : }
1480 : :
1481 : 3312 : prog->len = fprog->len;
1482 : :
1483 : 3312 : err = bpf_prog_store_orig_filter(prog, fprog);
1484 [ - + ]: 3312 : if (err) {
1485 : 0 : __bpf_prog_free(prog);
1486 : 0 : return ERR_PTR(-ENOMEM);
1487 : : }
1488 : :
1489 : : /* bpf_prepare_filter() already takes care of freeing
1490 : : * memory in case something goes wrong.
1491 : : */
1492 : 3312 : return bpf_prepare_filter(prog, NULL);
1493 : : }
1494 : :
1495 : : /**
1496 : : * sk_attach_filter - attach a socket filter
1497 : : * @fprog: the filter program
1498 : : * @sk: the socket to use
1499 : : *
1500 : : * Attach the user's filter code. We first run some sanity checks on
1501 : : * it to make sure it does not explode on us later. If an error
1502 : : * occurs or there is insufficient memory for the filter a negative
1503 : : * errno code is returned. On success the return is zero.
1504 : : */
1505 : 3312 : int sk_attach_filter(struct sock_fprog *fprog, struct sock *sk)
1506 : : {
1507 : 3312 : struct bpf_prog *prog = __get_filter(fprog, sk);
1508 : : int err;
1509 : :
1510 [ - + ]: 3312 : if (IS_ERR(prog))
1511 : 0 : return PTR_ERR(prog);
1512 : :
1513 : 3312 : err = __sk_attach_prog(prog, sk);
1514 [ - + ]: 3312 : if (err < 0) {
1515 : 0 : __bpf_prog_release(prog);
1516 : 0 : return err;
1517 : : }
1518 : :
1519 : : return 0;
1520 : : }
1521 : : EXPORT_SYMBOL_GPL(sk_attach_filter);
1522 : :
1523 : 0 : int sk_reuseport_attach_filter(struct sock_fprog *fprog, struct sock *sk)
1524 : : {
1525 : 0 : struct bpf_prog *prog = __get_filter(fprog, sk);
1526 : : int err;
1527 : :
1528 [ # # ]: 0 : if (IS_ERR(prog))
1529 : 0 : return PTR_ERR(prog);
1530 : :
1531 [ # # ]: 0 : if (bpf_prog_size(prog->len) > sysctl_optmem_max)
1532 : : err = -ENOMEM;
1533 : : else
1534 : 0 : err = reuseport_attach_prog(sk, prog);
1535 : :
1536 [ # # ]: 0 : if (err)
1537 : 0 : __bpf_prog_release(prog);
1538 : :
1539 : 0 : return err;
1540 : : }
1541 : :
1542 : 0 : static struct bpf_prog *__get_bpf(u32 ufd, struct sock *sk)
1543 : : {
1544 [ # # ]: 0 : if (sock_flag(sk, SOCK_FILTER_LOCKED))
1545 : : return ERR_PTR(-EPERM);
1546 : :
1547 : 0 : return bpf_prog_get_type(ufd, BPF_PROG_TYPE_SOCKET_FILTER);
1548 : : }
1549 : :
1550 : 0 : int sk_attach_bpf(u32 ufd, struct sock *sk)
1551 : : {
1552 : 0 : struct bpf_prog *prog = __get_bpf(ufd, sk);
1553 : : int err;
1554 : :
1555 [ # # ]: 0 : if (IS_ERR(prog))
1556 : 0 : return PTR_ERR(prog);
1557 : :
1558 : 0 : err = __sk_attach_prog(prog, sk);
1559 [ # # ]: 0 : if (err < 0) {
1560 : 0 : bpf_prog_put(prog);
1561 : 0 : return err;
1562 : : }
1563 : :
1564 : : return 0;
1565 : : }
1566 : :
1567 : 0 : int sk_reuseport_attach_bpf(u32 ufd, struct sock *sk)
1568 : : {
1569 : : struct bpf_prog *prog;
1570 : : int err;
1571 : :
1572 [ # # ]: 0 : if (sock_flag(sk, SOCK_FILTER_LOCKED))
1573 : : return -EPERM;
1574 : :
1575 : : prog = bpf_prog_get_type(ufd, BPF_PROG_TYPE_SOCKET_FILTER);
1576 [ # # # # ]: 0 : if (IS_ERR(prog) && PTR_ERR(prog) == -EINVAL)
1577 : : prog = bpf_prog_get_type(ufd, BPF_PROG_TYPE_SK_REUSEPORT);
1578 [ # # ]: 0 : if (IS_ERR(prog))
1579 : 0 : return PTR_ERR(prog);
1580 : :
1581 [ # # ]: 0 : if (prog->type == BPF_PROG_TYPE_SK_REUSEPORT) {
1582 : : /* Like other non BPF_PROG_TYPE_SOCKET_FILTER
1583 : : * bpf prog (e.g. sockmap). It depends on the
1584 : : * limitation imposed by bpf_prog_load().
1585 : : * Hence, sysctl_optmem_max is not checked.
1586 : : */
1587 [ # # ]: 0 : if ((sk->sk_type != SOCK_STREAM &&
1588 [ # # ]: 0 : sk->sk_type != SOCK_DGRAM) ||
1589 : 0 : (sk->sk_protocol != IPPROTO_UDP &&
1590 [ # # ]: 0 : sk->sk_protocol != IPPROTO_TCP) ||
1591 : 0 : (sk->sk_family != AF_INET &&
1592 : : sk->sk_family != AF_INET6)) {
1593 : : err = -ENOTSUPP;
1594 : : goto err_prog_put;
1595 : : }
1596 : : } else {
1597 : : /* BPF_PROG_TYPE_SOCKET_FILTER */
1598 [ # # ]: 0 : if (bpf_prog_size(prog->len) > sysctl_optmem_max) {
1599 : : err = -ENOMEM;
1600 : : goto err_prog_put;
1601 : : }
1602 : : }
1603 : :
1604 : 0 : err = reuseport_attach_prog(sk, prog);
1605 : : err_prog_put:
1606 [ # # ]: 0 : if (err)
1607 : 0 : bpf_prog_put(prog);
1608 : :
1609 : 0 : return err;
1610 : : }
1611 : :
1612 : 0 : void sk_reuseport_prog_free(struct bpf_prog *prog)
1613 : : {
1614 [ # # ]: 0 : if (!prog)
1615 : 0 : return;
1616 : :
1617 [ # # ]: 0 : if (prog->type == BPF_PROG_TYPE_SK_REUSEPORT)
1618 : 0 : bpf_prog_put(prog);
1619 : : else
1620 : : bpf_prog_destroy(prog);
1621 : : }
1622 : :
1623 : : struct bpf_scratchpad {
1624 : : union {
1625 : : __be32 diff[MAX_BPF_STACK / sizeof(__be32)];
1626 : : u8 buff[MAX_BPF_STACK];
1627 : : };
1628 : : };
1629 : :
1630 : : static DEFINE_PER_CPU(struct bpf_scratchpad, bpf_sp);
1631 : :
1632 : : static inline int __bpf_try_make_writable(struct sk_buff *skb,
1633 : : unsigned int write_len)
1634 : : {
1635 : 0 : return skb_ensure_writable(skb, write_len);
1636 : : }
1637 : :
1638 : 0 : static inline int bpf_try_make_writable(struct sk_buff *skb,
1639 : : unsigned int write_len)
1640 : : {
1641 : : int err = __bpf_try_make_writable(skb, write_len);
1642 : :
1643 : : bpf_compute_data_pointers(skb);
1644 : 0 : return err;
1645 : : }
1646 : :
1647 : 0 : static int bpf_try_make_head_writable(struct sk_buff *skb)
1648 : : {
1649 : 0 : return bpf_try_make_writable(skb, skb_headlen(skb));
1650 : : }
1651 : :
1652 : 0 : static inline void bpf_push_mac_rcsum(struct sk_buff *skb)
1653 : : {
1654 [ # # ]: 0 : if (skb_at_tc_ingress(skb))
1655 : 0 : skb_postpush_rcsum(skb, skb_mac_header(skb), skb->mac_len);
1656 : 0 : }
1657 : :
1658 : 0 : static inline void bpf_pull_mac_rcsum(struct sk_buff *skb)
1659 : : {
1660 [ # # ]: 0 : if (skb_at_tc_ingress(skb))
1661 : 0 : skb_postpull_rcsum(skb, skb_mac_header(skb), skb->mac_len);
1662 : 0 : }
1663 : :
1664 : 0 : BPF_CALL_5(bpf_skb_store_bytes, struct sk_buff *, skb, u32, offset,
1665 : : const void *, from, u32, len, u64, flags)
1666 : : {
1667 : : void *ptr;
1668 : :
1669 [ # # ]: 0 : if (unlikely(flags & ~(BPF_F_RECOMPUTE_CSUM | BPF_F_INVALIDATE_HASH)))
1670 : : return -EINVAL;
1671 [ # # ]: 0 : if (unlikely(offset > 0xffff))
1672 : : return -EFAULT;
1673 [ # # ]: 0 : if (unlikely(bpf_try_make_writable(skb, offset + len)))
1674 : : return -EFAULT;
1675 : :
1676 : 0 : ptr = skb->data + offset;
1677 [ # # ]: 0 : if (flags & BPF_F_RECOMPUTE_CSUM)
1678 : : __skb_postpull_rcsum(skb, ptr, len, offset);
1679 : :
1680 : 0 : memcpy(ptr, from, len);
1681 : :
1682 [ # # ]: 0 : if (flags & BPF_F_RECOMPUTE_CSUM)
1683 : : __skb_postpush_rcsum(skb, ptr, len, offset);
1684 [ # # ]: 0 : if (flags & BPF_F_INVALIDATE_HASH)
1685 : 0 : skb_clear_hash(skb);
1686 : :
1687 : : return 0;
1688 : : }
1689 : :
1690 : : static const struct bpf_func_proto bpf_skb_store_bytes_proto = {
1691 : : .func = bpf_skb_store_bytes,
1692 : : .gpl_only = false,
1693 : : .ret_type = RET_INTEGER,
1694 : : .arg1_type = ARG_PTR_TO_CTX,
1695 : : .arg2_type = ARG_ANYTHING,
1696 : : .arg3_type = ARG_PTR_TO_MEM,
1697 : : .arg4_type = ARG_CONST_SIZE,
1698 : : .arg5_type = ARG_ANYTHING,
1699 : : };
1700 : :
1701 : 0 : BPF_CALL_4(bpf_skb_load_bytes, const struct sk_buff *, skb, u32, offset,
1702 : : void *, to, u32, len)
1703 : : {
1704 : : void *ptr;
1705 : :
1706 [ # # # # ]: 0 : if (unlikely(offset > 0xffff))
1707 : : goto err_clear;
1708 : :
1709 : 0 : ptr = skb_header_pointer(skb, offset, len, to);
1710 [ # # # # ]: 0 : if (unlikely(!ptr))
1711 : : goto err_clear;
1712 [ # # # # ]: 0 : if (ptr != to)
1713 : 0 : memcpy(to, ptr, len);
1714 : :
1715 : : return 0;
1716 : : err_clear:
1717 : 0 : memset(to, 0, len);
1718 : : return -EFAULT;
1719 : : }
1720 : :
1721 : : static const struct bpf_func_proto bpf_skb_load_bytes_proto = {
1722 : : .func = bpf_skb_load_bytes,
1723 : : .gpl_only = false,
1724 : : .ret_type = RET_INTEGER,
1725 : : .arg1_type = ARG_PTR_TO_CTX,
1726 : : .arg2_type = ARG_ANYTHING,
1727 : : .arg3_type = ARG_PTR_TO_UNINIT_MEM,
1728 : : .arg4_type = ARG_CONST_SIZE,
1729 : : };
1730 : :
1731 : 0 : BPF_CALL_4(bpf_flow_dissector_load_bytes,
1732 : : const struct bpf_flow_dissector *, ctx, u32, offset,
1733 : : void *, to, u32, len)
1734 : : {
1735 : : void *ptr;
1736 : :
1737 [ # # ]: 0 : if (unlikely(offset > 0xffff))
1738 : : goto err_clear;
1739 : :
1740 [ # # ]: 0 : if (unlikely(!ctx->skb))
1741 : : goto err_clear;
1742 : :
1743 : 0 : ptr = skb_header_pointer(ctx->skb, offset, len, to);
1744 [ # # ]: 0 : if (unlikely(!ptr))
1745 : : goto err_clear;
1746 [ # # ]: 0 : if (ptr != to)
1747 : 0 : memcpy(to, ptr, len);
1748 : :
1749 : : return 0;
1750 : : err_clear:
1751 : 0 : memset(to, 0, len);
1752 : : return -EFAULT;
1753 : : }
1754 : :
1755 : : static const struct bpf_func_proto bpf_flow_dissector_load_bytes_proto = {
1756 : : .func = bpf_flow_dissector_load_bytes,
1757 : : .gpl_only = false,
1758 : : .ret_type = RET_INTEGER,
1759 : : .arg1_type = ARG_PTR_TO_CTX,
1760 : : .arg2_type = ARG_ANYTHING,
1761 : : .arg3_type = ARG_PTR_TO_UNINIT_MEM,
1762 : : .arg4_type = ARG_CONST_SIZE,
1763 : : };
1764 : :
1765 : 0 : BPF_CALL_5(bpf_skb_load_bytes_relative, const struct sk_buff *, skb,
1766 : : u32, offset, void *, to, u32, len, u32, start_header)
1767 : : {
1768 : 0 : u8 *end = skb_tail_pointer(skb);
1769 : : u8 *start, *ptr;
1770 : :
1771 [ # # # # ]: 0 : if (unlikely(offset > 0xffff))
1772 : : goto err_clear;
1773 : :
1774 [ # # # # : 0 : switch (start_header) {
# # ]
1775 : : case BPF_HDR_START_MAC:
1776 [ # # # # ]: 0 : if (unlikely(!skb_mac_header_was_set(skb)))
1777 : : goto err_clear;
1778 : 0 : start = skb_mac_header(skb);
1779 : : break;
1780 : : case BPF_HDR_START_NET:
1781 : 0 : start = skb_network_header(skb);
1782 : : break;
1783 : : default:
1784 : : goto err_clear;
1785 : : }
1786 : :
1787 : 0 : ptr = start + offset;
1788 : :
1789 [ # # # # ]: 0 : if (likely(ptr + len <= end)) {
1790 : 0 : memcpy(to, ptr, len);
1791 : : return 0;
1792 : : }
1793 : :
1794 : : err_clear:
1795 : 0 : memset(to, 0, len);
1796 : : return -EFAULT;
1797 : : }
1798 : :
1799 : : static const struct bpf_func_proto bpf_skb_load_bytes_relative_proto = {
1800 : : .func = bpf_skb_load_bytes_relative,
1801 : : .gpl_only = false,
1802 : : .ret_type = RET_INTEGER,
1803 : : .arg1_type = ARG_PTR_TO_CTX,
1804 : : .arg2_type = ARG_ANYTHING,
1805 : : .arg3_type = ARG_PTR_TO_UNINIT_MEM,
1806 : : .arg4_type = ARG_CONST_SIZE,
1807 : : .arg5_type = ARG_ANYTHING,
1808 : : };
1809 : :
1810 : 0 : BPF_CALL_2(bpf_skb_pull_data, struct sk_buff *, skb, u32, len)
1811 : : {
1812 : : /* Idea is the following: should the needed direct read/write
1813 : : * test fail during runtime, we can pull in more data and redo
1814 : : * again, since implicitly, we invalidate previous checks here.
1815 : : *
1816 : : * Or, since we know how much we need to make read/writeable,
1817 : : * this can be done once at the program beginning for direct
1818 : : * access case. By this we overcome limitations of only current
1819 : : * headroom being accessible.
1820 : : */
1821 [ # # ]: 0 : return bpf_try_make_writable(skb, len ? : skb_headlen(skb));
1822 : : }
1823 : :
1824 : : static const struct bpf_func_proto bpf_skb_pull_data_proto = {
1825 : : .func = bpf_skb_pull_data,
1826 : : .gpl_only = false,
1827 : : .ret_type = RET_INTEGER,
1828 : : .arg1_type = ARG_PTR_TO_CTX,
1829 : : .arg2_type = ARG_ANYTHING,
1830 : : };
1831 : :
1832 : 0 : BPF_CALL_1(bpf_sk_fullsock, struct sock *, sk)
1833 : : {
1834 [ # # ]: 0 : return sk_fullsock(sk) ? (unsigned long)sk : (unsigned long)NULL;
1835 : : }
1836 : :
1837 : : static const struct bpf_func_proto bpf_sk_fullsock_proto = {
1838 : : .func = bpf_sk_fullsock,
1839 : : .gpl_only = false,
1840 : : .ret_type = RET_PTR_TO_SOCKET_OR_NULL,
1841 : : .arg1_type = ARG_PTR_TO_SOCK_COMMON,
1842 : : };
1843 : :
1844 : 0 : static inline int sk_skb_try_make_writable(struct sk_buff *skb,
1845 : : unsigned int write_len)
1846 : : {
1847 : : int err = __bpf_try_make_writable(skb, write_len);
1848 : :
1849 : : bpf_compute_data_end_sk_skb(skb);
1850 : 0 : return err;
1851 : : }
1852 : :
1853 : 0 : BPF_CALL_2(sk_skb_pull_data, struct sk_buff *, skb, u32, len)
1854 : : {
1855 : : /* Idea is the following: should the needed direct read/write
1856 : : * test fail during runtime, we can pull in more data and redo
1857 : : * again, since implicitly, we invalidate previous checks here.
1858 : : *
1859 : : * Or, since we know how much we need to make read/writeable,
1860 : : * this can be done once at the program beginning for direct
1861 : : * access case. By this we overcome limitations of only current
1862 : : * headroom being accessible.
1863 : : */
1864 [ # # ]: 0 : return sk_skb_try_make_writable(skb, len ? : skb_headlen(skb));
1865 : : }
1866 : :
1867 : : static const struct bpf_func_proto sk_skb_pull_data_proto = {
1868 : : .func = sk_skb_pull_data,
1869 : : .gpl_only = false,
1870 : : .ret_type = RET_INTEGER,
1871 : : .arg1_type = ARG_PTR_TO_CTX,
1872 : : .arg2_type = ARG_ANYTHING,
1873 : : };
1874 : :
1875 : 0 : BPF_CALL_5(bpf_l3_csum_replace, struct sk_buff *, skb, u32, offset,
1876 : : u64, from, u64, to, u64, flags)
1877 : : {
1878 : : __sum16 *ptr;
1879 : :
1880 [ # # ]: 0 : if (unlikely(flags & ~(BPF_F_HDR_FIELD_MASK)))
1881 : : return -EINVAL;
1882 [ # # # # ]: 0 : if (unlikely(offset > 0xffff || offset & 1))
1883 : : return -EFAULT;
1884 [ # # ]: 0 : if (unlikely(bpf_try_make_writable(skb, offset + sizeof(*ptr))))
1885 : : return -EFAULT;
1886 : :
1887 : 0 : ptr = (__sum16 *)(skb->data + offset);
1888 [ # # # # ]: 0 : switch (flags & BPF_F_HDR_FIELD_MASK) {
1889 : : case 0:
1890 [ # # ]: 0 : if (unlikely(from != 0))
1891 : : return -EINVAL;
1892 : :
1893 : 0 : csum_replace_by_diff(ptr, to);
1894 : : break;
1895 : : case 2:
1896 : 0 : csum_replace2(ptr, from, to);
1897 : : break;
1898 : : case 4:
1899 : 0 : csum_replace4(ptr, from, to);
1900 : : break;
1901 : : default:
1902 : : return -EINVAL;
1903 : : }
1904 : :
1905 : : return 0;
1906 : : }
1907 : :
1908 : : static const struct bpf_func_proto bpf_l3_csum_replace_proto = {
1909 : : .func = bpf_l3_csum_replace,
1910 : : .gpl_only = false,
1911 : : .ret_type = RET_INTEGER,
1912 : : .arg1_type = ARG_PTR_TO_CTX,
1913 : : .arg2_type = ARG_ANYTHING,
1914 : : .arg3_type = ARG_ANYTHING,
1915 : : .arg4_type = ARG_ANYTHING,
1916 : : .arg5_type = ARG_ANYTHING,
1917 : : };
1918 : :
1919 : 0 : BPF_CALL_5(bpf_l4_csum_replace, struct sk_buff *, skb, u32, offset,
1920 : : u64, from, u64, to, u64, flags)
1921 : : {
1922 : 0 : bool is_pseudo = flags & BPF_F_PSEUDO_HDR;
1923 : 0 : bool is_mmzero = flags & BPF_F_MARK_MANGLED_0;
1924 : 0 : bool do_mforce = flags & BPF_F_MARK_ENFORCE;
1925 : : __sum16 *ptr;
1926 : :
1927 [ # # ]: 0 : if (unlikely(flags & ~(BPF_F_MARK_MANGLED_0 | BPF_F_MARK_ENFORCE |
1928 : : BPF_F_PSEUDO_HDR | BPF_F_HDR_FIELD_MASK)))
1929 : : return -EINVAL;
1930 [ # # # # ]: 0 : if (unlikely(offset > 0xffff || offset & 1))
1931 : : return -EFAULT;
1932 [ # # ]: 0 : if (unlikely(bpf_try_make_writable(skb, offset + sizeof(*ptr))))
1933 : : return -EFAULT;
1934 : :
1935 : 0 : ptr = (__sum16 *)(skb->data + offset);
1936 [ # # # # ]: 0 : if (is_mmzero && !do_mforce && !*ptr)
1937 : : return 0;
1938 : :
1939 [ # # # # ]: 0 : switch (flags & BPF_F_HDR_FIELD_MASK) {
1940 : : case 0:
1941 [ # # ]: 0 : if (unlikely(from != 0))
1942 : : return -EINVAL;
1943 : :
1944 : 0 : inet_proto_csum_replace_by_diff(ptr, skb, to, is_pseudo);
1945 : : break;
1946 : : case 2:
1947 : 0 : inet_proto_csum_replace2(ptr, skb, from, to, is_pseudo);
1948 : : break;
1949 : : case 4:
1950 : 0 : inet_proto_csum_replace4(ptr, skb, from, to, is_pseudo);
1951 : : break;
1952 : : default:
1953 : : return -EINVAL;
1954 : : }
1955 : :
1956 [ # # # # ]: 0 : if (is_mmzero && !*ptr)
1957 : 0 : *ptr = CSUM_MANGLED_0;
1958 : : return 0;
1959 : : }
1960 : :
1961 : : static const struct bpf_func_proto bpf_l4_csum_replace_proto = {
1962 : : .func = bpf_l4_csum_replace,
1963 : : .gpl_only = false,
1964 : : .ret_type = RET_INTEGER,
1965 : : .arg1_type = ARG_PTR_TO_CTX,
1966 : : .arg2_type = ARG_ANYTHING,
1967 : : .arg3_type = ARG_ANYTHING,
1968 : : .arg4_type = ARG_ANYTHING,
1969 : : .arg5_type = ARG_ANYTHING,
1970 : : };
1971 : :
1972 : 0 : BPF_CALL_5(bpf_csum_diff, __be32 *, from, u32, from_size,
1973 : : __be32 *, to, u32, to_size, __wsum, seed)
1974 : : {
1975 : 0 : struct bpf_scratchpad *sp = this_cpu_ptr(&bpf_sp);
1976 : 0 : u32 diff_size = from_size + to_size;
1977 : : int i, j = 0;
1978 : :
1979 : : /* This is quite flexible, some examples:
1980 : : *
1981 : : * from_size == 0, to_size > 0, seed := csum --> pushing data
1982 : : * from_size > 0, to_size == 0, seed := csum --> pulling data
1983 : : * from_size > 0, to_size > 0, seed := 0 --> diffing data
1984 : : *
1985 : : * Even for diffing, from_size and to_size don't need to be equal.
1986 : : */
1987 [ # # # # ]: 0 : if (unlikely(((from_size | to_size) & (sizeof(__be32) - 1)) ||
1988 : : diff_size > sizeof(sp->diff)))
1989 : : return -EINVAL;
1990 : :
1991 [ # # ]: 0 : for (i = 0; i < from_size / sizeof(__be32); i++, j++)
1992 : 0 : sp->diff[j] = ~from[i];
1993 [ # # ]: 0 : for (i = 0; i < to_size / sizeof(__be32); i++, j++)
1994 : 0 : sp->diff[j] = to[i];
1995 : :
1996 : 0 : return csum_partial(sp->diff, diff_size, seed);
1997 : : }
1998 : :
1999 : : static const struct bpf_func_proto bpf_csum_diff_proto = {
2000 : : .func = bpf_csum_diff,
2001 : : .gpl_only = false,
2002 : : .pkt_access = true,
2003 : : .ret_type = RET_INTEGER,
2004 : : .arg1_type = ARG_PTR_TO_MEM_OR_NULL,
2005 : : .arg2_type = ARG_CONST_SIZE_OR_ZERO,
2006 : : .arg3_type = ARG_PTR_TO_MEM_OR_NULL,
2007 : : .arg4_type = ARG_CONST_SIZE_OR_ZERO,
2008 : : .arg5_type = ARG_ANYTHING,
2009 : : };
2010 : :
2011 : 0 : BPF_CALL_2(bpf_csum_update, struct sk_buff *, skb, __wsum, csum)
2012 : : {
2013 : : /* The interface is to be used in combination with bpf_csum_diff()
2014 : : * for direct packet writes. csum rotation for alignment as well
2015 : : * as emulating csum_sub() can be done from the eBPF program.
2016 : : */
2017 [ # # ]: 0 : if (skb->ip_summed == CHECKSUM_COMPLETE)
2018 : 0 : return (skb->csum = csum_add(skb->csum, csum));
2019 : :
2020 : : return -ENOTSUPP;
2021 : : }
2022 : :
2023 : : static const struct bpf_func_proto bpf_csum_update_proto = {
2024 : : .func = bpf_csum_update,
2025 : : .gpl_only = false,
2026 : : .ret_type = RET_INTEGER,
2027 : : .arg1_type = ARG_PTR_TO_CTX,
2028 : : .arg2_type = ARG_ANYTHING,
2029 : : };
2030 : :
2031 : : static inline int __bpf_rx_skb(struct net_device *dev, struct sk_buff *skb)
2032 : : {
2033 : 0 : return dev_forward_skb(dev, skb);
2034 : : }
2035 : :
2036 : 0 : static inline int __bpf_rx_skb_no_mac(struct net_device *dev,
2037 : : struct sk_buff *skb)
2038 : : {
2039 : : int ret = ____dev_forward_skb(dev, skb);
2040 : :
2041 [ # # ]: 0 : if (likely(!ret)) {
2042 : 0 : skb->dev = dev;
2043 : 0 : ret = netif_rx(skb);
2044 : : }
2045 : :
2046 : 0 : return ret;
2047 : : }
2048 : :
2049 : 0 : static inline int __bpf_tx_skb(struct net_device *dev, struct sk_buff *skb)
2050 : : {
2051 : : int ret;
2052 : :
2053 [ # # ]: 0 : if (dev_xmit_recursion()) {
2054 [ # # ]: 0 : net_crit_ratelimited("bpf: recursion limit reached on datapath, buggy bpf program?\n");
2055 : 0 : kfree_skb(skb);
2056 : 0 : return -ENETDOWN;
2057 : : }
2058 : :
2059 : 0 : skb->dev = dev;
2060 : 0 : skb->tstamp = 0;
2061 : :
2062 : : dev_xmit_recursion_inc();
2063 : 0 : ret = dev_queue_xmit(skb);
2064 : : dev_xmit_recursion_dec();
2065 : :
2066 : 0 : return ret;
2067 : : }
2068 : :
2069 : 0 : static int __bpf_redirect_no_mac(struct sk_buff *skb, struct net_device *dev,
2070 : : u32 flags)
2071 : : {
2072 : 0 : unsigned int mlen = skb_network_offset(skb);
2073 : :
2074 [ # # ]: 0 : if (mlen) {
2075 : 0 : __skb_pull(skb, mlen);
2076 : :
2077 : : /* At ingress, the mac header has already been pulled once.
2078 : : * At egress, skb_pospull_rcsum has to be done in case that
2079 : : * the skb is originated from ingress (i.e. a forwarded skb)
2080 : : * to ensure that rcsum starts at net header.
2081 : : */
2082 [ # # ]: 0 : if (!skb_at_tc_ingress(skb))
2083 : 0 : skb_postpull_rcsum(skb, skb_mac_header(skb), mlen);
2084 : : }
2085 : : skb_pop_mac_header(skb);
2086 : : skb_reset_mac_len(skb);
2087 : 0 : return flags & BPF_F_INGRESS ?
2088 [ # # ]: 0 : __bpf_rx_skb_no_mac(dev, skb) : __bpf_tx_skb(dev, skb);
2089 : : }
2090 : :
2091 : 0 : static int __bpf_redirect_common(struct sk_buff *skb, struct net_device *dev,
2092 : : u32 flags)
2093 : : {
2094 : : /* Verify that a link layer header is carried */
2095 [ # # ]: 0 : if (unlikely(skb->mac_header >= skb->network_header)) {
2096 : 0 : kfree_skb(skb);
2097 : 0 : return -ERANGE;
2098 : : }
2099 : :
2100 : 0 : bpf_push_mac_rcsum(skb);
2101 : 0 : return flags & BPF_F_INGRESS ?
2102 [ # # ]: 0 : __bpf_rx_skb(dev, skb) : __bpf_tx_skb(dev, skb);
2103 : : }
2104 : :
2105 : 0 : static int __bpf_redirect(struct sk_buff *skb, struct net_device *dev,
2106 : : u32 flags)
2107 : : {
2108 [ # # ]: 0 : if (dev_is_mac_header_xmit(dev))
2109 : 0 : return __bpf_redirect_common(skb, dev, flags);
2110 : : else
2111 : 0 : return __bpf_redirect_no_mac(skb, dev, flags);
2112 : : }
2113 : :
2114 : 0 : BPF_CALL_3(bpf_clone_redirect, struct sk_buff *, skb, u32, ifindex, u64, flags)
2115 : : {
2116 : : struct net_device *dev;
2117 : : struct sk_buff *clone;
2118 : : int ret;
2119 : :
2120 [ # # ]: 0 : if (unlikely(flags & ~(BPF_F_INGRESS)))
2121 : : return -EINVAL;
2122 : :
2123 : 0 : dev = dev_get_by_index_rcu(dev_net(skb->dev), ifindex);
2124 [ # # ]: 0 : if (unlikely(!dev))
2125 : : return -EINVAL;
2126 : :
2127 : 0 : clone = skb_clone(skb, GFP_ATOMIC);
2128 [ # # ]: 0 : if (unlikely(!clone))
2129 : : return -ENOMEM;
2130 : :
2131 : : /* For direct write, we need to keep the invariant that the skbs
2132 : : * we're dealing with need to be uncloned. Should uncloning fail
2133 : : * here, we need to free the just generated clone to unclone once
2134 : : * again.
2135 : : */
2136 : 0 : ret = bpf_try_make_head_writable(skb);
2137 [ # # ]: 0 : if (unlikely(ret)) {
2138 : 0 : kfree_skb(clone);
2139 : : return -ENOMEM;
2140 : : }
2141 : :
2142 : 0 : return __bpf_redirect(clone, dev, flags);
2143 : : }
2144 : :
2145 : : static const struct bpf_func_proto bpf_clone_redirect_proto = {
2146 : : .func = bpf_clone_redirect,
2147 : : .gpl_only = false,
2148 : : .ret_type = RET_INTEGER,
2149 : : .arg1_type = ARG_PTR_TO_CTX,
2150 : : .arg2_type = ARG_ANYTHING,
2151 : : .arg3_type = ARG_ANYTHING,
2152 : : };
2153 : :
2154 : : DEFINE_PER_CPU(struct bpf_redirect_info, bpf_redirect_info);
2155 : : EXPORT_PER_CPU_SYMBOL_GPL(bpf_redirect_info);
2156 : :
2157 : 0 : BPF_CALL_2(bpf_redirect, u32, ifindex, u64, flags)
2158 : : {
2159 : 0 : struct bpf_redirect_info *ri = this_cpu_ptr(&bpf_redirect_info);
2160 : :
2161 [ # # ]: 0 : if (unlikely(flags & ~(BPF_F_INGRESS)))
2162 : : return TC_ACT_SHOT;
2163 : :
2164 : 0 : ri->flags = flags;
2165 : 0 : ri->tgt_index = ifindex;
2166 : :
2167 : : return TC_ACT_REDIRECT;
2168 : : }
2169 : :
2170 : 0 : int skb_do_redirect(struct sk_buff *skb)
2171 : : {
2172 : 0 : struct bpf_redirect_info *ri = this_cpu_ptr(&bpf_redirect_info);
2173 : : struct net_device *dev;
2174 : :
2175 : 0 : dev = dev_get_by_index_rcu(dev_net(skb->dev), ri->tgt_index);
2176 : 0 : ri->tgt_index = 0;
2177 [ # # ]: 0 : if (unlikely(!dev)) {
2178 : 0 : kfree_skb(skb);
2179 : 0 : return -EINVAL;
2180 : : }
2181 : :
2182 : 0 : return __bpf_redirect(skb, dev, ri->flags);
2183 : : }
2184 : :
2185 : : static const struct bpf_func_proto bpf_redirect_proto = {
2186 : : .func = bpf_redirect,
2187 : : .gpl_only = false,
2188 : : .ret_type = RET_INTEGER,
2189 : : .arg1_type = ARG_ANYTHING,
2190 : : .arg2_type = ARG_ANYTHING,
2191 : : };
2192 : :
2193 : 0 : BPF_CALL_2(bpf_msg_apply_bytes, struct sk_msg *, msg, u32, bytes)
2194 : : {
2195 : 0 : msg->apply_bytes = bytes;
2196 : : return 0;
2197 : : }
2198 : :
2199 : : static const struct bpf_func_proto bpf_msg_apply_bytes_proto = {
2200 : : .func = bpf_msg_apply_bytes,
2201 : : .gpl_only = false,
2202 : : .ret_type = RET_INTEGER,
2203 : : .arg1_type = ARG_PTR_TO_CTX,
2204 : : .arg2_type = ARG_ANYTHING,
2205 : : };
2206 : :
2207 : 0 : BPF_CALL_2(bpf_msg_cork_bytes, struct sk_msg *, msg, u32, bytes)
2208 : : {
2209 : 0 : msg->cork_bytes = bytes;
2210 : : return 0;
2211 : : }
2212 : :
2213 : : static const struct bpf_func_proto bpf_msg_cork_bytes_proto = {
2214 : : .func = bpf_msg_cork_bytes,
2215 : : .gpl_only = false,
2216 : : .ret_type = RET_INTEGER,
2217 : : .arg1_type = ARG_PTR_TO_CTX,
2218 : : .arg2_type = ARG_ANYTHING,
2219 : : };
2220 : :
2221 : 0 : BPF_CALL_4(bpf_msg_pull_data, struct sk_msg *, msg, u32, start,
2222 : : u32, end, u64, flags)
2223 : : {
2224 : 0 : u32 len = 0, offset = 0, copy = 0, poffset = 0, bytes = end - start;
2225 : : u32 first_sge, last_sge, i, shift, bytes_sg_total;
2226 : : struct scatterlist *sge;
2227 : : u8 *raw, *to, *from;
2228 : : struct page *page;
2229 : :
2230 [ # # ]: 0 : if (unlikely(flags || end <= start))
2231 : : return -EINVAL;
2232 : :
2233 : : /* First find the starting scatterlist element */
2234 : 0 : i = msg->sg.start;
2235 : : do {
2236 : 0 : offset += len;
2237 : 0 : len = sk_msg_elem(msg, i)->length;
2238 [ # # ]: 0 : if (start < offset + len)
2239 : : break;
2240 [ # # ]: 0 : sk_msg_iter_var_next(i);
2241 [ # # ]: 0 : } while (i != msg->sg.end);
2242 : :
2243 [ # # ]: 0 : if (unlikely(start >= offset + len))
2244 : : return -EINVAL;
2245 : :
2246 : : first_sge = i;
2247 : : /* The start may point into the sg element so we need to also
2248 : : * account for the headroom.
2249 : : */
2250 : 0 : bytes_sg_total = start - offset + bytes;
2251 [ # # # # ]: 0 : if (!msg->sg.copy[i] && bytes_sg_total <= len)
2252 : : goto out;
2253 : :
2254 : : /* At this point we need to linearize multiple scatterlist
2255 : : * elements or a single shared page. Either way we need to
2256 : : * copy into a linear buffer exclusively owned by BPF. Then
2257 : : * place the buffer in the scatterlist and fixup the original
2258 : : * entries by removing the entries now in the linear buffer
2259 : : * and shifting the remaining entries. For now we do not try
2260 : : * to copy partial entries to avoid complexity of running out
2261 : : * of sg_entry slots. The downside is reading a single byte
2262 : : * will copy the entire sg entry.
2263 : : */
2264 : : do {
2265 : 0 : copy += sk_msg_elem(msg, i)->length;
2266 [ # # ]: 0 : sk_msg_iter_var_next(i);
2267 [ # # ]: 0 : if (bytes_sg_total <= copy)
2268 : : break;
2269 [ # # ]: 0 : } while (i != msg->sg.end);
2270 : 0 : last_sge = i;
2271 : :
2272 [ # # ]: 0 : if (unlikely(bytes_sg_total > copy))
2273 : : return -EINVAL;
2274 : :
2275 : 0 : page = alloc_pages(__GFP_NOWARN | GFP_ATOMIC | __GFP_COMP,
2276 : : get_order(copy));
2277 [ # # ]: 0 : if (unlikely(!page))
2278 : : return -ENOMEM;
2279 : :
2280 : : raw = page_address(page);
2281 : : i = first_sge;
2282 : : do {
2283 : 0 : sge = sk_msg_elem(msg, i);
2284 : 0 : from = sg_virt(sge);
2285 : 0 : len = sge->length;
2286 : 0 : to = raw + poffset;
2287 : :
2288 : 0 : memcpy(to, from, len);
2289 : 0 : poffset += len;
2290 : 0 : sge->length = 0;
2291 : 0 : put_page(sg_page(sge));
2292 : :
2293 [ # # ]: 0 : sk_msg_iter_var_next(i);
2294 [ # # ]: 0 : } while (i != last_sge);
2295 : :
2296 : 0 : sg_set_page(&msg->sg.data[first_sge], page, copy, 0);
2297 : :
2298 : : /* To repair sg ring we need to shift entries. If we only
2299 : : * had a single entry though we can just replace it and
2300 : : * be done. Otherwise walk the ring and shift the entries.
2301 : : */
2302 [ # # # # ]: 0 : WARN_ON_ONCE(last_sge == first_sge);
2303 [ # # ]: 0 : shift = last_sge > first_sge ?
2304 : 0 : last_sge - first_sge - 1 :
2305 : 0 : NR_MSG_FRAG_IDS - first_sge + last_sge - 1;
2306 [ # # ]: 0 : if (!shift)
2307 : : goto out;
2308 : :
2309 : : i = first_sge;
2310 [ # # ]: 0 : sk_msg_iter_var_next(i);
2311 : : do {
2312 : : u32 move_from;
2313 : :
2314 [ # # ]: 0 : if (i + shift >= NR_MSG_FRAG_IDS)
2315 : 0 : move_from = i + shift - NR_MSG_FRAG_IDS;
2316 : : else
2317 : : move_from = i + shift;
2318 [ # # ]: 0 : if (move_from == msg->sg.end)
2319 : : break;
2320 : :
2321 : 0 : msg->sg.data[i] = msg->sg.data[move_from];
2322 : 0 : msg->sg.data[move_from].length = 0;
2323 : 0 : msg->sg.data[move_from].page_link = 0;
2324 : 0 : msg->sg.data[move_from].offset = 0;
2325 [ # # ]: 0 : sk_msg_iter_var_next(i);
2326 : : } while (1);
2327 : :
2328 [ # # ]: 0 : msg->sg.end = msg->sg.end - shift > msg->sg.end ?
2329 : : msg->sg.end - shift + NR_MSG_FRAG_IDS :
2330 : : msg->sg.end - shift;
2331 : : out:
2332 : 0 : msg->data = sg_virt(&msg->sg.data[first_sge]) + start - offset;
2333 : 0 : msg->data_end = msg->data + bytes;
2334 : : return 0;
2335 : : }
2336 : :
2337 : : static const struct bpf_func_proto bpf_msg_pull_data_proto = {
2338 : : .func = bpf_msg_pull_data,
2339 : : .gpl_only = false,
2340 : : .ret_type = RET_INTEGER,
2341 : : .arg1_type = ARG_PTR_TO_CTX,
2342 : : .arg2_type = ARG_ANYTHING,
2343 : : .arg3_type = ARG_ANYTHING,
2344 : : .arg4_type = ARG_ANYTHING,
2345 : : };
2346 : :
2347 : 0 : BPF_CALL_4(bpf_msg_push_data, struct sk_msg *, msg, u32, start,
2348 : : u32, len, u64, flags)
2349 : : {
2350 : 0 : struct scatterlist sge, nsge, nnsge, rsge = {0}, *psge;
2351 : : u32 new, i = 0, l = 0, space, copy = 0, offset = 0;
2352 : : u8 *raw, *to, *from;
2353 : : struct page *page;
2354 : :
2355 [ # # ]: 0 : if (unlikely(flags))
2356 : : return -EINVAL;
2357 : :
2358 : : /* First find the starting scatterlist element */
2359 : 0 : i = msg->sg.start;
2360 : : do {
2361 : 0 : offset += l;
2362 : 0 : l = sk_msg_elem(msg, i)->length;
2363 : :
2364 [ # # ]: 0 : if (start < offset + l)
2365 : : break;
2366 [ # # ]: 0 : sk_msg_iter_var_next(i);
2367 [ # # ]: 0 : } while (i != msg->sg.end);
2368 : :
2369 [ # # ]: 0 : if (start >= offset + l)
2370 : : return -EINVAL;
2371 : :
2372 : 0 : space = MAX_MSG_FRAGS - sk_msg_elem_used(msg);
2373 : :
2374 : : /* If no space available will fallback to copy, we need at
2375 : : * least one scatterlist elem available to push data into
2376 : : * when start aligns to the beginning of an element or two
2377 : : * when it falls inside an element. We handle the start equals
2378 : : * offset case because its the common case for inserting a
2379 : : * header.
2380 : : */
2381 [ # # # # ]: 0 : if (!space || (space == 1 && start != offset))
2382 : 0 : copy = msg->sg.data[i].length;
2383 : :
2384 : 0 : page = alloc_pages(__GFP_NOWARN | GFP_ATOMIC | __GFP_COMP,
2385 : : get_order(copy + len));
2386 [ # # ]: 0 : if (unlikely(!page))
2387 : : return -ENOMEM;
2388 : :
2389 [ # # ]: 0 : if (copy) {
2390 : : int front, back;
2391 : :
2392 : : raw = page_address(page);
2393 : :
2394 : 0 : psge = sk_msg_elem(msg, i);
2395 : 0 : front = start - offset;
2396 : 0 : back = psge->length - front;
2397 : 0 : from = sg_virt(psge);
2398 : :
2399 [ # # ]: 0 : if (front)
2400 : 0 : memcpy(raw, from, front);
2401 : :
2402 [ # # ]: 0 : if (back) {
2403 : 0 : from += front;
2404 : 0 : to = raw + front + len;
2405 : :
2406 : 0 : memcpy(to, from, back);
2407 : : }
2408 : :
2409 : 0 : put_page(sg_page(psge));
2410 [ # # ]: 0 : } else if (start - offset) {
2411 : 0 : psge = sk_msg_elem(msg, i);
2412 : 0 : rsge = sk_msg_elem_cpy(msg, i);
2413 : :
2414 : 0 : psge->length = start - offset;
2415 : 0 : rsge.length -= psge->length;
2416 : 0 : rsge.offset += start;
2417 : :
2418 [ # # ]: 0 : sk_msg_iter_var_next(i);
2419 : 0 : sg_unmark_end(psge);
2420 : 0 : sg_unmark_end(&rsge);
2421 [ # # ]: 0 : sk_msg_iter_next(msg, end);
2422 : : }
2423 : :
2424 : : /* Slot(s) to place newly allocated data */
2425 : : new = i;
2426 : :
2427 : : /* Shift one or two slots as needed */
2428 [ # # ]: 0 : if (!copy) {
2429 : 0 : sge = sk_msg_elem_cpy(msg, i);
2430 : :
2431 [ # # ]: 0 : sk_msg_iter_var_next(i);
2432 : 0 : sg_unmark_end(&sge);
2433 [ # # ]: 0 : sk_msg_iter_next(msg, end);
2434 : :
2435 : 0 : nsge = sk_msg_elem_cpy(msg, i);
2436 [ # # ]: 0 : if (rsge.length) {
2437 [ # # ]: 0 : sk_msg_iter_var_next(i);
2438 : 0 : nnsge = sk_msg_elem_cpy(msg, i);
2439 : : }
2440 : :
2441 [ # # ]: 0 : while (i != msg->sg.end) {
2442 : 0 : msg->sg.data[i] = sge;
2443 : 0 : sge = nsge;
2444 [ # # ]: 0 : sk_msg_iter_var_next(i);
2445 [ # # ]: 0 : if (rsge.length) {
2446 : 0 : nsge = nnsge;
2447 : 0 : nnsge = sk_msg_elem_cpy(msg, i);
2448 : : } else {
2449 : 0 : nsge = sk_msg_elem_cpy(msg, i);
2450 : : }
2451 : : }
2452 : : }
2453 : :
2454 : : /* Place newly allocated data buffer */
2455 : 0 : sk_mem_charge(msg->sk, len);
2456 : 0 : msg->sg.size += len;
2457 : 0 : msg->sg.copy[new] = false;
2458 : 0 : sg_set_page(&msg->sg.data[new], page, len + copy, 0);
2459 [ # # ]: 0 : if (rsge.length) {
2460 : 0 : get_page(sg_page(&rsge));
2461 [ # # ]: 0 : sk_msg_iter_var_next(new);
2462 : 0 : msg->sg.data[new] = rsge;
2463 : : }
2464 : :
2465 : 0 : sk_msg_compute_data_pointers(msg);
2466 : : return 0;
2467 : : }
2468 : :
2469 : : static const struct bpf_func_proto bpf_msg_push_data_proto = {
2470 : : .func = bpf_msg_push_data,
2471 : : .gpl_only = false,
2472 : : .ret_type = RET_INTEGER,
2473 : : .arg1_type = ARG_PTR_TO_CTX,
2474 : : .arg2_type = ARG_ANYTHING,
2475 : : .arg3_type = ARG_ANYTHING,
2476 : : .arg4_type = ARG_ANYTHING,
2477 : : };
2478 : :
2479 : 0 : static void sk_msg_shift_left(struct sk_msg *msg, int i)
2480 : : {
2481 : : int prev;
2482 : :
2483 : : do {
2484 : : prev = i;
2485 [ # # ]: 0 : sk_msg_iter_var_next(i);
2486 : 0 : msg->sg.data[prev] = msg->sg.data[i];
2487 [ # # ]: 0 : } while (i != msg->sg.end);
2488 : :
2489 [ # # ]: 0 : sk_msg_iter_prev(msg, end);
2490 : 0 : }
2491 : :
2492 : 0 : static void sk_msg_shift_right(struct sk_msg *msg, int i)
2493 : : {
2494 : : struct scatterlist tmp, sge;
2495 : :
2496 [ # # ]: 0 : sk_msg_iter_next(msg, end);
2497 : : sge = sk_msg_elem_cpy(msg, i);
2498 [ # # ]: 0 : sk_msg_iter_var_next(i);
2499 : : tmp = sk_msg_elem_cpy(msg, i);
2500 : :
2501 [ # # ]: 0 : while (i != msg->sg.end) {
2502 : 0 : msg->sg.data[i] = sge;
2503 [ # # ]: 0 : sk_msg_iter_var_next(i);
2504 : 0 : sge = tmp;
2505 : 0 : tmp = sk_msg_elem_cpy(msg, i);
2506 : : }
2507 : 0 : }
2508 : :
2509 : 0 : BPF_CALL_4(bpf_msg_pop_data, struct sk_msg *, msg, u32, start,
2510 : : u32, len, u64, flags)
2511 : : {
2512 : : u32 i = 0, l = 0, space, offset = 0;
2513 : 0 : u64 last = start + len;
2514 : : int pop;
2515 : :
2516 [ # # ]: 0 : if (unlikely(flags))
2517 : : return -EINVAL;
2518 : :
2519 : : /* First find the starting scatterlist element */
2520 : 0 : i = msg->sg.start;
2521 : : do {
2522 : 0 : offset += l;
2523 : 0 : l = sk_msg_elem(msg, i)->length;
2524 : :
2525 [ # # ]: 0 : if (start < offset + l)
2526 : : break;
2527 [ # # ]: 0 : sk_msg_iter_var_next(i);
2528 [ # # ]: 0 : } while (i != msg->sg.end);
2529 : :
2530 : : /* Bounds checks: start and pop must be inside message */
2531 [ # # # # ]: 0 : if (start >= offset + l || last >= msg->sg.size)
2532 : : return -EINVAL;
2533 : :
2534 : 0 : space = MAX_MSG_FRAGS - sk_msg_elem_used(msg);
2535 : :
2536 : 0 : pop = len;
2537 : : /* --------------| offset
2538 : : * -| start |-------- len -------|
2539 : : *
2540 : : * |----- a ----|-------- pop -------|----- b ----|
2541 : : * |______________________________________________| length
2542 : : *
2543 : : *
2544 : : * a: region at front of scatter element to save
2545 : : * b: region at back of scatter element to save when length > A + pop
2546 : : * pop: region to pop from element, same as input 'pop' here will be
2547 : : * decremented below per iteration.
2548 : : *
2549 : : * Two top-level cases to handle when start != offset, first B is non
2550 : : * zero and second B is zero corresponding to when a pop includes more
2551 : : * than one element.
2552 : : *
2553 : : * Then if B is non-zero AND there is no space allocate space and
2554 : : * compact A, B regions into page. If there is space shift ring to
2555 : : * the rigth free'ing the next element in ring to place B, leaving
2556 : : * A untouched except to reduce length.
2557 : : */
2558 [ # # ]: 0 : if (start != offset) {
2559 : 0 : struct scatterlist *nsge, *sge = sk_msg_elem(msg, i);
2560 : 0 : int a = start;
2561 : 0 : int b = sge->length - pop - a;
2562 : :
2563 [ # # ]: 0 : sk_msg_iter_var_next(i);
2564 : :
2565 [ # # ]: 0 : if (pop < sge->length - a) {
2566 [ # # ]: 0 : if (space) {
2567 : 0 : sge->length = a;
2568 : 0 : sk_msg_shift_right(msg, i);
2569 : 0 : nsge = sk_msg_elem(msg, i);
2570 : 0 : get_page(sg_page(sge));
2571 : 0 : sg_set_page(nsge,
2572 : : sg_page(sge),
2573 : 0 : b, sge->offset + pop + a);
2574 : : } else {
2575 : : struct page *page, *orig;
2576 : : u8 *to, *from;
2577 : :
2578 : 0 : page = alloc_pages(__GFP_NOWARN |
2579 : : __GFP_COMP | GFP_ATOMIC,
2580 : : get_order(a + b));
2581 [ # # ]: 0 : if (unlikely(!page))
2582 : : return -ENOMEM;
2583 : :
2584 : 0 : sge->length = a;
2585 : 0 : orig = sg_page(sge);
2586 : 0 : from = sg_virt(sge);
2587 : : to = page_address(page);
2588 : 0 : memcpy(to, from, a);
2589 : 0 : memcpy(to + a, from + a + pop, b);
2590 : 0 : sg_set_page(sge, page, a + b, 0);
2591 : 0 : put_page(orig);
2592 : : }
2593 : : pop = 0;
2594 [ # # ]: 0 : } else if (pop >= sge->length - a) {
2595 : 0 : pop -= (sge->length - a);
2596 : 0 : sge->length = a;
2597 : : }
2598 : : }
2599 : :
2600 : : /* From above the current layout _must_ be as follows,
2601 : : *
2602 : : * -| offset
2603 : : * -| start
2604 : : *
2605 : : * |---- pop ---|---------------- b ------------|
2606 : : * |____________________________________________| length
2607 : : *
2608 : : * Offset and start of the current msg elem are equal because in the
2609 : : * previous case we handled offset != start and either consumed the
2610 : : * entire element and advanced to the next element OR pop == 0.
2611 : : *
2612 : : * Two cases to handle here are first pop is less than the length
2613 : : * leaving some remainder b above. Simply adjust the element's layout
2614 : : * in this case. Or pop >= length of the element so that b = 0. In this
2615 : : * case advance to next element decrementing pop.
2616 : : */
2617 [ # # ]: 0 : while (pop) {
2618 : 0 : struct scatterlist *sge = sk_msg_elem(msg, i);
2619 : :
2620 [ # # ]: 0 : if (pop < sge->length) {
2621 : 0 : sge->length -= pop;
2622 : 0 : sge->offset += pop;
2623 : : pop = 0;
2624 : : } else {
2625 : 0 : pop -= sge->length;
2626 : 0 : sk_msg_shift_left(msg, i);
2627 : : }
2628 [ # # ]: 0 : sk_msg_iter_var_next(i);
2629 : : }
2630 : :
2631 : 0 : sk_mem_uncharge(msg->sk, len - pop);
2632 : 0 : msg->sg.size -= (len - pop);
2633 : 0 : sk_msg_compute_data_pointers(msg);
2634 : : return 0;
2635 : : }
2636 : :
2637 : : static const struct bpf_func_proto bpf_msg_pop_data_proto = {
2638 : : .func = bpf_msg_pop_data,
2639 : : .gpl_only = false,
2640 : : .ret_type = RET_INTEGER,
2641 : : .arg1_type = ARG_PTR_TO_CTX,
2642 : : .arg2_type = ARG_ANYTHING,
2643 : : .arg3_type = ARG_ANYTHING,
2644 : : .arg4_type = ARG_ANYTHING,
2645 : : };
2646 : :
2647 : 0 : BPF_CALL_1(bpf_get_cgroup_classid, const struct sk_buff *, skb)
2648 : : {
2649 : 0 : return task_get_classid(skb);
2650 : : }
2651 : :
2652 : : static const struct bpf_func_proto bpf_get_cgroup_classid_proto = {
2653 : : .func = bpf_get_cgroup_classid,
2654 : : .gpl_only = false,
2655 : : .ret_type = RET_INTEGER,
2656 : : .arg1_type = ARG_PTR_TO_CTX,
2657 : : };
2658 : :
2659 : 0 : BPF_CALL_1(bpf_get_route_realm, const struct sk_buff *, skb)
2660 : : {
2661 : 0 : return dst_tclassid(skb);
2662 : : }
2663 : :
2664 : : static const struct bpf_func_proto bpf_get_route_realm_proto = {
2665 : : .func = bpf_get_route_realm,
2666 : : .gpl_only = false,
2667 : : .ret_type = RET_INTEGER,
2668 : : .arg1_type = ARG_PTR_TO_CTX,
2669 : : };
2670 : :
2671 : 0 : BPF_CALL_1(bpf_get_hash_recalc, struct sk_buff *, skb)
2672 : : {
2673 : : /* If skb_clear_hash() was called due to mangling, we can
2674 : : * trigger SW recalculation here. Later access to hash
2675 : : * can then use the inline skb->hash via context directly
2676 : : * instead of calling this helper again.
2677 : : */
2678 : 0 : return skb_get_hash(skb);
2679 : : }
2680 : :
2681 : : static const struct bpf_func_proto bpf_get_hash_recalc_proto = {
2682 : : .func = bpf_get_hash_recalc,
2683 : : .gpl_only = false,
2684 : : .ret_type = RET_INTEGER,
2685 : : .arg1_type = ARG_PTR_TO_CTX,
2686 : : };
2687 : :
2688 : 0 : BPF_CALL_1(bpf_set_hash_invalid, struct sk_buff *, skb)
2689 : : {
2690 : : /* After all direct packet write, this can be used once for
2691 : : * triggering a lazy recalc on next skb_get_hash() invocation.
2692 : : */
2693 : 0 : skb_clear_hash(skb);
2694 : : return 0;
2695 : : }
2696 : :
2697 : : static const struct bpf_func_proto bpf_set_hash_invalid_proto = {
2698 : : .func = bpf_set_hash_invalid,
2699 : : .gpl_only = false,
2700 : : .ret_type = RET_INTEGER,
2701 : : .arg1_type = ARG_PTR_TO_CTX,
2702 : : };
2703 : :
2704 : 0 : BPF_CALL_2(bpf_set_hash, struct sk_buff *, skb, u32, hash)
2705 : : {
2706 : : /* Set user specified hash as L4(+), so that it gets returned
2707 : : * on skb_get_hash() call unless BPF prog later on triggers a
2708 : : * skb_clear_hash().
2709 : : */
2710 : 0 : __skb_set_sw_hash(skb, hash, true);
2711 : : return 0;
2712 : : }
2713 : :
2714 : : static const struct bpf_func_proto bpf_set_hash_proto = {
2715 : : .func = bpf_set_hash,
2716 : : .gpl_only = false,
2717 : : .ret_type = RET_INTEGER,
2718 : : .arg1_type = ARG_PTR_TO_CTX,
2719 : : .arg2_type = ARG_ANYTHING,
2720 : : };
2721 : :
2722 : 0 : BPF_CALL_3(bpf_skb_vlan_push, struct sk_buff *, skb, __be16, vlan_proto,
2723 : : u16, vlan_tci)
2724 : : {
2725 : : int ret;
2726 : :
2727 [ # # ]: 0 : if (unlikely(vlan_proto != htons(ETH_P_8021Q) &&
2728 : : vlan_proto != htons(ETH_P_8021AD)))
2729 : : vlan_proto = htons(ETH_P_8021Q);
2730 : :
2731 : 0 : bpf_push_mac_rcsum(skb);
2732 : 0 : ret = skb_vlan_push(skb, vlan_proto, vlan_tci);
2733 : 0 : bpf_pull_mac_rcsum(skb);
2734 : :
2735 : 0 : bpf_compute_data_pointers(skb);
2736 : 0 : return ret;
2737 : : }
2738 : :
2739 : : static const struct bpf_func_proto bpf_skb_vlan_push_proto = {
2740 : : .func = bpf_skb_vlan_push,
2741 : : .gpl_only = false,
2742 : : .ret_type = RET_INTEGER,
2743 : : .arg1_type = ARG_PTR_TO_CTX,
2744 : : .arg2_type = ARG_ANYTHING,
2745 : : .arg3_type = ARG_ANYTHING,
2746 : : };
2747 : :
2748 : 0 : BPF_CALL_1(bpf_skb_vlan_pop, struct sk_buff *, skb)
2749 : : {
2750 : : int ret;
2751 : :
2752 : 0 : bpf_push_mac_rcsum(skb);
2753 : 0 : ret = skb_vlan_pop(skb);
2754 : 0 : bpf_pull_mac_rcsum(skb);
2755 : :
2756 : 0 : bpf_compute_data_pointers(skb);
2757 : 0 : return ret;
2758 : : }
2759 : :
2760 : : static const struct bpf_func_proto bpf_skb_vlan_pop_proto = {
2761 : : .func = bpf_skb_vlan_pop,
2762 : : .gpl_only = false,
2763 : : .ret_type = RET_INTEGER,
2764 : : .arg1_type = ARG_PTR_TO_CTX,
2765 : : };
2766 : :
2767 : 0 : static int bpf_skb_generic_push(struct sk_buff *skb, u32 off, u32 len)
2768 : : {
2769 : : /* Caller already did skb_cow() with len as headroom,
2770 : : * so no need to do it here.
2771 : : */
2772 : 0 : skb_push(skb, len);
2773 : 0 : memmove(skb->data, skb->data + len, off);
2774 : 0 : memset(skb->data + off, 0, len);
2775 : :
2776 : : /* No skb_postpush_rcsum(skb, skb->data + off, len)
2777 : : * needed here as it does not change the skb->csum
2778 : : * result for checksum complete when summing over
2779 : : * zeroed blocks.
2780 : : */
2781 : 0 : return 0;
2782 : : }
2783 : :
2784 : 0 : static int bpf_skb_generic_pop(struct sk_buff *skb, u32 off, u32 len)
2785 : : {
2786 : : /* skb_ensure_writable() is not needed here, as we're
2787 : : * already working on an uncloned skb.
2788 : : */
2789 [ # # ]: 0 : if (unlikely(!pskb_may_pull(skb, off + len)))
2790 : : return -ENOMEM;
2791 : :
2792 : 0 : skb_postpull_rcsum(skb, skb->data + off, len);
2793 : 0 : memmove(skb->data + len, skb->data, off);
2794 : 0 : __skb_pull(skb, len);
2795 : :
2796 : 0 : return 0;
2797 : : }
2798 : :
2799 : 0 : static int bpf_skb_net_hdr_push(struct sk_buff *skb, u32 off, u32 len)
2800 : : {
2801 : 0 : bool trans_same = skb->transport_header == skb->network_header;
2802 : : int ret;
2803 : :
2804 : : /* There's no need for __skb_push()/__skb_pull() pair to
2805 : : * get to the start of the mac header as we're guaranteed
2806 : : * to always start from here under eBPF.
2807 : : */
2808 : 0 : ret = bpf_skb_generic_push(skb, off, len);
2809 [ # # ]: 0 : if (likely(!ret)) {
2810 : 0 : skb->mac_header -= len;
2811 : 0 : skb->network_header -= len;
2812 [ # # ]: 0 : if (trans_same)
2813 : 0 : skb->transport_header = skb->network_header;
2814 : : }
2815 : :
2816 : 0 : return ret;
2817 : : }
2818 : :
2819 : 0 : static int bpf_skb_net_hdr_pop(struct sk_buff *skb, u32 off, u32 len)
2820 : : {
2821 : 0 : bool trans_same = skb->transport_header == skb->network_header;
2822 : : int ret;
2823 : :
2824 : : /* Same here, __skb_push()/__skb_pull() pair not needed. */
2825 : 0 : ret = bpf_skb_generic_pop(skb, off, len);
2826 [ # # ]: 0 : if (likely(!ret)) {
2827 : 0 : skb->mac_header += len;
2828 : 0 : skb->network_header += len;
2829 [ # # ]: 0 : if (trans_same)
2830 : 0 : skb->transport_header = skb->network_header;
2831 : : }
2832 : :
2833 : 0 : return ret;
2834 : : }
2835 : :
2836 : 0 : static int bpf_skb_proto_4_to_6(struct sk_buff *skb)
2837 : : {
2838 : : const u32 len_diff = sizeof(struct ipv6hdr) - sizeof(struct iphdr);
2839 : : u32 off = skb_mac_header_len(skb);
2840 : : int ret;
2841 : :
2842 [ # # # # ]: 0 : if (skb_is_gso(skb) && !skb_is_gso_tcp(skb))
2843 : : return -ENOTSUPP;
2844 : :
2845 : 0 : ret = skb_cow(skb, len_diff);
2846 [ # # ]: 0 : if (unlikely(ret < 0))
2847 : : return ret;
2848 : :
2849 : 0 : ret = bpf_skb_net_hdr_push(skb, off, len_diff);
2850 [ # # ]: 0 : if (unlikely(ret < 0))
2851 : : return ret;
2852 : :
2853 [ # # ]: 0 : if (skb_is_gso(skb)) {
2854 : : struct skb_shared_info *shinfo = skb_shinfo(skb);
2855 : :
2856 : : /* SKB_GSO_TCPV4 needs to be changed into
2857 : : * SKB_GSO_TCPV6.
2858 : : */
2859 [ # # ]: 0 : if (shinfo->gso_type & SKB_GSO_TCPV4) {
2860 : 0 : shinfo->gso_type &= ~SKB_GSO_TCPV4;
2861 : 0 : shinfo->gso_type |= SKB_GSO_TCPV6;
2862 : : }
2863 : :
2864 : : /* Due to IPv6 header, MSS needs to be downgraded. */
2865 : 0 : skb_decrease_gso_size(shinfo, len_diff);
2866 : : /* Header must be checked, and gso_segs recomputed. */
2867 : 0 : shinfo->gso_type |= SKB_GSO_DODGY;
2868 : 0 : shinfo->gso_segs = 0;
2869 : : }
2870 : :
2871 : 0 : skb->protocol = htons(ETH_P_IPV6);
2872 : : skb_clear_hash(skb);
2873 : :
2874 : 0 : return 0;
2875 : : }
2876 : :
2877 : 0 : static int bpf_skb_proto_6_to_4(struct sk_buff *skb)
2878 : : {
2879 : : const u32 len_diff = sizeof(struct ipv6hdr) - sizeof(struct iphdr);
2880 : : u32 off = skb_mac_header_len(skb);
2881 : : int ret;
2882 : :
2883 [ # # # # ]: 0 : if (skb_is_gso(skb) && !skb_is_gso_tcp(skb))
2884 : : return -ENOTSUPP;
2885 : :
2886 : 0 : ret = skb_unclone(skb, GFP_ATOMIC);
2887 [ # # ]: 0 : if (unlikely(ret < 0))
2888 : : return ret;
2889 : :
2890 : 0 : ret = bpf_skb_net_hdr_pop(skb, off, len_diff);
2891 [ # # ]: 0 : if (unlikely(ret < 0))
2892 : : return ret;
2893 : :
2894 [ # # ]: 0 : if (skb_is_gso(skb)) {
2895 : : struct skb_shared_info *shinfo = skb_shinfo(skb);
2896 : :
2897 : : /* SKB_GSO_TCPV6 needs to be changed into
2898 : : * SKB_GSO_TCPV4.
2899 : : */
2900 [ # # ]: 0 : if (shinfo->gso_type & SKB_GSO_TCPV6) {
2901 : 0 : shinfo->gso_type &= ~SKB_GSO_TCPV6;
2902 : 0 : shinfo->gso_type |= SKB_GSO_TCPV4;
2903 : : }
2904 : :
2905 : : /* Due to IPv4 header, MSS can be upgraded. */
2906 : 0 : skb_increase_gso_size(shinfo, len_diff);
2907 : : /* Header must be checked, and gso_segs recomputed. */
2908 : 0 : shinfo->gso_type |= SKB_GSO_DODGY;
2909 : 0 : shinfo->gso_segs = 0;
2910 : : }
2911 : :
2912 : 0 : skb->protocol = htons(ETH_P_IP);
2913 : : skb_clear_hash(skb);
2914 : :
2915 : 0 : return 0;
2916 : : }
2917 : :
2918 : 0 : static int bpf_skb_proto_xlat(struct sk_buff *skb, __be16 to_proto)
2919 : : {
2920 : 0 : __be16 from_proto = skb->protocol;
2921 : :
2922 [ # # ]: 0 : if (from_proto == htons(ETH_P_IP) &&
2923 : 0 : to_proto == htons(ETH_P_IPV6))
2924 : 0 : return bpf_skb_proto_4_to_6(skb);
2925 : :
2926 [ # # ]: 0 : if (from_proto == htons(ETH_P_IPV6) &&
2927 : 0 : to_proto == htons(ETH_P_IP))
2928 : 0 : return bpf_skb_proto_6_to_4(skb);
2929 : :
2930 : : return -ENOTSUPP;
2931 : : }
2932 : :
2933 : 0 : BPF_CALL_3(bpf_skb_change_proto, struct sk_buff *, skb, __be16, proto,
2934 : : u64, flags)
2935 : : {
2936 : : int ret;
2937 : :
2938 [ # # ]: 0 : if (unlikely(flags))
2939 : : return -EINVAL;
2940 : :
2941 : : /* General idea is that this helper does the basic groundwork
2942 : : * needed for changing the protocol, and eBPF program fills the
2943 : : * rest through bpf_skb_store_bytes(), bpf_lX_csum_replace()
2944 : : * and other helpers, rather than passing a raw buffer here.
2945 : : *
2946 : : * The rationale is to keep this minimal and without a need to
2947 : : * deal with raw packet data. F.e. even if we would pass buffers
2948 : : * here, the program still needs to call the bpf_lX_csum_replace()
2949 : : * helpers anyway. Plus, this way we keep also separation of
2950 : : * concerns, since f.e. bpf_skb_store_bytes() should only take
2951 : : * care of stores.
2952 : : *
2953 : : * Currently, additional options and extension header space are
2954 : : * not supported, but flags register is reserved so we can adapt
2955 : : * that. For offloads, we mark packet as dodgy, so that headers
2956 : : * need to be verified first.
2957 : : */
2958 : 0 : ret = bpf_skb_proto_xlat(skb, proto);
2959 : 0 : bpf_compute_data_pointers(skb);
2960 : 0 : return ret;
2961 : : }
2962 : :
2963 : : static const struct bpf_func_proto bpf_skb_change_proto_proto = {
2964 : : .func = bpf_skb_change_proto,
2965 : : .gpl_only = false,
2966 : : .ret_type = RET_INTEGER,
2967 : : .arg1_type = ARG_PTR_TO_CTX,
2968 : : .arg2_type = ARG_ANYTHING,
2969 : : .arg3_type = ARG_ANYTHING,
2970 : : };
2971 : :
2972 : 0 : BPF_CALL_2(bpf_skb_change_type, struct sk_buff *, skb, u32, pkt_type)
2973 : : {
2974 : : /* We only allow a restricted subset to be changed for now. */
2975 [ # # # # ]: 0 : if (unlikely(!skb_pkt_type_ok(skb->pkt_type) ||
2976 : : !skb_pkt_type_ok(pkt_type)))
2977 : : return -EINVAL;
2978 : :
2979 : 0 : skb->pkt_type = pkt_type;
2980 : : return 0;
2981 : : }
2982 : :
2983 : : static const struct bpf_func_proto bpf_skb_change_type_proto = {
2984 : : .func = bpf_skb_change_type,
2985 : : .gpl_only = false,
2986 : : .ret_type = RET_INTEGER,
2987 : : .arg1_type = ARG_PTR_TO_CTX,
2988 : : .arg2_type = ARG_ANYTHING,
2989 : : };
2990 : :
2991 : 0 : static u32 bpf_skb_net_base_len(const struct sk_buff *skb)
2992 : : {
2993 [ # # # ]: 0 : switch (skb->protocol) {
2994 : : case htons(ETH_P_IP):
2995 : : return sizeof(struct iphdr);
2996 : : case htons(ETH_P_IPV6):
2997 : 0 : return sizeof(struct ipv6hdr);
2998 : : default:
2999 : 0 : return ~0U;
3000 : : }
3001 : : }
3002 : :
3003 : : #define BPF_F_ADJ_ROOM_ENCAP_L3_MASK (BPF_F_ADJ_ROOM_ENCAP_L3_IPV4 | \
3004 : : BPF_F_ADJ_ROOM_ENCAP_L3_IPV6)
3005 : :
3006 : : #define BPF_F_ADJ_ROOM_MASK (BPF_F_ADJ_ROOM_FIXED_GSO | \
3007 : : BPF_F_ADJ_ROOM_ENCAP_L3_MASK | \
3008 : : BPF_F_ADJ_ROOM_ENCAP_L4_GRE | \
3009 : : BPF_F_ADJ_ROOM_ENCAP_L4_UDP | \
3010 : : BPF_F_ADJ_ROOM_ENCAP_L2( \
3011 : : BPF_ADJ_ROOM_ENCAP_L2_MASK))
3012 : :
3013 : 0 : static int bpf_skb_net_grow(struct sk_buff *skb, u32 off, u32 len_diff,
3014 : : u64 flags)
3015 : : {
3016 : 0 : u8 inner_mac_len = flags >> BPF_ADJ_ROOM_ENCAP_L2_SHIFT;
3017 : 0 : bool encap = flags & BPF_F_ADJ_ROOM_ENCAP_L3_MASK;
3018 : : u16 mac_len = 0, inner_net = 0, inner_trans = 0;
3019 : : unsigned int gso_type = SKB_GSO_DODGY;
3020 : : int ret;
3021 : :
3022 [ # # # # ]: 0 : if (skb_is_gso(skb) && !skb_is_gso_tcp(skb)) {
3023 : : /* udp gso_size delineates datagrams, only allow if fixed */
3024 [ # # # # ]: 0 : if (!(skb_shinfo(skb)->gso_type & SKB_GSO_UDP_L4) ||
3025 : 0 : !(flags & BPF_F_ADJ_ROOM_FIXED_GSO))
3026 : : return -ENOTSUPP;
3027 : : }
3028 : :
3029 : 0 : ret = skb_cow_head(skb, len_diff);
3030 [ # # ]: 0 : if (unlikely(ret < 0))
3031 : : return ret;
3032 : :
3033 [ # # ]: 0 : if (encap) {
3034 [ # # ]: 0 : if (skb->protocol != htons(ETH_P_IP) &&
3035 : : skb->protocol != htons(ETH_P_IPV6))
3036 : : return -ENOTSUPP;
3037 : :
3038 [ # # # # ]: 0 : if (flags & BPF_F_ADJ_ROOM_ENCAP_L3_IPV4 &&
3039 : 0 : flags & BPF_F_ADJ_ROOM_ENCAP_L3_IPV6)
3040 : : return -EINVAL;
3041 : :
3042 [ # # # # ]: 0 : if (flags & BPF_F_ADJ_ROOM_ENCAP_L4_GRE &&
3043 : 0 : flags & BPF_F_ADJ_ROOM_ENCAP_L4_UDP)
3044 : : return -EINVAL;
3045 : :
3046 [ # # ]: 0 : if (skb->encapsulation)
3047 : : return -EALREADY;
3048 : :
3049 : 0 : mac_len = skb->network_header - skb->mac_header;
3050 : : inner_net = skb->network_header;
3051 [ # # ]: 0 : if (inner_mac_len > len_diff)
3052 : : return -EINVAL;
3053 : 0 : inner_trans = skb->transport_header;
3054 : : }
3055 : :
3056 : 0 : ret = bpf_skb_net_hdr_push(skb, off, len_diff);
3057 [ # # ]: 0 : if (unlikely(ret < 0))
3058 : : return ret;
3059 : :
3060 [ # # ]: 0 : if (encap) {
3061 : 0 : skb->inner_mac_header = inner_net - inner_mac_len;
3062 : 0 : skb->inner_network_header = inner_net;
3063 : 0 : skb->inner_transport_header = inner_trans;
3064 : 0 : skb_set_inner_protocol(skb, skb->protocol);
3065 : :
3066 : 0 : skb->encapsulation = 1;
3067 : : skb_set_network_header(skb, mac_len);
3068 : :
3069 [ # # ]: 0 : if (flags & BPF_F_ADJ_ROOM_ENCAP_L4_UDP)
3070 : : gso_type |= SKB_GSO_UDP_TUNNEL;
3071 [ # # ]: 0 : else if (flags & BPF_F_ADJ_ROOM_ENCAP_L4_GRE)
3072 : : gso_type |= SKB_GSO_GRE;
3073 [ # # ]: 0 : else if (flags & BPF_F_ADJ_ROOM_ENCAP_L3_IPV6)
3074 : : gso_type |= SKB_GSO_IPXIP6;
3075 [ # # ]: 0 : else if (flags & BPF_F_ADJ_ROOM_ENCAP_L3_IPV4)
3076 : : gso_type |= SKB_GSO_IPXIP4;
3077 : :
3078 [ # # # # ]: 0 : if (flags & BPF_F_ADJ_ROOM_ENCAP_L4_GRE ||
3079 : : flags & BPF_F_ADJ_ROOM_ENCAP_L4_UDP) {
3080 [ # # ]: 0 : int nh_len = flags & BPF_F_ADJ_ROOM_ENCAP_L3_IPV6 ?
3081 : : sizeof(struct ipv6hdr) :
3082 : : sizeof(struct iphdr);
3083 : :
3084 : 0 : skb_set_transport_header(skb, mac_len + nh_len);
3085 : : }
3086 : :
3087 : : /* Match skb->protocol to new outer l3 protocol */
3088 [ # # # # ]: 0 : if (skb->protocol == htons(ETH_P_IP) &&
3089 : 0 : flags & BPF_F_ADJ_ROOM_ENCAP_L3_IPV6)
3090 : 0 : skb->protocol = htons(ETH_P_IPV6);
3091 [ # # # # ]: 0 : else if (skb->protocol == htons(ETH_P_IPV6) &&
3092 : 0 : flags & BPF_F_ADJ_ROOM_ENCAP_L3_IPV4)
3093 : 0 : skb->protocol = htons(ETH_P_IP);
3094 : : }
3095 : :
3096 [ # # ]: 0 : if (skb_is_gso(skb)) {
3097 : : struct skb_shared_info *shinfo = skb_shinfo(skb);
3098 : :
3099 : : /* Due to header grow, MSS needs to be downgraded. */
3100 [ # # ]: 0 : if (!(flags & BPF_F_ADJ_ROOM_FIXED_GSO))
3101 : 0 : skb_decrease_gso_size(shinfo, len_diff);
3102 : :
3103 : : /* Header must be checked, and gso_segs recomputed. */
3104 : 0 : shinfo->gso_type |= gso_type;
3105 : 0 : shinfo->gso_segs = 0;
3106 : : }
3107 : :
3108 : : return 0;
3109 : : }
3110 : :
3111 : 0 : static int bpf_skb_net_shrink(struct sk_buff *skb, u32 off, u32 len_diff,
3112 : : u64 flags)
3113 : : {
3114 : : int ret;
3115 : :
3116 [ # # ]: 0 : if (flags & ~BPF_F_ADJ_ROOM_FIXED_GSO)
3117 : : return -EINVAL;
3118 : :
3119 [ # # # # ]: 0 : if (skb_is_gso(skb) && !skb_is_gso_tcp(skb)) {
3120 : : /* udp gso_size delineates datagrams, only allow if fixed */
3121 [ # # # # ]: 0 : if (!(skb_shinfo(skb)->gso_type & SKB_GSO_UDP_L4) ||
3122 : 0 : !(flags & BPF_F_ADJ_ROOM_FIXED_GSO))
3123 : : return -ENOTSUPP;
3124 : : }
3125 : :
3126 : 0 : ret = skb_unclone(skb, GFP_ATOMIC);
3127 [ # # ]: 0 : if (unlikely(ret < 0))
3128 : : return ret;
3129 : :
3130 : 0 : ret = bpf_skb_net_hdr_pop(skb, off, len_diff);
3131 [ # # ]: 0 : if (unlikely(ret < 0))
3132 : : return ret;
3133 : :
3134 [ # # ]: 0 : if (skb_is_gso(skb)) {
3135 : : struct skb_shared_info *shinfo = skb_shinfo(skb);
3136 : :
3137 : : /* Due to header shrink, MSS can be upgraded. */
3138 [ # # ]: 0 : if (!(flags & BPF_F_ADJ_ROOM_FIXED_GSO))
3139 : 0 : skb_increase_gso_size(shinfo, len_diff);
3140 : :
3141 : : /* Header must be checked, and gso_segs recomputed. */
3142 : 0 : shinfo->gso_type |= SKB_GSO_DODGY;
3143 : 0 : shinfo->gso_segs = 0;
3144 : : }
3145 : :
3146 : : return 0;
3147 : : }
3148 : :
3149 : 0 : static u32 __bpf_skb_max_len(const struct sk_buff *skb)
3150 : : {
3151 [ # # # # : 0 : return skb->dev ? skb->dev->mtu + skb->dev->hard_header_len :
# # ]
3152 : : SKB_MAX_ALLOC;
3153 : : }
3154 : :
3155 : 0 : BPF_CALL_4(bpf_skb_adjust_room, struct sk_buff *, skb, s32, len_diff,
3156 : : u32, mode, u64, flags)
3157 : : {
3158 : 0 : u32 len_cur, len_diff_abs = abs(len_diff);
3159 : 0 : u32 len_min = bpf_skb_net_base_len(skb);
3160 : 0 : u32 len_max = __bpf_skb_max_len(skb);
3161 : 0 : __be16 proto = skb->protocol;
3162 : 0 : bool shrink = len_diff < 0;
3163 : : u32 off;
3164 : : int ret;
3165 : :
3166 [ # # ]: 0 : if (unlikely(flags & ~BPF_F_ADJ_ROOM_MASK))
3167 : : return -EINVAL;
3168 [ # # ]: 0 : if (unlikely(len_diff_abs > 0xfffU))
3169 : : return -EFAULT;
3170 [ # # ]: 0 : if (unlikely(proto != htons(ETH_P_IP) &&
3171 : : proto != htons(ETH_P_IPV6)))
3172 : : return -ENOTSUPP;
3173 : :
3174 : 0 : off = skb_mac_header_len(skb);
3175 [ # # # ]: 0 : switch (mode) {
3176 : : case BPF_ADJ_ROOM_NET:
3177 : 0 : off += bpf_skb_net_base_len(skb);
3178 : : break;
3179 : : case BPF_ADJ_ROOM_MAC:
3180 : : break;
3181 : : default:
3182 : : return -ENOTSUPP;
3183 : : }
3184 : :
3185 : 0 : len_cur = skb->len - skb_network_offset(skb);
3186 [ # # # # : 0 : if ((shrink && (len_diff_abs >= len_cur ||
# # ]
3187 [ # # ]: 0 : len_cur - len_diff_abs < len_min)) ||
3188 [ # # # # ]: 0 : (!shrink && (skb->len + len_diff_abs > len_max &&
3189 : 0 : !skb_is_gso(skb))))
3190 : : return -ENOTSUPP;
3191 : :
3192 [ # # ]: 0 : ret = shrink ? bpf_skb_net_shrink(skb, off, len_diff_abs, flags) :
3193 : : bpf_skb_net_grow(skb, off, len_diff_abs, flags);
3194 : :
3195 : 0 : bpf_compute_data_pointers(skb);
3196 : 0 : return ret;
3197 : : }
3198 : :
3199 : : static const struct bpf_func_proto bpf_skb_adjust_room_proto = {
3200 : : .func = bpf_skb_adjust_room,
3201 : : .gpl_only = false,
3202 : : .ret_type = RET_INTEGER,
3203 : : .arg1_type = ARG_PTR_TO_CTX,
3204 : : .arg2_type = ARG_ANYTHING,
3205 : : .arg3_type = ARG_ANYTHING,
3206 : : .arg4_type = ARG_ANYTHING,
3207 : : };
3208 : :
3209 : 0 : static u32 __bpf_skb_min_len(const struct sk_buff *skb)
3210 : : {
3211 : 0 : u32 min_len = skb_network_offset(skb);
3212 : :
3213 [ # # ]: 0 : if (skb_transport_header_was_set(skb))
3214 : 0 : min_len = skb_transport_offset(skb);
3215 [ # # ]: 0 : if (skb->ip_summed == CHECKSUM_PARTIAL)
3216 : 0 : min_len = skb_checksum_start_offset(skb) +
3217 : 0 : skb->csum_offset + sizeof(__sum16);
3218 : 0 : return min_len;
3219 : : }
3220 : :
3221 : 0 : static int bpf_skb_grow_rcsum(struct sk_buff *skb, unsigned int new_len)
3222 : : {
3223 : 0 : unsigned int old_len = skb->len;
3224 : : int ret;
3225 : :
3226 : : ret = __skb_grow_rcsum(skb, new_len);
3227 [ # # ]: 0 : if (!ret)
3228 : 0 : memset(skb->data + old_len, 0, new_len - old_len);
3229 : 0 : return ret;
3230 : : }
3231 : :
3232 : : static int bpf_skb_trim_rcsum(struct sk_buff *skb, unsigned int new_len)
3233 : : {
3234 : : return __skb_trim_rcsum(skb, new_len);
3235 : : }
3236 : :
3237 : 0 : static inline int __bpf_skb_change_tail(struct sk_buff *skb, u32 new_len,
3238 : : u64 flags)
3239 : : {
3240 : : u32 max_len = __bpf_skb_max_len(skb);
3241 : 0 : u32 min_len = __bpf_skb_min_len(skb);
3242 : : int ret;
3243 : :
3244 [ # # # # ]: 0 : if (unlikely(flags || new_len > max_len || new_len < min_len))
3245 : : return -EINVAL;
3246 [ # # ]: 0 : if (skb->encapsulation)
3247 : : return -ENOTSUPP;
3248 : :
3249 : : /* The basic idea of this helper is that it's performing the
3250 : : * needed work to either grow or trim an skb, and eBPF program
3251 : : * rewrites the rest via helpers like bpf_skb_store_bytes(),
3252 : : * bpf_lX_csum_replace() and others rather than passing a raw
3253 : : * buffer here. This one is a slow path helper and intended
3254 : : * for replies with control messages.
3255 : : *
3256 : : * Like in bpf_skb_change_proto(), we want to keep this rather
3257 : : * minimal and without protocol specifics so that we are able
3258 : : * to separate concerns as in bpf_skb_store_bytes() should only
3259 : : * be the one responsible for writing buffers.
3260 : : *
3261 : : * It's really expected to be a slow path operation here for
3262 : : * control message replies, so we're implicitly linearizing,
3263 : : * uncloning and drop offloads from the skb by this.
3264 : : */
3265 : 0 : ret = __bpf_try_make_writable(skb, skb->len);
3266 [ # # ]: 0 : if (!ret) {
3267 [ # # ]: 0 : if (new_len > skb->len)
3268 : 0 : ret = bpf_skb_grow_rcsum(skb, new_len);
3269 [ # # ]: 0 : else if (new_len < skb->len)
3270 : : ret = bpf_skb_trim_rcsum(skb, new_len);
3271 [ # # # # ]: 0 : if (!ret && skb_is_gso(skb))
3272 : : skb_gso_reset(skb);
3273 : : }
3274 : 0 : return ret;
3275 : : }
3276 : :
3277 : 0 : BPF_CALL_3(bpf_skb_change_tail, struct sk_buff *, skb, u32, new_len,
3278 : : u64, flags)
3279 : : {
3280 : 0 : int ret = __bpf_skb_change_tail(skb, new_len, flags);
3281 : :
3282 : 0 : bpf_compute_data_pointers(skb);
3283 : 0 : return ret;
3284 : : }
3285 : :
3286 : : static const struct bpf_func_proto bpf_skb_change_tail_proto = {
3287 : : .func = bpf_skb_change_tail,
3288 : : .gpl_only = false,
3289 : : .ret_type = RET_INTEGER,
3290 : : .arg1_type = ARG_PTR_TO_CTX,
3291 : : .arg2_type = ARG_ANYTHING,
3292 : : .arg3_type = ARG_ANYTHING,
3293 : : };
3294 : :
3295 : 0 : BPF_CALL_3(sk_skb_change_tail, struct sk_buff *, skb, u32, new_len,
3296 : : u64, flags)
3297 : : {
3298 : 0 : int ret = __bpf_skb_change_tail(skb, new_len, flags);
3299 : :
3300 : 0 : bpf_compute_data_end_sk_skb(skb);
3301 : 0 : return ret;
3302 : : }
3303 : :
3304 : : static const struct bpf_func_proto sk_skb_change_tail_proto = {
3305 : : .func = sk_skb_change_tail,
3306 : : .gpl_only = false,
3307 : : .ret_type = RET_INTEGER,
3308 : : .arg1_type = ARG_PTR_TO_CTX,
3309 : : .arg2_type = ARG_ANYTHING,
3310 : : .arg3_type = ARG_ANYTHING,
3311 : : };
3312 : :
3313 : 0 : static inline int __bpf_skb_change_head(struct sk_buff *skb, u32 head_room,
3314 : : u64 flags)
3315 : : {
3316 : : u32 max_len = __bpf_skb_max_len(skb);
3317 : 0 : u32 new_len = skb->len + head_room;
3318 : : int ret;
3319 : :
3320 [ # # # # : 0 : if (unlikely(flags || (!skb_is_gso(skb) && new_len > max_len) ||
# # # # #
# # # ]
3321 : : new_len < skb->len))
3322 : : return -EINVAL;
3323 : :
3324 : 0 : ret = skb_cow(skb, head_room);
3325 [ # # ]: 0 : if (likely(!ret)) {
3326 : : /* Idea for this helper is that we currently only
3327 : : * allow to expand on mac header. This means that
3328 : : * skb->protocol network header, etc, stay as is.
3329 : : * Compared to bpf_skb_change_tail(), we're more
3330 : : * flexible due to not needing to linearize or
3331 : : * reset GSO. Intention for this helper is to be
3332 : : * used by an L3 skb that needs to push mac header
3333 : : * for redirection into L2 device.
3334 : : */
3335 : : __skb_push(skb, head_room);
3336 : 0 : memset(skb->data, 0, head_room);
3337 : : skb_reset_mac_header(skb);
3338 : : }
3339 : :
3340 : 0 : return ret;
3341 : : }
3342 : :
3343 : 0 : BPF_CALL_3(bpf_skb_change_head, struct sk_buff *, skb, u32, head_room,
3344 : : u64, flags)
3345 : : {
3346 : 0 : int ret = __bpf_skb_change_head(skb, head_room, flags);
3347 : :
3348 : 0 : bpf_compute_data_pointers(skb);
3349 : 0 : return ret;
3350 : : }
3351 : :
3352 : : static const struct bpf_func_proto bpf_skb_change_head_proto = {
3353 : : .func = bpf_skb_change_head,
3354 : : .gpl_only = false,
3355 : : .ret_type = RET_INTEGER,
3356 : : .arg1_type = ARG_PTR_TO_CTX,
3357 : : .arg2_type = ARG_ANYTHING,
3358 : : .arg3_type = ARG_ANYTHING,
3359 : : };
3360 : :
3361 : 0 : BPF_CALL_3(sk_skb_change_head, struct sk_buff *, skb, u32, head_room,
3362 : : u64, flags)
3363 : : {
3364 : 0 : int ret = __bpf_skb_change_head(skb, head_room, flags);
3365 : :
3366 : 0 : bpf_compute_data_end_sk_skb(skb);
3367 : 0 : return ret;
3368 : : }
3369 : :
3370 : : static const struct bpf_func_proto sk_skb_change_head_proto = {
3371 : : .func = sk_skb_change_head,
3372 : : .gpl_only = false,
3373 : : .ret_type = RET_INTEGER,
3374 : : .arg1_type = ARG_PTR_TO_CTX,
3375 : : .arg2_type = ARG_ANYTHING,
3376 : : .arg3_type = ARG_ANYTHING,
3377 : : };
3378 : 0 : static unsigned long xdp_get_metalen(const struct xdp_buff *xdp)
3379 : : {
3380 [ # # ]: 0 : return xdp_data_meta_unsupported(xdp) ? 0 :
3381 : 0 : xdp->data - xdp->data_meta;
3382 : : }
3383 : :
3384 : 0 : BPF_CALL_2(bpf_xdp_adjust_head, struct xdp_buff *, xdp, int, offset)
3385 : : {
3386 : 0 : void *xdp_frame_end = xdp->data_hard_start + sizeof(struct xdp_frame);
3387 : 0 : unsigned long metalen = xdp_get_metalen(xdp);
3388 : 0 : void *data_start = xdp_frame_end + metalen;
3389 : 0 : void *data = xdp->data + offset;
3390 : :
3391 [ # # # # ]: 0 : if (unlikely(data < data_start ||
3392 : : data > xdp->data_end - ETH_HLEN))
3393 : : return -EINVAL;
3394 : :
3395 [ # # ]: 0 : if (metalen)
3396 : 0 : memmove(xdp->data_meta + offset,
3397 : : xdp->data_meta, metalen);
3398 : 0 : xdp->data_meta += offset;
3399 : 0 : xdp->data = data;
3400 : :
3401 : : return 0;
3402 : : }
3403 : :
3404 : : static const struct bpf_func_proto bpf_xdp_adjust_head_proto = {
3405 : : .func = bpf_xdp_adjust_head,
3406 : : .gpl_only = false,
3407 : : .ret_type = RET_INTEGER,
3408 : : .arg1_type = ARG_PTR_TO_CTX,
3409 : : .arg2_type = ARG_ANYTHING,
3410 : : };
3411 : :
3412 : 0 : BPF_CALL_2(bpf_xdp_adjust_tail, struct xdp_buff *, xdp, int, offset)
3413 : : {
3414 : 0 : void *data_end = xdp->data_end + offset;
3415 : :
3416 : : /* only shrinking is allowed for now. */
3417 [ # # ]: 0 : if (unlikely(offset >= 0))
3418 : : return -EINVAL;
3419 : :
3420 [ # # ]: 0 : if (unlikely(data_end < xdp->data + ETH_HLEN))
3421 : : return -EINVAL;
3422 : :
3423 : 0 : xdp->data_end = data_end;
3424 : :
3425 : : return 0;
3426 : : }
3427 : :
3428 : : static const struct bpf_func_proto bpf_xdp_adjust_tail_proto = {
3429 : : .func = bpf_xdp_adjust_tail,
3430 : : .gpl_only = false,
3431 : : .ret_type = RET_INTEGER,
3432 : : .arg1_type = ARG_PTR_TO_CTX,
3433 : : .arg2_type = ARG_ANYTHING,
3434 : : };
3435 : :
3436 : 0 : BPF_CALL_2(bpf_xdp_adjust_meta, struct xdp_buff *, xdp, int, offset)
3437 : : {
3438 : 0 : void *xdp_frame_end = xdp->data_hard_start + sizeof(struct xdp_frame);
3439 : 0 : void *meta = xdp->data_meta + offset;
3440 : 0 : unsigned long metalen = xdp->data - meta;
3441 : :
3442 [ # # ]: 0 : if (xdp_data_meta_unsupported(xdp))
3443 : : return -ENOTSUPP;
3444 [ # # # # ]: 0 : if (unlikely(meta < xdp_frame_end ||
3445 : : meta > xdp->data))
3446 : : return -EINVAL;
3447 [ # # # # ]: 0 : if (unlikely((metalen & (sizeof(__u32) - 1)) ||
3448 : : (metalen > 32)))
3449 : : return -EACCES;
3450 : :
3451 : 0 : xdp->data_meta = meta;
3452 : :
3453 : : return 0;
3454 : : }
3455 : :
3456 : : static const struct bpf_func_proto bpf_xdp_adjust_meta_proto = {
3457 : : .func = bpf_xdp_adjust_meta,
3458 : : .gpl_only = false,
3459 : : .ret_type = RET_INTEGER,
3460 : : .arg1_type = ARG_PTR_TO_CTX,
3461 : : .arg2_type = ARG_ANYTHING,
3462 : : };
3463 : :
3464 : 0 : static int __bpf_tx_xdp(struct net_device *dev,
3465 : : struct bpf_map *map,
3466 : : struct xdp_buff *xdp,
3467 : : u32 index)
3468 : : {
3469 : : struct xdp_frame *xdpf;
3470 : : int err, sent;
3471 : :
3472 [ # # ]: 0 : if (!dev->netdev_ops->ndo_xdp_xmit) {
3473 : : return -EOPNOTSUPP;
3474 : : }
3475 : :
3476 : 0 : err = xdp_ok_fwd_dev(dev, xdp->data_end - xdp->data);
3477 [ # # ]: 0 : if (unlikely(err))
3478 : : return err;
3479 : :
3480 : 0 : xdpf = convert_to_xdp_frame(xdp);
3481 [ # # ]: 0 : if (unlikely(!xdpf))
3482 : : return -EOVERFLOW;
3483 : :
3484 : 0 : sent = dev->netdev_ops->ndo_xdp_xmit(dev, 1, &xdpf, XDP_XMIT_FLUSH);
3485 [ # # ]: 0 : if (sent <= 0)
3486 : 0 : return sent;
3487 : : return 0;
3488 : : }
3489 : :
3490 : : static noinline int
3491 : 0 : xdp_do_redirect_slow(struct net_device *dev, struct xdp_buff *xdp,
3492 : : struct bpf_prog *xdp_prog, struct bpf_redirect_info *ri)
3493 : : {
3494 : : struct net_device *fwd;
3495 : 0 : u32 index = ri->tgt_index;
3496 : : int err;
3497 : :
3498 : 0 : fwd = dev_get_by_index_rcu(dev_net(dev), index);
3499 : 0 : ri->tgt_index = 0;
3500 [ # # ]: 0 : if (unlikely(!fwd)) {
3501 : : err = -EINVAL;
3502 : : goto err;
3503 : : }
3504 : :
3505 : 0 : err = __bpf_tx_xdp(fwd, NULL, xdp, 0);
3506 [ # # ]: 0 : if (unlikely(err))
3507 : : goto err;
3508 : :
3509 : 0 : _trace_xdp_redirect(dev, xdp_prog, index);
3510 : 0 : return 0;
3511 : : err:
3512 : 0 : _trace_xdp_redirect_err(dev, xdp_prog, index, err);
3513 : 0 : return err;
3514 : : }
3515 : :
3516 : 0 : static int __bpf_tx_xdp_map(struct net_device *dev_rx, void *fwd,
3517 : : struct bpf_map *map,
3518 : : struct xdp_buff *xdp,
3519 : : u32 index)
3520 : : {
3521 : : int err;
3522 : :
3523 [ # # # # ]: 0 : switch (map->map_type) {
3524 : : case BPF_MAP_TYPE_DEVMAP:
3525 : : case BPF_MAP_TYPE_DEVMAP_HASH: {
3526 : : struct bpf_dtab_netdev *dst = fwd;
3527 : :
3528 : 0 : err = dev_map_enqueue(dst, xdp, dev_rx);
3529 [ # # ]: 0 : if (unlikely(err))
3530 : 0 : return err;
3531 : : break;
3532 : : }
3533 : : case BPF_MAP_TYPE_CPUMAP: {
3534 : : struct bpf_cpu_map_entry *rcpu = fwd;
3535 : :
3536 : 0 : err = cpu_map_enqueue(rcpu, xdp, dev_rx);
3537 [ # # ]: 0 : if (unlikely(err))
3538 : 0 : return err;
3539 : : break;
3540 : : }
3541 : : case BPF_MAP_TYPE_XSKMAP: {
3542 : : struct xdp_sock *xs = fwd;
3543 : :
3544 : : err = __xsk_map_redirect(map, xdp, xs);
3545 : : return err;
3546 : : }
3547 : : default:
3548 : 0 : return -EBADRQC;
3549 : : }
3550 : : return 0;
3551 : : }
3552 : :
3553 : 0 : void xdp_do_flush_map(void)
3554 : : {
3555 : 0 : struct bpf_redirect_info *ri = this_cpu_ptr(&bpf_redirect_info);
3556 : 0 : struct bpf_map *map = ri->map_to_flush;
3557 : :
3558 : 0 : ri->map_to_flush = NULL;
3559 [ # # ]: 0 : if (map) {
3560 [ # # # ]: 0 : switch (map->map_type) {
3561 : : case BPF_MAP_TYPE_DEVMAP:
3562 : : case BPF_MAP_TYPE_DEVMAP_HASH:
3563 : 0 : __dev_map_flush(map);
3564 : 0 : break;
3565 : : case BPF_MAP_TYPE_CPUMAP:
3566 : 0 : __cpu_map_flush(map);
3567 : 0 : break;
3568 : : case BPF_MAP_TYPE_XSKMAP:
3569 : : __xsk_map_flush(map);
3570 : : break;
3571 : : default:
3572 : : break;
3573 : : }
3574 : : }
3575 : 0 : }
3576 : : EXPORT_SYMBOL_GPL(xdp_do_flush_map);
3577 : :
3578 : 0 : static inline void *__xdp_map_lookup_elem(struct bpf_map *map, u32 index)
3579 : : {
3580 [ # # # # ]: 0 : switch (map->map_type) {
3581 : : case BPF_MAP_TYPE_DEVMAP:
3582 : 0 : return __dev_map_lookup_elem(map, index);
3583 : : case BPF_MAP_TYPE_DEVMAP_HASH:
3584 : 0 : return __dev_map_hash_lookup_elem(map, index);
3585 : : case BPF_MAP_TYPE_CPUMAP:
3586 : 0 : return __cpu_map_lookup_elem(map, index);
3587 : : case BPF_MAP_TYPE_XSKMAP:
3588 : : return __xsk_map_lookup_elem(map, index);
3589 : : default:
3590 : : return NULL;
3591 : : }
3592 : : }
3593 : :
3594 : 0 : void bpf_clear_redirect_map(struct bpf_map *map)
3595 : : {
3596 : : struct bpf_redirect_info *ri;
3597 : : int cpu;
3598 : :
3599 [ # # ]: 0 : for_each_possible_cpu(cpu) {
3600 : 0 : ri = per_cpu_ptr(&bpf_redirect_info, cpu);
3601 : : /* Avoid polluting remote cacheline due to writes if
3602 : : * not needed. Once we pass this test, we need the
3603 : : * cmpxchg() to make sure it hasn't been changed in
3604 : : * the meantime by remote CPU.
3605 : : */
3606 [ # # ]: 0 : if (unlikely(READ_ONCE(ri->map) == map))
3607 : 0 : cmpxchg(&ri->map, map, NULL);
3608 : : }
3609 : 0 : }
3610 : :
3611 : 0 : static int xdp_do_redirect_map(struct net_device *dev, struct xdp_buff *xdp,
3612 : : struct bpf_prog *xdp_prog, struct bpf_map *map,
3613 : : struct bpf_redirect_info *ri)
3614 : : {
3615 : 0 : u32 index = ri->tgt_index;
3616 : 0 : void *fwd = ri->tgt_value;
3617 : : int err;
3618 : :
3619 : 0 : ri->tgt_index = 0;
3620 : 0 : ri->tgt_value = NULL;
3621 : : WRITE_ONCE(ri->map, NULL);
3622 : :
3623 [ # # # # ]: 0 : if (ri->map_to_flush && unlikely(ri->map_to_flush != map))
3624 : 0 : xdp_do_flush_map();
3625 : :
3626 : 0 : err = __bpf_tx_xdp_map(dev, fwd, map, xdp, index);
3627 [ # # ]: 0 : if (unlikely(err))
3628 : : goto err;
3629 : :
3630 : 0 : ri->map_to_flush = map;
3631 [ # # ]: 0 : _trace_xdp_redirect_map(dev, xdp_prog, fwd, map, index);
3632 : 0 : return 0;
3633 : : err:
3634 [ # # ]: 0 : _trace_xdp_redirect_map_err(dev, xdp_prog, fwd, map, index, err);
3635 : 0 : return err;
3636 : : }
3637 : :
3638 : 0 : int xdp_do_redirect(struct net_device *dev, struct xdp_buff *xdp,
3639 : : struct bpf_prog *xdp_prog)
3640 : : {
3641 : 0 : struct bpf_redirect_info *ri = this_cpu_ptr(&bpf_redirect_info);
3642 : 0 : struct bpf_map *map = READ_ONCE(ri->map);
3643 : :
3644 [ # # ]: 0 : if (likely(map))
3645 : 0 : return xdp_do_redirect_map(dev, xdp, xdp_prog, map, ri);
3646 : :
3647 : 0 : return xdp_do_redirect_slow(dev, xdp, xdp_prog, ri);
3648 : : }
3649 : : EXPORT_SYMBOL_GPL(xdp_do_redirect);
3650 : :
3651 : 0 : static int xdp_do_generic_redirect_map(struct net_device *dev,
3652 : : struct sk_buff *skb,
3653 : : struct xdp_buff *xdp,
3654 : : struct bpf_prog *xdp_prog,
3655 : : struct bpf_map *map)
3656 : : {
3657 : 0 : struct bpf_redirect_info *ri = this_cpu_ptr(&bpf_redirect_info);
3658 : 0 : u32 index = ri->tgt_index;
3659 : 0 : void *fwd = ri->tgt_value;
3660 : : int err = 0;
3661 : :
3662 : 0 : ri->tgt_index = 0;
3663 : 0 : ri->tgt_value = NULL;
3664 : : WRITE_ONCE(ri->map, NULL);
3665 : :
3666 [ # # ]: 0 : if (map->map_type == BPF_MAP_TYPE_DEVMAP ||
3667 : : map->map_type == BPF_MAP_TYPE_DEVMAP_HASH) {
3668 : : struct bpf_dtab_netdev *dst = fwd;
3669 : :
3670 : 0 : err = dev_map_generic_redirect(dst, skb, xdp_prog);
3671 [ # # ]: 0 : if (unlikely(err))
3672 : : goto err;
3673 [ # # ]: 0 : } else if (map->map_type == BPF_MAP_TYPE_XSKMAP) {
3674 : : struct xdp_sock *xs = fwd;
3675 : :
3676 : : err = xsk_generic_rcv(xs, xdp);
3677 : : if (err)
3678 : : goto err;
3679 : : consume_skb(skb);
3680 : : } else {
3681 : : /* TODO: Handle BPF_MAP_TYPE_CPUMAP */
3682 : : err = -EBADRQC;
3683 : 0 : goto err;
3684 : : }
3685 : :
3686 [ # # ]: 0 : _trace_xdp_redirect_map(dev, xdp_prog, fwd, map, index);
3687 : 0 : return 0;
3688 : : err:
3689 [ # # ]: 0 : _trace_xdp_redirect_map_err(dev, xdp_prog, fwd, map, index, err);
3690 : 0 : return err;
3691 : : }
3692 : :
3693 : 0 : int xdp_do_generic_redirect(struct net_device *dev, struct sk_buff *skb,
3694 : : struct xdp_buff *xdp, struct bpf_prog *xdp_prog)
3695 : : {
3696 : 0 : struct bpf_redirect_info *ri = this_cpu_ptr(&bpf_redirect_info);
3697 : 0 : struct bpf_map *map = READ_ONCE(ri->map);
3698 : 0 : u32 index = ri->tgt_index;
3699 : : struct net_device *fwd;
3700 : : int err = 0;
3701 : :
3702 [ # # ]: 0 : if (map)
3703 : 0 : return xdp_do_generic_redirect_map(dev, skb, xdp, xdp_prog,
3704 : : map);
3705 : 0 : ri->tgt_index = 0;
3706 : 0 : fwd = dev_get_by_index_rcu(dev_net(dev), index);
3707 [ # # ]: 0 : if (unlikely(!fwd)) {
3708 : : err = -EINVAL;
3709 : : goto err;
3710 : : }
3711 : :
3712 : 0 : err = xdp_ok_fwd_dev(fwd, skb->len);
3713 [ # # ]: 0 : if (unlikely(err))
3714 : : goto err;
3715 : :
3716 : 0 : skb->dev = fwd;
3717 : 0 : _trace_xdp_redirect(dev, xdp_prog, index);
3718 : 0 : generic_xdp_tx(skb, xdp_prog);
3719 : 0 : return 0;
3720 : : err:
3721 : 0 : _trace_xdp_redirect_err(dev, xdp_prog, index, err);
3722 : 0 : return err;
3723 : : }
3724 : : EXPORT_SYMBOL_GPL(xdp_do_generic_redirect);
3725 : :
3726 : 0 : BPF_CALL_2(bpf_xdp_redirect, u32, ifindex, u64, flags)
3727 : : {
3728 : 0 : struct bpf_redirect_info *ri = this_cpu_ptr(&bpf_redirect_info);
3729 : :
3730 [ # # ]: 0 : if (unlikely(flags))
3731 : : return XDP_ABORTED;
3732 : :
3733 : 0 : ri->flags = flags;
3734 : 0 : ri->tgt_index = ifindex;
3735 : 0 : ri->tgt_value = NULL;
3736 : : WRITE_ONCE(ri->map, NULL);
3737 : :
3738 : : return XDP_REDIRECT;
3739 : : }
3740 : :
3741 : : static const struct bpf_func_proto bpf_xdp_redirect_proto = {
3742 : : .func = bpf_xdp_redirect,
3743 : : .gpl_only = false,
3744 : : .ret_type = RET_INTEGER,
3745 : : .arg1_type = ARG_ANYTHING,
3746 : : .arg2_type = ARG_ANYTHING,
3747 : : };
3748 : :
3749 : 0 : BPF_CALL_3(bpf_xdp_redirect_map, struct bpf_map *, map, u32, ifindex,
3750 : : u64, flags)
3751 : : {
3752 : 0 : struct bpf_redirect_info *ri = this_cpu_ptr(&bpf_redirect_info);
3753 : :
3754 : : /* Lower bits of the flags are used as return code on lookup failure */
3755 [ # # ]: 0 : if (unlikely(flags > XDP_TX))
3756 : : return XDP_ABORTED;
3757 : :
3758 : 0 : ri->tgt_value = __xdp_map_lookup_elem(map, ifindex);
3759 [ # # ]: 0 : if (unlikely(!ri->tgt_value)) {
3760 : : /* If the lookup fails we want to clear out the state in the
3761 : : * redirect_info struct completely, so that if an eBPF program
3762 : : * performs multiple lookups, the last one always takes
3763 : : * precedence.
3764 : : */
3765 : : WRITE_ONCE(ri->map, NULL);
3766 : : return flags;
3767 : : }
3768 : :
3769 : 0 : ri->flags = flags;
3770 : 0 : ri->tgt_index = ifindex;
3771 : : WRITE_ONCE(ri->map, map);
3772 : :
3773 : : return XDP_REDIRECT;
3774 : : }
3775 : :
3776 : : static const struct bpf_func_proto bpf_xdp_redirect_map_proto = {
3777 : : .func = bpf_xdp_redirect_map,
3778 : : .gpl_only = false,
3779 : : .ret_type = RET_INTEGER,
3780 : : .arg1_type = ARG_CONST_MAP_PTR,
3781 : : .arg2_type = ARG_ANYTHING,
3782 : : .arg3_type = ARG_ANYTHING,
3783 : : };
3784 : :
3785 : 0 : static unsigned long bpf_skb_copy(void *dst_buff, const void *skb,
3786 : : unsigned long off, unsigned long len)
3787 : : {
3788 : 0 : void *ptr = skb_header_pointer(skb, off, len, dst_buff);
3789 : :
3790 [ # # ]: 0 : if (unlikely(!ptr))
3791 : : return len;
3792 [ # # ]: 0 : if (ptr != dst_buff)
3793 : 0 : memcpy(dst_buff, ptr, len);
3794 : :
3795 : : return 0;
3796 : : }
3797 : :
3798 : 0 : BPF_CALL_5(bpf_skb_event_output, struct sk_buff *, skb, struct bpf_map *, map,
3799 : : u64, flags, void *, meta, u64, meta_size)
3800 : : {
3801 : 0 : u64 skb_size = (flags & BPF_F_CTXLEN_MASK) >> 32;
3802 : :
3803 [ # # ]: 0 : if (unlikely(flags & ~(BPF_F_CTXLEN_MASK | BPF_F_INDEX_MASK)))
3804 : : return -EINVAL;
3805 [ # # ]: 0 : if (unlikely(skb_size > skb->len))
3806 : : return -EFAULT;
3807 : :
3808 : 0 : return bpf_event_output(map, flags, meta, meta_size, skb, skb_size,
3809 : : bpf_skb_copy);
3810 : : }
3811 : :
3812 : : static const struct bpf_func_proto bpf_skb_event_output_proto = {
3813 : : .func = bpf_skb_event_output,
3814 : : .gpl_only = true,
3815 : : .ret_type = RET_INTEGER,
3816 : : .arg1_type = ARG_PTR_TO_CTX,
3817 : : .arg2_type = ARG_CONST_MAP_PTR,
3818 : : .arg3_type = ARG_ANYTHING,
3819 : : .arg4_type = ARG_PTR_TO_MEM,
3820 : : .arg5_type = ARG_CONST_SIZE_OR_ZERO,
3821 : : };
3822 : :
3823 : 0 : static unsigned short bpf_tunnel_key_af(u64 flags)
3824 : : {
3825 [ # # ]: 0 : return flags & BPF_F_TUNINFO_IPV6 ? AF_INET6 : AF_INET;
3826 : : }
3827 : :
3828 : 0 : BPF_CALL_4(bpf_skb_get_tunnel_key, struct sk_buff *, skb, struct bpf_tunnel_key *, to,
3829 : : u32, size, u64, flags)
3830 : : {
3831 : 0 : const struct ip_tunnel_info *info = skb_tunnel_info(skb);
3832 : : u8 compat[sizeof(struct bpf_tunnel_key)];
3833 : : void *to_orig = to;
3834 : : int err;
3835 : :
3836 [ # # # # ]: 0 : if (unlikely(!info || (flags & ~(BPF_F_TUNINFO_IPV6)))) {
3837 : : err = -EINVAL;
3838 : : goto err_clear;
3839 : : }
3840 [ # # ]: 0 : if (ip_tunnel_info_af(info) != bpf_tunnel_key_af(flags)) {
3841 : : err = -EPROTO;
3842 : : goto err_clear;
3843 : : }
3844 [ # # ]: 0 : if (unlikely(size != sizeof(struct bpf_tunnel_key))) {
3845 : : err = -EINVAL;
3846 [ # # # ]: 0 : switch (size) {
3847 : : case offsetof(struct bpf_tunnel_key, tunnel_label):
3848 : : case offsetof(struct bpf_tunnel_key, tunnel_ext):
3849 : : goto set_compat;
3850 : : case offsetof(struct bpf_tunnel_key, remote_ipv6[1]):
3851 : : /* Fixup deprecated structure layouts here, so we have
3852 : : * a common path later on.
3853 : : */
3854 [ # # ]: 0 : if (ip_tunnel_info_af(info) != AF_INET)
3855 : : goto err_clear;
3856 : : set_compat:
3857 : : to = (struct bpf_tunnel_key *)compat;
3858 : : break;
3859 : : default:
3860 : : goto err_clear;
3861 : : }
3862 : : }
3863 : :
3864 : 0 : to->tunnel_id = be64_to_cpu(info->key.tun_id);
3865 : 0 : to->tunnel_tos = info->key.tos;
3866 : 0 : to->tunnel_ttl = info->key.ttl;
3867 : 0 : to->tunnel_ext = 0;
3868 : :
3869 [ # # ]: 0 : if (flags & BPF_F_TUNINFO_IPV6) {
3870 : 0 : memcpy(to->remote_ipv6, &info->key.u.ipv6.src,
3871 : : sizeof(to->remote_ipv6));
3872 : 0 : to->tunnel_label = be32_to_cpu(info->key.label);
3873 : : } else {
3874 : 0 : to->remote_ipv4 = be32_to_cpu(info->key.u.ipv4.src);
3875 : 0 : memset(&to->remote_ipv6[1], 0, sizeof(__u32) * 3);
3876 : 0 : to->tunnel_label = 0;
3877 : : }
3878 : :
3879 [ # # ]: 0 : if (unlikely(size != sizeof(struct bpf_tunnel_key)))
3880 : 0 : memcpy(to_orig, to, size);
3881 : :
3882 : : return 0;
3883 : : err_clear:
3884 : 0 : memset(to_orig, 0, size);
3885 : 0 : return err;
3886 : : }
3887 : :
3888 : : static const struct bpf_func_proto bpf_skb_get_tunnel_key_proto = {
3889 : : .func = bpf_skb_get_tunnel_key,
3890 : : .gpl_only = false,
3891 : : .ret_type = RET_INTEGER,
3892 : : .arg1_type = ARG_PTR_TO_CTX,
3893 : : .arg2_type = ARG_PTR_TO_UNINIT_MEM,
3894 : : .arg3_type = ARG_CONST_SIZE,
3895 : : .arg4_type = ARG_ANYTHING,
3896 : : };
3897 : :
3898 : 0 : BPF_CALL_3(bpf_skb_get_tunnel_opt, struct sk_buff *, skb, u8 *, to, u32, size)
3899 : : {
3900 : 0 : const struct ip_tunnel_info *info = skb_tunnel_info(skb);
3901 : : int err;
3902 : :
3903 [ # # # # ]: 0 : if (unlikely(!info ||
3904 : : !(info->key.tun_flags & TUNNEL_OPTIONS_PRESENT))) {
3905 : : err = -ENOENT;
3906 : : goto err_clear;
3907 : : }
3908 [ # # ]: 0 : if (unlikely(size < info->options_len)) {
3909 : : err = -ENOMEM;
3910 : : goto err_clear;
3911 : : }
3912 : :
3913 : 0 : ip_tunnel_info_opts_get(to, info);
3914 [ # # ]: 0 : if (size > info->options_len)
3915 : 0 : memset(to + info->options_len, 0, size - info->options_len);
3916 : :
3917 : 0 : return info->options_len;
3918 : : err_clear:
3919 : 0 : memset(to, 0, size);
3920 : 0 : return err;
3921 : : }
3922 : :
3923 : : static const struct bpf_func_proto bpf_skb_get_tunnel_opt_proto = {
3924 : : .func = bpf_skb_get_tunnel_opt,
3925 : : .gpl_only = false,
3926 : : .ret_type = RET_INTEGER,
3927 : : .arg1_type = ARG_PTR_TO_CTX,
3928 : : .arg2_type = ARG_PTR_TO_UNINIT_MEM,
3929 : : .arg3_type = ARG_CONST_SIZE,
3930 : : };
3931 : :
3932 : : static struct metadata_dst __percpu *md_dst;
3933 : :
3934 : 0 : BPF_CALL_4(bpf_skb_set_tunnel_key, struct sk_buff *, skb,
3935 : : const struct bpf_tunnel_key *, from, u32, size, u64, flags)
3936 : : {
3937 : 0 : struct metadata_dst *md = this_cpu_ptr(md_dst);
3938 : : u8 compat[sizeof(struct bpf_tunnel_key)];
3939 : : struct ip_tunnel_info *info;
3940 : :
3941 [ # # ]: 0 : if (unlikely(flags & ~(BPF_F_TUNINFO_IPV6 | BPF_F_ZERO_CSUM_TX |
3942 : : BPF_F_DONT_FRAGMENT | BPF_F_SEQ_NUMBER)))
3943 : : return -EINVAL;
3944 [ # # ]: 0 : if (unlikely(size != sizeof(struct bpf_tunnel_key))) {
3945 [ # # ]: 0 : switch (size) {
3946 : : case offsetof(struct bpf_tunnel_key, tunnel_label):
3947 : : case offsetof(struct bpf_tunnel_key, tunnel_ext):
3948 : : case offsetof(struct bpf_tunnel_key, remote_ipv6[1]):
3949 : : /* Fixup deprecated structure layouts here, so we have
3950 : : * a common path later on.
3951 : : */
3952 : 0 : memcpy(compat, from, size);
3953 : 0 : memset(compat + size, 0, sizeof(compat) - size);
3954 : : from = (const struct bpf_tunnel_key *) compat;
3955 : : break;
3956 : : default:
3957 : : return -EINVAL;
3958 : : }
3959 : : }
3960 [ # # # # : 0 : if (unlikely((!(flags & BPF_F_TUNINFO_IPV6) && from->tunnel_label) ||
# # # # ]
3961 : : from->tunnel_ext))
3962 : : return -EINVAL;
3963 : :
3964 : 0 : skb_dst_drop(skb);
3965 : 0 : dst_hold((struct dst_entry *) md);
3966 : 0 : skb_dst_set(skb, (struct dst_entry *) md);
3967 : :
3968 : 0 : info = &md->u.tun_info;
3969 : 0 : memset(info, 0, sizeof(*info));
3970 : 0 : info->mode = IP_TUNNEL_INFO_TX;
3971 : :
3972 : 0 : info->key.tun_flags = TUNNEL_KEY | TUNNEL_CSUM | TUNNEL_NOCACHE;
3973 [ # # ]: 0 : if (flags & BPF_F_DONT_FRAGMENT)
3974 : 0 : info->key.tun_flags |= TUNNEL_DONT_FRAGMENT;
3975 [ # # ]: 0 : if (flags & BPF_F_ZERO_CSUM_TX)
3976 : 0 : info->key.tun_flags &= ~TUNNEL_CSUM;
3977 [ # # ]: 0 : if (flags & BPF_F_SEQ_NUMBER)
3978 : 0 : info->key.tun_flags |= TUNNEL_SEQ;
3979 : :
3980 : 0 : info->key.tun_id = cpu_to_be64(from->tunnel_id);
3981 : 0 : info->key.tos = from->tunnel_tos;
3982 : 0 : info->key.ttl = from->tunnel_ttl;
3983 : :
3984 [ # # ]: 0 : if (flags & BPF_F_TUNINFO_IPV6) {
3985 : 0 : info->mode |= IP_TUNNEL_INFO_IPV6;
3986 : 0 : memcpy(&info->key.u.ipv6.dst, from->remote_ipv6,
3987 : : sizeof(from->remote_ipv6));
3988 : 0 : info->key.label = cpu_to_be32(from->tunnel_label) &
3989 : : IPV6_FLOWLABEL_MASK;
3990 : : } else {
3991 : 0 : info->key.u.ipv4.dst = cpu_to_be32(from->remote_ipv4);
3992 : : }
3993 : :
3994 : : return 0;
3995 : : }
3996 : :
3997 : : static const struct bpf_func_proto bpf_skb_set_tunnel_key_proto = {
3998 : : .func = bpf_skb_set_tunnel_key,
3999 : : .gpl_only = false,
4000 : : .ret_type = RET_INTEGER,
4001 : : .arg1_type = ARG_PTR_TO_CTX,
4002 : : .arg2_type = ARG_PTR_TO_MEM,
4003 : : .arg3_type = ARG_CONST_SIZE,
4004 : : .arg4_type = ARG_ANYTHING,
4005 : : };
4006 : :
4007 : 0 : BPF_CALL_3(bpf_skb_set_tunnel_opt, struct sk_buff *, skb,
4008 : : const u8 *, from, u32, size)
4009 : : {
4010 : 0 : struct ip_tunnel_info *info = skb_tunnel_info(skb);
4011 : 0 : const struct metadata_dst *md = this_cpu_ptr(md_dst);
4012 : :
4013 [ # # # # ]: 0 : if (unlikely(info != &md->u.tun_info || (size & (sizeof(u32) - 1))))
4014 : : return -EINVAL;
4015 [ # # ]: 0 : if (unlikely(size > IP_TUNNEL_OPTS_MAX))
4016 : : return -ENOMEM;
4017 : :
4018 : 0 : ip_tunnel_info_opts_set(info, from, size, TUNNEL_OPTIONS_PRESENT);
4019 : :
4020 : : return 0;
4021 : : }
4022 : :
4023 : : static const struct bpf_func_proto bpf_skb_set_tunnel_opt_proto = {
4024 : : .func = bpf_skb_set_tunnel_opt,
4025 : : .gpl_only = false,
4026 : : .ret_type = RET_INTEGER,
4027 : : .arg1_type = ARG_PTR_TO_CTX,
4028 : : .arg2_type = ARG_PTR_TO_MEM,
4029 : : .arg3_type = ARG_CONST_SIZE,
4030 : : };
4031 : :
4032 : : static const struct bpf_func_proto *
4033 : 0 : bpf_get_skb_set_tunnel_proto(enum bpf_func_id which)
4034 : : {
4035 [ # # ]: 0 : if (!md_dst) {
4036 : : struct metadata_dst __percpu *tmp;
4037 : :
4038 : 0 : tmp = metadata_dst_alloc_percpu(IP_TUNNEL_OPTS_MAX,
4039 : : METADATA_IP_TUNNEL,
4040 : : GFP_KERNEL);
4041 [ # # ]: 0 : if (!tmp)
4042 : : return NULL;
4043 [ # # ]: 0 : if (cmpxchg(&md_dst, NULL, tmp))
4044 : 0 : metadata_dst_free_percpu(tmp);
4045 : : }
4046 : :
4047 [ # # # ]: 0 : switch (which) {
4048 : : case BPF_FUNC_skb_set_tunnel_key:
4049 : : return &bpf_skb_set_tunnel_key_proto;
4050 : : case BPF_FUNC_skb_set_tunnel_opt:
4051 : 0 : return &bpf_skb_set_tunnel_opt_proto;
4052 : : default:
4053 : 0 : return NULL;
4054 : : }
4055 : : }
4056 : :
4057 : 0 : BPF_CALL_3(bpf_skb_under_cgroup, struct sk_buff *, skb, struct bpf_map *, map,
4058 : : u32, idx)
4059 : : {
4060 : : struct bpf_array *array = container_of(map, struct bpf_array, map);
4061 : : struct cgroup *cgrp;
4062 : : struct sock *sk;
4063 : :
4064 : 0 : sk = skb_to_full_sk(skb);
4065 [ # # # # ]: 0 : if (!sk || !sk_fullsock(sk))
4066 : : return -ENOENT;
4067 [ # # ]: 0 : if (unlikely(idx >= array->map.max_entries))
4068 : : return -E2BIG;
4069 : :
4070 : 0 : cgrp = READ_ONCE(array->ptrs[idx]);
4071 [ # # ]: 0 : if (unlikely(!cgrp))
4072 : : return -EAGAIN;
4073 : :
4074 : 0 : return sk_under_cgroup_hierarchy(sk, cgrp);
4075 : : }
4076 : :
4077 : : static const struct bpf_func_proto bpf_skb_under_cgroup_proto = {
4078 : : .func = bpf_skb_under_cgroup,
4079 : : .gpl_only = false,
4080 : : .ret_type = RET_INTEGER,
4081 : : .arg1_type = ARG_PTR_TO_CTX,
4082 : : .arg2_type = ARG_CONST_MAP_PTR,
4083 : : .arg3_type = ARG_ANYTHING,
4084 : : };
4085 : :
4086 : : #ifdef CONFIG_SOCK_CGROUP_DATA
4087 : 0 : BPF_CALL_1(bpf_skb_cgroup_id, const struct sk_buff *, skb)
4088 : : {
4089 : 0 : struct sock *sk = skb_to_full_sk(skb);
4090 : : struct cgroup *cgrp;
4091 : :
4092 [ # # # # ]: 0 : if (!sk || !sk_fullsock(sk))
4093 : : return 0;
4094 : :
4095 : 0 : cgrp = sock_cgroup_ptr(&sk->sk_cgrp_data);
4096 : 0 : return cgrp->kn->id.id;
4097 : : }
4098 : :
4099 : : static const struct bpf_func_proto bpf_skb_cgroup_id_proto = {
4100 : : .func = bpf_skb_cgroup_id,
4101 : : .gpl_only = false,
4102 : : .ret_type = RET_INTEGER,
4103 : : .arg1_type = ARG_PTR_TO_CTX,
4104 : : };
4105 : :
4106 : 0 : BPF_CALL_2(bpf_skb_ancestor_cgroup_id, const struct sk_buff *, skb, int,
4107 : : ancestor_level)
4108 : : {
4109 : 0 : struct sock *sk = skb_to_full_sk(skb);
4110 : : struct cgroup *ancestor;
4111 : : struct cgroup *cgrp;
4112 : :
4113 [ # # # # ]: 0 : if (!sk || !sk_fullsock(sk))
4114 : : return 0;
4115 : :
4116 : 0 : cgrp = sock_cgroup_ptr(&sk->sk_cgrp_data);
4117 : 0 : ancestor = cgroup_ancestor(cgrp, ancestor_level);
4118 [ # # ]: 0 : if (!ancestor)
4119 : : return 0;
4120 : :
4121 : 0 : return ancestor->kn->id.id;
4122 : : }
4123 : :
4124 : : static const struct bpf_func_proto bpf_skb_ancestor_cgroup_id_proto = {
4125 : : .func = bpf_skb_ancestor_cgroup_id,
4126 : : .gpl_only = false,
4127 : : .ret_type = RET_INTEGER,
4128 : : .arg1_type = ARG_PTR_TO_CTX,
4129 : : .arg2_type = ARG_ANYTHING,
4130 : : };
4131 : : #endif
4132 : :
4133 : 0 : static unsigned long bpf_xdp_copy(void *dst_buff, const void *src_buff,
4134 : : unsigned long off, unsigned long len)
4135 : : {
4136 : 0 : memcpy(dst_buff, src_buff + off, len);
4137 : 0 : return 0;
4138 : : }
4139 : :
4140 : 0 : BPF_CALL_5(bpf_xdp_event_output, struct xdp_buff *, xdp, struct bpf_map *, map,
4141 : : u64, flags, void *, meta, u64, meta_size)
4142 : : {
4143 : 0 : u64 xdp_size = (flags & BPF_F_CTXLEN_MASK) >> 32;
4144 : :
4145 [ # # ]: 0 : if (unlikely(flags & ~(BPF_F_CTXLEN_MASK | BPF_F_INDEX_MASK)))
4146 : : return -EINVAL;
4147 [ # # ]: 0 : if (unlikely(xdp_size > (unsigned long)(xdp->data_end - xdp->data)))
4148 : : return -EFAULT;
4149 : :
4150 : 0 : return bpf_event_output(map, flags, meta, meta_size, xdp->data,
4151 : : xdp_size, bpf_xdp_copy);
4152 : : }
4153 : :
4154 : : static const struct bpf_func_proto bpf_xdp_event_output_proto = {
4155 : : .func = bpf_xdp_event_output,
4156 : : .gpl_only = true,
4157 : : .ret_type = RET_INTEGER,
4158 : : .arg1_type = ARG_PTR_TO_CTX,
4159 : : .arg2_type = ARG_CONST_MAP_PTR,
4160 : : .arg3_type = ARG_ANYTHING,
4161 : : .arg4_type = ARG_PTR_TO_MEM,
4162 : : .arg5_type = ARG_CONST_SIZE_OR_ZERO,
4163 : : };
4164 : :
4165 : 0 : BPF_CALL_1(bpf_get_socket_cookie, struct sk_buff *, skb)
4166 : : {
4167 [ # # ]: 0 : return skb->sk ? sock_gen_cookie(skb->sk) : 0;
4168 : : }
4169 : :
4170 : : static const struct bpf_func_proto bpf_get_socket_cookie_proto = {
4171 : : .func = bpf_get_socket_cookie,
4172 : : .gpl_only = false,
4173 : : .ret_type = RET_INTEGER,
4174 : : .arg1_type = ARG_PTR_TO_CTX,
4175 : : };
4176 : :
4177 : 0 : BPF_CALL_1(bpf_get_socket_cookie_sock_addr, struct bpf_sock_addr_kern *, ctx)
4178 : : {
4179 : 0 : return sock_gen_cookie(ctx->sk);
4180 : : }
4181 : :
4182 : : static const struct bpf_func_proto bpf_get_socket_cookie_sock_addr_proto = {
4183 : : .func = bpf_get_socket_cookie_sock_addr,
4184 : : .gpl_only = false,
4185 : : .ret_type = RET_INTEGER,
4186 : : .arg1_type = ARG_PTR_TO_CTX,
4187 : : };
4188 : :
4189 : 0 : BPF_CALL_1(bpf_get_socket_cookie_sock_ops, struct bpf_sock_ops_kern *, ctx)
4190 : : {
4191 : 0 : return sock_gen_cookie(ctx->sk);
4192 : : }
4193 : :
4194 : : static const struct bpf_func_proto bpf_get_socket_cookie_sock_ops_proto = {
4195 : : .func = bpf_get_socket_cookie_sock_ops,
4196 : : .gpl_only = false,
4197 : : .ret_type = RET_INTEGER,
4198 : : .arg1_type = ARG_PTR_TO_CTX,
4199 : : };
4200 : :
4201 : 0 : BPF_CALL_1(bpf_get_socket_uid, struct sk_buff *, skb)
4202 : : {
4203 : 0 : struct sock *sk = sk_to_full_sk(skb->sk);
4204 : : kuid_t kuid;
4205 : :
4206 [ # # # # ]: 0 : if (!sk || !sk_fullsock(sk))
4207 : 0 : return overflowuid;
4208 : 0 : kuid = sock_net_uid(sock_net(sk), sk);
4209 : 0 : return from_kuid_munged(sock_net(sk)->user_ns, kuid);
4210 : : }
4211 : :
4212 : : static const struct bpf_func_proto bpf_get_socket_uid_proto = {
4213 : : .func = bpf_get_socket_uid,
4214 : : .gpl_only = false,
4215 : : .ret_type = RET_INTEGER,
4216 : : .arg1_type = ARG_PTR_TO_CTX,
4217 : : };
4218 : :
4219 : 0 : BPF_CALL_5(bpf_sockopt_event_output, struct bpf_sock_ops_kern *, bpf_sock,
4220 : : struct bpf_map *, map, u64, flags, void *, data, u64, size)
4221 : : {
4222 [ # # ]: 0 : if (unlikely(flags & ~(BPF_F_INDEX_MASK)))
4223 : : return -EINVAL;
4224 : :
4225 : 0 : return bpf_event_output(map, flags, data, size, NULL, 0, NULL);
4226 : : }
4227 : :
4228 : : static const struct bpf_func_proto bpf_sockopt_event_output_proto = {
4229 : : .func = bpf_sockopt_event_output,
4230 : : .gpl_only = true,
4231 : : .ret_type = RET_INTEGER,
4232 : : .arg1_type = ARG_PTR_TO_CTX,
4233 : : .arg2_type = ARG_CONST_MAP_PTR,
4234 : : .arg3_type = ARG_ANYTHING,
4235 : : .arg4_type = ARG_PTR_TO_MEM,
4236 : : .arg5_type = ARG_CONST_SIZE_OR_ZERO,
4237 : : };
4238 : :
4239 : 0 : BPF_CALL_5(bpf_setsockopt, struct bpf_sock_ops_kern *, bpf_sock,
4240 : : int, level, int, optname, char *, optval, int, optlen)
4241 : : {
4242 : 0 : struct sock *sk = bpf_sock->sk;
4243 : : int ret = 0;
4244 : : int val;
4245 : :
4246 [ # # ]: 0 : if (!sk_fullsock(sk))
4247 : : return -EINVAL;
4248 : :
4249 [ # # ]: 0 : if (level == SOL_SOCKET) {
4250 [ # # ]: 0 : if (optlen != sizeof(int))
4251 : : return -EINVAL;
4252 : 0 : val = *((int *)optval);
4253 : :
4254 : : /* Only some socketops are supported */
4255 [ # # # # : 0 : switch (optname) {
# # # ]
4256 : : case SO_RCVBUF:
4257 : 0 : val = min_t(u32, val, sysctl_rmem_max);
4258 : 0 : sk->sk_userlocks |= SOCK_RCVBUF_LOCK;
4259 : 0 : WRITE_ONCE(sk->sk_rcvbuf,
4260 : : max_t(int, val * 2, SOCK_MIN_RCVBUF));
4261 : : break;
4262 : : case SO_SNDBUF:
4263 : 0 : val = min_t(u32, val, sysctl_wmem_max);
4264 : 0 : sk->sk_userlocks |= SOCK_SNDBUF_LOCK;
4265 : 0 : WRITE_ONCE(sk->sk_sndbuf,
4266 : : max_t(int, val * 2, SOCK_MIN_SNDBUF));
4267 : : break;
4268 : : case SO_MAX_PACING_RATE: /* 32bit version */
4269 [ # # ]: 0 : if (val != ~0U)
4270 : 0 : cmpxchg(&sk->sk_pacing_status,
4271 : : SK_PACING_NONE,
4272 : : SK_PACING_NEEDED);
4273 [ # # ]: 0 : sk->sk_max_pacing_rate = (val == ~0U) ? ~0UL : val;
4274 : 0 : sk->sk_pacing_rate = min(sk->sk_pacing_rate,
4275 : : sk->sk_max_pacing_rate);
4276 : : break;
4277 : : case SO_PRIORITY:
4278 : 0 : sk->sk_priority = val;
4279 : : break;
4280 : : case SO_RCVLOWAT:
4281 [ # # ]: 0 : if (val < 0)
4282 : : val = INT_MAX;
4283 [ # # ]: 0 : WRITE_ONCE(sk->sk_rcvlowat, val ? : 1);
4284 : : break;
4285 : : case SO_MARK:
4286 [ # # ]: 0 : if (sk->sk_mark != val) {
4287 : 0 : sk->sk_mark = val;
4288 : 0 : sk_dst_reset(sk);
4289 : : }
4290 : : break;
4291 : : default:
4292 : : ret = -EINVAL;
4293 : : }
4294 : : #ifdef CONFIG_INET
4295 [ # # ]: 0 : } else if (level == SOL_IP) {
4296 [ # # # # ]: 0 : if (optlen != sizeof(int) || sk->sk_family != AF_INET)
4297 : : return -EINVAL;
4298 : :
4299 : 0 : val = *((int *)optval);
4300 : : /* Only some options are supported */
4301 [ # # ]: 0 : switch (optname) {
4302 : : case IP_TOS:
4303 [ # # ]: 0 : if (val < -1 || val > 0xff) {
4304 : : ret = -EINVAL;
4305 : : } else {
4306 : 0 : struct inet_sock *inet = inet_sk(sk);
4307 : :
4308 [ # # ]: 0 : if (val == -1)
4309 : : val = 0;
4310 : 0 : inet->tos = val;
4311 : : }
4312 : : break;
4313 : : default:
4314 : : ret = -EINVAL;
4315 : : }
4316 : : #if IS_ENABLED(CONFIG_IPV6)
4317 [ # # ]: 0 : } else if (level == SOL_IPV6) {
4318 [ # # # # ]: 0 : if (optlen != sizeof(int) || sk->sk_family != AF_INET6)
4319 : : return -EINVAL;
4320 : :
4321 : 0 : val = *((int *)optval);
4322 : : /* Only some options are supported */
4323 [ # # ]: 0 : switch (optname) {
4324 : : case IPV6_TCLASS:
4325 [ # # ]: 0 : if (val < -1 || val > 0xff) {
4326 : : ret = -EINVAL;
4327 : : } else {
4328 : 0 : struct ipv6_pinfo *np = inet6_sk(sk);
4329 : :
4330 [ # # ]: 0 : if (val == -1)
4331 : : val = 0;
4332 : 0 : np->tclass = val;
4333 : : }
4334 : : break;
4335 : : default:
4336 : : ret = -EINVAL;
4337 : : }
4338 : : #endif
4339 [ # # # # ]: 0 : } else if (level == SOL_TCP &&
4340 : 0 : sk->sk_prot->setsockopt == tcp_setsockopt) {
4341 [ # # ]: 0 : if (optname == TCP_CONGESTION) {
4342 : : char name[TCP_CA_NAME_MAX];
4343 : 0 : bool reinit = bpf_sock->op > BPF_SOCK_OPS_NEEDS_ECN;
4344 : :
4345 : 0 : strncpy(name, optval, min_t(long, optlen,
4346 : : TCP_CA_NAME_MAX-1));
4347 : 0 : name[TCP_CA_NAME_MAX-1] = 0;
4348 : 0 : ret = tcp_set_congestion_control(sk, name, false,
4349 : : reinit, true);
4350 : : } else {
4351 : 0 : struct tcp_sock *tp = tcp_sk(sk);
4352 : :
4353 [ # # ]: 0 : if (optlen != sizeof(int))
4354 : : return -EINVAL;
4355 : :
4356 : 0 : val = *((int *)optval);
4357 : : /* Only some options are supported */
4358 [ # # # # ]: 0 : switch (optname) {
4359 : : case TCP_BPF_IW:
4360 [ # # # # ]: 0 : if (val <= 0 || tp->data_segs_out > tp->syn_data)
4361 : : ret = -EINVAL;
4362 : : else
4363 : 0 : tp->snd_cwnd = val;
4364 : : break;
4365 : : case TCP_BPF_SNDCWND_CLAMP:
4366 [ # # ]: 0 : if (val <= 0) {
4367 : : ret = -EINVAL;
4368 : : } else {
4369 : 0 : tp->snd_cwnd_clamp = val;
4370 : 0 : tp->snd_ssthresh = val;
4371 : : }
4372 : : break;
4373 : : case TCP_SAVE_SYN:
4374 [ # # ]: 0 : if (val < 0 || val > 1)
4375 : : ret = -EINVAL;
4376 : : else
4377 : 0 : tp->save_syn = val;
4378 : : break;
4379 : : default:
4380 : : ret = -EINVAL;
4381 : : }
4382 : : }
4383 : : #endif
4384 : : } else {
4385 : : ret = -EINVAL;
4386 : : }
4387 : 0 : return ret;
4388 : : }
4389 : :
4390 : : static const struct bpf_func_proto bpf_setsockopt_proto = {
4391 : : .func = bpf_setsockopt,
4392 : : .gpl_only = false,
4393 : : .ret_type = RET_INTEGER,
4394 : : .arg1_type = ARG_PTR_TO_CTX,
4395 : : .arg2_type = ARG_ANYTHING,
4396 : : .arg3_type = ARG_ANYTHING,
4397 : : .arg4_type = ARG_PTR_TO_MEM,
4398 : : .arg5_type = ARG_CONST_SIZE,
4399 : : };
4400 : :
4401 : 0 : BPF_CALL_5(bpf_getsockopt, struct bpf_sock_ops_kern *, bpf_sock,
4402 : : int, level, int, optname, char *, optval, int, optlen)
4403 : : {
4404 : 0 : struct sock *sk = bpf_sock->sk;
4405 : :
4406 [ # # ]: 0 : if (!sk_fullsock(sk))
4407 : : goto err_clear;
4408 : : #ifdef CONFIG_INET
4409 [ # # # # ]: 0 : if (level == SOL_TCP && sk->sk_prot->getsockopt == tcp_getsockopt) {
4410 : : struct inet_connection_sock *icsk;
4411 : : struct tcp_sock *tp;
4412 : :
4413 [ # # # ]: 0 : switch (optname) {
4414 : : case TCP_CONGESTION:
4415 : 0 : icsk = inet_csk(sk);
4416 : :
4417 [ # # # # ]: 0 : if (!icsk->icsk_ca_ops || optlen <= 1)
4418 : : goto err_clear;
4419 : 0 : strncpy(optval, icsk->icsk_ca_ops->name, optlen);
4420 : 0 : optval[optlen - 1] = 0;
4421 : : break;
4422 : : case TCP_SAVED_SYN:
4423 : 0 : tp = tcp_sk(sk);
4424 : :
4425 [ # # # # : 0 : if (optlen <= 0 || !tp->saved_syn ||
# # ]
4426 : 0 : optlen > tp->saved_syn[0])
4427 : : goto err_clear;
4428 : 0 : memcpy(optval, tp->saved_syn + 1, optlen);
4429 : : break;
4430 : : default:
4431 : : goto err_clear;
4432 : : }
4433 [ # # ]: 0 : } else if (level == SOL_IP) {
4434 : 0 : struct inet_sock *inet = inet_sk(sk);
4435 : :
4436 [ # # # # ]: 0 : if (optlen != sizeof(int) || sk->sk_family != AF_INET)
4437 : : goto err_clear;
4438 : :
4439 : : /* Only some options are supported */
4440 [ # # ]: 0 : switch (optname) {
4441 : : case IP_TOS:
4442 : 0 : *((int *)optval) = (int)inet->tos;
4443 : : break;
4444 : : default:
4445 : : goto err_clear;
4446 : : }
4447 : : #if IS_ENABLED(CONFIG_IPV6)
4448 [ # # ]: 0 : } else if (level == SOL_IPV6) {
4449 : 0 : struct ipv6_pinfo *np = inet6_sk(sk);
4450 : :
4451 [ # # # # ]: 0 : if (optlen != sizeof(int) || sk->sk_family != AF_INET6)
4452 : : goto err_clear;
4453 : :
4454 : : /* Only some options are supported */
4455 [ # # ]: 0 : switch (optname) {
4456 : : case IPV6_TCLASS:
4457 : 0 : *((int *)optval) = (int)np->tclass;
4458 : : break;
4459 : : default:
4460 : : goto err_clear;
4461 : : }
4462 : : #endif
4463 : : } else {
4464 : : goto err_clear;
4465 : : }
4466 : : return 0;
4467 : : #endif
4468 : : err_clear:
4469 : 0 : memset(optval, 0, optlen);
4470 : : return -EINVAL;
4471 : : }
4472 : :
4473 : : static const struct bpf_func_proto bpf_getsockopt_proto = {
4474 : : .func = bpf_getsockopt,
4475 : : .gpl_only = false,
4476 : : .ret_type = RET_INTEGER,
4477 : : .arg1_type = ARG_PTR_TO_CTX,
4478 : : .arg2_type = ARG_ANYTHING,
4479 : : .arg3_type = ARG_ANYTHING,
4480 : : .arg4_type = ARG_PTR_TO_UNINIT_MEM,
4481 : : .arg5_type = ARG_CONST_SIZE,
4482 : : };
4483 : :
4484 : 0 : BPF_CALL_2(bpf_sock_ops_cb_flags_set, struct bpf_sock_ops_kern *, bpf_sock,
4485 : : int, argval)
4486 : : {
4487 : 0 : struct sock *sk = bpf_sock->sk;
4488 : 0 : int val = argval & BPF_SOCK_OPS_ALL_CB_FLAGS;
4489 : :
4490 [ # # ]: 0 : if (!IS_ENABLED(CONFIG_INET) || !sk_fullsock(sk))
4491 : : return -EINVAL;
4492 : :
4493 : 0 : tcp_sk(sk)->bpf_sock_ops_cb_flags = val;
4494 : :
4495 : 0 : return argval & (~BPF_SOCK_OPS_ALL_CB_FLAGS);
4496 : : }
4497 : :
4498 : : static const struct bpf_func_proto bpf_sock_ops_cb_flags_set_proto = {
4499 : : .func = bpf_sock_ops_cb_flags_set,
4500 : : .gpl_only = false,
4501 : : .ret_type = RET_INTEGER,
4502 : : .arg1_type = ARG_PTR_TO_CTX,
4503 : : .arg2_type = ARG_ANYTHING,
4504 : : };
4505 : :
4506 : : const struct ipv6_bpf_stub *ipv6_bpf_stub __read_mostly;
4507 : : EXPORT_SYMBOL_GPL(ipv6_bpf_stub);
4508 : :
4509 : 0 : BPF_CALL_3(bpf_bind, struct bpf_sock_addr_kern *, ctx, struct sockaddr *, addr,
4510 : : int, addr_len)
4511 : : {
4512 : : #ifdef CONFIG_INET
4513 : 0 : struct sock *sk = ctx->sk;
4514 : : int err;
4515 : :
4516 : : /* Binding to port can be expensive so it's prohibited in the helper.
4517 : : * Only binding to IP is supported.
4518 : : */
4519 : : err = -EINVAL;
4520 [ # # ]: 0 : if (addr_len < offsetofend(struct sockaddr, sa_family))
4521 : : return err;
4522 [ # # ]: 0 : if (addr->sa_family == AF_INET) {
4523 [ # # ]: 0 : if (addr_len < sizeof(struct sockaddr_in))
4524 : : return err;
4525 [ # # ]: 0 : if (((struct sockaddr_in *)addr)->sin_port != htons(0))
4526 : : return err;
4527 : 0 : return __inet_bind(sk, addr, addr_len, true, false);
4528 : : #if IS_ENABLED(CONFIG_IPV6)
4529 [ # # ]: 0 : } else if (addr->sa_family == AF_INET6) {
4530 [ # # ]: 0 : if (addr_len < SIN6_LEN_RFC2133)
4531 : : return err;
4532 [ # # ]: 0 : if (((struct sockaddr_in6 *)addr)->sin6_port != htons(0))
4533 : : return err;
4534 : : /* ipv6_bpf_stub cannot be NULL, since it's called from
4535 : : * bpf_cgroup_inet6_connect hook and ipv6 is already loaded
4536 : : */
4537 : 0 : return ipv6_bpf_stub->inet6_bind(sk, addr, addr_len, true, false);
4538 : : #endif /* CONFIG_IPV6 */
4539 : : }
4540 : : #endif /* CONFIG_INET */
4541 : :
4542 : : return -EAFNOSUPPORT;
4543 : : }
4544 : :
4545 : : static const struct bpf_func_proto bpf_bind_proto = {
4546 : : .func = bpf_bind,
4547 : : .gpl_only = false,
4548 : : .ret_type = RET_INTEGER,
4549 : : .arg1_type = ARG_PTR_TO_CTX,
4550 : : .arg2_type = ARG_PTR_TO_MEM,
4551 : : .arg3_type = ARG_CONST_SIZE,
4552 : : };
4553 : :
4554 : : #ifdef CONFIG_XFRM
4555 : 0 : BPF_CALL_5(bpf_skb_get_xfrm_state, struct sk_buff *, skb, u32, index,
4556 : : struct bpf_xfrm_state *, to, u32, size, u64, flags)
4557 : : {
4558 : 0 : const struct sec_path *sp = skb_sec_path(skb);
4559 : : const struct xfrm_state *x;
4560 : :
4561 [ # # # # : 0 : if (!sp || unlikely(index >= sp->len || flags))
# # ]
4562 : : goto err_clear;
4563 : :
4564 : 0 : x = sp->xvec[index];
4565 : :
4566 [ # # ]: 0 : if (unlikely(size != sizeof(struct bpf_xfrm_state)))
4567 : : goto err_clear;
4568 : :
4569 : 0 : to->reqid = x->props.reqid;
4570 : 0 : to->spi = x->id.spi;
4571 : 0 : to->family = x->props.family;
4572 : 0 : to->ext = 0;
4573 : :
4574 [ # # ]: 0 : if (to->family == AF_INET6) {
4575 : 0 : memcpy(to->remote_ipv6, x->props.saddr.a6,
4576 : : sizeof(to->remote_ipv6));
4577 : : } else {
4578 : 0 : to->remote_ipv4 = x->props.saddr.a4;
4579 : 0 : memset(&to->remote_ipv6[1], 0, sizeof(__u32) * 3);
4580 : : }
4581 : :
4582 : : return 0;
4583 : : err_clear:
4584 : 0 : memset(to, 0, size);
4585 : : return -EINVAL;
4586 : : }
4587 : :
4588 : : static const struct bpf_func_proto bpf_skb_get_xfrm_state_proto = {
4589 : : .func = bpf_skb_get_xfrm_state,
4590 : : .gpl_only = false,
4591 : : .ret_type = RET_INTEGER,
4592 : : .arg1_type = ARG_PTR_TO_CTX,
4593 : : .arg2_type = ARG_ANYTHING,
4594 : : .arg3_type = ARG_PTR_TO_UNINIT_MEM,
4595 : : .arg4_type = ARG_CONST_SIZE,
4596 : : .arg5_type = ARG_ANYTHING,
4597 : : };
4598 : : #endif
4599 : :
4600 : : #if IS_ENABLED(CONFIG_INET) || IS_ENABLED(CONFIG_IPV6)
4601 : 0 : static int bpf_fib_set_fwd_params(struct bpf_fib_lookup *params,
4602 : : const struct neighbour *neigh,
4603 : : const struct net_device *dev)
4604 : : {
4605 : 0 : memcpy(params->dmac, neigh->ha, ETH_ALEN);
4606 : 0 : memcpy(params->smac, dev->dev_addr, ETH_ALEN);
4607 : 0 : params->h_vlan_TCI = 0;
4608 : 0 : params->h_vlan_proto = 0;
4609 : 0 : params->ifindex = dev->ifindex;
4610 : :
4611 : 0 : return 0;
4612 : : }
4613 : : #endif
4614 : :
4615 : : #if IS_ENABLED(CONFIG_INET)
4616 : 0 : static int bpf_ipv4_fib_lookup(struct net *net, struct bpf_fib_lookup *params,
4617 : : u32 flags, bool check_mtu)
4618 : : {
4619 : : struct fib_nh_common *nhc;
4620 : : struct in_device *in_dev;
4621 : : struct neighbour *neigh;
4622 : : struct net_device *dev;
4623 : : struct fib_result res;
4624 : : struct flowi4 fl4;
4625 : : int err;
4626 : : u32 mtu;
4627 : :
4628 : 0 : dev = dev_get_by_index_rcu(net, params->ifindex);
4629 [ # # ]: 0 : if (unlikely(!dev))
4630 : : return -ENODEV;
4631 : :
4632 : : /* verify forwarding is enabled on this interface */
4633 : : in_dev = __in_dev_get_rcu(dev);
4634 [ # # # # ]: 0 : if (unlikely(!in_dev || !IN_DEV_FORWARD(in_dev)))
4635 : : return BPF_FIB_LKUP_RET_FWD_DISABLED;
4636 : :
4637 [ # # ]: 0 : if (flags & BPF_FIB_LOOKUP_OUTPUT) {
4638 : 0 : fl4.flowi4_iif = 1;
4639 : 0 : fl4.flowi4_oif = params->ifindex;
4640 : : } else {
4641 : 0 : fl4.flowi4_iif = params->ifindex;
4642 : 0 : fl4.flowi4_oif = 0;
4643 : : }
4644 : 0 : fl4.flowi4_tos = params->tos & IPTOS_RT_MASK;
4645 : 0 : fl4.flowi4_scope = RT_SCOPE_UNIVERSE;
4646 : 0 : fl4.flowi4_flags = 0;
4647 : :
4648 : 0 : fl4.flowi4_proto = params->l4_protocol;
4649 : 0 : fl4.daddr = params->ipv4_dst;
4650 : 0 : fl4.saddr = params->ipv4_src;
4651 : 0 : fl4.fl4_sport = params->sport;
4652 : 0 : fl4.fl4_dport = params->dport;
4653 : :
4654 [ # # ]: 0 : if (flags & BPF_FIB_LOOKUP_DIRECT) {
4655 [ # # ]: 0 : u32 tbid = l3mdev_fib_table_rcu(dev) ? : RT_TABLE_MAIN;
4656 : : struct fib_table *tb;
4657 : :
4658 : 0 : tb = fib_get_table(net, tbid);
4659 [ # # ]: 0 : if (unlikely(!tb))
4660 : : return BPF_FIB_LKUP_RET_NOT_FWDED;
4661 : :
4662 : 0 : err = fib_table_lookup(tb, &fl4, &res, FIB_LOOKUP_NOREF);
4663 : : } else {
4664 : 0 : fl4.flowi4_mark = 0;
4665 : 0 : fl4.flowi4_secid = 0;
4666 : 0 : fl4.flowi4_tun_key.tun_id = 0;
4667 : 0 : fl4.flowi4_uid = sock_net_uid(net, NULL);
4668 : :
4669 : 0 : err = fib_lookup(net, &fl4, &res, FIB_LOOKUP_NOREF);
4670 : : }
4671 : :
4672 [ # # ]: 0 : if (err) {
4673 : : /* map fib lookup errors to RTN_ type */
4674 [ # # ]: 0 : if (err == -EINVAL)
4675 : : return BPF_FIB_LKUP_RET_BLACKHOLE;
4676 [ # # ]: 0 : if (err == -EHOSTUNREACH)
4677 : : return BPF_FIB_LKUP_RET_UNREACHABLE;
4678 [ # # ]: 0 : if (err == -EACCES)
4679 : : return BPF_FIB_LKUP_RET_PROHIBIT;
4680 : :
4681 : 0 : return BPF_FIB_LKUP_RET_NOT_FWDED;
4682 : : }
4683 : :
4684 [ # # ]: 0 : if (res.type != RTN_UNICAST)
4685 : : return BPF_FIB_LKUP_RET_NOT_FWDED;
4686 : :
4687 [ # # ]: 0 : if (fib_info_num_path(res.fi) > 1)
4688 : 0 : fib_select_path(net, &res, &fl4, NULL);
4689 : :
4690 [ # # ]: 0 : if (check_mtu) {
4691 : 0 : mtu = ip_mtu_from_fib_result(&res, params->ipv4_dst);
4692 [ # # ]: 0 : if (params->tot_len > mtu)
4693 : : return BPF_FIB_LKUP_RET_FRAG_NEEDED;
4694 : : }
4695 : :
4696 : 0 : nhc = res.nhc;
4697 : :
4698 : : /* do not handle lwt encaps right now */
4699 [ # # ]: 0 : if (nhc->nhc_lwtstate)
4700 : : return BPF_FIB_LKUP_RET_UNSUPP_LWT;
4701 : :
4702 : 0 : dev = nhc->nhc_dev;
4703 : :
4704 : 0 : params->rt_metric = res.fi->fib_priority;
4705 : :
4706 : : /* xdp and cls_bpf programs are run in RCU-bh so
4707 : : * rcu_read_lock_bh is not needed here
4708 : : */
4709 [ # # ]: 0 : if (likely(nhc->nhc_gw_family != AF_INET6)) {
4710 [ # # ]: 0 : if (nhc->nhc_gw_family)
4711 : 0 : params->ipv4_dst = nhc->nhc_gw.ipv4;
4712 : :
4713 : 0 : neigh = __ipv4_neigh_lookup_noref(dev,
4714 : : (__force u32)params->ipv4_dst);
4715 : : } else {
4716 : 0 : struct in6_addr *dst = (struct in6_addr *)params->ipv6_dst;
4717 : :
4718 : 0 : params->family = AF_INET6;
4719 : 0 : *dst = nhc->nhc_gw.ipv6;
4720 : : neigh = __ipv6_neigh_lookup_noref_stub(dev, dst);
4721 : : }
4722 : :
4723 [ # # ]: 0 : if (!neigh)
4724 : : return BPF_FIB_LKUP_RET_NO_NEIGH;
4725 : :
4726 : 0 : return bpf_fib_set_fwd_params(params, neigh, dev);
4727 : : }
4728 : : #endif
4729 : :
4730 : : #if IS_ENABLED(CONFIG_IPV6)
4731 : 0 : static int bpf_ipv6_fib_lookup(struct net *net, struct bpf_fib_lookup *params,
4732 : : u32 flags, bool check_mtu)
4733 : : {
4734 : 0 : struct in6_addr *src = (struct in6_addr *) params->ipv6_src;
4735 : 0 : struct in6_addr *dst = (struct in6_addr *) params->ipv6_dst;
4736 : 0 : struct fib6_result res = {};
4737 : : struct neighbour *neigh;
4738 : : struct net_device *dev;
4739 : : struct inet6_dev *idev;
4740 : : struct flowi6 fl6;
4741 : : int strict = 0;
4742 : : int oif, err;
4743 : : u32 mtu;
4744 : :
4745 : : /* link local addresses are never forwarded */
4746 [ # # # # ]: 0 : if (rt6_need_strict(dst) || rt6_need_strict(src))
4747 : : return BPF_FIB_LKUP_RET_NOT_FWDED;
4748 : :
4749 : 0 : dev = dev_get_by_index_rcu(net, params->ifindex);
4750 [ # # ]: 0 : if (unlikely(!dev))
4751 : : return -ENODEV;
4752 : :
4753 : : idev = __in6_dev_get_safely(dev);
4754 [ # # # # ]: 0 : if (unlikely(!idev || !idev->cnf.forwarding))
4755 : : return BPF_FIB_LKUP_RET_FWD_DISABLED;
4756 : :
4757 [ # # ]: 0 : if (flags & BPF_FIB_LOOKUP_OUTPUT) {
4758 : 0 : fl6.flowi6_iif = 1;
4759 : 0 : oif = fl6.flowi6_oif = params->ifindex;
4760 : : } else {
4761 : 0 : oif = fl6.flowi6_iif = params->ifindex;
4762 : 0 : fl6.flowi6_oif = 0;
4763 : : strict = RT6_LOOKUP_F_HAS_SADDR;
4764 : : }
4765 : 0 : fl6.flowlabel = params->flowinfo;
4766 : 0 : fl6.flowi6_scope = 0;
4767 : 0 : fl6.flowi6_flags = 0;
4768 : 0 : fl6.mp_hash = 0;
4769 : :
4770 : 0 : fl6.flowi6_proto = params->l4_protocol;
4771 : 0 : fl6.daddr = *dst;
4772 : 0 : fl6.saddr = *src;
4773 : 0 : fl6.fl6_sport = params->sport;
4774 : 0 : fl6.fl6_dport = params->dport;
4775 : :
4776 [ # # ]: 0 : if (flags & BPF_FIB_LOOKUP_DIRECT) {
4777 [ # # ]: 0 : u32 tbid = l3mdev_fib_table_rcu(dev) ? : RT_TABLE_MAIN;
4778 : : struct fib6_table *tb;
4779 : :
4780 : 0 : tb = ipv6_stub->fib6_get_table(net, tbid);
4781 [ # # ]: 0 : if (unlikely(!tb))
4782 : : return BPF_FIB_LKUP_RET_NOT_FWDED;
4783 : :
4784 : 0 : err = ipv6_stub->fib6_table_lookup(net, tb, oif, &fl6, &res,
4785 : : strict);
4786 : : } else {
4787 : 0 : fl6.flowi6_mark = 0;
4788 : 0 : fl6.flowi6_secid = 0;
4789 : 0 : fl6.flowi6_tun_key.tun_id = 0;
4790 : 0 : fl6.flowi6_uid = sock_net_uid(net, NULL);
4791 : :
4792 : 0 : err = ipv6_stub->fib6_lookup(net, oif, &fl6, &res, strict);
4793 : : }
4794 : :
4795 [ # # # # : 0 : if (unlikely(err || IS_ERR_OR_NULL(res.f6i) ||
# # # # ]
4796 : : res.f6i == net->ipv6.fib6_null_entry))
4797 : : return BPF_FIB_LKUP_RET_NOT_FWDED;
4798 : :
4799 [ # # # # : 0 : switch (res.fib6_type) {
# ]
4800 : : /* only unicast is forwarded */
4801 : : case RTN_UNICAST:
4802 : : break;
4803 : : case RTN_BLACKHOLE:
4804 : : return BPF_FIB_LKUP_RET_BLACKHOLE;
4805 : : case RTN_UNREACHABLE:
4806 : 0 : return BPF_FIB_LKUP_RET_UNREACHABLE;
4807 : : case RTN_PROHIBIT:
4808 : 0 : return BPF_FIB_LKUP_RET_PROHIBIT;
4809 : : default:
4810 : 0 : return BPF_FIB_LKUP_RET_NOT_FWDED;
4811 : : }
4812 : :
4813 : 0 : ipv6_stub->fib6_select_path(net, &res, &fl6, fl6.flowi6_oif,
4814 : 0 : fl6.flowi6_oif != 0, NULL, strict);
4815 : :
4816 [ # # ]: 0 : if (check_mtu) {
4817 : 0 : mtu = ipv6_stub->ip6_mtu_from_fib6(&res, dst, src);
4818 [ # # ]: 0 : if (params->tot_len > mtu)
4819 : : return BPF_FIB_LKUP_RET_FRAG_NEEDED;
4820 : : }
4821 : :
4822 [ # # ]: 0 : if (res.nh->fib_nh_lws)
4823 : : return BPF_FIB_LKUP_RET_UNSUPP_LWT;
4824 : :
4825 [ # # ]: 0 : if (res.nh->fib_nh_gw_family)
4826 : 0 : *dst = res.nh->fib_nh_gw6;
4827 : :
4828 : 0 : dev = res.nh->fib_nh_dev;
4829 : 0 : params->rt_metric = res.f6i->fib6_metric;
4830 : :
4831 : : /* xdp and cls_bpf programs are run in RCU-bh so rcu_read_lock_bh is
4832 : : * not needed here.
4833 : : */
4834 : : neigh = __ipv6_neigh_lookup_noref_stub(dev, dst);
4835 [ # # ]: 0 : if (!neigh)
4836 : : return BPF_FIB_LKUP_RET_NO_NEIGH;
4837 : :
4838 : 0 : return bpf_fib_set_fwd_params(params, neigh, dev);
4839 : : }
4840 : : #endif
4841 : :
4842 : 0 : BPF_CALL_4(bpf_xdp_fib_lookup, struct xdp_buff *, ctx,
4843 : : struct bpf_fib_lookup *, params, int, plen, u32, flags)
4844 : : {
4845 [ # # ]: 0 : if (plen < sizeof(*params))
4846 : : return -EINVAL;
4847 : :
4848 [ # # ]: 0 : if (flags & ~(BPF_FIB_LOOKUP_DIRECT | BPF_FIB_LOOKUP_OUTPUT))
4849 : : return -EINVAL;
4850 : :
4851 [ # # # ]: 0 : switch (params->family) {
4852 : : #if IS_ENABLED(CONFIG_INET)
4853 : : case AF_INET:
4854 : 0 : return bpf_ipv4_fib_lookup(dev_net(ctx->rxq->dev), params,
4855 : : flags, true);
4856 : : #endif
4857 : : #if IS_ENABLED(CONFIG_IPV6)
4858 : : case AF_INET6:
4859 : 0 : return bpf_ipv6_fib_lookup(dev_net(ctx->rxq->dev), params,
4860 : : flags, true);
4861 : : #endif
4862 : : }
4863 : : return -EAFNOSUPPORT;
4864 : : }
4865 : :
4866 : : static const struct bpf_func_proto bpf_xdp_fib_lookup_proto = {
4867 : : .func = bpf_xdp_fib_lookup,
4868 : : .gpl_only = true,
4869 : : .ret_type = RET_INTEGER,
4870 : : .arg1_type = ARG_PTR_TO_CTX,
4871 : : .arg2_type = ARG_PTR_TO_MEM,
4872 : : .arg3_type = ARG_CONST_SIZE,
4873 : : .arg4_type = ARG_ANYTHING,
4874 : : };
4875 : :
4876 : 0 : BPF_CALL_4(bpf_skb_fib_lookup, struct sk_buff *, skb,
4877 : : struct bpf_fib_lookup *, params, int, plen, u32, flags)
4878 : : {
4879 : 0 : struct net *net = dev_net(skb->dev);
4880 : : int rc = -EAFNOSUPPORT;
4881 : :
4882 [ # # ]: 0 : if (plen < sizeof(*params))
4883 : : return -EINVAL;
4884 : :
4885 [ # # ]: 0 : if (flags & ~(BPF_FIB_LOOKUP_DIRECT | BPF_FIB_LOOKUP_OUTPUT))
4886 : : return -EINVAL;
4887 : :
4888 [ # # # ]: 0 : switch (params->family) {
4889 : : #if IS_ENABLED(CONFIG_INET)
4890 : : case AF_INET:
4891 : 0 : rc = bpf_ipv4_fib_lookup(net, params, flags, false);
4892 : : break;
4893 : : #endif
4894 : : #if IS_ENABLED(CONFIG_IPV6)
4895 : : case AF_INET6:
4896 : 0 : rc = bpf_ipv6_fib_lookup(net, params, flags, false);
4897 : : break;
4898 : : #endif
4899 : : }
4900 : :
4901 [ # # ]: 0 : if (!rc) {
4902 : : struct net_device *dev;
4903 : :
4904 : 0 : dev = dev_get_by_index_rcu(net, params->ifindex);
4905 [ # # ]: 0 : if (!is_skb_forwardable(dev, skb))
4906 : : rc = BPF_FIB_LKUP_RET_FRAG_NEEDED;
4907 : : }
4908 : :
4909 : 0 : return rc;
4910 : : }
4911 : :
4912 : : static const struct bpf_func_proto bpf_skb_fib_lookup_proto = {
4913 : : .func = bpf_skb_fib_lookup,
4914 : : .gpl_only = true,
4915 : : .ret_type = RET_INTEGER,
4916 : : .arg1_type = ARG_PTR_TO_CTX,
4917 : : .arg2_type = ARG_PTR_TO_MEM,
4918 : : .arg3_type = ARG_CONST_SIZE,
4919 : : .arg4_type = ARG_ANYTHING,
4920 : : };
4921 : :
4922 : : #if IS_ENABLED(CONFIG_IPV6_SEG6_BPF)
4923 : : static int bpf_push_seg6_encap(struct sk_buff *skb, u32 type, void *hdr, u32 len)
4924 : : {
4925 : : int err;
4926 : : struct ipv6_sr_hdr *srh = (struct ipv6_sr_hdr *)hdr;
4927 : :
4928 : : if (!seg6_validate_srh(srh, len))
4929 : : return -EINVAL;
4930 : :
4931 : : switch (type) {
4932 : : case BPF_LWT_ENCAP_SEG6_INLINE:
4933 : : if (skb->protocol != htons(ETH_P_IPV6))
4934 : : return -EBADMSG;
4935 : :
4936 : : err = seg6_do_srh_inline(skb, srh);
4937 : : break;
4938 : : case BPF_LWT_ENCAP_SEG6:
4939 : : skb_reset_inner_headers(skb);
4940 : : skb->encapsulation = 1;
4941 : : err = seg6_do_srh_encap(skb, srh, IPPROTO_IPV6);
4942 : : break;
4943 : : default:
4944 : : return -EINVAL;
4945 : : }
4946 : :
4947 : : bpf_compute_data_pointers(skb);
4948 : : if (err)
4949 : : return err;
4950 : :
4951 : : ipv6_hdr(skb)->payload_len = htons(skb->len - sizeof(struct ipv6hdr));
4952 : : skb_set_transport_header(skb, sizeof(struct ipv6hdr));
4953 : :
4954 : : return seg6_lookup_nexthop(skb, NULL, 0);
4955 : : }
4956 : : #endif /* CONFIG_IPV6_SEG6_BPF */
4957 : :
4958 : : #if IS_ENABLED(CONFIG_LWTUNNEL_BPF)
4959 : : static int bpf_push_ip_encap(struct sk_buff *skb, void *hdr, u32 len,
4960 : : bool ingress)
4961 : : {
4962 : : return bpf_lwt_push_ip_encap(skb, hdr, len, ingress);
4963 : : }
4964 : : #endif
4965 : :
4966 : 0 : BPF_CALL_4(bpf_lwt_in_push_encap, struct sk_buff *, skb, u32, type, void *, hdr,
4967 : : u32, len)
4968 : : {
4969 : : switch (type) {
4970 : : #if IS_ENABLED(CONFIG_IPV6_SEG6_BPF)
4971 : : case BPF_LWT_ENCAP_SEG6:
4972 : : case BPF_LWT_ENCAP_SEG6_INLINE:
4973 : : return bpf_push_seg6_encap(skb, type, hdr, len);
4974 : : #endif
4975 : : #if IS_ENABLED(CONFIG_LWTUNNEL_BPF)
4976 : : case BPF_LWT_ENCAP_IP:
4977 : : return bpf_push_ip_encap(skb, hdr, len, true /* ingress */);
4978 : : #endif
4979 : : default:
4980 : : return -EINVAL;
4981 : : }
4982 : : }
4983 : :
4984 : 0 : BPF_CALL_4(bpf_lwt_xmit_push_encap, struct sk_buff *, skb, u32, type,
4985 : : void *, hdr, u32, len)
4986 : : {
4987 : : switch (type) {
4988 : : #if IS_ENABLED(CONFIG_LWTUNNEL_BPF)
4989 : : case BPF_LWT_ENCAP_IP:
4990 : : return bpf_push_ip_encap(skb, hdr, len, false /* egress */);
4991 : : #endif
4992 : : default:
4993 : : return -EINVAL;
4994 : : }
4995 : : }
4996 : :
4997 : : static const struct bpf_func_proto bpf_lwt_in_push_encap_proto = {
4998 : : .func = bpf_lwt_in_push_encap,
4999 : : .gpl_only = false,
5000 : : .ret_type = RET_INTEGER,
5001 : : .arg1_type = ARG_PTR_TO_CTX,
5002 : : .arg2_type = ARG_ANYTHING,
5003 : : .arg3_type = ARG_PTR_TO_MEM,
5004 : : .arg4_type = ARG_CONST_SIZE
5005 : : };
5006 : :
5007 : : static const struct bpf_func_proto bpf_lwt_xmit_push_encap_proto = {
5008 : : .func = bpf_lwt_xmit_push_encap,
5009 : : .gpl_only = false,
5010 : : .ret_type = RET_INTEGER,
5011 : : .arg1_type = ARG_PTR_TO_CTX,
5012 : : .arg2_type = ARG_ANYTHING,
5013 : : .arg3_type = ARG_PTR_TO_MEM,
5014 : : .arg4_type = ARG_CONST_SIZE
5015 : : };
5016 : :
5017 : : #if IS_ENABLED(CONFIG_IPV6_SEG6_BPF)
5018 : : BPF_CALL_4(bpf_lwt_seg6_store_bytes, struct sk_buff *, skb, u32, offset,
5019 : : const void *, from, u32, len)
5020 : : {
5021 : : struct seg6_bpf_srh_state *srh_state =
5022 : : this_cpu_ptr(&seg6_bpf_srh_states);
5023 : : struct ipv6_sr_hdr *srh = srh_state->srh;
5024 : : void *srh_tlvs, *srh_end, *ptr;
5025 : : int srhoff = 0;
5026 : :
5027 : : if (srh == NULL)
5028 : : return -EINVAL;
5029 : :
5030 : : srh_tlvs = (void *)((char *)srh + ((srh->first_segment + 1) << 4));
5031 : : srh_end = (void *)((char *)srh + sizeof(*srh) + srh_state->hdrlen);
5032 : :
5033 : : ptr = skb->data + offset;
5034 : : if (ptr >= srh_tlvs && ptr + len <= srh_end)
5035 : : srh_state->valid = false;
5036 : : else if (ptr < (void *)&srh->flags ||
5037 : : ptr + len > (void *)&srh->segments)
5038 : : return -EFAULT;
5039 : :
5040 : : if (unlikely(bpf_try_make_writable(skb, offset + len)))
5041 : : return -EFAULT;
5042 : : if (ipv6_find_hdr(skb, &srhoff, IPPROTO_ROUTING, NULL, NULL) < 0)
5043 : : return -EINVAL;
5044 : : srh_state->srh = (struct ipv6_sr_hdr *)(skb->data + srhoff);
5045 : :
5046 : : memcpy(skb->data + offset, from, len);
5047 : : return 0;
5048 : : }
5049 : :
5050 : : static const struct bpf_func_proto bpf_lwt_seg6_store_bytes_proto = {
5051 : : .func = bpf_lwt_seg6_store_bytes,
5052 : : .gpl_only = false,
5053 : : .ret_type = RET_INTEGER,
5054 : : .arg1_type = ARG_PTR_TO_CTX,
5055 : : .arg2_type = ARG_ANYTHING,
5056 : : .arg3_type = ARG_PTR_TO_MEM,
5057 : : .arg4_type = ARG_CONST_SIZE
5058 : : };
5059 : :
5060 : : static void bpf_update_srh_state(struct sk_buff *skb)
5061 : : {
5062 : : struct seg6_bpf_srh_state *srh_state =
5063 : : this_cpu_ptr(&seg6_bpf_srh_states);
5064 : : int srhoff = 0;
5065 : :
5066 : : if (ipv6_find_hdr(skb, &srhoff, IPPROTO_ROUTING, NULL, NULL) < 0) {
5067 : : srh_state->srh = NULL;
5068 : : } else {
5069 : : srh_state->srh = (struct ipv6_sr_hdr *)(skb->data + srhoff);
5070 : : srh_state->hdrlen = srh_state->srh->hdrlen << 3;
5071 : : srh_state->valid = true;
5072 : : }
5073 : : }
5074 : :
5075 : : BPF_CALL_4(bpf_lwt_seg6_action, struct sk_buff *, skb,
5076 : : u32, action, void *, param, u32, param_len)
5077 : : {
5078 : : struct seg6_bpf_srh_state *srh_state =
5079 : : this_cpu_ptr(&seg6_bpf_srh_states);
5080 : : int hdroff = 0;
5081 : : int err;
5082 : :
5083 : : switch (action) {
5084 : : case SEG6_LOCAL_ACTION_END_X:
5085 : : if (!seg6_bpf_has_valid_srh(skb))
5086 : : return -EBADMSG;
5087 : : if (param_len != sizeof(struct in6_addr))
5088 : : return -EINVAL;
5089 : : return seg6_lookup_nexthop(skb, (struct in6_addr *)param, 0);
5090 : : case SEG6_LOCAL_ACTION_END_T:
5091 : : if (!seg6_bpf_has_valid_srh(skb))
5092 : : return -EBADMSG;
5093 : : if (param_len != sizeof(int))
5094 : : return -EINVAL;
5095 : : return seg6_lookup_nexthop(skb, NULL, *(int *)param);
5096 : : case SEG6_LOCAL_ACTION_END_DT6:
5097 : : if (!seg6_bpf_has_valid_srh(skb))
5098 : : return -EBADMSG;
5099 : : if (param_len != sizeof(int))
5100 : : return -EINVAL;
5101 : :
5102 : : if (ipv6_find_hdr(skb, &hdroff, IPPROTO_IPV6, NULL, NULL) < 0)
5103 : : return -EBADMSG;
5104 : : if (!pskb_pull(skb, hdroff))
5105 : : return -EBADMSG;
5106 : :
5107 : : skb_postpull_rcsum(skb, skb_network_header(skb), hdroff);
5108 : : skb_reset_network_header(skb);
5109 : : skb_reset_transport_header(skb);
5110 : : skb->encapsulation = 0;
5111 : :
5112 : : bpf_compute_data_pointers(skb);
5113 : : bpf_update_srh_state(skb);
5114 : : return seg6_lookup_nexthop(skb, NULL, *(int *)param);
5115 : : case SEG6_LOCAL_ACTION_END_B6:
5116 : : if (srh_state->srh && !seg6_bpf_has_valid_srh(skb))
5117 : : return -EBADMSG;
5118 : : err = bpf_push_seg6_encap(skb, BPF_LWT_ENCAP_SEG6_INLINE,
5119 : : param, param_len);
5120 : : if (!err)
5121 : : bpf_update_srh_state(skb);
5122 : :
5123 : : return err;
5124 : : case SEG6_LOCAL_ACTION_END_B6_ENCAP:
5125 : : if (srh_state->srh && !seg6_bpf_has_valid_srh(skb))
5126 : : return -EBADMSG;
5127 : : err = bpf_push_seg6_encap(skb, BPF_LWT_ENCAP_SEG6,
5128 : : param, param_len);
5129 : : if (!err)
5130 : : bpf_update_srh_state(skb);
5131 : :
5132 : : return err;
5133 : : default:
5134 : : return -EINVAL;
5135 : : }
5136 : : }
5137 : :
5138 : : static const struct bpf_func_proto bpf_lwt_seg6_action_proto = {
5139 : : .func = bpf_lwt_seg6_action,
5140 : : .gpl_only = false,
5141 : : .ret_type = RET_INTEGER,
5142 : : .arg1_type = ARG_PTR_TO_CTX,
5143 : : .arg2_type = ARG_ANYTHING,
5144 : : .arg3_type = ARG_PTR_TO_MEM,
5145 : : .arg4_type = ARG_CONST_SIZE
5146 : : };
5147 : :
5148 : : BPF_CALL_3(bpf_lwt_seg6_adjust_srh, struct sk_buff *, skb, u32, offset,
5149 : : s32, len)
5150 : : {
5151 : : struct seg6_bpf_srh_state *srh_state =
5152 : : this_cpu_ptr(&seg6_bpf_srh_states);
5153 : : struct ipv6_sr_hdr *srh = srh_state->srh;
5154 : : void *srh_end, *srh_tlvs, *ptr;
5155 : : struct ipv6hdr *hdr;
5156 : : int srhoff = 0;
5157 : : int ret;
5158 : :
5159 : : if (unlikely(srh == NULL))
5160 : : return -EINVAL;
5161 : :
5162 : : srh_tlvs = (void *)((unsigned char *)srh + sizeof(*srh) +
5163 : : ((srh->first_segment + 1) << 4));
5164 : : srh_end = (void *)((unsigned char *)srh + sizeof(*srh) +
5165 : : srh_state->hdrlen);
5166 : : ptr = skb->data + offset;
5167 : :
5168 : : if (unlikely(ptr < srh_tlvs || ptr > srh_end))
5169 : : return -EFAULT;
5170 : : if (unlikely(len < 0 && (void *)((char *)ptr - len) > srh_end))
5171 : : return -EFAULT;
5172 : :
5173 : : if (len > 0) {
5174 : : ret = skb_cow_head(skb, len);
5175 : : if (unlikely(ret < 0))
5176 : : return ret;
5177 : :
5178 : : ret = bpf_skb_net_hdr_push(skb, offset, len);
5179 : : } else {
5180 : : ret = bpf_skb_net_hdr_pop(skb, offset, -1 * len);
5181 : : }
5182 : :
5183 : : bpf_compute_data_pointers(skb);
5184 : : if (unlikely(ret < 0))
5185 : : return ret;
5186 : :
5187 : : hdr = (struct ipv6hdr *)skb->data;
5188 : : hdr->payload_len = htons(skb->len - sizeof(struct ipv6hdr));
5189 : :
5190 : : if (ipv6_find_hdr(skb, &srhoff, IPPROTO_ROUTING, NULL, NULL) < 0)
5191 : : return -EINVAL;
5192 : : srh_state->srh = (struct ipv6_sr_hdr *)(skb->data + srhoff);
5193 : : srh_state->hdrlen += len;
5194 : : srh_state->valid = false;
5195 : : return 0;
5196 : : }
5197 : :
5198 : : static const struct bpf_func_proto bpf_lwt_seg6_adjust_srh_proto = {
5199 : : .func = bpf_lwt_seg6_adjust_srh,
5200 : : .gpl_only = false,
5201 : : .ret_type = RET_INTEGER,
5202 : : .arg1_type = ARG_PTR_TO_CTX,
5203 : : .arg2_type = ARG_ANYTHING,
5204 : : .arg3_type = ARG_ANYTHING,
5205 : : };
5206 : : #endif /* CONFIG_IPV6_SEG6_BPF */
5207 : :
5208 : : #ifdef CONFIG_INET
5209 : 0 : static struct sock *sk_lookup(struct net *net, struct bpf_sock_tuple *tuple,
5210 : : int dif, int sdif, u8 family, u8 proto)
5211 : : {
5212 : 0 : bool refcounted = false;
5213 : : struct sock *sk = NULL;
5214 : :
5215 [ # # ]: 0 : if (family == AF_INET) {
5216 : 0 : __be32 src4 = tuple->ipv4.saddr;
5217 : 0 : __be32 dst4 = tuple->ipv4.daddr;
5218 : :
5219 [ # # ]: 0 : if (proto == IPPROTO_TCP)
5220 : 0 : sk = __inet_lookup(net, &tcp_hashinfo, NULL, 0,
5221 : : src4, tuple->ipv4.sport,
5222 : : dst4, tuple->ipv4.dport,
5223 : : dif, sdif, &refcounted);
5224 : : else
5225 : 0 : sk = __udp4_lib_lookup(net, src4, tuple->ipv4.sport,
5226 : : dst4, tuple->ipv4.dport,
5227 : : dif, sdif, &udp_table, NULL);
5228 : : #if IS_ENABLED(CONFIG_IPV6)
5229 : : } else {
5230 : 0 : struct in6_addr *src6 = (struct in6_addr *)&tuple->ipv6.saddr;
5231 : 0 : struct in6_addr *dst6 = (struct in6_addr *)&tuple->ipv6.daddr;
5232 : :
5233 [ # # ]: 0 : if (proto == IPPROTO_TCP)
5234 : 0 : sk = __inet6_lookup(net, &tcp_hashinfo, NULL, 0,
5235 : : src6, tuple->ipv6.sport,
5236 : : dst6, ntohs(tuple->ipv6.dport),
5237 : : dif, sdif, &refcounted);
5238 [ # # ]: 0 : else if (likely(ipv6_bpf_stub))
5239 : 0 : sk = ipv6_bpf_stub->udp6_lib_lookup(net,
5240 : : src6, tuple->ipv6.sport,
5241 : : dst6, tuple->ipv6.dport,
5242 : : dif, sdif,
5243 : : &udp_table, NULL);
5244 : : #endif
5245 : : }
5246 : :
5247 [ # # # # : 0 : if (unlikely(sk && !refcounted && !sock_flag(sk, SOCK_RCU_FREE))) {
# # # # ]
5248 [ # # ]: 0 : WARN_ONCE(1, "Found non-RCU, unreferenced socket!");
5249 : : sk = NULL;
5250 : : }
5251 : 0 : return sk;
5252 : : }
5253 : :
5254 : : /* bpf_skc_lookup performs the core lookup for different types of sockets,
5255 : : * taking a reference on the socket if it doesn't have the flag SOCK_RCU_FREE.
5256 : : * Returns the socket as an 'unsigned long' to simplify the casting in the
5257 : : * callers to satisfy BPF_CALL declarations.
5258 : : */
5259 : : static struct sock *
5260 : 0 : __bpf_skc_lookup(struct sk_buff *skb, struct bpf_sock_tuple *tuple, u32 len,
5261 : : struct net *caller_net, u32 ifindex, u8 proto, u64 netns_id,
5262 : : u64 flags)
5263 : : {
5264 : : struct sock *sk = NULL;
5265 : : u8 family = AF_UNSPEC;
5266 : : struct net *net;
5267 : : int sdif;
5268 : :
5269 [ # # ]: 0 : if (len == sizeof(tuple->ipv4))
5270 : : family = AF_INET;
5271 [ # # ]: 0 : else if (len == sizeof(tuple->ipv6))
5272 : : family = AF_INET6;
5273 : : else
5274 : : return NULL;
5275 : :
5276 [ # # # # : 0 : if (unlikely(family == AF_UNSPEC || flags ||
# # # # ]
5277 : : !((s32)netns_id < 0 || netns_id <= S32_MAX)))
5278 : : goto out;
5279 : :
5280 [ # # ]: 0 : if (family == AF_INET)
5281 : : sdif = inet_sdif(skb);
5282 : : else
5283 : : sdif = inet6_sdif(skb);
5284 : :
5285 [ # # ]: 0 : if ((s32)netns_id < 0) {
5286 : : net = caller_net;
5287 : 0 : sk = sk_lookup(net, tuple, ifindex, sdif, family, proto);
5288 : : } else {
5289 : 0 : net = get_net_ns_by_id(caller_net, netns_id);
5290 [ # # ]: 0 : if (unlikely(!net))
5291 : : goto out;
5292 : 0 : sk = sk_lookup(net, tuple, ifindex, sdif, family, proto);
5293 : 0 : put_net(net);
5294 : : }
5295 : :
5296 : : out:
5297 : 0 : return sk;
5298 : : }
5299 : :
5300 : : static struct sock *
5301 : 0 : __bpf_sk_lookup(struct sk_buff *skb, struct bpf_sock_tuple *tuple, u32 len,
5302 : : struct net *caller_net, u32 ifindex, u8 proto, u64 netns_id,
5303 : : u64 flags)
5304 : : {
5305 : 0 : struct sock *sk = __bpf_skc_lookup(skb, tuple, len, caller_net,
5306 : : ifindex, proto, netns_id, flags);
5307 : :
5308 [ # # ]: 0 : if (sk) {
5309 : : sk = sk_to_full_sk(sk);
5310 [ # # ]: 0 : if (!sk_fullsock(sk)) {
5311 : 0 : sock_gen_put(sk);
5312 : 0 : return NULL;
5313 : : }
5314 : : }
5315 : :
5316 : 0 : return sk;
5317 : : }
5318 : :
5319 : : static struct sock *
5320 : 0 : bpf_skc_lookup(struct sk_buff *skb, struct bpf_sock_tuple *tuple, u32 len,
5321 : : u8 proto, u64 netns_id, u64 flags)
5322 : : {
5323 : : struct net *caller_net;
5324 : : int ifindex;
5325 : :
5326 [ # # ]: 0 : if (skb->dev) {
5327 : : caller_net = dev_net(skb->dev);
5328 : 0 : ifindex = skb->dev->ifindex;
5329 : : } else {
5330 : 0 : caller_net = sock_net(skb->sk);
5331 : : ifindex = 0;
5332 : : }
5333 : :
5334 : 0 : return __bpf_skc_lookup(skb, tuple, len, caller_net, ifindex, proto,
5335 : : netns_id, flags);
5336 : : }
5337 : :
5338 : : static struct sock *
5339 : 0 : bpf_sk_lookup(struct sk_buff *skb, struct bpf_sock_tuple *tuple, u32 len,
5340 : : u8 proto, u64 netns_id, u64 flags)
5341 : : {
5342 : 0 : struct sock *sk = bpf_skc_lookup(skb, tuple, len, proto, netns_id,
5343 : : flags);
5344 : :
5345 [ # # ]: 0 : if (sk) {
5346 : : sk = sk_to_full_sk(sk);
5347 [ # # ]: 0 : if (!sk_fullsock(sk)) {
5348 : 0 : sock_gen_put(sk);
5349 : 0 : return NULL;
5350 : : }
5351 : : }
5352 : :
5353 : 0 : return sk;
5354 : : }
5355 : :
5356 : 0 : BPF_CALL_5(bpf_skc_lookup_tcp, struct sk_buff *, skb,
5357 : : struct bpf_sock_tuple *, tuple, u32, len, u64, netns_id, u64, flags)
5358 : : {
5359 : 0 : return (unsigned long)bpf_skc_lookup(skb, tuple, len, IPPROTO_TCP,
5360 : : netns_id, flags);
5361 : : }
5362 : :
5363 : : static const struct bpf_func_proto bpf_skc_lookup_tcp_proto = {
5364 : : .func = bpf_skc_lookup_tcp,
5365 : : .gpl_only = false,
5366 : : .pkt_access = true,
5367 : : .ret_type = RET_PTR_TO_SOCK_COMMON_OR_NULL,
5368 : : .arg1_type = ARG_PTR_TO_CTX,
5369 : : .arg2_type = ARG_PTR_TO_MEM,
5370 : : .arg3_type = ARG_CONST_SIZE,
5371 : : .arg4_type = ARG_ANYTHING,
5372 : : .arg5_type = ARG_ANYTHING,
5373 : : };
5374 : :
5375 : 0 : BPF_CALL_5(bpf_sk_lookup_tcp, struct sk_buff *, skb,
5376 : : struct bpf_sock_tuple *, tuple, u32, len, u64, netns_id, u64, flags)
5377 : : {
5378 : 0 : return (unsigned long)bpf_sk_lookup(skb, tuple, len, IPPROTO_TCP,
5379 : : netns_id, flags);
5380 : : }
5381 : :
5382 : : static const struct bpf_func_proto bpf_sk_lookup_tcp_proto = {
5383 : : .func = bpf_sk_lookup_tcp,
5384 : : .gpl_only = false,
5385 : : .pkt_access = true,
5386 : : .ret_type = RET_PTR_TO_SOCKET_OR_NULL,
5387 : : .arg1_type = ARG_PTR_TO_CTX,
5388 : : .arg2_type = ARG_PTR_TO_MEM,
5389 : : .arg3_type = ARG_CONST_SIZE,
5390 : : .arg4_type = ARG_ANYTHING,
5391 : : .arg5_type = ARG_ANYTHING,
5392 : : };
5393 : :
5394 : 0 : BPF_CALL_5(bpf_sk_lookup_udp, struct sk_buff *, skb,
5395 : : struct bpf_sock_tuple *, tuple, u32, len, u64, netns_id, u64, flags)
5396 : : {
5397 : 0 : return (unsigned long)bpf_sk_lookup(skb, tuple, len, IPPROTO_UDP,
5398 : : netns_id, flags);
5399 : : }
5400 : :
5401 : : static const struct bpf_func_proto bpf_sk_lookup_udp_proto = {
5402 : : .func = bpf_sk_lookup_udp,
5403 : : .gpl_only = false,
5404 : : .pkt_access = true,
5405 : : .ret_type = RET_PTR_TO_SOCKET_OR_NULL,
5406 : : .arg1_type = ARG_PTR_TO_CTX,
5407 : : .arg2_type = ARG_PTR_TO_MEM,
5408 : : .arg3_type = ARG_CONST_SIZE,
5409 : : .arg4_type = ARG_ANYTHING,
5410 : : .arg5_type = ARG_ANYTHING,
5411 : : };
5412 : :
5413 : 0 : BPF_CALL_1(bpf_sk_release, struct sock *, sk)
5414 : : {
5415 : : /* Only full sockets have sk->sk_flags. */
5416 [ # # # # ]: 0 : if (!sk_fullsock(sk) || !sock_flag(sk, SOCK_RCU_FREE))
5417 : 0 : sock_gen_put(sk);
5418 : : return 0;
5419 : : }
5420 : :
5421 : : static const struct bpf_func_proto bpf_sk_release_proto = {
5422 : : .func = bpf_sk_release,
5423 : : .gpl_only = false,
5424 : : .ret_type = RET_INTEGER,
5425 : : .arg1_type = ARG_PTR_TO_SOCK_COMMON,
5426 : : };
5427 : :
5428 : 0 : BPF_CALL_5(bpf_xdp_sk_lookup_udp, struct xdp_buff *, ctx,
5429 : : struct bpf_sock_tuple *, tuple, u32, len, u32, netns_id, u64, flags)
5430 : : {
5431 : 0 : struct net *caller_net = dev_net(ctx->rxq->dev);
5432 : 0 : int ifindex = ctx->rxq->dev->ifindex;
5433 : :
5434 : 0 : return (unsigned long)__bpf_sk_lookup(NULL, tuple, len, caller_net,
5435 : : ifindex, IPPROTO_UDP, netns_id,
5436 : : flags);
5437 : : }
5438 : :
5439 : : static const struct bpf_func_proto bpf_xdp_sk_lookup_udp_proto = {
5440 : : .func = bpf_xdp_sk_lookup_udp,
5441 : : .gpl_only = false,
5442 : : .pkt_access = true,
5443 : : .ret_type = RET_PTR_TO_SOCKET_OR_NULL,
5444 : : .arg1_type = ARG_PTR_TO_CTX,
5445 : : .arg2_type = ARG_PTR_TO_MEM,
5446 : : .arg3_type = ARG_CONST_SIZE,
5447 : : .arg4_type = ARG_ANYTHING,
5448 : : .arg5_type = ARG_ANYTHING,
5449 : : };
5450 : :
5451 : 0 : BPF_CALL_5(bpf_xdp_skc_lookup_tcp, struct xdp_buff *, ctx,
5452 : : struct bpf_sock_tuple *, tuple, u32, len, u32, netns_id, u64, flags)
5453 : : {
5454 : 0 : struct net *caller_net = dev_net(ctx->rxq->dev);
5455 : 0 : int ifindex = ctx->rxq->dev->ifindex;
5456 : :
5457 : 0 : return (unsigned long)__bpf_skc_lookup(NULL, tuple, len, caller_net,
5458 : : ifindex, IPPROTO_TCP, netns_id,
5459 : : flags);
5460 : : }
5461 : :
5462 : : static const struct bpf_func_proto bpf_xdp_skc_lookup_tcp_proto = {
5463 : : .func = bpf_xdp_skc_lookup_tcp,
5464 : : .gpl_only = false,
5465 : : .pkt_access = true,
5466 : : .ret_type = RET_PTR_TO_SOCK_COMMON_OR_NULL,
5467 : : .arg1_type = ARG_PTR_TO_CTX,
5468 : : .arg2_type = ARG_PTR_TO_MEM,
5469 : : .arg3_type = ARG_CONST_SIZE,
5470 : : .arg4_type = ARG_ANYTHING,
5471 : : .arg5_type = ARG_ANYTHING,
5472 : : };
5473 : :
5474 : 0 : BPF_CALL_5(bpf_xdp_sk_lookup_tcp, struct xdp_buff *, ctx,
5475 : : struct bpf_sock_tuple *, tuple, u32, len, u32, netns_id, u64, flags)
5476 : : {
5477 : 0 : struct net *caller_net = dev_net(ctx->rxq->dev);
5478 : 0 : int ifindex = ctx->rxq->dev->ifindex;
5479 : :
5480 : 0 : return (unsigned long)__bpf_sk_lookup(NULL, tuple, len, caller_net,
5481 : : ifindex, IPPROTO_TCP, netns_id,
5482 : : flags);
5483 : : }
5484 : :
5485 : : static const struct bpf_func_proto bpf_xdp_sk_lookup_tcp_proto = {
5486 : : .func = bpf_xdp_sk_lookup_tcp,
5487 : : .gpl_only = false,
5488 : : .pkt_access = true,
5489 : : .ret_type = RET_PTR_TO_SOCKET_OR_NULL,
5490 : : .arg1_type = ARG_PTR_TO_CTX,
5491 : : .arg2_type = ARG_PTR_TO_MEM,
5492 : : .arg3_type = ARG_CONST_SIZE,
5493 : : .arg4_type = ARG_ANYTHING,
5494 : : .arg5_type = ARG_ANYTHING,
5495 : : };
5496 : :
5497 : 0 : BPF_CALL_5(bpf_sock_addr_skc_lookup_tcp, struct bpf_sock_addr_kern *, ctx,
5498 : : struct bpf_sock_tuple *, tuple, u32, len, u64, netns_id, u64, flags)
5499 : : {
5500 : 0 : return (unsigned long)__bpf_skc_lookup(NULL, tuple, len,
5501 : 0 : sock_net(ctx->sk), 0,
5502 : : IPPROTO_TCP, netns_id, flags);
5503 : : }
5504 : :
5505 : : static const struct bpf_func_proto bpf_sock_addr_skc_lookup_tcp_proto = {
5506 : : .func = bpf_sock_addr_skc_lookup_tcp,
5507 : : .gpl_only = false,
5508 : : .ret_type = RET_PTR_TO_SOCK_COMMON_OR_NULL,
5509 : : .arg1_type = ARG_PTR_TO_CTX,
5510 : : .arg2_type = ARG_PTR_TO_MEM,
5511 : : .arg3_type = ARG_CONST_SIZE,
5512 : : .arg4_type = ARG_ANYTHING,
5513 : : .arg5_type = ARG_ANYTHING,
5514 : : };
5515 : :
5516 : 0 : BPF_CALL_5(bpf_sock_addr_sk_lookup_tcp, struct bpf_sock_addr_kern *, ctx,
5517 : : struct bpf_sock_tuple *, tuple, u32, len, u64, netns_id, u64, flags)
5518 : : {
5519 : 0 : return (unsigned long)__bpf_sk_lookup(NULL, tuple, len,
5520 : 0 : sock_net(ctx->sk), 0, IPPROTO_TCP,
5521 : : netns_id, flags);
5522 : : }
5523 : :
5524 : : static const struct bpf_func_proto bpf_sock_addr_sk_lookup_tcp_proto = {
5525 : : .func = bpf_sock_addr_sk_lookup_tcp,
5526 : : .gpl_only = false,
5527 : : .ret_type = RET_PTR_TO_SOCKET_OR_NULL,
5528 : : .arg1_type = ARG_PTR_TO_CTX,
5529 : : .arg2_type = ARG_PTR_TO_MEM,
5530 : : .arg3_type = ARG_CONST_SIZE,
5531 : : .arg4_type = ARG_ANYTHING,
5532 : : .arg5_type = ARG_ANYTHING,
5533 : : };
5534 : :
5535 : 0 : BPF_CALL_5(bpf_sock_addr_sk_lookup_udp, struct bpf_sock_addr_kern *, ctx,
5536 : : struct bpf_sock_tuple *, tuple, u32, len, u64, netns_id, u64, flags)
5537 : : {
5538 : 0 : return (unsigned long)__bpf_sk_lookup(NULL, tuple, len,
5539 : 0 : sock_net(ctx->sk), 0, IPPROTO_UDP,
5540 : : netns_id, flags);
5541 : : }
5542 : :
5543 : : static const struct bpf_func_proto bpf_sock_addr_sk_lookup_udp_proto = {
5544 : : .func = bpf_sock_addr_sk_lookup_udp,
5545 : : .gpl_only = false,
5546 : : .ret_type = RET_PTR_TO_SOCKET_OR_NULL,
5547 : : .arg1_type = ARG_PTR_TO_CTX,
5548 : : .arg2_type = ARG_PTR_TO_MEM,
5549 : : .arg3_type = ARG_CONST_SIZE,
5550 : : .arg4_type = ARG_ANYTHING,
5551 : : .arg5_type = ARG_ANYTHING,
5552 : : };
5553 : :
5554 : 0 : bool bpf_tcp_sock_is_valid_access(int off, int size, enum bpf_access_type type,
5555 : : struct bpf_insn_access_aux *info)
5556 : : {
5557 [ # # ]: 0 : if (off < 0 || off >= offsetofend(struct bpf_tcp_sock,
5558 : : icsk_retransmits))
5559 : : return false;
5560 : :
5561 [ # # ]: 0 : if (off % size != 0)
5562 : : return false;
5563 : :
5564 [ # # ]: 0 : switch (off) {
5565 : : case offsetof(struct bpf_tcp_sock, bytes_received):
5566 : : case offsetof(struct bpf_tcp_sock, bytes_acked):
5567 : 0 : return size == sizeof(__u64);
5568 : : default:
5569 : 0 : return size == sizeof(__u32);
5570 : : }
5571 : : }
5572 : :
5573 : 0 : u32 bpf_tcp_sock_convert_ctx_access(enum bpf_access_type type,
5574 : : const struct bpf_insn *si,
5575 : : struct bpf_insn *insn_buf,
5576 : : struct bpf_prog *prog, u32 *target_size)
5577 : : {
5578 : : struct bpf_insn *insn = insn_buf;
5579 : :
5580 : : #define BPF_TCP_SOCK_GET_COMMON(FIELD) \
5581 : : do { \
5582 : : BUILD_BUG_ON(FIELD_SIZEOF(struct tcp_sock, FIELD) > \
5583 : : FIELD_SIZEOF(struct bpf_tcp_sock, FIELD)); \
5584 : : *insn++ = BPF_LDX_MEM(BPF_FIELD_SIZEOF(struct tcp_sock, FIELD),\
5585 : : si->dst_reg, si->src_reg, \
5586 : : offsetof(struct tcp_sock, FIELD)); \
5587 : : } while (0)
5588 : :
5589 : : #define BPF_INET_SOCK_GET_COMMON(FIELD) \
5590 : : do { \
5591 : : BUILD_BUG_ON(FIELD_SIZEOF(struct inet_connection_sock, \
5592 : : FIELD) > \
5593 : : FIELD_SIZEOF(struct bpf_tcp_sock, FIELD)); \
5594 : : *insn++ = BPF_LDX_MEM(BPF_FIELD_SIZEOF( \
5595 : : struct inet_connection_sock, \
5596 : : FIELD), \
5597 : : si->dst_reg, si->src_reg, \
5598 : : offsetof( \
5599 : : struct inet_connection_sock, \
5600 : : FIELD)); \
5601 : : } while (0)
5602 : :
5603 : : if (insn > insn_buf)
5604 : : return insn - insn_buf;
5605 : :
5606 [ # # # # : 0 : switch (si->off) {
# # # # #
# # # # #
# # # # #
# # # # #
# # # ]
5607 : : case offsetof(struct bpf_tcp_sock, rtt_min):
5608 : : BUILD_BUG_ON(FIELD_SIZEOF(struct tcp_sock, rtt_min) !=
5609 : : sizeof(struct minmax));
5610 : : BUILD_BUG_ON(sizeof(struct minmax) <
5611 : : sizeof(struct minmax_sample));
5612 : :
5613 : 0 : *insn++ = BPF_LDX_MEM(BPF_W, si->dst_reg, si->src_reg,
5614 : : offsetof(struct tcp_sock, rtt_min) +
5615 : : offsetof(struct minmax_sample, v));
5616 : 0 : break;
5617 : : case offsetof(struct bpf_tcp_sock, snd_cwnd):
5618 : 0 : BPF_TCP_SOCK_GET_COMMON(snd_cwnd);
5619 : 0 : break;
5620 : : case offsetof(struct bpf_tcp_sock, srtt_us):
5621 : 0 : BPF_TCP_SOCK_GET_COMMON(srtt_us);
5622 : 0 : break;
5623 : : case offsetof(struct bpf_tcp_sock, snd_ssthresh):
5624 : 0 : BPF_TCP_SOCK_GET_COMMON(snd_ssthresh);
5625 : 0 : break;
5626 : : case offsetof(struct bpf_tcp_sock, rcv_nxt):
5627 : 0 : BPF_TCP_SOCK_GET_COMMON(rcv_nxt);
5628 : 0 : break;
5629 : : case offsetof(struct bpf_tcp_sock, snd_nxt):
5630 : 0 : BPF_TCP_SOCK_GET_COMMON(snd_nxt);
5631 : 0 : break;
5632 : : case offsetof(struct bpf_tcp_sock, snd_una):
5633 : 0 : BPF_TCP_SOCK_GET_COMMON(snd_una);
5634 : 0 : break;
5635 : : case offsetof(struct bpf_tcp_sock, mss_cache):
5636 : 0 : BPF_TCP_SOCK_GET_COMMON(mss_cache);
5637 : 0 : break;
5638 : : case offsetof(struct bpf_tcp_sock, ecn_flags):
5639 : 0 : BPF_TCP_SOCK_GET_COMMON(ecn_flags);
5640 : 0 : break;
5641 : : case offsetof(struct bpf_tcp_sock, rate_delivered):
5642 : 0 : BPF_TCP_SOCK_GET_COMMON(rate_delivered);
5643 : 0 : break;
5644 : : case offsetof(struct bpf_tcp_sock, rate_interval_us):
5645 : 0 : BPF_TCP_SOCK_GET_COMMON(rate_interval_us);
5646 : 0 : break;
5647 : : case offsetof(struct bpf_tcp_sock, packets_out):
5648 : 0 : BPF_TCP_SOCK_GET_COMMON(packets_out);
5649 : 0 : break;
5650 : : case offsetof(struct bpf_tcp_sock, retrans_out):
5651 : 0 : BPF_TCP_SOCK_GET_COMMON(retrans_out);
5652 : 0 : break;
5653 : : case offsetof(struct bpf_tcp_sock, total_retrans):
5654 : 0 : BPF_TCP_SOCK_GET_COMMON(total_retrans);
5655 : 0 : break;
5656 : : case offsetof(struct bpf_tcp_sock, segs_in):
5657 : 0 : BPF_TCP_SOCK_GET_COMMON(segs_in);
5658 : 0 : break;
5659 : : case offsetof(struct bpf_tcp_sock, data_segs_in):
5660 : 0 : BPF_TCP_SOCK_GET_COMMON(data_segs_in);
5661 : 0 : break;
5662 : : case offsetof(struct bpf_tcp_sock, segs_out):
5663 : 0 : BPF_TCP_SOCK_GET_COMMON(segs_out);
5664 : 0 : break;
5665 : : case offsetof(struct bpf_tcp_sock, data_segs_out):
5666 : 0 : BPF_TCP_SOCK_GET_COMMON(data_segs_out);
5667 : 0 : break;
5668 : : case offsetof(struct bpf_tcp_sock, lost_out):
5669 : 0 : BPF_TCP_SOCK_GET_COMMON(lost_out);
5670 : 0 : break;
5671 : : case offsetof(struct bpf_tcp_sock, sacked_out):
5672 : 0 : BPF_TCP_SOCK_GET_COMMON(sacked_out);
5673 : 0 : break;
5674 : : case offsetof(struct bpf_tcp_sock, bytes_received):
5675 : 0 : BPF_TCP_SOCK_GET_COMMON(bytes_received);
5676 : 0 : break;
5677 : : case offsetof(struct bpf_tcp_sock, bytes_acked):
5678 : 0 : BPF_TCP_SOCK_GET_COMMON(bytes_acked);
5679 : 0 : break;
5680 : : case offsetof(struct bpf_tcp_sock, dsack_dups):
5681 : 0 : BPF_TCP_SOCK_GET_COMMON(dsack_dups);
5682 : 0 : break;
5683 : : case offsetof(struct bpf_tcp_sock, delivered):
5684 : 0 : BPF_TCP_SOCK_GET_COMMON(delivered);
5685 : 0 : break;
5686 : : case offsetof(struct bpf_tcp_sock, delivered_ce):
5687 : 0 : BPF_TCP_SOCK_GET_COMMON(delivered_ce);
5688 : 0 : break;
5689 : : case offsetof(struct bpf_tcp_sock, icsk_retransmits):
5690 : 0 : BPF_INET_SOCK_GET_COMMON(icsk_retransmits);
5691 : 0 : break;
5692 : : }
5693 : :
5694 : 0 : return insn - insn_buf;
5695 : : }
5696 : :
5697 : 0 : BPF_CALL_1(bpf_tcp_sock, struct sock *, sk)
5698 : : {
5699 [ # # # # ]: 0 : if (sk_fullsock(sk) && sk->sk_protocol == IPPROTO_TCP)
5700 : 0 : return (unsigned long)sk;
5701 : :
5702 : : return (unsigned long)NULL;
5703 : : }
5704 : :
5705 : : const struct bpf_func_proto bpf_tcp_sock_proto = {
5706 : : .func = bpf_tcp_sock,
5707 : : .gpl_only = false,
5708 : : .ret_type = RET_PTR_TO_TCP_SOCK_OR_NULL,
5709 : : .arg1_type = ARG_PTR_TO_SOCK_COMMON,
5710 : : };
5711 : :
5712 : 0 : BPF_CALL_1(bpf_get_listener_sock, struct sock *, sk)
5713 : : {
5714 : 0 : sk = sk_to_full_sk(sk);
5715 : :
5716 [ # # # # ]: 0 : if (sk->sk_state == TCP_LISTEN && sock_flag(sk, SOCK_RCU_FREE))
5717 : 0 : return (unsigned long)sk;
5718 : :
5719 : : return (unsigned long)NULL;
5720 : : }
5721 : :
5722 : : static const struct bpf_func_proto bpf_get_listener_sock_proto = {
5723 : : .func = bpf_get_listener_sock,
5724 : : .gpl_only = false,
5725 : : .ret_type = RET_PTR_TO_SOCKET_OR_NULL,
5726 : : .arg1_type = ARG_PTR_TO_SOCK_COMMON,
5727 : : };
5728 : :
5729 : 0 : BPF_CALL_1(bpf_skb_ecn_set_ce, struct sk_buff *, skb)
5730 : : {
5731 : : unsigned int iphdr_len;
5732 : :
5733 [ # # # ]: 0 : switch (skb_protocol(skb, true)) {
5734 : : case cpu_to_be16(ETH_P_IP):
5735 : : iphdr_len = sizeof(struct iphdr);
5736 : : break;
5737 : : case cpu_to_be16(ETH_P_IPV6):
5738 : : iphdr_len = sizeof(struct ipv6hdr);
5739 : : break;
5740 : : default:
5741 : : return 0;
5742 : : }
5743 : :
5744 [ # # ]: 0 : if (skb_headlen(skb) < iphdr_len)
5745 : : return 0;
5746 : :
5747 [ # # # # ]: 0 : if (skb_cloned(skb) && !skb_clone_writable(skb, iphdr_len))
5748 : : return 0;
5749 : :
5750 : 0 : return INET_ECN_set_ce(skb);
5751 : : }
5752 : :
5753 : 0 : bool bpf_xdp_sock_is_valid_access(int off, int size, enum bpf_access_type type,
5754 : : struct bpf_insn_access_aux *info)
5755 : : {
5756 [ # # ]: 0 : if (off < 0 || off >= offsetofend(struct bpf_xdp_sock, queue_id))
5757 : : return false;
5758 : :
5759 [ # # ]: 0 : if (off % size != 0)
5760 : : return false;
5761 : :
5762 : : switch (off) {
5763 : : default:
5764 : 0 : return size == sizeof(__u32);
5765 : : }
5766 : : }
5767 : :
5768 : 0 : u32 bpf_xdp_sock_convert_ctx_access(enum bpf_access_type type,
5769 : : const struct bpf_insn *si,
5770 : : struct bpf_insn *insn_buf,
5771 : : struct bpf_prog *prog, u32 *target_size)
5772 : : {
5773 : : struct bpf_insn *insn = insn_buf;
5774 : :
5775 : : #define BPF_XDP_SOCK_GET(FIELD) \
5776 : : do { \
5777 : : BUILD_BUG_ON(FIELD_SIZEOF(struct xdp_sock, FIELD) > \
5778 : : FIELD_SIZEOF(struct bpf_xdp_sock, FIELD)); \
5779 : : *insn++ = BPF_LDX_MEM(BPF_FIELD_SIZEOF(struct xdp_sock, FIELD),\
5780 : : si->dst_reg, si->src_reg, \
5781 : : offsetof(struct xdp_sock, FIELD)); \
5782 : : } while (0)
5783 : :
5784 [ # # ]: 0 : switch (si->off) {
5785 : : case offsetof(struct bpf_xdp_sock, queue_id):
5786 : 0 : BPF_XDP_SOCK_GET(queue_id);
5787 : 0 : break;
5788 : : }
5789 : :
5790 : 0 : return insn - insn_buf;
5791 : : }
5792 : :
5793 : : static const struct bpf_func_proto bpf_skb_ecn_set_ce_proto = {
5794 : : .func = bpf_skb_ecn_set_ce,
5795 : : .gpl_only = false,
5796 : : .ret_type = RET_INTEGER,
5797 : : .arg1_type = ARG_PTR_TO_CTX,
5798 : : };
5799 : :
5800 : 0 : BPF_CALL_5(bpf_tcp_check_syncookie, struct sock *, sk, void *, iph, u32, iph_len,
5801 : : struct tcphdr *, th, u32, th_len)
5802 : : {
5803 : : #ifdef CONFIG_SYN_COOKIES
5804 : : u32 cookie;
5805 : : int ret;
5806 : :
5807 [ # # ]: 0 : if (unlikely(th_len < sizeof(*th)))
5808 : : return -EINVAL;
5809 : :
5810 : : /* sk_listener() allows TCP_NEW_SYN_RECV, which makes no sense here. */
5811 [ # # # # ]: 0 : if (sk->sk_protocol != IPPROTO_TCP || sk->sk_state != TCP_LISTEN)
5812 : : return -EINVAL;
5813 : :
5814 [ # # ]: 0 : if (!sock_net(sk)->ipv4.sysctl_tcp_syncookies)
5815 : : return -EINVAL;
5816 : :
5817 [ # # ]: 0 : if (!th->ack || th->rst || th->syn)
5818 : : return -ENOENT;
5819 : :
5820 [ # # ]: 0 : if (tcp_synq_no_recent_overflow(sk))
5821 : : return -ENOENT;
5822 : :
5823 : 0 : cookie = ntohl(th->ack_seq) - 1;
5824 : :
5825 [ # # ]: 0 : switch (sk->sk_family) {
5826 : : case AF_INET:
5827 [ # # ]: 0 : if (unlikely(iph_len < sizeof(struct iphdr)))
5828 : : return -EINVAL;
5829 : :
5830 : 0 : ret = __cookie_v4_check((struct iphdr *)iph, th, cookie);
5831 : : break;
5832 : :
5833 : : #if IS_BUILTIN(CONFIG_IPV6)
5834 : : case AF_INET6:
5835 : : if (unlikely(iph_len < sizeof(struct ipv6hdr)))
5836 : : return -EINVAL;
5837 : :
5838 : : ret = __cookie_v6_check((struct ipv6hdr *)iph, th, cookie);
5839 : : break;
5840 : : #endif /* CONFIG_IPV6 */
5841 : :
5842 : : default:
5843 : : return -EPROTONOSUPPORT;
5844 : : }
5845 : :
5846 [ # # ]: 0 : if (ret > 0)
5847 : : return 0;
5848 : :
5849 : : return -ENOENT;
5850 : : #else
5851 : : return -ENOTSUPP;
5852 : : #endif
5853 : : }
5854 : :
5855 : : static const struct bpf_func_proto bpf_tcp_check_syncookie_proto = {
5856 : : .func = bpf_tcp_check_syncookie,
5857 : : .gpl_only = true,
5858 : : .pkt_access = true,
5859 : : .ret_type = RET_INTEGER,
5860 : : .arg1_type = ARG_PTR_TO_SOCK_COMMON,
5861 : : .arg2_type = ARG_PTR_TO_MEM,
5862 : : .arg3_type = ARG_CONST_SIZE,
5863 : : .arg4_type = ARG_PTR_TO_MEM,
5864 : : .arg5_type = ARG_CONST_SIZE,
5865 : : };
5866 : :
5867 : 0 : BPF_CALL_5(bpf_tcp_gen_syncookie, struct sock *, sk, void *, iph, u32, iph_len,
5868 : : struct tcphdr *, th, u32, th_len)
5869 : : {
5870 : : #ifdef CONFIG_SYN_COOKIES
5871 : : u32 cookie;
5872 : : u16 mss;
5873 : :
5874 [ # # # # ]: 0 : if (unlikely(th_len < sizeof(*th) || th_len != th->doff * 4))
5875 : : return -EINVAL;
5876 : :
5877 [ # # # # ]: 0 : if (sk->sk_protocol != IPPROTO_TCP || sk->sk_state != TCP_LISTEN)
5878 : : return -EINVAL;
5879 : :
5880 [ # # ]: 0 : if (!sock_net(sk)->ipv4.sysctl_tcp_syncookies)
5881 : : return -ENOENT;
5882 : :
5883 [ # # ]: 0 : if (!th->syn || th->ack || th->fin || th->rst)
5884 : : return -EINVAL;
5885 : :
5886 [ # # ]: 0 : if (unlikely(iph_len < sizeof(struct iphdr)))
5887 : : return -EINVAL;
5888 : :
5889 : : /* Both struct iphdr and struct ipv6hdr have the version field at the
5890 : : * same offset so we can cast to the shorter header (struct iphdr).
5891 : : */
5892 [ # # ]: 0 : switch (((struct iphdr *)iph)->version) {
5893 : : case 4:
5894 [ # # ]: 0 : if (sk->sk_family == AF_INET6 && sk->sk_ipv6only)
5895 : : return -EINVAL;
5896 : :
5897 : 0 : mss = tcp_v4_get_syncookie(sk, iph, th, &cookie);
5898 : : break;
5899 : :
5900 : : #if IS_BUILTIN(CONFIG_IPV6)
5901 : : case 6:
5902 : : if (unlikely(iph_len < sizeof(struct ipv6hdr)))
5903 : : return -EINVAL;
5904 : :
5905 : : if (sk->sk_family != AF_INET6)
5906 : : return -EINVAL;
5907 : :
5908 : : mss = tcp_v6_get_syncookie(sk, iph, th, &cookie);
5909 : : break;
5910 : : #endif /* CONFIG_IPV6 */
5911 : :
5912 : : default:
5913 : : return -EPROTONOSUPPORT;
5914 : : }
5915 [ # # ]: 0 : if (mss == 0)
5916 : : return -ENOENT;
5917 : :
5918 : 0 : return cookie | ((u64)mss << 32);
5919 : : #else
5920 : : return -EOPNOTSUPP;
5921 : : #endif /* CONFIG_SYN_COOKIES */
5922 : : }
5923 : :
5924 : : static const struct bpf_func_proto bpf_tcp_gen_syncookie_proto = {
5925 : : .func = bpf_tcp_gen_syncookie,
5926 : : .gpl_only = true, /* __cookie_v*_init_sequence() is GPL */
5927 : : .pkt_access = true,
5928 : : .ret_type = RET_INTEGER,
5929 : : .arg1_type = ARG_PTR_TO_SOCK_COMMON,
5930 : : .arg2_type = ARG_PTR_TO_MEM,
5931 : : .arg3_type = ARG_CONST_SIZE,
5932 : : .arg4_type = ARG_PTR_TO_MEM,
5933 : : .arg5_type = ARG_CONST_SIZE,
5934 : : };
5935 : :
5936 : : #endif /* CONFIG_INET */
5937 : :
5938 : 4968 : bool bpf_helper_changes_pkt_data(void *func)
5939 : : {
5940 [ + - + - ]: 4968 : if (func == bpf_skb_vlan_push ||
5941 [ + - ]: 4968 : func == bpf_skb_vlan_pop ||
5942 [ + - ]: 4968 : func == bpf_skb_store_bytes ||
5943 [ + - ]: 4968 : func == bpf_skb_change_proto ||
5944 [ + - ]: 4968 : func == bpf_skb_change_head ||
5945 [ + - ]: 4968 : func == sk_skb_change_head ||
5946 [ + - ]: 4968 : func == bpf_skb_change_tail ||
5947 [ + - ]: 4968 : func == sk_skb_change_tail ||
5948 [ + - ]: 4968 : func == bpf_skb_adjust_room ||
5949 [ + - ]: 4968 : func == bpf_skb_pull_data ||
5950 [ + - ]: 4968 : func == sk_skb_pull_data ||
5951 [ + - ]: 4968 : func == bpf_clone_redirect ||
5952 [ + - ]: 4968 : func == bpf_l3_csum_replace ||
5953 [ + - ]: 4968 : func == bpf_l4_csum_replace ||
5954 [ + - ]: 4968 : func == bpf_xdp_adjust_head ||
5955 [ + - ]: 4968 : func == bpf_xdp_adjust_meta ||
5956 [ + - ]: 4968 : func == bpf_msg_pull_data ||
5957 [ + - ]: 4968 : func == bpf_msg_push_data ||
5958 [ + - ]: 4968 : func == bpf_msg_pop_data ||
5959 [ + - ]: 4968 : func == bpf_xdp_adjust_tail ||
5960 : : #if IS_ENABLED(CONFIG_IPV6_SEG6_BPF)
5961 : : func == bpf_lwt_seg6_store_bytes ||
5962 : : func == bpf_lwt_seg6_adjust_srh ||
5963 : : func == bpf_lwt_seg6_action ||
5964 : : #endif
5965 [ + - ]: 4968 : func == bpf_lwt_in_push_encap ||
5966 : : func == bpf_lwt_xmit_push_encap)
5967 : : return true;
5968 : :
5969 : 4968 : return false;
5970 : : }
5971 : :
5972 : : static const struct bpf_func_proto *
5973 : 4968 : bpf_base_func_proto(enum bpf_func_id func_id)
5974 : : {
5975 [ - - - - : 4968 : switch (func_id) {
- - - - -
- - + ]
5976 : : case BPF_FUNC_map_lookup_elem:
5977 : : return &bpf_map_lookup_elem_proto;
5978 : : case BPF_FUNC_map_update_elem:
5979 : 0 : return &bpf_map_update_elem_proto;
5980 : : case BPF_FUNC_map_delete_elem:
5981 : 0 : return &bpf_map_delete_elem_proto;
5982 : : case BPF_FUNC_map_push_elem:
5983 : 0 : return &bpf_map_push_elem_proto;
5984 : : case BPF_FUNC_map_pop_elem:
5985 : 0 : return &bpf_map_pop_elem_proto;
5986 : : case BPF_FUNC_map_peek_elem:
5987 : 0 : return &bpf_map_peek_elem_proto;
5988 : : case BPF_FUNC_get_prandom_u32:
5989 : 0 : return &bpf_get_prandom_u32_proto;
5990 : : case BPF_FUNC_get_smp_processor_id:
5991 : 0 : return &bpf_get_raw_smp_processor_id_proto;
5992 : : case BPF_FUNC_get_numa_node_id:
5993 : 0 : return &bpf_get_numa_node_id_proto;
5994 : : case BPF_FUNC_tail_call:
5995 : 0 : return &bpf_tail_call_proto;
5996 : : case BPF_FUNC_ktime_get_ns:
5997 : 0 : return &bpf_ktime_get_ns_proto;
5998 : : default:
5999 : : break;
6000 : : }
6001 : :
6002 [ # # ]: 0 : if (!capable(CAP_SYS_ADMIN))
6003 : : return NULL;
6004 : :
6005 [ # # # # ]: 0 : switch (func_id) {
6006 : : case BPF_FUNC_spin_lock:
6007 : : return &bpf_spin_lock_proto;
6008 : : case BPF_FUNC_spin_unlock:
6009 : 0 : return &bpf_spin_unlock_proto;
6010 : : case BPF_FUNC_trace_printk:
6011 : 0 : return bpf_get_trace_printk_proto();
6012 : : default:
6013 : 0 : return NULL;
6014 : : }
6015 : : }
6016 : :
6017 : : static const struct bpf_func_proto *
6018 : 0 : sock_filter_func_proto(enum bpf_func_id func_id, const struct bpf_prog *prog)
6019 : : {
6020 [ # # # ]: 0 : switch (func_id) {
6021 : : /* inet and inet6 sockets are created in a process
6022 : : * context so there is always a valid uid/gid
6023 : : */
6024 : : case BPF_FUNC_get_current_uid_gid:
6025 : : return &bpf_get_current_uid_gid_proto;
6026 : : case BPF_FUNC_get_local_storage:
6027 : 0 : return &bpf_get_local_storage_proto;
6028 : : default:
6029 : 0 : return bpf_base_func_proto(func_id);
6030 : : }
6031 : : }
6032 : :
6033 : : static const struct bpf_func_proto *
6034 : 0 : sock_addr_func_proto(enum bpf_func_id func_id, const struct bpf_prog *prog)
6035 : : {
6036 [ # # # # : 0 : switch (func_id) {
# # # # #
# # ]
6037 : : /* inet and inet6 sockets are created in a process
6038 : : * context so there is always a valid uid/gid
6039 : : */
6040 : : case BPF_FUNC_get_current_uid_gid:
6041 : : return &bpf_get_current_uid_gid_proto;
6042 : : case BPF_FUNC_bind:
6043 [ # # ]: 0 : switch (prog->expected_attach_type) {
6044 : : case BPF_CGROUP_INET4_CONNECT:
6045 : : case BPF_CGROUP_INET6_CONNECT:
6046 : : return &bpf_bind_proto;
6047 : : default:
6048 : 0 : return NULL;
6049 : : }
6050 : : case BPF_FUNC_get_socket_cookie:
6051 : 0 : return &bpf_get_socket_cookie_sock_addr_proto;
6052 : : case BPF_FUNC_get_local_storage:
6053 : 0 : return &bpf_get_local_storage_proto;
6054 : : #ifdef CONFIG_INET
6055 : : case BPF_FUNC_sk_lookup_tcp:
6056 : 0 : return &bpf_sock_addr_sk_lookup_tcp_proto;
6057 : : case BPF_FUNC_sk_lookup_udp:
6058 : 0 : return &bpf_sock_addr_sk_lookup_udp_proto;
6059 : : case BPF_FUNC_sk_release:
6060 : 0 : return &bpf_sk_release_proto;
6061 : : case BPF_FUNC_skc_lookup_tcp:
6062 : 0 : return &bpf_sock_addr_skc_lookup_tcp_proto;
6063 : : #endif /* CONFIG_INET */
6064 : : case BPF_FUNC_sk_storage_get:
6065 : 0 : return &bpf_sk_storage_get_proto;
6066 : : case BPF_FUNC_sk_storage_delete:
6067 : 0 : return &bpf_sk_storage_delete_proto;
6068 : : default:
6069 : 0 : return bpf_base_func_proto(func_id);
6070 : : }
6071 : : }
6072 : :
6073 : : static const struct bpf_func_proto *
6074 : 9936 : sk_filter_func_proto(enum bpf_func_id func_id, const struct bpf_prog *prog)
6075 : : {
6076 [ - - - - : 9936 : switch (func_id) {
+ + ]
6077 : : case BPF_FUNC_skb_load_bytes:
6078 : : return &bpf_skb_load_bytes_proto;
6079 : : case BPF_FUNC_skb_load_bytes_relative:
6080 : 0 : return &bpf_skb_load_bytes_relative_proto;
6081 : : case BPF_FUNC_get_socket_cookie:
6082 : 0 : return &bpf_get_socket_cookie_proto;
6083 : : case BPF_FUNC_get_socket_uid:
6084 : 0 : return &bpf_get_socket_uid_proto;
6085 : : case BPF_FUNC_perf_event_output:
6086 : 0 : return &bpf_skb_event_output_proto;
6087 : : default:
6088 : 4968 : return bpf_base_func_proto(func_id);
6089 : : }
6090 : : }
6091 : :
6092 : : const struct bpf_func_proto bpf_sk_storage_get_proto __weak;
6093 : : const struct bpf_func_proto bpf_sk_storage_delete_proto __weak;
6094 : :
6095 : : static const struct bpf_func_proto *
6096 : 9936 : cg_skb_func_proto(enum bpf_func_id func_id, const struct bpf_prog *prog)
6097 : : {
6098 [ - - - - : 9936 : switch (func_id) {
- - - - +
- ]
6099 : : case BPF_FUNC_get_local_storage:
6100 : : return &bpf_get_local_storage_proto;
6101 : : case BPF_FUNC_sk_fullsock:
6102 : 0 : return &bpf_sk_fullsock_proto;
6103 : : case BPF_FUNC_sk_storage_get:
6104 : 0 : return &bpf_sk_storage_get_proto;
6105 : : case BPF_FUNC_sk_storage_delete:
6106 : 0 : return &bpf_sk_storage_delete_proto;
6107 : : case BPF_FUNC_perf_event_output:
6108 : 0 : return &bpf_skb_event_output_proto;
6109 : : #ifdef CONFIG_SOCK_CGROUP_DATA
6110 : : case BPF_FUNC_skb_cgroup_id:
6111 : 0 : return &bpf_skb_cgroup_id_proto;
6112 : : #endif
6113 : : #ifdef CONFIG_INET
6114 : : case BPF_FUNC_tcp_sock:
6115 : 0 : return &bpf_tcp_sock_proto;
6116 : : case BPF_FUNC_get_listener_sock:
6117 : 0 : return &bpf_get_listener_sock_proto;
6118 : : case BPF_FUNC_skb_ecn_set_ce:
6119 : 0 : return &bpf_skb_ecn_set_ce_proto;
6120 : : #endif
6121 : : default:
6122 : 9936 : return sk_filter_func_proto(func_id, prog);
6123 : : }
6124 : : }
6125 : :
6126 : : static const struct bpf_func_proto *
6127 : 0 : tc_cls_act_func_proto(enum bpf_func_id func_id, const struct bpf_prog *prog)
6128 : : {
6129 [ # # # # : 0 : switch (func_id) {
# # # # #
# # # # #
# # # # #
# # # # #
# # # # #
# # # # #
# # # # #
# # # # #
# # # ]
6130 : : case BPF_FUNC_skb_store_bytes:
6131 : : return &bpf_skb_store_bytes_proto;
6132 : : case BPF_FUNC_skb_load_bytes:
6133 : 0 : return &bpf_skb_load_bytes_proto;
6134 : : case BPF_FUNC_skb_load_bytes_relative:
6135 : 0 : return &bpf_skb_load_bytes_relative_proto;
6136 : : case BPF_FUNC_skb_pull_data:
6137 : 0 : return &bpf_skb_pull_data_proto;
6138 : : case BPF_FUNC_csum_diff:
6139 : 0 : return &bpf_csum_diff_proto;
6140 : : case BPF_FUNC_csum_update:
6141 : 0 : return &bpf_csum_update_proto;
6142 : : case BPF_FUNC_l3_csum_replace:
6143 : 0 : return &bpf_l3_csum_replace_proto;
6144 : : case BPF_FUNC_l4_csum_replace:
6145 : 0 : return &bpf_l4_csum_replace_proto;
6146 : : case BPF_FUNC_clone_redirect:
6147 : 0 : return &bpf_clone_redirect_proto;
6148 : : case BPF_FUNC_get_cgroup_classid:
6149 : 0 : return &bpf_get_cgroup_classid_proto;
6150 : : case BPF_FUNC_skb_vlan_push:
6151 : 0 : return &bpf_skb_vlan_push_proto;
6152 : : case BPF_FUNC_skb_vlan_pop:
6153 : 0 : return &bpf_skb_vlan_pop_proto;
6154 : : case BPF_FUNC_skb_change_proto:
6155 : 0 : return &bpf_skb_change_proto_proto;
6156 : : case BPF_FUNC_skb_change_type:
6157 : 0 : return &bpf_skb_change_type_proto;
6158 : : case BPF_FUNC_skb_adjust_room:
6159 : 0 : return &bpf_skb_adjust_room_proto;
6160 : : case BPF_FUNC_skb_change_tail:
6161 : 0 : return &bpf_skb_change_tail_proto;
6162 : : case BPF_FUNC_skb_get_tunnel_key:
6163 : 0 : return &bpf_skb_get_tunnel_key_proto;
6164 : : case BPF_FUNC_skb_set_tunnel_key:
6165 : 0 : return bpf_get_skb_set_tunnel_proto(func_id);
6166 : : case BPF_FUNC_skb_get_tunnel_opt:
6167 : 0 : return &bpf_skb_get_tunnel_opt_proto;
6168 : : case BPF_FUNC_skb_set_tunnel_opt:
6169 : 0 : return bpf_get_skb_set_tunnel_proto(func_id);
6170 : : case BPF_FUNC_redirect:
6171 : 0 : return &bpf_redirect_proto;
6172 : : case BPF_FUNC_get_route_realm:
6173 : 0 : return &bpf_get_route_realm_proto;
6174 : : case BPF_FUNC_get_hash_recalc:
6175 : 0 : return &bpf_get_hash_recalc_proto;
6176 : : case BPF_FUNC_set_hash_invalid:
6177 : 0 : return &bpf_set_hash_invalid_proto;
6178 : : case BPF_FUNC_set_hash:
6179 : 0 : return &bpf_set_hash_proto;
6180 : : case BPF_FUNC_perf_event_output:
6181 : 0 : return &bpf_skb_event_output_proto;
6182 : : case BPF_FUNC_get_smp_processor_id:
6183 : 0 : return &bpf_get_smp_processor_id_proto;
6184 : : case BPF_FUNC_skb_under_cgroup:
6185 : 0 : return &bpf_skb_under_cgroup_proto;
6186 : : case BPF_FUNC_get_socket_cookie:
6187 : 0 : return &bpf_get_socket_cookie_proto;
6188 : : case BPF_FUNC_get_socket_uid:
6189 : 0 : return &bpf_get_socket_uid_proto;
6190 : : case BPF_FUNC_fib_lookup:
6191 : 0 : return &bpf_skb_fib_lookup_proto;
6192 : : case BPF_FUNC_sk_fullsock:
6193 : 0 : return &bpf_sk_fullsock_proto;
6194 : : case BPF_FUNC_sk_storage_get:
6195 : 0 : return &bpf_sk_storage_get_proto;
6196 : : case BPF_FUNC_sk_storage_delete:
6197 : 0 : return &bpf_sk_storage_delete_proto;
6198 : : #ifdef CONFIG_XFRM
6199 : : case BPF_FUNC_skb_get_xfrm_state:
6200 : 0 : return &bpf_skb_get_xfrm_state_proto;
6201 : : #endif
6202 : : #ifdef CONFIG_SOCK_CGROUP_DATA
6203 : : case BPF_FUNC_skb_cgroup_id:
6204 : 0 : return &bpf_skb_cgroup_id_proto;
6205 : : case BPF_FUNC_skb_ancestor_cgroup_id:
6206 : 0 : return &bpf_skb_ancestor_cgroup_id_proto;
6207 : : #endif
6208 : : #ifdef CONFIG_INET
6209 : : case BPF_FUNC_sk_lookup_tcp:
6210 : 0 : return &bpf_sk_lookup_tcp_proto;
6211 : : case BPF_FUNC_sk_lookup_udp:
6212 : 0 : return &bpf_sk_lookup_udp_proto;
6213 : : case BPF_FUNC_sk_release:
6214 : 0 : return &bpf_sk_release_proto;
6215 : : case BPF_FUNC_tcp_sock:
6216 : 0 : return &bpf_tcp_sock_proto;
6217 : : case BPF_FUNC_get_listener_sock:
6218 : 0 : return &bpf_get_listener_sock_proto;
6219 : : case BPF_FUNC_skc_lookup_tcp:
6220 : 0 : return &bpf_skc_lookup_tcp_proto;
6221 : : case BPF_FUNC_tcp_check_syncookie:
6222 : 0 : return &bpf_tcp_check_syncookie_proto;
6223 : : case BPF_FUNC_skb_ecn_set_ce:
6224 : 0 : return &bpf_skb_ecn_set_ce_proto;
6225 : : case BPF_FUNC_tcp_gen_syncookie:
6226 : 0 : return &bpf_tcp_gen_syncookie_proto;
6227 : : #endif
6228 : : default:
6229 : 0 : return bpf_base_func_proto(func_id);
6230 : : }
6231 : : }
6232 : :
6233 : : static const struct bpf_func_proto *
6234 : 0 : xdp_func_proto(enum bpf_func_id func_id, const struct bpf_prog *prog)
6235 : : {
6236 [ # # # # : 0 : switch (func_id) {
# # # # #
# # # # #
# # ]
6237 : : case BPF_FUNC_perf_event_output:
6238 : : return &bpf_xdp_event_output_proto;
6239 : : case BPF_FUNC_get_smp_processor_id:
6240 : 0 : return &bpf_get_smp_processor_id_proto;
6241 : : case BPF_FUNC_csum_diff:
6242 : 0 : return &bpf_csum_diff_proto;
6243 : : case BPF_FUNC_xdp_adjust_head:
6244 : 0 : return &bpf_xdp_adjust_head_proto;
6245 : : case BPF_FUNC_xdp_adjust_meta:
6246 : 0 : return &bpf_xdp_adjust_meta_proto;
6247 : : case BPF_FUNC_redirect:
6248 : 0 : return &bpf_xdp_redirect_proto;
6249 : : case BPF_FUNC_redirect_map:
6250 : 0 : return &bpf_xdp_redirect_map_proto;
6251 : : case BPF_FUNC_xdp_adjust_tail:
6252 : 0 : return &bpf_xdp_adjust_tail_proto;
6253 : : case BPF_FUNC_fib_lookup:
6254 : 0 : return &bpf_xdp_fib_lookup_proto;
6255 : : #ifdef CONFIG_INET
6256 : : case BPF_FUNC_sk_lookup_udp:
6257 : 0 : return &bpf_xdp_sk_lookup_udp_proto;
6258 : : case BPF_FUNC_sk_lookup_tcp:
6259 : 0 : return &bpf_xdp_sk_lookup_tcp_proto;
6260 : : case BPF_FUNC_sk_release:
6261 : 0 : return &bpf_sk_release_proto;
6262 : : case BPF_FUNC_skc_lookup_tcp:
6263 : 0 : return &bpf_xdp_skc_lookup_tcp_proto;
6264 : : case BPF_FUNC_tcp_check_syncookie:
6265 : 0 : return &bpf_tcp_check_syncookie_proto;
6266 : : case BPF_FUNC_tcp_gen_syncookie:
6267 : 0 : return &bpf_tcp_gen_syncookie_proto;
6268 : : #endif
6269 : : default:
6270 : 0 : return bpf_base_func_proto(func_id);
6271 : : }
6272 : : }
6273 : :
6274 : : const struct bpf_func_proto bpf_sock_map_update_proto __weak;
6275 : : const struct bpf_func_proto bpf_sock_hash_update_proto __weak;
6276 : :
6277 : : static const struct bpf_func_proto *
6278 : 0 : sock_ops_func_proto(enum bpf_func_id func_id, const struct bpf_prog *prog)
6279 : : {
6280 [ # # # # : 0 : switch (func_id) {
# # # # #
# # # ]
6281 : : case BPF_FUNC_setsockopt:
6282 : : return &bpf_setsockopt_proto;
6283 : : case BPF_FUNC_getsockopt:
6284 : 0 : return &bpf_getsockopt_proto;
6285 : : case BPF_FUNC_sock_ops_cb_flags_set:
6286 : 0 : return &bpf_sock_ops_cb_flags_set_proto;
6287 : : case BPF_FUNC_sock_map_update:
6288 : 0 : return &bpf_sock_map_update_proto;
6289 : : case BPF_FUNC_sock_hash_update:
6290 : 0 : return &bpf_sock_hash_update_proto;
6291 : : case BPF_FUNC_get_socket_cookie:
6292 : 0 : return &bpf_get_socket_cookie_sock_ops_proto;
6293 : : case BPF_FUNC_get_local_storage:
6294 : 0 : return &bpf_get_local_storage_proto;
6295 : : case BPF_FUNC_perf_event_output:
6296 : 0 : return &bpf_sockopt_event_output_proto;
6297 : : case BPF_FUNC_sk_storage_get:
6298 : 0 : return &bpf_sk_storage_get_proto;
6299 : : case BPF_FUNC_sk_storage_delete:
6300 : 0 : return &bpf_sk_storage_delete_proto;
6301 : : #ifdef CONFIG_INET
6302 : : case BPF_FUNC_tcp_sock:
6303 : 0 : return &bpf_tcp_sock_proto;
6304 : : #endif /* CONFIG_INET */
6305 : : default:
6306 : 0 : return bpf_base_func_proto(func_id);
6307 : : }
6308 : : }
6309 : :
6310 : : const struct bpf_func_proto bpf_msg_redirect_map_proto __weak;
6311 : : const struct bpf_func_proto bpf_msg_redirect_hash_proto __weak;
6312 : :
6313 : : static const struct bpf_func_proto *
6314 : 0 : sk_msg_func_proto(enum bpf_func_id func_id, const struct bpf_prog *prog)
6315 : : {
6316 [ # # # # : 0 : switch (func_id) {
# # # # ]
6317 : : case BPF_FUNC_msg_redirect_map:
6318 : : return &bpf_msg_redirect_map_proto;
6319 : : case BPF_FUNC_msg_redirect_hash:
6320 : 0 : return &bpf_msg_redirect_hash_proto;
6321 : : case BPF_FUNC_msg_apply_bytes:
6322 : 0 : return &bpf_msg_apply_bytes_proto;
6323 : : case BPF_FUNC_msg_cork_bytes:
6324 : 0 : return &bpf_msg_cork_bytes_proto;
6325 : : case BPF_FUNC_msg_pull_data:
6326 : 0 : return &bpf_msg_pull_data_proto;
6327 : : case BPF_FUNC_msg_push_data:
6328 : 0 : return &bpf_msg_push_data_proto;
6329 : : case BPF_FUNC_msg_pop_data:
6330 : 0 : return &bpf_msg_pop_data_proto;
6331 : : default:
6332 : 0 : return bpf_base_func_proto(func_id);
6333 : : }
6334 : : }
6335 : :
6336 : : const struct bpf_func_proto bpf_sk_redirect_map_proto __weak;
6337 : : const struct bpf_func_proto bpf_sk_redirect_hash_proto __weak;
6338 : :
6339 : : static const struct bpf_func_proto *
6340 : 0 : sk_skb_func_proto(enum bpf_func_id func_id, const struct bpf_prog *prog)
6341 : : {
6342 [ # # # # : 0 : switch (func_id) {
# # # # #
# # # # #
# ]
6343 : : case BPF_FUNC_skb_store_bytes:
6344 : : return &bpf_skb_store_bytes_proto;
6345 : : case BPF_FUNC_skb_load_bytes:
6346 : 0 : return &bpf_skb_load_bytes_proto;
6347 : : case BPF_FUNC_skb_pull_data:
6348 : 0 : return &sk_skb_pull_data_proto;
6349 : : case BPF_FUNC_skb_change_tail:
6350 : 0 : return &sk_skb_change_tail_proto;
6351 : : case BPF_FUNC_skb_change_head:
6352 : 0 : return &sk_skb_change_head_proto;
6353 : : case BPF_FUNC_get_socket_cookie:
6354 : 0 : return &bpf_get_socket_cookie_proto;
6355 : : case BPF_FUNC_get_socket_uid:
6356 : 0 : return &bpf_get_socket_uid_proto;
6357 : : case BPF_FUNC_sk_redirect_map:
6358 : 0 : return &bpf_sk_redirect_map_proto;
6359 : : case BPF_FUNC_sk_redirect_hash:
6360 : 0 : return &bpf_sk_redirect_hash_proto;
6361 : : case BPF_FUNC_perf_event_output:
6362 : 0 : return &bpf_skb_event_output_proto;
6363 : : #ifdef CONFIG_INET
6364 : : case BPF_FUNC_sk_lookup_tcp:
6365 : 0 : return &bpf_sk_lookup_tcp_proto;
6366 : : case BPF_FUNC_sk_lookup_udp:
6367 : 0 : return &bpf_sk_lookup_udp_proto;
6368 : : case BPF_FUNC_sk_release:
6369 : 0 : return &bpf_sk_release_proto;
6370 : : case BPF_FUNC_skc_lookup_tcp:
6371 : 0 : return &bpf_skc_lookup_tcp_proto;
6372 : : #endif
6373 : : default:
6374 : 0 : return bpf_base_func_proto(func_id);
6375 : : }
6376 : : }
6377 : :
6378 : : static const struct bpf_func_proto *
6379 : 0 : flow_dissector_func_proto(enum bpf_func_id func_id, const struct bpf_prog *prog)
6380 : : {
6381 [ # # ]: 0 : switch (func_id) {
6382 : : case BPF_FUNC_skb_load_bytes:
6383 : : return &bpf_flow_dissector_load_bytes_proto;
6384 : : default:
6385 : 0 : return bpf_base_func_proto(func_id);
6386 : : }
6387 : : }
6388 : :
6389 : : static const struct bpf_func_proto *
6390 : 0 : lwt_out_func_proto(enum bpf_func_id func_id, const struct bpf_prog *prog)
6391 : : {
6392 [ # # # # : 0 : switch (func_id) {
# # # # #
# ]
6393 : : case BPF_FUNC_skb_load_bytes:
6394 : : return &bpf_skb_load_bytes_proto;
6395 : : case BPF_FUNC_skb_pull_data:
6396 : 0 : return &bpf_skb_pull_data_proto;
6397 : : case BPF_FUNC_csum_diff:
6398 : 0 : return &bpf_csum_diff_proto;
6399 : : case BPF_FUNC_get_cgroup_classid:
6400 : 0 : return &bpf_get_cgroup_classid_proto;
6401 : : case BPF_FUNC_get_route_realm:
6402 : 0 : return &bpf_get_route_realm_proto;
6403 : : case BPF_FUNC_get_hash_recalc:
6404 : 0 : return &bpf_get_hash_recalc_proto;
6405 : : case BPF_FUNC_perf_event_output:
6406 : 0 : return &bpf_skb_event_output_proto;
6407 : : case BPF_FUNC_get_smp_processor_id:
6408 : 0 : return &bpf_get_smp_processor_id_proto;
6409 : : case BPF_FUNC_skb_under_cgroup:
6410 : 0 : return &bpf_skb_under_cgroup_proto;
6411 : : default:
6412 : 0 : return bpf_base_func_proto(func_id);
6413 : : }
6414 : : }
6415 : :
6416 : : static const struct bpf_func_proto *
6417 : 0 : lwt_in_func_proto(enum bpf_func_id func_id, const struct bpf_prog *prog)
6418 : : {
6419 [ # # ]: 0 : switch (func_id) {
6420 : : case BPF_FUNC_lwt_push_encap:
6421 : : return &bpf_lwt_in_push_encap_proto;
6422 : : default:
6423 : 0 : return lwt_out_func_proto(func_id, prog);
6424 : : }
6425 : : }
6426 : :
6427 : : static const struct bpf_func_proto *
6428 : 0 : lwt_xmit_func_proto(enum bpf_func_id func_id, const struct bpf_prog *prog)
6429 : : {
6430 [ # # # # : 0 : switch (func_id) {
# # # # #
# # # # #
# ]
6431 : : case BPF_FUNC_skb_get_tunnel_key:
6432 : : return &bpf_skb_get_tunnel_key_proto;
6433 : : case BPF_FUNC_skb_set_tunnel_key:
6434 : 0 : return bpf_get_skb_set_tunnel_proto(func_id);
6435 : : case BPF_FUNC_skb_get_tunnel_opt:
6436 : 0 : return &bpf_skb_get_tunnel_opt_proto;
6437 : : case BPF_FUNC_skb_set_tunnel_opt:
6438 : 0 : return bpf_get_skb_set_tunnel_proto(func_id);
6439 : : case BPF_FUNC_redirect:
6440 : 0 : return &bpf_redirect_proto;
6441 : : case BPF_FUNC_clone_redirect:
6442 : 0 : return &bpf_clone_redirect_proto;
6443 : : case BPF_FUNC_skb_change_tail:
6444 : 0 : return &bpf_skb_change_tail_proto;
6445 : : case BPF_FUNC_skb_change_head:
6446 : 0 : return &bpf_skb_change_head_proto;
6447 : : case BPF_FUNC_skb_store_bytes:
6448 : 0 : return &bpf_skb_store_bytes_proto;
6449 : : case BPF_FUNC_csum_update:
6450 : 0 : return &bpf_csum_update_proto;
6451 : : case BPF_FUNC_l3_csum_replace:
6452 : 0 : return &bpf_l3_csum_replace_proto;
6453 : : case BPF_FUNC_l4_csum_replace:
6454 : 0 : return &bpf_l4_csum_replace_proto;
6455 : : case BPF_FUNC_set_hash_invalid:
6456 : 0 : return &bpf_set_hash_invalid_proto;
6457 : : case BPF_FUNC_lwt_push_encap:
6458 : 0 : return &bpf_lwt_xmit_push_encap_proto;
6459 : : default:
6460 : 0 : return lwt_out_func_proto(func_id, prog);
6461 : : }
6462 : : }
6463 : :
6464 : : static const struct bpf_func_proto *
6465 : 0 : lwt_seg6local_func_proto(enum bpf_func_id func_id, const struct bpf_prog *prog)
6466 : : {
6467 : : switch (func_id) {
6468 : : #if IS_ENABLED(CONFIG_IPV6_SEG6_BPF)
6469 : : case BPF_FUNC_lwt_seg6_store_bytes:
6470 : : return &bpf_lwt_seg6_store_bytes_proto;
6471 : : case BPF_FUNC_lwt_seg6_action:
6472 : : return &bpf_lwt_seg6_action_proto;
6473 : : case BPF_FUNC_lwt_seg6_adjust_srh:
6474 : : return &bpf_lwt_seg6_adjust_srh_proto;
6475 : : #endif
6476 : : default:
6477 : 0 : return lwt_out_func_proto(func_id, prog);
6478 : : }
6479 : : }
6480 : :
6481 : 1242 : static bool bpf_skb_is_valid_access(int off, int size, enum bpf_access_type type,
6482 : : const struct bpf_prog *prog,
6483 : : struct bpf_insn_access_aux *info)
6484 : : {
6485 : : const int size_default = sizeof(__u32);
6486 : :
6487 [ + - ]: 1242 : if (off < 0 || off >= sizeof(struct __sk_buff))
6488 : : return false;
6489 : :
6490 : : /* The verifier guarantees that size > 0. */
6491 [ + - ]: 1242 : if (off % size != 0)
6492 : : return false;
6493 : :
6494 [ - - - - : 1242 : switch (off) {
+ - ]
6495 : : case bpf_ctx_range_till(struct __sk_buff, cb[0], cb[4]):
6496 [ # # ]: 0 : if (off + size > offsetofend(struct __sk_buff, cb[4]))
6497 : : return false;
6498 : : break;
6499 : : case bpf_ctx_range_till(struct __sk_buff, remote_ip6[0], remote_ip6[3]):
6500 : : case bpf_ctx_range_till(struct __sk_buff, local_ip6[0], local_ip6[3]):
6501 : : case bpf_ctx_range_till(struct __sk_buff, remote_ip4, remote_ip4):
6502 : : case bpf_ctx_range_till(struct __sk_buff, local_ip4, local_ip4):
6503 : : case bpf_ctx_range(struct __sk_buff, data):
6504 : : case bpf_ctx_range(struct __sk_buff, data_meta):
6505 : : case bpf_ctx_range(struct __sk_buff, data_end):
6506 [ # # ]: 0 : if (size != size_default)
6507 : : return false;
6508 : : break;
6509 : : case bpf_ctx_range_ptr(struct __sk_buff, flow_keys):
6510 : : return false;
6511 : : case bpf_ctx_range(struct __sk_buff, tstamp):
6512 [ # # ]: 0 : if (size != sizeof(__u64))
6513 : : return false;
6514 : : break;
6515 : : case offsetof(struct __sk_buff, sk):
6516 [ # # ]: 0 : if (type == BPF_WRITE || size != sizeof(__u64))
6517 : : return false;
6518 : 0 : info->reg_type = PTR_TO_SOCK_COMMON_OR_NULL;
6519 : 0 : break;
6520 : : default:
6521 : : /* Only narrow read access allowed for now. */
6522 [ - + ]: 1242 : if (type == BPF_WRITE) {
6523 [ # # ]: 0 : if (size != size_default)
6524 : : return false;
6525 : : } else {
6526 : : bpf_ctx_record_field_size(info, size_default);
6527 [ + - ]: 2484 : if (!bpf_ctx_narrow_access_ok(off, size, size_default))
6528 : : return false;
6529 : : }
6530 : : }
6531 : :
6532 : : return true;
6533 : : }
6534 : :
6535 : 0 : static bool sk_filter_is_valid_access(int off, int size,
6536 : : enum bpf_access_type type,
6537 : : const struct bpf_prog *prog,
6538 : : struct bpf_insn_access_aux *info)
6539 : : {
6540 [ # # ]: 0 : switch (off) {
6541 : : case bpf_ctx_range(struct __sk_buff, tc_classid):
6542 : : case bpf_ctx_range(struct __sk_buff, data):
6543 : : case bpf_ctx_range(struct __sk_buff, data_meta):
6544 : : case bpf_ctx_range(struct __sk_buff, data_end):
6545 : : case bpf_ctx_range_till(struct __sk_buff, family, local_port):
6546 : : case bpf_ctx_range(struct __sk_buff, tstamp):
6547 : : case bpf_ctx_range(struct __sk_buff, wire_len):
6548 : : return false;
6549 : : }
6550 : :
6551 [ # # ]: 0 : if (type == BPF_WRITE) {
6552 [ # # ]: 0 : switch (off) {
6553 : : case bpf_ctx_range_till(struct __sk_buff, cb[0], cb[4]):
6554 : : break;
6555 : : default:
6556 : : return false;
6557 : : }
6558 : : }
6559 : :
6560 : 0 : return bpf_skb_is_valid_access(off, size, type, prog, info);
6561 : : }
6562 : :
6563 : 1242 : static bool cg_skb_is_valid_access(int off, int size,
6564 : : enum bpf_access_type type,
6565 : : const struct bpf_prog *prog,
6566 : : struct bpf_insn_access_aux *info)
6567 : : {
6568 [ - + - ]: 1242 : switch (off) {
6569 : : case bpf_ctx_range(struct __sk_buff, tc_classid):
6570 : : case bpf_ctx_range(struct __sk_buff, data_meta):
6571 : : case bpf_ctx_range(struct __sk_buff, wire_len):
6572 : : return false;
6573 : : case bpf_ctx_range(struct __sk_buff, data):
6574 : : case bpf_ctx_range(struct __sk_buff, data_end):
6575 [ # # ]: 0 : if (!capable(CAP_SYS_ADMIN))
6576 : : return false;
6577 : : break;
6578 : : }
6579 : :
6580 [ - + ]: 1242 : if (type == BPF_WRITE) {
6581 [ # # # ]: 0 : switch (off) {
6582 : : case bpf_ctx_range(struct __sk_buff, mark):
6583 : : case bpf_ctx_range(struct __sk_buff, priority):
6584 : : case bpf_ctx_range_till(struct __sk_buff, cb[0], cb[4]):
6585 : : break;
6586 : : case bpf_ctx_range(struct __sk_buff, tstamp):
6587 [ # # ]: 0 : if (!capable(CAP_SYS_ADMIN))
6588 : : return false;
6589 : : break;
6590 : : default:
6591 : : return false;
6592 : : }
6593 : : }
6594 : :
6595 [ - - + ]: 1242 : switch (off) {
6596 : : case bpf_ctx_range(struct __sk_buff, data):
6597 : 0 : info->reg_type = PTR_TO_PACKET;
6598 : 0 : break;
6599 : : case bpf_ctx_range(struct __sk_buff, data_end):
6600 : 0 : info->reg_type = PTR_TO_PACKET_END;
6601 : 0 : break;
6602 : : }
6603 : :
6604 : 1242 : return bpf_skb_is_valid_access(off, size, type, prog, info);
6605 : : }
6606 : :
6607 : 0 : static bool lwt_is_valid_access(int off, int size,
6608 : : enum bpf_access_type type,
6609 : : const struct bpf_prog *prog,
6610 : : struct bpf_insn_access_aux *info)
6611 : : {
6612 [ # # ]: 0 : switch (off) {
6613 : : case bpf_ctx_range(struct __sk_buff, tc_classid):
6614 : : case bpf_ctx_range_till(struct __sk_buff, family, local_port):
6615 : : case bpf_ctx_range(struct __sk_buff, data_meta):
6616 : : case bpf_ctx_range(struct __sk_buff, tstamp):
6617 : : case bpf_ctx_range(struct __sk_buff, wire_len):
6618 : : return false;
6619 : : }
6620 : :
6621 [ # # ]: 0 : if (type == BPF_WRITE) {
6622 [ # # ]: 0 : switch (off) {
6623 : : case bpf_ctx_range(struct __sk_buff, mark):
6624 : : case bpf_ctx_range(struct __sk_buff, priority):
6625 : : case bpf_ctx_range_till(struct __sk_buff, cb[0], cb[4]):
6626 : : break;
6627 : : default:
6628 : : return false;
6629 : : }
6630 : : }
6631 : :
6632 [ # # # ]: 0 : switch (off) {
6633 : : case bpf_ctx_range(struct __sk_buff, data):
6634 : 0 : info->reg_type = PTR_TO_PACKET;
6635 : 0 : break;
6636 : : case bpf_ctx_range(struct __sk_buff, data_end):
6637 : 0 : info->reg_type = PTR_TO_PACKET_END;
6638 : 0 : break;
6639 : : }
6640 : :
6641 : 0 : return bpf_skb_is_valid_access(off, size, type, prog, info);
6642 : : }
6643 : :
6644 : : /* Attach type specific accesses */
6645 : 0 : static bool __sock_filter_check_attach_type(int off,
6646 : : enum bpf_access_type access_type,
6647 : : enum bpf_attach_type attach_type)
6648 : : {
6649 [ # # # # : 0 : switch (off) {
# ]
6650 : : case offsetof(struct bpf_sock, bound_dev_if):
6651 : : case offsetof(struct bpf_sock, mark):
6652 : : case offsetof(struct bpf_sock, priority):
6653 [ # # ]: 0 : switch (attach_type) {
6654 : : case BPF_CGROUP_INET_SOCK_CREATE:
6655 : : goto full_access;
6656 : : default:
6657 : : return false;
6658 : : }
6659 : : case bpf_ctx_range(struct bpf_sock, src_ip4):
6660 [ # # ]: 0 : switch (attach_type) {
6661 : : case BPF_CGROUP_INET4_POST_BIND:
6662 : : goto read_only;
6663 : : default:
6664 : : return false;
6665 : : }
6666 : : case bpf_ctx_range_till(struct bpf_sock, src_ip6[0], src_ip6[3]):
6667 [ # # ]: 0 : switch (attach_type) {
6668 : : case BPF_CGROUP_INET6_POST_BIND:
6669 : : goto read_only;
6670 : : default:
6671 : : return false;
6672 : : }
6673 : : case bpf_ctx_range(struct bpf_sock, src_port):
6674 [ # # ]: 0 : switch (attach_type) {
6675 : : case BPF_CGROUP_INET4_POST_BIND:
6676 : : case BPF_CGROUP_INET6_POST_BIND:
6677 : : goto read_only;
6678 : : default:
6679 : : return false;
6680 : : }
6681 : : }
6682 : : read_only:
6683 : 0 : return access_type == BPF_READ;
6684 : : full_access:
6685 : 0 : return true;
6686 : : }
6687 : :
6688 : 0 : bool bpf_sock_common_is_valid_access(int off, int size,
6689 : : enum bpf_access_type type,
6690 : : struct bpf_insn_access_aux *info)
6691 : : {
6692 [ # # ]: 0 : switch (off) {
6693 : : case bpf_ctx_range_till(struct bpf_sock, type, priority):
6694 : : return false;
6695 : : default:
6696 : 0 : return bpf_sock_is_valid_access(off, size, type, info);
6697 : : }
6698 : : }
6699 : :
6700 : 0 : bool bpf_sock_is_valid_access(int off, int size, enum bpf_access_type type,
6701 : : struct bpf_insn_access_aux *info)
6702 : : {
6703 : : const int size_default = sizeof(__u32);
6704 : :
6705 [ # # ]: 0 : if (off < 0 || off >= sizeof(struct bpf_sock))
6706 : : return false;
6707 [ # # ]: 0 : if (off % size != 0)
6708 : : return false;
6709 : :
6710 [ # # ]: 0 : switch (off) {
6711 : : case offsetof(struct bpf_sock, state):
6712 : : case offsetof(struct bpf_sock, family):
6713 : : case offsetof(struct bpf_sock, type):
6714 : : case offsetof(struct bpf_sock, protocol):
6715 : : case offsetof(struct bpf_sock, dst_port):
6716 : : case offsetof(struct bpf_sock, src_port):
6717 : : case bpf_ctx_range(struct bpf_sock, src_ip4):
6718 : : case bpf_ctx_range_till(struct bpf_sock, src_ip6[0], src_ip6[3]):
6719 : : case bpf_ctx_range(struct bpf_sock, dst_ip4):
6720 : : case bpf_ctx_range_till(struct bpf_sock, dst_ip6[0], dst_ip6[3]):
6721 : : bpf_ctx_record_field_size(info, size_default);
6722 : 0 : return bpf_ctx_narrow_access_ok(off, size, size_default);
6723 : : }
6724 : :
6725 : 0 : return size == size_default;
6726 : : }
6727 : :
6728 : 0 : static bool sock_filter_is_valid_access(int off, int size,
6729 : : enum bpf_access_type type,
6730 : : const struct bpf_prog *prog,
6731 : : struct bpf_insn_access_aux *info)
6732 : : {
6733 [ # # ]: 0 : if (!bpf_sock_is_valid_access(off, size, type, info))
6734 : : return false;
6735 : 0 : return __sock_filter_check_attach_type(off, type,
6736 : : prog->expected_attach_type);
6737 : : }
6738 : :
6739 : 0 : static int bpf_noop_prologue(struct bpf_insn *insn_buf, bool direct_write,
6740 : : const struct bpf_prog *prog)
6741 : : {
6742 : : /* Neither direct read nor direct write requires any preliminary
6743 : : * action.
6744 : : */
6745 : 0 : return 0;
6746 : : }
6747 : :
6748 : 0 : static int bpf_unclone_prologue(struct bpf_insn *insn_buf, bool direct_write,
6749 : : const struct bpf_prog *prog, int drop_verdict)
6750 : : {
6751 : : struct bpf_insn *insn = insn_buf;
6752 : :
6753 [ # # ]: 0 : if (!direct_write)
6754 : : return 0;
6755 : :
6756 : : /* if (!skb->cloned)
6757 : : * goto start;
6758 : : *
6759 : : * (Fast-path, otherwise approximation that we might be
6760 : : * a clone, do the rest in helper.)
6761 : : */
6762 : 0 : *insn++ = BPF_LDX_MEM(BPF_B, BPF_REG_6, BPF_REG_1, CLONED_OFFSET());
6763 : 0 : *insn++ = BPF_ALU32_IMM(BPF_AND, BPF_REG_6, CLONED_MASK);
6764 : 0 : *insn++ = BPF_JMP_IMM(BPF_JEQ, BPF_REG_6, 0, 7);
6765 : :
6766 : : /* ret = bpf_skb_pull_data(skb, 0); */
6767 : 0 : *insn++ = BPF_MOV64_REG(BPF_REG_6, BPF_REG_1);
6768 : 0 : *insn++ = BPF_ALU64_REG(BPF_XOR, BPF_REG_2, BPF_REG_2);
6769 : 0 : *insn++ = BPF_RAW_INSN(BPF_JMP | BPF_CALL, 0, 0, 0,
6770 : : BPF_FUNC_skb_pull_data);
6771 : : /* if (!ret)
6772 : : * goto restore;
6773 : : * return TC_ACT_SHOT;
6774 : : */
6775 : 0 : *insn++ = BPF_JMP_IMM(BPF_JEQ, BPF_REG_0, 0, 2);
6776 : 0 : *insn++ = BPF_ALU32_IMM(BPF_MOV, BPF_REG_0, drop_verdict);
6777 : 0 : *insn++ = BPF_EXIT_INSN();
6778 : :
6779 : : /* restore: */
6780 : 0 : *insn++ = BPF_MOV64_REG(BPF_REG_1, BPF_REG_6);
6781 : : /* start: */
6782 : 0 : *insn++ = prog->insnsi[0];
6783 : :
6784 : 0 : return insn - insn_buf;
6785 : : }
6786 : :
6787 : 0 : static int bpf_gen_ld_abs(const struct bpf_insn *orig,
6788 : : struct bpf_insn *insn_buf)
6789 : : {
6790 : 0 : bool indirect = BPF_MODE(orig->code) == BPF_IND;
6791 : : struct bpf_insn *insn = insn_buf;
6792 : :
6793 : : /* We're guaranteed here that CTX is in R6. */
6794 : 0 : *insn++ = BPF_MOV64_REG(BPF_REG_1, BPF_REG_CTX);
6795 [ # # ]: 0 : if (!indirect) {
6796 : 0 : *insn++ = BPF_MOV64_IMM(BPF_REG_2, orig->imm);
6797 : : } else {
6798 : 0 : *insn++ = BPF_MOV64_REG(BPF_REG_2, orig->src_reg);
6799 [ # # ]: 0 : if (orig->imm)
6800 : 0 : *insn++ = BPF_ALU64_IMM(BPF_ADD, BPF_REG_2, orig->imm);
6801 : : }
6802 : :
6803 [ # # # # ]: 0 : switch (BPF_SIZE(orig->code)) {
6804 : : case BPF_B:
6805 : 0 : *insn++ = BPF_EMIT_CALL(bpf_skb_load_helper_8_no_cache);
6806 : 0 : break;
6807 : : case BPF_H:
6808 : 0 : *insn++ = BPF_EMIT_CALL(bpf_skb_load_helper_16_no_cache);
6809 : 0 : break;
6810 : : case BPF_W:
6811 : 0 : *insn++ = BPF_EMIT_CALL(bpf_skb_load_helper_32_no_cache);
6812 : 0 : break;
6813 : : }
6814 : :
6815 : 0 : *insn++ = BPF_JMP_IMM(BPF_JSGE, BPF_REG_0, 0, 2);
6816 : 0 : *insn++ = BPF_ALU32_REG(BPF_XOR, BPF_REG_0, BPF_REG_0);
6817 : 0 : *insn++ = BPF_EXIT_INSN();
6818 : :
6819 : 0 : return insn - insn_buf;
6820 : : }
6821 : :
6822 : 0 : static int tc_cls_act_prologue(struct bpf_insn *insn_buf, bool direct_write,
6823 : : const struct bpf_prog *prog)
6824 : : {
6825 : 0 : return bpf_unclone_prologue(insn_buf, direct_write, prog, TC_ACT_SHOT);
6826 : : }
6827 : :
6828 : 0 : static bool tc_cls_act_is_valid_access(int off, int size,
6829 : : enum bpf_access_type type,
6830 : : const struct bpf_prog *prog,
6831 : : struct bpf_insn_access_aux *info)
6832 : : {
6833 [ # # ]: 0 : if (type == BPF_WRITE) {
6834 [ # # ]: 0 : switch (off) {
6835 : : case bpf_ctx_range(struct __sk_buff, mark):
6836 : : case bpf_ctx_range(struct __sk_buff, tc_index):
6837 : : case bpf_ctx_range(struct __sk_buff, priority):
6838 : : case bpf_ctx_range(struct __sk_buff, tc_classid):
6839 : : case bpf_ctx_range_till(struct __sk_buff, cb[0], cb[4]):
6840 : : case bpf_ctx_range(struct __sk_buff, tstamp):
6841 : : case bpf_ctx_range(struct __sk_buff, queue_mapping):
6842 : : break;
6843 : : default:
6844 : : return false;
6845 : : }
6846 : : }
6847 : :
6848 [ # # # # : 0 : switch (off) {
# ]
6849 : : case bpf_ctx_range(struct __sk_buff, data):
6850 : 0 : info->reg_type = PTR_TO_PACKET;
6851 : 0 : break;
6852 : : case bpf_ctx_range(struct __sk_buff, data_meta):
6853 : 0 : info->reg_type = PTR_TO_PACKET_META;
6854 : 0 : break;
6855 : : case bpf_ctx_range(struct __sk_buff, data_end):
6856 : 0 : info->reg_type = PTR_TO_PACKET_END;
6857 : 0 : break;
6858 : : case bpf_ctx_range_till(struct __sk_buff, family, local_port):
6859 : : return false;
6860 : : }
6861 : :
6862 : 0 : return bpf_skb_is_valid_access(off, size, type, prog, info);
6863 : : }
6864 : :
6865 : : static bool __is_valid_xdp_access(int off, int size)
6866 : : {
6867 [ # # # # ]: 0 : if (off < 0 || off >= sizeof(struct xdp_md))
6868 : : return false;
6869 [ # # # # ]: 0 : if (off % size != 0)
6870 : : return false;
6871 [ # # # # ]: 0 : if (size != sizeof(__u32))
6872 : : return false;
6873 : :
6874 : : return true;
6875 : : }
6876 : :
6877 : 0 : static bool xdp_is_valid_access(int off, int size,
6878 : : enum bpf_access_type type,
6879 : : const struct bpf_prog *prog,
6880 : : struct bpf_insn_access_aux *info)
6881 : : {
6882 [ # # ]: 0 : if (type == BPF_WRITE) {
6883 [ # # ]: 0 : if (bpf_prog_is_dev_bound(prog->aux)) {
6884 [ # # ]: 0 : switch (off) {
6885 : : case offsetof(struct xdp_md, rx_queue_index):
6886 : 0 : return __is_valid_xdp_access(off, size);
6887 : : }
6888 : : }
6889 : : return false;
6890 : : }
6891 : :
6892 [ # # # # ]: 0 : switch (off) {
6893 : : case offsetof(struct xdp_md, data):
6894 : 0 : info->reg_type = PTR_TO_PACKET;
6895 : 0 : break;
6896 : : case offsetof(struct xdp_md, data_meta):
6897 : 0 : info->reg_type = PTR_TO_PACKET_META;
6898 : 0 : break;
6899 : : case offsetof(struct xdp_md, data_end):
6900 : 0 : info->reg_type = PTR_TO_PACKET_END;
6901 : 0 : break;
6902 : : }
6903 : :
6904 : 0 : return __is_valid_xdp_access(off, size);
6905 : : }
6906 : :
6907 : 0 : void bpf_warn_invalid_xdp_action(u32 act)
6908 : : {
6909 : : const u32 act_max = XDP_REDIRECT;
6910 : :
6911 [ # # # # ]: 0 : WARN_ONCE(1, "%s XDP return value %u, expect packet loss!\n",
6912 : : act > act_max ? "Illegal" : "Driver unsupported",
6913 : : act);
6914 : 0 : }
6915 : : EXPORT_SYMBOL_GPL(bpf_warn_invalid_xdp_action);
6916 : :
6917 : 0 : static bool sock_addr_is_valid_access(int off, int size,
6918 : : enum bpf_access_type type,
6919 : : const struct bpf_prog *prog,
6920 : : struct bpf_insn_access_aux *info)
6921 : : {
6922 : : const int size_default = sizeof(__u32);
6923 : :
6924 [ # # ]: 0 : if (off < 0 || off >= sizeof(struct bpf_sock_addr))
6925 : : return false;
6926 [ # # ]: 0 : if (off % size != 0)
6927 : : return false;
6928 : :
6929 : : /* Disallow access to IPv6 fields from IPv4 contex and vise
6930 : : * versa.
6931 : : */
6932 [ # # # # : 0 : switch (off) {
# ]
6933 : : case bpf_ctx_range(struct bpf_sock_addr, user_ip4):
6934 [ # # ]: 0 : switch (prog->expected_attach_type) {
6935 : : case BPF_CGROUP_INET4_BIND:
6936 : : case BPF_CGROUP_INET4_CONNECT:
6937 : : case BPF_CGROUP_UDP4_SENDMSG:
6938 : : case BPF_CGROUP_UDP4_RECVMSG:
6939 : : break;
6940 : : default:
6941 : : return false;
6942 : : }
6943 : : break;
6944 : : case bpf_ctx_range_till(struct bpf_sock_addr, user_ip6[0], user_ip6[3]):
6945 [ # # ]: 0 : switch (prog->expected_attach_type) {
6946 : : case BPF_CGROUP_INET6_BIND:
6947 : : case BPF_CGROUP_INET6_CONNECT:
6948 : : case BPF_CGROUP_UDP6_SENDMSG:
6949 : : case BPF_CGROUP_UDP6_RECVMSG:
6950 : : break;
6951 : : default:
6952 : : return false;
6953 : : }
6954 : : break;
6955 : : case bpf_ctx_range(struct bpf_sock_addr, msg_src_ip4):
6956 [ # # ]: 0 : switch (prog->expected_attach_type) {
6957 : : case BPF_CGROUP_UDP4_SENDMSG:
6958 : : break;
6959 : : default:
6960 : : return false;
6961 : : }
6962 : : break;
6963 : : case bpf_ctx_range_till(struct bpf_sock_addr, msg_src_ip6[0],
6964 : : msg_src_ip6[3]):
6965 [ # # ]: 0 : switch (prog->expected_attach_type) {
6966 : : case BPF_CGROUP_UDP6_SENDMSG:
6967 : : break;
6968 : : default:
6969 : : return false;
6970 : : }
6971 : : break;
6972 : : }
6973 : :
6974 [ # # # # ]: 0 : switch (off) {
6975 : : case bpf_ctx_range(struct bpf_sock_addr, user_ip4):
6976 : : case bpf_ctx_range_till(struct bpf_sock_addr, user_ip6[0], user_ip6[3]):
6977 : : case bpf_ctx_range(struct bpf_sock_addr, msg_src_ip4):
6978 : : case bpf_ctx_range_till(struct bpf_sock_addr, msg_src_ip6[0],
6979 : : msg_src_ip6[3]):
6980 [ # # ]: 0 : if (type == BPF_READ) {
6981 : : bpf_ctx_record_field_size(info, size_default);
6982 : :
6983 [ # # # # : 0 : if (bpf_ctx_wide_access_ok(off, size,
# # ]
6984 : : struct bpf_sock_addr,
6985 : : user_ip6))
6986 : : return true;
6987 : :
6988 [ # # # # : 0 : if (bpf_ctx_wide_access_ok(off, size,
# # ]
6989 : : struct bpf_sock_addr,
6990 : : msg_src_ip6))
6991 : : return true;
6992 : :
6993 [ # # ]: 0 : if (!bpf_ctx_narrow_access_ok(off, size, size_default))
6994 : : return false;
6995 : : } else {
6996 [ # # # # : 0 : if (bpf_ctx_wide_access_ok(off, size,
# # ]
6997 : : struct bpf_sock_addr,
6998 : : user_ip6))
6999 : : return true;
7000 : :
7001 [ # # # # : 0 : if (bpf_ctx_wide_access_ok(off, size,
# # ]
7002 : : struct bpf_sock_addr,
7003 : : msg_src_ip6))
7004 : : return true;
7005 : :
7006 [ # # ]: 0 : if (size != size_default)
7007 : : return false;
7008 : : }
7009 : : break;
7010 : : case bpf_ctx_range(struct bpf_sock_addr, user_port):
7011 [ # # ]: 0 : if (size != size_default)
7012 : : return false;
7013 : : break;
7014 : : case offsetof(struct bpf_sock_addr, sk):
7015 [ # # ]: 0 : if (type != BPF_READ)
7016 : : return false;
7017 [ # # ]: 0 : if (size != sizeof(__u64))
7018 : : return false;
7019 : 0 : info->reg_type = PTR_TO_SOCKET;
7020 : 0 : break;
7021 : : default:
7022 [ # # ]: 0 : if (type == BPF_READ) {
7023 [ # # ]: 0 : if (size != size_default)
7024 : : return false;
7025 : : } else {
7026 : : return false;
7027 : : }
7028 : : }
7029 : :
7030 : : return true;
7031 : : }
7032 : :
7033 : 0 : static bool sock_ops_is_valid_access(int off, int size,
7034 : : enum bpf_access_type type,
7035 : : const struct bpf_prog *prog,
7036 : : struct bpf_insn_access_aux *info)
7037 : : {
7038 : : const int size_default = sizeof(__u32);
7039 : :
7040 [ # # ]: 0 : if (off < 0 || off >= sizeof(struct bpf_sock_ops))
7041 : : return false;
7042 : :
7043 : : /* The verifier guarantees that size > 0. */
7044 [ # # ]: 0 : if (off % size != 0)
7045 : : return false;
7046 : :
7047 [ # # ]: 0 : if (type == BPF_WRITE) {
7048 [ # # ]: 0 : switch (off) {
7049 : : case offsetof(struct bpf_sock_ops, reply):
7050 : : case offsetof(struct bpf_sock_ops, sk_txhash):
7051 [ # # ]: 0 : if (size != size_default)
7052 : : return false;
7053 : : break;
7054 : : default:
7055 : : return false;
7056 : : }
7057 : : } else {
7058 [ # # # ]: 0 : switch (off) {
7059 : : case bpf_ctx_range_till(struct bpf_sock_ops, bytes_received,
7060 : : bytes_acked):
7061 [ # # ]: 0 : if (size != sizeof(__u64))
7062 : : return false;
7063 : : break;
7064 : : case offsetof(struct bpf_sock_ops, sk):
7065 [ # # ]: 0 : if (size != sizeof(__u64))
7066 : : return false;
7067 : 0 : info->reg_type = PTR_TO_SOCKET_OR_NULL;
7068 : 0 : break;
7069 : : default:
7070 [ # # ]: 0 : if (size != size_default)
7071 : : return false;
7072 : : break;
7073 : : }
7074 : : }
7075 : :
7076 : : return true;
7077 : : }
7078 : :
7079 : 0 : static int sk_skb_prologue(struct bpf_insn *insn_buf, bool direct_write,
7080 : : const struct bpf_prog *prog)
7081 : : {
7082 : 0 : return bpf_unclone_prologue(insn_buf, direct_write, prog, SK_DROP);
7083 : : }
7084 : :
7085 : 0 : static bool sk_skb_is_valid_access(int off, int size,
7086 : : enum bpf_access_type type,
7087 : : const struct bpf_prog *prog,
7088 : : struct bpf_insn_access_aux *info)
7089 : : {
7090 [ # # ]: 0 : switch (off) {
7091 : : case bpf_ctx_range(struct __sk_buff, tc_classid):
7092 : : case bpf_ctx_range(struct __sk_buff, data_meta):
7093 : : case bpf_ctx_range(struct __sk_buff, tstamp):
7094 : : case bpf_ctx_range(struct __sk_buff, wire_len):
7095 : : return false;
7096 : : }
7097 : :
7098 [ # # ]: 0 : if (type == BPF_WRITE) {
7099 [ # # ]: 0 : switch (off) {
7100 : : case bpf_ctx_range(struct __sk_buff, tc_index):
7101 : : case bpf_ctx_range(struct __sk_buff, priority):
7102 : : break;
7103 : : default:
7104 : : return false;
7105 : : }
7106 : : }
7107 : :
7108 [ # # # # ]: 0 : switch (off) {
7109 : : case bpf_ctx_range(struct __sk_buff, mark):
7110 : : return false;
7111 : : case bpf_ctx_range(struct __sk_buff, data):
7112 : 0 : info->reg_type = PTR_TO_PACKET;
7113 : 0 : break;
7114 : : case bpf_ctx_range(struct __sk_buff, data_end):
7115 : 0 : info->reg_type = PTR_TO_PACKET_END;
7116 : 0 : break;
7117 : : }
7118 : :
7119 : 0 : return bpf_skb_is_valid_access(off, size, type, prog, info);
7120 : : }
7121 : :
7122 : 0 : static bool sk_msg_is_valid_access(int off, int size,
7123 : : enum bpf_access_type type,
7124 : : const struct bpf_prog *prog,
7125 : : struct bpf_insn_access_aux *info)
7126 : : {
7127 [ # # ]: 0 : if (type == BPF_WRITE)
7128 : : return false;
7129 : :
7130 [ # # ]: 0 : if (off % size != 0)
7131 : : return false;
7132 : :
7133 [ # # # # ]: 0 : switch (off) {
7134 : : case offsetof(struct sk_msg_md, data):
7135 : 0 : info->reg_type = PTR_TO_PACKET;
7136 [ # # ]: 0 : if (size != sizeof(__u64))
7137 : : return false;
7138 : : break;
7139 : : case offsetof(struct sk_msg_md, data_end):
7140 : 0 : info->reg_type = PTR_TO_PACKET_END;
7141 [ # # ]: 0 : if (size != sizeof(__u64))
7142 : : return false;
7143 : : break;
7144 : : case bpf_ctx_range(struct sk_msg_md, family):
7145 : : case bpf_ctx_range(struct sk_msg_md, remote_ip4):
7146 : : case bpf_ctx_range(struct sk_msg_md, local_ip4):
7147 : : case bpf_ctx_range_till(struct sk_msg_md, remote_ip6[0], remote_ip6[3]):
7148 : : case bpf_ctx_range_till(struct sk_msg_md, local_ip6[0], local_ip6[3]):
7149 : : case bpf_ctx_range(struct sk_msg_md, remote_port):
7150 : : case bpf_ctx_range(struct sk_msg_md, local_port):
7151 : : case bpf_ctx_range(struct sk_msg_md, size):
7152 [ # # ]: 0 : if (size != sizeof(__u32))
7153 : : return false;
7154 : : break;
7155 : : default:
7156 : : return false;
7157 : : }
7158 : : return true;
7159 : : }
7160 : :
7161 : 0 : static bool flow_dissector_is_valid_access(int off, int size,
7162 : : enum bpf_access_type type,
7163 : : const struct bpf_prog *prog,
7164 : : struct bpf_insn_access_aux *info)
7165 : : {
7166 : : const int size_default = sizeof(__u32);
7167 : :
7168 [ # # ]: 0 : if (off < 0 || off >= sizeof(struct __sk_buff))
7169 : : return false;
7170 : :
7171 [ # # ]: 0 : if (type == BPF_WRITE)
7172 : : return false;
7173 : :
7174 [ # # # # ]: 0 : switch (off) {
7175 : : case bpf_ctx_range(struct __sk_buff, data):
7176 [ # # ]: 0 : if (size != size_default)
7177 : : return false;
7178 : 0 : info->reg_type = PTR_TO_PACKET;
7179 : 0 : return true;
7180 : : case bpf_ctx_range(struct __sk_buff, data_end):
7181 [ # # ]: 0 : if (size != size_default)
7182 : : return false;
7183 : 0 : info->reg_type = PTR_TO_PACKET_END;
7184 : 0 : return true;
7185 : : case bpf_ctx_range_ptr(struct __sk_buff, flow_keys):
7186 [ # # ]: 0 : if (size != sizeof(__u64))
7187 : : return false;
7188 : 0 : info->reg_type = PTR_TO_FLOW_KEYS;
7189 : 0 : return true;
7190 : : default:
7191 : : return false;
7192 : : }
7193 : : }
7194 : :
7195 : 0 : static u32 flow_dissector_convert_ctx_access(enum bpf_access_type type,
7196 : : const struct bpf_insn *si,
7197 : : struct bpf_insn *insn_buf,
7198 : : struct bpf_prog *prog,
7199 : : u32 *target_size)
7200 : :
7201 : : {
7202 : : struct bpf_insn *insn = insn_buf;
7203 : :
7204 [ # # # # ]: 0 : switch (si->off) {
7205 : : case offsetof(struct __sk_buff, data):
7206 : 0 : *insn++ = BPF_LDX_MEM(BPF_FIELD_SIZEOF(struct bpf_flow_dissector, data),
7207 : : si->dst_reg, si->src_reg,
7208 : : offsetof(struct bpf_flow_dissector, data));
7209 : 0 : break;
7210 : :
7211 : : case offsetof(struct __sk_buff, data_end):
7212 : 0 : *insn++ = BPF_LDX_MEM(BPF_FIELD_SIZEOF(struct bpf_flow_dissector, data_end),
7213 : : si->dst_reg, si->src_reg,
7214 : : offsetof(struct bpf_flow_dissector, data_end));
7215 : 0 : break;
7216 : :
7217 : : case offsetof(struct __sk_buff, flow_keys):
7218 : 0 : *insn++ = BPF_LDX_MEM(BPF_FIELD_SIZEOF(struct bpf_flow_dissector, flow_keys),
7219 : : si->dst_reg, si->src_reg,
7220 : : offsetof(struct bpf_flow_dissector, flow_keys));
7221 : 0 : break;
7222 : : }
7223 : :
7224 : 0 : return insn - insn_buf;
7225 : : }
7226 : :
7227 : 1242 : static u32 bpf_convert_ctx_access(enum bpf_access_type type,
7228 : : const struct bpf_insn *si,
7229 : : struct bpf_insn *insn_buf,
7230 : : struct bpf_prog *prog, u32 *target_size)
7231 : : {
7232 : : struct bpf_insn *insn = insn_buf;
7233 : : int off;
7234 : :
7235 [ - + - - : 1242 : switch (si->off) {
- - - - -
- - - - -
- - - - -
- - - - -
- - - - -
- - ]
7236 : : case offsetof(struct __sk_buff, len):
7237 : 0 : *insn++ = BPF_LDX_MEM(BPF_W, si->dst_reg, si->src_reg,
7238 : : bpf_target_off(struct sk_buff, len, 4,
7239 : : target_size));
7240 : 0 : break;
7241 : :
7242 : : case offsetof(struct __sk_buff, protocol):
7243 : 1242 : *insn++ = BPF_LDX_MEM(BPF_H, si->dst_reg, si->src_reg,
7244 : : bpf_target_off(struct sk_buff, protocol, 2,
7245 : : target_size));
7246 : 1242 : break;
7247 : :
7248 : : case offsetof(struct __sk_buff, vlan_proto):
7249 : 0 : *insn++ = BPF_LDX_MEM(BPF_H, si->dst_reg, si->src_reg,
7250 : : bpf_target_off(struct sk_buff, vlan_proto, 2,
7251 : : target_size));
7252 : 0 : break;
7253 : :
7254 : : case offsetof(struct __sk_buff, priority):
7255 [ # # ]: 0 : if (type == BPF_WRITE)
7256 : 0 : *insn++ = BPF_STX_MEM(BPF_W, si->dst_reg, si->src_reg,
7257 : : bpf_target_off(struct sk_buff, priority, 4,
7258 : : target_size));
7259 : : else
7260 : 0 : *insn++ = BPF_LDX_MEM(BPF_W, si->dst_reg, si->src_reg,
7261 : : bpf_target_off(struct sk_buff, priority, 4,
7262 : : target_size));
7263 : : break;
7264 : :
7265 : : case offsetof(struct __sk_buff, ingress_ifindex):
7266 : 0 : *insn++ = BPF_LDX_MEM(BPF_W, si->dst_reg, si->src_reg,
7267 : : bpf_target_off(struct sk_buff, skb_iif, 4,
7268 : : target_size));
7269 : 0 : break;
7270 : :
7271 : : case offsetof(struct __sk_buff, ifindex):
7272 : 0 : *insn++ = BPF_LDX_MEM(BPF_FIELD_SIZEOF(struct sk_buff, dev),
7273 : : si->dst_reg, si->src_reg,
7274 : : offsetof(struct sk_buff, dev));
7275 : 0 : *insn++ = BPF_JMP_IMM(BPF_JEQ, si->dst_reg, 0, 1);
7276 : 0 : *insn++ = BPF_LDX_MEM(BPF_W, si->dst_reg, si->dst_reg,
7277 : : bpf_target_off(struct net_device, ifindex, 4,
7278 : : target_size));
7279 : 0 : break;
7280 : :
7281 : : case offsetof(struct __sk_buff, hash):
7282 : 0 : *insn++ = BPF_LDX_MEM(BPF_W, si->dst_reg, si->src_reg,
7283 : : bpf_target_off(struct sk_buff, hash, 4,
7284 : : target_size));
7285 : 0 : break;
7286 : :
7287 : : case offsetof(struct __sk_buff, mark):
7288 [ # # ]: 0 : if (type == BPF_WRITE)
7289 : 0 : *insn++ = BPF_STX_MEM(BPF_W, si->dst_reg, si->src_reg,
7290 : : bpf_target_off(struct sk_buff, mark, 4,
7291 : : target_size));
7292 : : else
7293 : 0 : *insn++ = BPF_LDX_MEM(BPF_W, si->dst_reg, si->src_reg,
7294 : : bpf_target_off(struct sk_buff, mark, 4,
7295 : : target_size));
7296 : : break;
7297 : :
7298 : : case offsetof(struct __sk_buff, pkt_type):
7299 : 0 : *target_size = 1;
7300 : 0 : *insn++ = BPF_LDX_MEM(BPF_B, si->dst_reg, si->src_reg,
7301 : : PKT_TYPE_OFFSET());
7302 : 0 : *insn++ = BPF_ALU32_IMM(BPF_AND, si->dst_reg, PKT_TYPE_MAX);
7303 : : #ifdef __BIG_ENDIAN_BITFIELD
7304 : : *insn++ = BPF_ALU32_IMM(BPF_RSH, si->dst_reg, 5);
7305 : : #endif
7306 : 0 : break;
7307 : :
7308 : : case offsetof(struct __sk_buff, queue_mapping):
7309 [ # # ]: 0 : if (type == BPF_WRITE) {
7310 : 0 : *insn++ = BPF_JMP_IMM(BPF_JGE, si->src_reg, NO_QUEUE_MAPPING, 1);
7311 : 0 : *insn++ = BPF_STX_MEM(BPF_H, si->dst_reg, si->src_reg,
7312 : : bpf_target_off(struct sk_buff,
7313 : : queue_mapping,
7314 : : 2, target_size));
7315 : : } else {
7316 : 0 : *insn++ = BPF_LDX_MEM(BPF_H, si->dst_reg, si->src_reg,
7317 : : bpf_target_off(struct sk_buff,
7318 : : queue_mapping,
7319 : : 2, target_size));
7320 : : }
7321 : : break;
7322 : :
7323 : : case offsetof(struct __sk_buff, vlan_present):
7324 : 0 : *target_size = 1;
7325 : 0 : *insn++ = BPF_LDX_MEM(BPF_B, si->dst_reg, si->src_reg,
7326 : : PKT_VLAN_PRESENT_OFFSET());
7327 : : if (PKT_VLAN_PRESENT_BIT)
7328 : : *insn++ = BPF_ALU32_IMM(BPF_RSH, si->dst_reg, PKT_VLAN_PRESENT_BIT);
7329 : : if (PKT_VLAN_PRESENT_BIT < 7)
7330 : 0 : *insn++ = BPF_ALU32_IMM(BPF_AND, si->dst_reg, 1);
7331 : : break;
7332 : :
7333 : : case offsetof(struct __sk_buff, vlan_tci):
7334 : 0 : *insn++ = BPF_LDX_MEM(BPF_H, si->dst_reg, si->src_reg,
7335 : : bpf_target_off(struct sk_buff, vlan_tci, 2,
7336 : : target_size));
7337 : 0 : break;
7338 : :
7339 : : case offsetof(struct __sk_buff, cb[0]) ...
7340 : : offsetofend(struct __sk_buff, cb[4]) - 1:
7341 : : BUILD_BUG_ON(FIELD_SIZEOF(struct qdisc_skb_cb, data) < 20);
7342 : : BUILD_BUG_ON((offsetof(struct sk_buff, cb) +
7343 : : offsetof(struct qdisc_skb_cb, data)) %
7344 : : sizeof(__u64));
7345 : :
7346 : 0 : prog->cb_access = 1;
7347 : 0 : off = si->off;
7348 : 0 : off -= offsetof(struct __sk_buff, cb[0]);
7349 : 0 : off += offsetof(struct sk_buff, cb);
7350 : 0 : off += offsetof(struct qdisc_skb_cb, data);
7351 [ # # ]: 0 : if (type == BPF_WRITE)
7352 : 0 : *insn++ = BPF_STX_MEM(BPF_SIZE(si->code), si->dst_reg,
7353 : : si->src_reg, off);
7354 : : else
7355 : 0 : *insn++ = BPF_LDX_MEM(BPF_SIZE(si->code), si->dst_reg,
7356 : : si->src_reg, off);
7357 : : break;
7358 : :
7359 : : case offsetof(struct __sk_buff, tc_classid):
7360 : : BUILD_BUG_ON(FIELD_SIZEOF(struct qdisc_skb_cb, tc_classid) != 2);
7361 : :
7362 : : off = si->off;
7363 : 0 : off -= offsetof(struct __sk_buff, tc_classid);
7364 : 0 : off += offsetof(struct sk_buff, cb);
7365 : 0 : off += offsetof(struct qdisc_skb_cb, tc_classid);
7366 : 0 : *target_size = 2;
7367 [ # # ]: 0 : if (type == BPF_WRITE)
7368 : 0 : *insn++ = BPF_STX_MEM(BPF_H, si->dst_reg,
7369 : : si->src_reg, off);
7370 : : else
7371 : 0 : *insn++ = BPF_LDX_MEM(BPF_H, si->dst_reg,
7372 : : si->src_reg, off);
7373 : : break;
7374 : :
7375 : : case offsetof(struct __sk_buff, data):
7376 : 0 : *insn++ = BPF_LDX_MEM(BPF_FIELD_SIZEOF(struct sk_buff, data),
7377 : : si->dst_reg, si->src_reg,
7378 : : offsetof(struct sk_buff, data));
7379 : 0 : break;
7380 : :
7381 : : case offsetof(struct __sk_buff, data_meta):
7382 : : off = si->off;
7383 : 0 : off -= offsetof(struct __sk_buff, data_meta);
7384 : 0 : off += offsetof(struct sk_buff, cb);
7385 : 0 : off += offsetof(struct bpf_skb_data_end, data_meta);
7386 : 0 : *insn++ = BPF_LDX_MEM(BPF_SIZEOF(void *), si->dst_reg,
7387 : : si->src_reg, off);
7388 : 0 : break;
7389 : :
7390 : : case offsetof(struct __sk_buff, data_end):
7391 : : off = si->off;
7392 : 0 : off -= offsetof(struct __sk_buff, data_end);
7393 : 0 : off += offsetof(struct sk_buff, cb);
7394 : 0 : off += offsetof(struct bpf_skb_data_end, data_end);
7395 : 0 : *insn++ = BPF_LDX_MEM(BPF_SIZEOF(void *), si->dst_reg,
7396 : : si->src_reg, off);
7397 : 0 : break;
7398 : :
7399 : : case offsetof(struct __sk_buff, tc_index):
7400 : : #ifdef CONFIG_NET_SCHED
7401 [ # # ]: 0 : if (type == BPF_WRITE)
7402 : 0 : *insn++ = BPF_STX_MEM(BPF_H, si->dst_reg, si->src_reg,
7403 : : bpf_target_off(struct sk_buff, tc_index, 2,
7404 : : target_size));
7405 : : else
7406 : 0 : *insn++ = BPF_LDX_MEM(BPF_H, si->dst_reg, si->src_reg,
7407 : : bpf_target_off(struct sk_buff, tc_index, 2,
7408 : : target_size));
7409 : : #else
7410 : : *target_size = 2;
7411 : : if (type == BPF_WRITE)
7412 : : *insn++ = BPF_MOV64_REG(si->dst_reg, si->dst_reg);
7413 : : else
7414 : : *insn++ = BPF_MOV64_IMM(si->dst_reg, 0);
7415 : : #endif
7416 : : break;
7417 : :
7418 : : case offsetof(struct __sk_buff, napi_id):
7419 : : #if defined(CONFIG_NET_RX_BUSY_POLL)
7420 : 0 : *insn++ = BPF_LDX_MEM(BPF_W, si->dst_reg, si->src_reg,
7421 : : bpf_target_off(struct sk_buff, napi_id, 4,
7422 : : target_size));
7423 : 0 : *insn++ = BPF_JMP_IMM(BPF_JGE, si->dst_reg, MIN_NAPI_ID, 1);
7424 : 0 : *insn++ = BPF_MOV64_IMM(si->dst_reg, 0);
7425 : : #else
7426 : : *target_size = 4;
7427 : : *insn++ = BPF_MOV64_IMM(si->dst_reg, 0);
7428 : : #endif
7429 : 0 : break;
7430 : : case offsetof(struct __sk_buff, family):
7431 : : BUILD_BUG_ON(FIELD_SIZEOF(struct sock_common, skc_family) != 2);
7432 : :
7433 : 0 : *insn++ = BPF_LDX_MEM(BPF_FIELD_SIZEOF(struct sk_buff, sk),
7434 : : si->dst_reg, si->src_reg,
7435 : : offsetof(struct sk_buff, sk));
7436 : 0 : *insn++ = BPF_LDX_MEM(BPF_H, si->dst_reg, si->dst_reg,
7437 : : bpf_target_off(struct sock_common,
7438 : : skc_family,
7439 : : 2, target_size));
7440 : 0 : break;
7441 : : case offsetof(struct __sk_buff, remote_ip4):
7442 : : BUILD_BUG_ON(FIELD_SIZEOF(struct sock_common, skc_daddr) != 4);
7443 : :
7444 : 0 : *insn++ = BPF_LDX_MEM(BPF_FIELD_SIZEOF(struct sk_buff, sk),
7445 : : si->dst_reg, si->src_reg,
7446 : : offsetof(struct sk_buff, sk));
7447 : 0 : *insn++ = BPF_LDX_MEM(BPF_W, si->dst_reg, si->dst_reg,
7448 : : bpf_target_off(struct sock_common,
7449 : : skc_daddr,
7450 : : 4, target_size));
7451 : 0 : break;
7452 : : case offsetof(struct __sk_buff, local_ip4):
7453 : : BUILD_BUG_ON(FIELD_SIZEOF(struct sock_common,
7454 : : skc_rcv_saddr) != 4);
7455 : :
7456 : 0 : *insn++ = BPF_LDX_MEM(BPF_FIELD_SIZEOF(struct sk_buff, sk),
7457 : : si->dst_reg, si->src_reg,
7458 : : offsetof(struct sk_buff, sk));
7459 : 0 : *insn++ = BPF_LDX_MEM(BPF_W, si->dst_reg, si->dst_reg,
7460 : : bpf_target_off(struct sock_common,
7461 : : skc_rcv_saddr,
7462 : : 4, target_size));
7463 : 0 : break;
7464 : : case offsetof(struct __sk_buff, remote_ip6[0]) ...
7465 : : offsetof(struct __sk_buff, remote_ip6[3]):
7466 : : #if IS_ENABLED(CONFIG_IPV6)
7467 : : BUILD_BUG_ON(FIELD_SIZEOF(struct sock_common,
7468 : : skc_v6_daddr.s6_addr32[0]) != 4);
7469 : :
7470 : : off = si->off;
7471 : 0 : off -= offsetof(struct __sk_buff, remote_ip6[0]);
7472 : :
7473 : 0 : *insn++ = BPF_LDX_MEM(BPF_FIELD_SIZEOF(struct sk_buff, sk),
7474 : : si->dst_reg, si->src_reg,
7475 : : offsetof(struct sk_buff, sk));
7476 : 0 : *insn++ = BPF_LDX_MEM(BPF_W, si->dst_reg, si->dst_reg,
7477 : : offsetof(struct sock_common,
7478 : : skc_v6_daddr.s6_addr32[0]) +
7479 : : off);
7480 : : #else
7481 : : *insn++ = BPF_MOV32_IMM(si->dst_reg, 0);
7482 : : #endif
7483 : 0 : break;
7484 : : case offsetof(struct __sk_buff, local_ip6[0]) ...
7485 : : offsetof(struct __sk_buff, local_ip6[3]):
7486 : : #if IS_ENABLED(CONFIG_IPV6)
7487 : : BUILD_BUG_ON(FIELD_SIZEOF(struct sock_common,
7488 : : skc_v6_rcv_saddr.s6_addr32[0]) != 4);
7489 : :
7490 : : off = si->off;
7491 : 0 : off -= offsetof(struct __sk_buff, local_ip6[0]);
7492 : :
7493 : 0 : *insn++ = BPF_LDX_MEM(BPF_FIELD_SIZEOF(struct sk_buff, sk),
7494 : : si->dst_reg, si->src_reg,
7495 : : offsetof(struct sk_buff, sk));
7496 : 0 : *insn++ = BPF_LDX_MEM(BPF_W, si->dst_reg, si->dst_reg,
7497 : : offsetof(struct sock_common,
7498 : : skc_v6_rcv_saddr.s6_addr32[0]) +
7499 : : off);
7500 : : #else
7501 : : *insn++ = BPF_MOV32_IMM(si->dst_reg, 0);
7502 : : #endif
7503 : 0 : break;
7504 : :
7505 : : case offsetof(struct __sk_buff, remote_port):
7506 : : BUILD_BUG_ON(FIELD_SIZEOF(struct sock_common, skc_dport) != 2);
7507 : :
7508 : 0 : *insn++ = BPF_LDX_MEM(BPF_FIELD_SIZEOF(struct sk_buff, sk),
7509 : : si->dst_reg, si->src_reg,
7510 : : offsetof(struct sk_buff, sk));
7511 : 0 : *insn++ = BPF_LDX_MEM(BPF_H, si->dst_reg, si->dst_reg,
7512 : : bpf_target_off(struct sock_common,
7513 : : skc_dport,
7514 : : 2, target_size));
7515 : : #ifndef __BIG_ENDIAN_BITFIELD
7516 : 0 : *insn++ = BPF_ALU32_IMM(BPF_LSH, si->dst_reg, 16);
7517 : : #endif
7518 : 0 : break;
7519 : :
7520 : : case offsetof(struct __sk_buff, local_port):
7521 : : BUILD_BUG_ON(FIELD_SIZEOF(struct sock_common, skc_num) != 2);
7522 : :
7523 : 0 : *insn++ = BPF_LDX_MEM(BPF_FIELD_SIZEOF(struct sk_buff, sk),
7524 : : si->dst_reg, si->src_reg,
7525 : : offsetof(struct sk_buff, sk));
7526 : 0 : *insn++ = BPF_LDX_MEM(BPF_H, si->dst_reg, si->dst_reg,
7527 : : bpf_target_off(struct sock_common,
7528 : : skc_num, 2, target_size));
7529 : 0 : break;
7530 : :
7531 : : case offsetof(struct __sk_buff, tstamp):
7532 : : BUILD_BUG_ON(FIELD_SIZEOF(struct sk_buff, tstamp) != 8);
7533 : :
7534 [ # # ]: 0 : if (type == BPF_WRITE)
7535 : 0 : *insn++ = BPF_STX_MEM(BPF_DW,
7536 : : si->dst_reg, si->src_reg,
7537 : : bpf_target_off(struct sk_buff,
7538 : : tstamp, 8,
7539 : : target_size));
7540 : : else
7541 : 0 : *insn++ = BPF_LDX_MEM(BPF_DW,
7542 : : si->dst_reg, si->src_reg,
7543 : : bpf_target_off(struct sk_buff,
7544 : : tstamp, 8,
7545 : : target_size));
7546 : : break;
7547 : :
7548 : : case offsetof(struct __sk_buff, gso_segs):
7549 : : /* si->dst_reg = skb_shinfo(SKB); */
7550 : : #ifdef NET_SKBUFF_DATA_USES_OFFSET
7551 : : *insn++ = BPF_LDX_MEM(BPF_FIELD_SIZEOF(struct sk_buff, end),
7552 : : BPF_REG_AX, si->src_reg,
7553 : : offsetof(struct sk_buff, end));
7554 : : *insn++ = BPF_LDX_MEM(BPF_FIELD_SIZEOF(struct sk_buff, head),
7555 : : si->dst_reg, si->src_reg,
7556 : : offsetof(struct sk_buff, head));
7557 : : *insn++ = BPF_ALU64_REG(BPF_ADD, si->dst_reg, BPF_REG_AX);
7558 : : #else
7559 : 0 : *insn++ = BPF_LDX_MEM(BPF_FIELD_SIZEOF(struct sk_buff, end),
7560 : : si->dst_reg, si->src_reg,
7561 : : offsetof(struct sk_buff, end));
7562 : : #endif
7563 : 0 : *insn++ = BPF_LDX_MEM(BPF_FIELD_SIZEOF(struct skb_shared_info, gso_segs),
7564 : : si->dst_reg, si->dst_reg,
7565 : : bpf_target_off(struct skb_shared_info,
7566 : : gso_segs, 2,
7567 : : target_size));
7568 : 0 : break;
7569 : : case offsetof(struct __sk_buff, wire_len):
7570 : : BUILD_BUG_ON(FIELD_SIZEOF(struct qdisc_skb_cb, pkt_len) != 4);
7571 : :
7572 : : off = si->off;
7573 : 0 : off -= offsetof(struct __sk_buff, wire_len);
7574 : 0 : off += offsetof(struct sk_buff, cb);
7575 : : off += offsetof(struct qdisc_skb_cb, pkt_len);
7576 : 0 : *target_size = 4;
7577 : 0 : *insn++ = BPF_LDX_MEM(BPF_W, si->dst_reg, si->src_reg, off);
7578 : 0 : break;
7579 : :
7580 : : case offsetof(struct __sk_buff, sk):
7581 : 0 : *insn++ = BPF_LDX_MEM(BPF_FIELD_SIZEOF(struct sk_buff, sk),
7582 : : si->dst_reg, si->src_reg,
7583 : : offsetof(struct sk_buff, sk));
7584 : 0 : break;
7585 : : }
7586 : :
7587 : 1242 : return insn - insn_buf;
7588 : : }
7589 : :
7590 : 0 : u32 bpf_sock_convert_ctx_access(enum bpf_access_type type,
7591 : : const struct bpf_insn *si,
7592 : : struct bpf_insn *insn_buf,
7593 : : struct bpf_prog *prog, u32 *target_size)
7594 : : {
7595 : : struct bpf_insn *insn = insn_buf;
7596 : : int off;
7597 : :
7598 [ # # # # : 0 : switch (si->off) {
# # # # #
# # # #
# ]
7599 : : case offsetof(struct bpf_sock, bound_dev_if):
7600 : : BUILD_BUG_ON(FIELD_SIZEOF(struct sock, sk_bound_dev_if) != 4);
7601 : :
7602 [ # # ]: 0 : if (type == BPF_WRITE)
7603 : 0 : *insn++ = BPF_STX_MEM(BPF_W, si->dst_reg, si->src_reg,
7604 : : offsetof(struct sock, sk_bound_dev_if));
7605 : : else
7606 : 0 : *insn++ = BPF_LDX_MEM(BPF_W, si->dst_reg, si->src_reg,
7607 : : offsetof(struct sock, sk_bound_dev_if));
7608 : : break;
7609 : :
7610 : : case offsetof(struct bpf_sock, mark):
7611 : : BUILD_BUG_ON(FIELD_SIZEOF(struct sock, sk_mark) != 4);
7612 : :
7613 [ # # ]: 0 : if (type == BPF_WRITE)
7614 : 0 : *insn++ = BPF_STX_MEM(BPF_W, si->dst_reg, si->src_reg,
7615 : : offsetof(struct sock, sk_mark));
7616 : : else
7617 : 0 : *insn++ = BPF_LDX_MEM(BPF_W, si->dst_reg, si->src_reg,
7618 : : offsetof(struct sock, sk_mark));
7619 : : break;
7620 : :
7621 : : case offsetof(struct bpf_sock, priority):
7622 : : BUILD_BUG_ON(FIELD_SIZEOF(struct sock, sk_priority) != 4);
7623 : :
7624 [ # # ]: 0 : if (type == BPF_WRITE)
7625 : 0 : *insn++ = BPF_STX_MEM(BPF_W, si->dst_reg, si->src_reg,
7626 : : offsetof(struct sock, sk_priority));
7627 : : else
7628 : 0 : *insn++ = BPF_LDX_MEM(BPF_W, si->dst_reg, si->src_reg,
7629 : : offsetof(struct sock, sk_priority));
7630 : : break;
7631 : :
7632 : : case offsetof(struct bpf_sock, family):
7633 : 0 : *insn++ = BPF_LDX_MEM(
7634 : : BPF_FIELD_SIZEOF(struct sock_common, skc_family),
7635 : : si->dst_reg, si->src_reg,
7636 : : bpf_target_off(struct sock_common,
7637 : : skc_family,
7638 : : FIELD_SIZEOF(struct sock_common,
7639 : : skc_family),
7640 : : target_size));
7641 : 0 : break;
7642 : :
7643 : : case offsetof(struct bpf_sock, type):
7644 : : BUILD_BUG_ON(HWEIGHT32(SK_FL_TYPE_MASK) != BITS_PER_BYTE * 2);
7645 : 0 : *insn++ = BPF_LDX_MEM(BPF_W, si->dst_reg, si->src_reg,
7646 : : offsetof(struct sock, __sk_flags_offset));
7647 : 0 : *insn++ = BPF_ALU32_IMM(BPF_AND, si->dst_reg, SK_FL_TYPE_MASK);
7648 : 0 : *insn++ = BPF_ALU32_IMM(BPF_RSH, si->dst_reg, SK_FL_TYPE_SHIFT);
7649 : 0 : *target_size = 2;
7650 : 0 : break;
7651 : :
7652 : : case offsetof(struct bpf_sock, protocol):
7653 : : BUILD_BUG_ON(HWEIGHT32(SK_FL_PROTO_MASK) != BITS_PER_BYTE);
7654 : 0 : *insn++ = BPF_LDX_MEM(BPF_W, si->dst_reg, si->src_reg,
7655 : : offsetof(struct sock, __sk_flags_offset));
7656 : 0 : *insn++ = BPF_ALU32_IMM(BPF_AND, si->dst_reg, SK_FL_PROTO_MASK);
7657 : 0 : *insn++ = BPF_ALU32_IMM(BPF_RSH, si->dst_reg, SK_FL_PROTO_SHIFT);
7658 : 0 : *target_size = 1;
7659 : 0 : break;
7660 : :
7661 : : case offsetof(struct bpf_sock, src_ip4):
7662 : 0 : *insn++ = BPF_LDX_MEM(
7663 : : BPF_SIZE(si->code), si->dst_reg, si->src_reg,
7664 : : bpf_target_off(struct sock_common, skc_rcv_saddr,
7665 : : FIELD_SIZEOF(struct sock_common,
7666 : : skc_rcv_saddr),
7667 : : target_size));
7668 : 0 : break;
7669 : :
7670 : : case offsetof(struct bpf_sock, dst_ip4):
7671 : 0 : *insn++ = BPF_LDX_MEM(
7672 : : BPF_SIZE(si->code), si->dst_reg, si->src_reg,
7673 : : bpf_target_off(struct sock_common, skc_daddr,
7674 : : FIELD_SIZEOF(struct sock_common,
7675 : : skc_daddr),
7676 : : target_size));
7677 : 0 : break;
7678 : :
7679 : : case bpf_ctx_range_till(struct bpf_sock, src_ip6[0], src_ip6[3]):
7680 : : #if IS_ENABLED(CONFIG_IPV6)
7681 : : off = si->off;
7682 : 0 : off -= offsetof(struct bpf_sock, src_ip6[0]);
7683 : 0 : *insn++ = BPF_LDX_MEM(
7684 : : BPF_SIZE(si->code), si->dst_reg, si->src_reg,
7685 : : bpf_target_off(
7686 : : struct sock_common,
7687 : : skc_v6_rcv_saddr.s6_addr32[0],
7688 : : FIELD_SIZEOF(struct sock_common,
7689 : : skc_v6_rcv_saddr.s6_addr32[0]),
7690 : : target_size) + off);
7691 : : #else
7692 : : (void)off;
7693 : : *insn++ = BPF_MOV32_IMM(si->dst_reg, 0);
7694 : : #endif
7695 : 0 : break;
7696 : :
7697 : : case bpf_ctx_range_till(struct bpf_sock, dst_ip6[0], dst_ip6[3]):
7698 : : #if IS_ENABLED(CONFIG_IPV6)
7699 : : off = si->off;
7700 : 0 : off -= offsetof(struct bpf_sock, dst_ip6[0]);
7701 : 0 : *insn++ = BPF_LDX_MEM(
7702 : : BPF_SIZE(si->code), si->dst_reg, si->src_reg,
7703 : : bpf_target_off(struct sock_common,
7704 : : skc_v6_daddr.s6_addr32[0],
7705 : : FIELD_SIZEOF(struct sock_common,
7706 : : skc_v6_daddr.s6_addr32[0]),
7707 : : target_size) + off);
7708 : : #else
7709 : : *insn++ = BPF_MOV32_IMM(si->dst_reg, 0);
7710 : : *target_size = 4;
7711 : : #endif
7712 : 0 : break;
7713 : :
7714 : : case offsetof(struct bpf_sock, src_port):
7715 : 0 : *insn++ = BPF_LDX_MEM(
7716 : : BPF_FIELD_SIZEOF(struct sock_common, skc_num),
7717 : : si->dst_reg, si->src_reg,
7718 : : bpf_target_off(struct sock_common, skc_num,
7719 : : FIELD_SIZEOF(struct sock_common,
7720 : : skc_num),
7721 : : target_size));
7722 : 0 : break;
7723 : :
7724 : : case offsetof(struct bpf_sock, dst_port):
7725 : 0 : *insn++ = BPF_LDX_MEM(
7726 : : BPF_FIELD_SIZEOF(struct sock_common, skc_dport),
7727 : : si->dst_reg, si->src_reg,
7728 : : bpf_target_off(struct sock_common, skc_dport,
7729 : : FIELD_SIZEOF(struct sock_common,
7730 : : skc_dport),
7731 : : target_size));
7732 : 0 : break;
7733 : :
7734 : : case offsetof(struct bpf_sock, state):
7735 : 0 : *insn++ = BPF_LDX_MEM(
7736 : : BPF_FIELD_SIZEOF(struct sock_common, skc_state),
7737 : : si->dst_reg, si->src_reg,
7738 : : bpf_target_off(struct sock_common, skc_state,
7739 : : FIELD_SIZEOF(struct sock_common,
7740 : : skc_state),
7741 : : target_size));
7742 : 0 : break;
7743 : : }
7744 : :
7745 : 0 : return insn - insn_buf;
7746 : : }
7747 : :
7748 : 0 : static u32 tc_cls_act_convert_ctx_access(enum bpf_access_type type,
7749 : : const struct bpf_insn *si,
7750 : : struct bpf_insn *insn_buf,
7751 : : struct bpf_prog *prog, u32 *target_size)
7752 : : {
7753 : : struct bpf_insn *insn = insn_buf;
7754 : :
7755 [ # # ]: 0 : switch (si->off) {
7756 : : case offsetof(struct __sk_buff, ifindex):
7757 : 0 : *insn++ = BPF_LDX_MEM(BPF_FIELD_SIZEOF(struct sk_buff, dev),
7758 : : si->dst_reg, si->src_reg,
7759 : : offsetof(struct sk_buff, dev));
7760 : 0 : *insn++ = BPF_LDX_MEM(BPF_W, si->dst_reg, si->dst_reg,
7761 : : bpf_target_off(struct net_device, ifindex, 4,
7762 : : target_size));
7763 : : break;
7764 : : default:
7765 : 0 : return bpf_convert_ctx_access(type, si, insn_buf, prog,
7766 : : target_size);
7767 : : }
7768 : :
7769 : 0 : return insn - insn_buf;
7770 : : }
7771 : :
7772 : 0 : static u32 xdp_convert_ctx_access(enum bpf_access_type type,
7773 : : const struct bpf_insn *si,
7774 : : struct bpf_insn *insn_buf,
7775 : : struct bpf_prog *prog, u32 *target_size)
7776 : : {
7777 : : struct bpf_insn *insn = insn_buf;
7778 : :
7779 [ # # # # : 0 : switch (si->off) {
# # ]
7780 : : case offsetof(struct xdp_md, data):
7781 : 0 : *insn++ = BPF_LDX_MEM(BPF_FIELD_SIZEOF(struct xdp_buff, data),
7782 : : si->dst_reg, si->src_reg,
7783 : : offsetof(struct xdp_buff, data));
7784 : 0 : break;
7785 : : case offsetof(struct xdp_md, data_meta):
7786 : 0 : *insn++ = BPF_LDX_MEM(BPF_FIELD_SIZEOF(struct xdp_buff, data_meta),
7787 : : si->dst_reg, si->src_reg,
7788 : : offsetof(struct xdp_buff, data_meta));
7789 : 0 : break;
7790 : : case offsetof(struct xdp_md, data_end):
7791 : 0 : *insn++ = BPF_LDX_MEM(BPF_FIELD_SIZEOF(struct xdp_buff, data_end),
7792 : : si->dst_reg, si->src_reg,
7793 : : offsetof(struct xdp_buff, data_end));
7794 : 0 : break;
7795 : : case offsetof(struct xdp_md, ingress_ifindex):
7796 : 0 : *insn++ = BPF_LDX_MEM(BPF_FIELD_SIZEOF(struct xdp_buff, rxq),
7797 : : si->dst_reg, si->src_reg,
7798 : : offsetof(struct xdp_buff, rxq));
7799 : 0 : *insn++ = BPF_LDX_MEM(BPF_FIELD_SIZEOF(struct xdp_rxq_info, dev),
7800 : : si->dst_reg, si->dst_reg,
7801 : : offsetof(struct xdp_rxq_info, dev));
7802 : 0 : *insn++ = BPF_LDX_MEM(BPF_W, si->dst_reg, si->dst_reg,
7803 : : offsetof(struct net_device, ifindex));
7804 : 0 : break;
7805 : : case offsetof(struct xdp_md, rx_queue_index):
7806 : 0 : *insn++ = BPF_LDX_MEM(BPF_FIELD_SIZEOF(struct xdp_buff, rxq),
7807 : : si->dst_reg, si->src_reg,
7808 : : offsetof(struct xdp_buff, rxq));
7809 : 0 : *insn++ = BPF_LDX_MEM(BPF_W, si->dst_reg, si->dst_reg,
7810 : : offsetof(struct xdp_rxq_info,
7811 : : queue_index));
7812 : 0 : break;
7813 : : }
7814 : :
7815 : 0 : return insn - insn_buf;
7816 : : }
7817 : :
7818 : : /* SOCK_ADDR_LOAD_NESTED_FIELD() loads Nested Field S.F.NF where S is type of
7819 : : * context Structure, F is Field in context structure that contains a pointer
7820 : : * to Nested Structure of type NS that has the field NF.
7821 : : *
7822 : : * SIZE encodes the load size (BPF_B, BPF_H, etc). It's up to caller to make
7823 : : * sure that SIZE is not greater than actual size of S.F.NF.
7824 : : *
7825 : : * If offset OFF is provided, the load happens from that offset relative to
7826 : : * offset of NF.
7827 : : */
7828 : : #define SOCK_ADDR_LOAD_NESTED_FIELD_SIZE_OFF(S, NS, F, NF, SIZE, OFF) \
7829 : : do { \
7830 : : *insn++ = BPF_LDX_MEM(BPF_FIELD_SIZEOF(S, F), si->dst_reg, \
7831 : : si->src_reg, offsetof(S, F)); \
7832 : : *insn++ = BPF_LDX_MEM( \
7833 : : SIZE, si->dst_reg, si->dst_reg, \
7834 : : bpf_target_off(NS, NF, FIELD_SIZEOF(NS, NF), \
7835 : : target_size) \
7836 : : + OFF); \
7837 : : } while (0)
7838 : :
7839 : : #define SOCK_ADDR_LOAD_NESTED_FIELD(S, NS, F, NF) \
7840 : : SOCK_ADDR_LOAD_NESTED_FIELD_SIZE_OFF(S, NS, F, NF, \
7841 : : BPF_FIELD_SIZEOF(NS, NF), 0)
7842 : :
7843 : : /* SOCK_ADDR_STORE_NESTED_FIELD_OFF() has semantic similar to
7844 : : * SOCK_ADDR_LOAD_NESTED_FIELD_SIZE_OFF() but for store operation.
7845 : : *
7846 : : * In addition it uses Temporary Field TF (member of struct S) as the 3rd
7847 : : * "register" since two registers available in convert_ctx_access are not
7848 : : * enough: we can't override neither SRC, since it contains value to store, nor
7849 : : * DST since it contains pointer to context that may be used by later
7850 : : * instructions. But we need a temporary place to save pointer to nested
7851 : : * structure whose field we want to store to.
7852 : : */
7853 : : #define SOCK_ADDR_STORE_NESTED_FIELD_OFF(S, NS, F, NF, SIZE, OFF, TF) \
7854 : : do { \
7855 : : int tmp_reg = BPF_REG_9; \
7856 : : if (si->src_reg == tmp_reg || si->dst_reg == tmp_reg) \
7857 : : --tmp_reg; \
7858 : : if (si->src_reg == tmp_reg || si->dst_reg == tmp_reg) \
7859 : : --tmp_reg; \
7860 : : *insn++ = BPF_STX_MEM(BPF_DW, si->dst_reg, tmp_reg, \
7861 : : offsetof(S, TF)); \
7862 : : *insn++ = BPF_LDX_MEM(BPF_FIELD_SIZEOF(S, F), tmp_reg, \
7863 : : si->dst_reg, offsetof(S, F)); \
7864 : : *insn++ = BPF_STX_MEM(SIZE, tmp_reg, si->src_reg, \
7865 : : bpf_target_off(NS, NF, FIELD_SIZEOF(NS, NF), \
7866 : : target_size) \
7867 : : + OFF); \
7868 : : *insn++ = BPF_LDX_MEM(BPF_DW, tmp_reg, si->dst_reg, \
7869 : : offsetof(S, TF)); \
7870 : : } while (0)
7871 : :
7872 : : #define SOCK_ADDR_LOAD_OR_STORE_NESTED_FIELD_SIZE_OFF(S, NS, F, NF, SIZE, OFF, \
7873 : : TF) \
7874 : : do { \
7875 : : if (type == BPF_WRITE) { \
7876 : : SOCK_ADDR_STORE_NESTED_FIELD_OFF(S, NS, F, NF, SIZE, \
7877 : : OFF, TF); \
7878 : : } else { \
7879 : : SOCK_ADDR_LOAD_NESTED_FIELD_SIZE_OFF( \
7880 : : S, NS, F, NF, SIZE, OFF); \
7881 : : } \
7882 : : } while (0)
7883 : :
7884 : : #define SOCK_ADDR_LOAD_OR_STORE_NESTED_FIELD(S, NS, F, NF, TF) \
7885 : : SOCK_ADDR_LOAD_OR_STORE_NESTED_FIELD_SIZE_OFF( \
7886 : : S, NS, F, NF, BPF_FIELD_SIZEOF(NS, NF), 0, TF)
7887 : :
7888 : 0 : static u32 sock_addr_convert_ctx_access(enum bpf_access_type type,
7889 : : const struct bpf_insn *si,
7890 : : struct bpf_insn *insn_buf,
7891 : : struct bpf_prog *prog, u32 *target_size)
7892 : : {
7893 : : struct bpf_insn *insn = insn_buf;
7894 : : int off;
7895 : :
7896 [ # # # # : 0 : switch (si->off) {
# # # # #
# # ]
7897 : : case offsetof(struct bpf_sock_addr, user_family):
7898 : 0 : SOCK_ADDR_LOAD_NESTED_FIELD(struct bpf_sock_addr_kern,
7899 : : struct sockaddr, uaddr, sa_family);
7900 : 0 : break;
7901 : :
7902 : : case offsetof(struct bpf_sock_addr, user_ip4):
7903 [ # # # # : 0 : SOCK_ADDR_LOAD_OR_STORE_NESTED_FIELD_SIZE_OFF(
# # # # #
# ]
7904 : : struct bpf_sock_addr_kern, struct sockaddr_in, uaddr,
7905 : : sin_addr, BPF_SIZE(si->code), 0, tmp_reg);
7906 : : break;
7907 : :
7908 : : case bpf_ctx_range_till(struct bpf_sock_addr, user_ip6[0], user_ip6[3]):
7909 : : off = si->off;
7910 : 0 : off -= offsetof(struct bpf_sock_addr, user_ip6[0]);
7911 [ # # # # : 0 : SOCK_ADDR_LOAD_OR_STORE_NESTED_FIELD_SIZE_OFF(
# # # # #
# ]
7912 : : struct bpf_sock_addr_kern, struct sockaddr_in6, uaddr,
7913 : : sin6_addr.s6_addr32[0], BPF_SIZE(si->code), off,
7914 : : tmp_reg);
7915 : : break;
7916 : :
7917 : : case offsetof(struct bpf_sock_addr, user_port):
7918 : : /* To get port we need to know sa_family first and then treat
7919 : : * sockaddr as either sockaddr_in or sockaddr_in6.
7920 : : * Though we can simplify since port field has same offset and
7921 : : * size in both structures.
7922 : : * Here we check this invariant and use just one of the
7923 : : * structures if it's true.
7924 : : */
7925 : : BUILD_BUG_ON(offsetof(struct sockaddr_in, sin_port) !=
7926 : : offsetof(struct sockaddr_in6, sin6_port));
7927 : : BUILD_BUG_ON(FIELD_SIZEOF(struct sockaddr_in, sin_port) !=
7928 : : FIELD_SIZEOF(struct sockaddr_in6, sin6_port));
7929 [ # # # # : 0 : SOCK_ADDR_LOAD_OR_STORE_NESTED_FIELD(struct bpf_sock_addr_kern,
# # # # #
# ]
7930 : : struct sockaddr_in6, uaddr,
7931 : : sin6_port, tmp_reg);
7932 : : break;
7933 : :
7934 : : case offsetof(struct bpf_sock_addr, family):
7935 : 0 : SOCK_ADDR_LOAD_NESTED_FIELD(struct bpf_sock_addr_kern,
7936 : : struct sock, sk, sk_family);
7937 : 0 : break;
7938 : :
7939 : : case offsetof(struct bpf_sock_addr, type):
7940 : 0 : SOCK_ADDR_LOAD_NESTED_FIELD_SIZE_OFF(
7941 : : struct bpf_sock_addr_kern, struct sock, sk,
7942 : : __sk_flags_offset, BPF_W, 0);
7943 : 0 : *insn++ = BPF_ALU32_IMM(BPF_AND, si->dst_reg, SK_FL_TYPE_MASK);
7944 : 0 : *insn++ = BPF_ALU32_IMM(BPF_RSH, si->dst_reg, SK_FL_TYPE_SHIFT);
7945 : 0 : break;
7946 : :
7947 : : case offsetof(struct bpf_sock_addr, protocol):
7948 : 0 : SOCK_ADDR_LOAD_NESTED_FIELD_SIZE_OFF(
7949 : : struct bpf_sock_addr_kern, struct sock, sk,
7950 : : __sk_flags_offset, BPF_W, 0);
7951 : 0 : *insn++ = BPF_ALU32_IMM(BPF_AND, si->dst_reg, SK_FL_PROTO_MASK);
7952 : 0 : *insn++ = BPF_ALU32_IMM(BPF_RSH, si->dst_reg,
7953 : : SK_FL_PROTO_SHIFT);
7954 : 0 : break;
7955 : :
7956 : : case offsetof(struct bpf_sock_addr, msg_src_ip4):
7957 : : /* Treat t_ctx as struct in_addr for msg_src_ip4. */
7958 [ # # # # : 0 : SOCK_ADDR_LOAD_OR_STORE_NESTED_FIELD_SIZE_OFF(
# # # # #
# ]
7959 : : struct bpf_sock_addr_kern, struct in_addr, t_ctx,
7960 : : s_addr, BPF_SIZE(si->code), 0, tmp_reg);
7961 : : break;
7962 : :
7963 : : case bpf_ctx_range_till(struct bpf_sock_addr, msg_src_ip6[0],
7964 : : msg_src_ip6[3]):
7965 : : off = si->off;
7966 : 0 : off -= offsetof(struct bpf_sock_addr, msg_src_ip6[0]);
7967 : : /* Treat t_ctx as struct in6_addr for msg_src_ip6. */
7968 [ # # # # : 0 : SOCK_ADDR_LOAD_OR_STORE_NESTED_FIELD_SIZE_OFF(
# # # # #
# ]
7969 : : struct bpf_sock_addr_kern, struct in6_addr, t_ctx,
7970 : : s6_addr32[0], BPF_SIZE(si->code), off, tmp_reg);
7971 : : break;
7972 : : case offsetof(struct bpf_sock_addr, sk):
7973 : 0 : *insn++ = BPF_LDX_MEM(BPF_FIELD_SIZEOF(struct bpf_sock_addr_kern, sk),
7974 : : si->dst_reg, si->src_reg,
7975 : : offsetof(struct bpf_sock_addr_kern, sk));
7976 : 0 : break;
7977 : : }
7978 : :
7979 : 0 : return insn - insn_buf;
7980 : : }
7981 : :
7982 : 0 : static u32 sock_ops_convert_ctx_access(enum bpf_access_type type,
7983 : : const struct bpf_insn *si,
7984 : : struct bpf_insn *insn_buf,
7985 : : struct bpf_prog *prog,
7986 : : u32 *target_size)
7987 : : {
7988 : : struct bpf_insn *insn = insn_buf;
7989 : : int off;
7990 : :
7991 : : /* Helper macro for adding read access to tcp_sock or sock fields. */
7992 : : #define SOCK_OPS_GET_FIELD(BPF_FIELD, OBJ_FIELD, OBJ) \
7993 : : do { \
7994 : : BUILD_BUG_ON(FIELD_SIZEOF(OBJ, OBJ_FIELD) > \
7995 : : FIELD_SIZEOF(struct bpf_sock_ops, BPF_FIELD)); \
7996 : : *insn++ = BPF_LDX_MEM(BPF_FIELD_SIZEOF( \
7997 : : struct bpf_sock_ops_kern, \
7998 : : is_fullsock), \
7999 : : si->dst_reg, si->src_reg, \
8000 : : offsetof(struct bpf_sock_ops_kern, \
8001 : : is_fullsock)); \
8002 : : *insn++ = BPF_JMP_IMM(BPF_JEQ, si->dst_reg, 0, 2); \
8003 : : *insn++ = BPF_LDX_MEM(BPF_FIELD_SIZEOF( \
8004 : : struct bpf_sock_ops_kern, sk),\
8005 : : si->dst_reg, si->src_reg, \
8006 : : offsetof(struct bpf_sock_ops_kern, sk));\
8007 : : *insn++ = BPF_LDX_MEM(BPF_FIELD_SIZEOF(OBJ, \
8008 : : OBJ_FIELD), \
8009 : : si->dst_reg, si->dst_reg, \
8010 : : offsetof(OBJ, OBJ_FIELD)); \
8011 : : } while (0)
8012 : :
8013 : : #define SOCK_OPS_GET_SK() \
8014 : : do { \
8015 : : int fullsock_reg = si->dst_reg, reg = BPF_REG_9, jmp = 1; \
8016 : : if (si->dst_reg == reg || si->src_reg == reg) \
8017 : : reg--; \
8018 : : if (si->dst_reg == reg || si->src_reg == reg) \
8019 : : reg--; \
8020 : : if (si->dst_reg == si->src_reg) { \
8021 : : *insn++ = BPF_STX_MEM(BPF_DW, si->src_reg, reg, \
8022 : : offsetof(struct bpf_sock_ops_kern, \
8023 : : temp)); \
8024 : : fullsock_reg = reg; \
8025 : : jmp += 2; \
8026 : : } \
8027 : : *insn++ = BPF_LDX_MEM(BPF_FIELD_SIZEOF( \
8028 : : struct bpf_sock_ops_kern, \
8029 : : is_fullsock), \
8030 : : fullsock_reg, si->src_reg, \
8031 : : offsetof(struct bpf_sock_ops_kern, \
8032 : : is_fullsock)); \
8033 : : *insn++ = BPF_JMP_IMM(BPF_JEQ, fullsock_reg, 0, jmp); \
8034 : : if (si->dst_reg == si->src_reg) \
8035 : : *insn++ = BPF_LDX_MEM(BPF_DW, reg, si->src_reg, \
8036 : : offsetof(struct bpf_sock_ops_kern, \
8037 : : temp)); \
8038 : : *insn++ = BPF_LDX_MEM(BPF_FIELD_SIZEOF( \
8039 : : struct bpf_sock_ops_kern, sk),\
8040 : : si->dst_reg, si->src_reg, \
8041 : : offsetof(struct bpf_sock_ops_kern, sk));\
8042 : : if (si->dst_reg == si->src_reg) { \
8043 : : *insn++ = BPF_JMP_A(1); \
8044 : : *insn++ = BPF_LDX_MEM(BPF_DW, reg, si->src_reg, \
8045 : : offsetof(struct bpf_sock_ops_kern, \
8046 : : temp)); \
8047 : : } \
8048 : : } while (0)
8049 : :
8050 : : #define SOCK_OPS_GET_TCP_SOCK_FIELD(FIELD) \
8051 : : SOCK_OPS_GET_FIELD(FIELD, FIELD, struct tcp_sock)
8052 : :
8053 : : /* Helper macro for adding write access to tcp_sock or sock fields.
8054 : : * The macro is called with two registers, dst_reg which contains a pointer
8055 : : * to ctx (context) and src_reg which contains the value that should be
8056 : : * stored. However, we need an additional register since we cannot overwrite
8057 : : * dst_reg because it may be used later in the program.
8058 : : * Instead we "borrow" one of the other register. We first save its value
8059 : : * into a new (temp) field in bpf_sock_ops_kern, use it, and then restore
8060 : : * it at the end of the macro.
8061 : : */
8062 : : #define SOCK_OPS_SET_FIELD(BPF_FIELD, OBJ_FIELD, OBJ) \
8063 : : do { \
8064 : : int reg = BPF_REG_9; \
8065 : : BUILD_BUG_ON(FIELD_SIZEOF(OBJ, OBJ_FIELD) > \
8066 : : FIELD_SIZEOF(struct bpf_sock_ops, BPF_FIELD)); \
8067 : : if (si->dst_reg == reg || si->src_reg == reg) \
8068 : : reg--; \
8069 : : if (si->dst_reg == reg || si->src_reg == reg) \
8070 : : reg--; \
8071 : : *insn++ = BPF_STX_MEM(BPF_DW, si->dst_reg, reg, \
8072 : : offsetof(struct bpf_sock_ops_kern, \
8073 : : temp)); \
8074 : : *insn++ = BPF_LDX_MEM(BPF_FIELD_SIZEOF( \
8075 : : struct bpf_sock_ops_kern, \
8076 : : is_fullsock), \
8077 : : reg, si->dst_reg, \
8078 : : offsetof(struct bpf_sock_ops_kern, \
8079 : : is_fullsock)); \
8080 : : *insn++ = BPF_JMP_IMM(BPF_JEQ, reg, 0, 2); \
8081 : : *insn++ = BPF_LDX_MEM(BPF_FIELD_SIZEOF( \
8082 : : struct bpf_sock_ops_kern, sk),\
8083 : : reg, si->dst_reg, \
8084 : : offsetof(struct bpf_sock_ops_kern, sk));\
8085 : : *insn++ = BPF_STX_MEM(BPF_FIELD_SIZEOF(OBJ, OBJ_FIELD), \
8086 : : reg, si->src_reg, \
8087 : : offsetof(OBJ, OBJ_FIELD)); \
8088 : : *insn++ = BPF_LDX_MEM(BPF_DW, reg, si->dst_reg, \
8089 : : offsetof(struct bpf_sock_ops_kern, \
8090 : : temp)); \
8091 : : } while (0)
8092 : :
8093 : : #define SOCK_OPS_GET_OR_SET_FIELD(BPF_FIELD, OBJ_FIELD, OBJ, TYPE) \
8094 : : do { \
8095 : : if (TYPE == BPF_WRITE) \
8096 : : SOCK_OPS_SET_FIELD(BPF_FIELD, OBJ_FIELD, OBJ); \
8097 : : else \
8098 : : SOCK_OPS_GET_FIELD(BPF_FIELD, OBJ_FIELD, OBJ); \
8099 : : } while (0)
8100 : :
8101 : : if (insn > insn_buf)
8102 : : return insn - insn_buf;
8103 : :
8104 [ # # # # : 0 : switch (si->off) {
# # # # #
# # # # #
# # # # #
# # # # #
# # # # #
# # # # #
# # ]
8105 : : case offsetof(struct bpf_sock_ops, op) ...
8106 : : offsetof(struct bpf_sock_ops, replylong[3]):
8107 : : BUILD_BUG_ON(FIELD_SIZEOF(struct bpf_sock_ops, op) !=
8108 : : FIELD_SIZEOF(struct bpf_sock_ops_kern, op));
8109 : : BUILD_BUG_ON(FIELD_SIZEOF(struct bpf_sock_ops, reply) !=
8110 : : FIELD_SIZEOF(struct bpf_sock_ops_kern, reply));
8111 : : BUILD_BUG_ON(FIELD_SIZEOF(struct bpf_sock_ops, replylong) !=
8112 : : FIELD_SIZEOF(struct bpf_sock_ops_kern, replylong));
8113 : 0 : off = si->off;
8114 : : off -= offsetof(struct bpf_sock_ops, op);
8115 : 0 : off += offsetof(struct bpf_sock_ops_kern, op);
8116 [ # # ]: 0 : if (type == BPF_WRITE)
8117 : 0 : *insn++ = BPF_STX_MEM(BPF_W, si->dst_reg, si->src_reg,
8118 : : off);
8119 : : else
8120 : 0 : *insn++ = BPF_LDX_MEM(BPF_W, si->dst_reg, si->src_reg,
8121 : : off);
8122 : : break;
8123 : :
8124 : : case offsetof(struct bpf_sock_ops, family):
8125 : : BUILD_BUG_ON(FIELD_SIZEOF(struct sock_common, skc_family) != 2);
8126 : :
8127 : 0 : *insn++ = BPF_LDX_MEM(BPF_FIELD_SIZEOF(
8128 : : struct bpf_sock_ops_kern, sk),
8129 : : si->dst_reg, si->src_reg,
8130 : : offsetof(struct bpf_sock_ops_kern, sk));
8131 : 0 : *insn++ = BPF_LDX_MEM(BPF_H, si->dst_reg, si->dst_reg,
8132 : : offsetof(struct sock_common, skc_family));
8133 : 0 : break;
8134 : :
8135 : : case offsetof(struct bpf_sock_ops, remote_ip4):
8136 : : BUILD_BUG_ON(FIELD_SIZEOF(struct sock_common, skc_daddr) != 4);
8137 : :
8138 : 0 : *insn++ = BPF_LDX_MEM(BPF_FIELD_SIZEOF(
8139 : : struct bpf_sock_ops_kern, sk),
8140 : : si->dst_reg, si->src_reg,
8141 : : offsetof(struct bpf_sock_ops_kern, sk));
8142 : 0 : *insn++ = BPF_LDX_MEM(BPF_W, si->dst_reg, si->dst_reg,
8143 : : offsetof(struct sock_common, skc_daddr));
8144 : 0 : break;
8145 : :
8146 : : case offsetof(struct bpf_sock_ops, local_ip4):
8147 : : BUILD_BUG_ON(FIELD_SIZEOF(struct sock_common,
8148 : : skc_rcv_saddr) != 4);
8149 : :
8150 : 0 : *insn++ = BPF_LDX_MEM(BPF_FIELD_SIZEOF(
8151 : : struct bpf_sock_ops_kern, sk),
8152 : : si->dst_reg, si->src_reg,
8153 : : offsetof(struct bpf_sock_ops_kern, sk));
8154 : 0 : *insn++ = BPF_LDX_MEM(BPF_W, si->dst_reg, si->dst_reg,
8155 : : offsetof(struct sock_common,
8156 : : skc_rcv_saddr));
8157 : 0 : break;
8158 : :
8159 : : case offsetof(struct bpf_sock_ops, remote_ip6[0]) ...
8160 : : offsetof(struct bpf_sock_ops, remote_ip6[3]):
8161 : : #if IS_ENABLED(CONFIG_IPV6)
8162 : : BUILD_BUG_ON(FIELD_SIZEOF(struct sock_common,
8163 : : skc_v6_daddr.s6_addr32[0]) != 4);
8164 : :
8165 : : off = si->off;
8166 : 0 : off -= offsetof(struct bpf_sock_ops, remote_ip6[0]);
8167 : 0 : *insn++ = BPF_LDX_MEM(BPF_FIELD_SIZEOF(
8168 : : struct bpf_sock_ops_kern, sk),
8169 : : si->dst_reg, si->src_reg,
8170 : : offsetof(struct bpf_sock_ops_kern, sk));
8171 : 0 : *insn++ = BPF_LDX_MEM(BPF_W, si->dst_reg, si->dst_reg,
8172 : : offsetof(struct sock_common,
8173 : : skc_v6_daddr.s6_addr32[0]) +
8174 : : off);
8175 : : #else
8176 : : *insn++ = BPF_MOV32_IMM(si->dst_reg, 0);
8177 : : #endif
8178 : 0 : break;
8179 : :
8180 : : case offsetof(struct bpf_sock_ops, local_ip6[0]) ...
8181 : : offsetof(struct bpf_sock_ops, local_ip6[3]):
8182 : : #if IS_ENABLED(CONFIG_IPV6)
8183 : : BUILD_BUG_ON(FIELD_SIZEOF(struct sock_common,
8184 : : skc_v6_rcv_saddr.s6_addr32[0]) != 4);
8185 : :
8186 : : off = si->off;
8187 : 0 : off -= offsetof(struct bpf_sock_ops, local_ip6[0]);
8188 : 0 : *insn++ = BPF_LDX_MEM(BPF_FIELD_SIZEOF(
8189 : : struct bpf_sock_ops_kern, sk),
8190 : : si->dst_reg, si->src_reg,
8191 : : offsetof(struct bpf_sock_ops_kern, sk));
8192 : 0 : *insn++ = BPF_LDX_MEM(BPF_W, si->dst_reg, si->dst_reg,
8193 : : offsetof(struct sock_common,
8194 : : skc_v6_rcv_saddr.s6_addr32[0]) +
8195 : : off);
8196 : : #else
8197 : : *insn++ = BPF_MOV32_IMM(si->dst_reg, 0);
8198 : : #endif
8199 : 0 : break;
8200 : :
8201 : : case offsetof(struct bpf_sock_ops, remote_port):
8202 : : BUILD_BUG_ON(FIELD_SIZEOF(struct sock_common, skc_dport) != 2);
8203 : :
8204 : 0 : *insn++ = BPF_LDX_MEM(BPF_FIELD_SIZEOF(
8205 : : struct bpf_sock_ops_kern, sk),
8206 : : si->dst_reg, si->src_reg,
8207 : : offsetof(struct bpf_sock_ops_kern, sk));
8208 : 0 : *insn++ = BPF_LDX_MEM(BPF_H, si->dst_reg, si->dst_reg,
8209 : : offsetof(struct sock_common, skc_dport));
8210 : : #ifndef __BIG_ENDIAN_BITFIELD
8211 : 0 : *insn++ = BPF_ALU32_IMM(BPF_LSH, si->dst_reg, 16);
8212 : : #endif
8213 : 0 : break;
8214 : :
8215 : : case offsetof(struct bpf_sock_ops, local_port):
8216 : : BUILD_BUG_ON(FIELD_SIZEOF(struct sock_common, skc_num) != 2);
8217 : :
8218 : 0 : *insn++ = BPF_LDX_MEM(BPF_FIELD_SIZEOF(
8219 : : struct bpf_sock_ops_kern, sk),
8220 : : si->dst_reg, si->src_reg,
8221 : : offsetof(struct bpf_sock_ops_kern, sk));
8222 : 0 : *insn++ = BPF_LDX_MEM(BPF_H, si->dst_reg, si->dst_reg,
8223 : : offsetof(struct sock_common, skc_num));
8224 : 0 : break;
8225 : :
8226 : : case offsetof(struct bpf_sock_ops, is_fullsock):
8227 : 0 : *insn++ = BPF_LDX_MEM(BPF_FIELD_SIZEOF(
8228 : : struct bpf_sock_ops_kern,
8229 : : is_fullsock),
8230 : : si->dst_reg, si->src_reg,
8231 : : offsetof(struct bpf_sock_ops_kern,
8232 : : is_fullsock));
8233 : 0 : break;
8234 : :
8235 : : case offsetof(struct bpf_sock_ops, state):
8236 : : BUILD_BUG_ON(FIELD_SIZEOF(struct sock_common, skc_state) != 1);
8237 : :
8238 : 0 : *insn++ = BPF_LDX_MEM(BPF_FIELD_SIZEOF(
8239 : : struct bpf_sock_ops_kern, sk),
8240 : : si->dst_reg, si->src_reg,
8241 : : offsetof(struct bpf_sock_ops_kern, sk));
8242 : 0 : *insn++ = BPF_LDX_MEM(BPF_B, si->dst_reg, si->dst_reg,
8243 : : offsetof(struct sock_common, skc_state));
8244 : 0 : break;
8245 : :
8246 : : case offsetof(struct bpf_sock_ops, rtt_min):
8247 : : BUILD_BUG_ON(FIELD_SIZEOF(struct tcp_sock, rtt_min) !=
8248 : : sizeof(struct minmax));
8249 : : BUILD_BUG_ON(sizeof(struct minmax) <
8250 : : sizeof(struct minmax_sample));
8251 : :
8252 : 0 : *insn++ = BPF_LDX_MEM(BPF_FIELD_SIZEOF(
8253 : : struct bpf_sock_ops_kern, sk),
8254 : : si->dst_reg, si->src_reg,
8255 : : offsetof(struct bpf_sock_ops_kern, sk));
8256 : 0 : *insn++ = BPF_LDX_MEM(BPF_W, si->dst_reg, si->dst_reg,
8257 : : offsetof(struct tcp_sock, rtt_min) +
8258 : : FIELD_SIZEOF(struct minmax_sample, t));
8259 : 0 : break;
8260 : :
8261 : : case offsetof(struct bpf_sock_ops, bpf_sock_ops_cb_flags):
8262 : 0 : SOCK_OPS_GET_FIELD(bpf_sock_ops_cb_flags, bpf_sock_ops_cb_flags,
8263 : : struct tcp_sock);
8264 : 0 : break;
8265 : :
8266 : : case offsetof(struct bpf_sock_ops, sk_txhash):
8267 [ # # # # : 0 : SOCK_OPS_GET_OR_SET_FIELD(sk_txhash, sk_txhash,
# # # # #
# ]
8268 : : struct sock, type);
8269 : : break;
8270 : : case offsetof(struct bpf_sock_ops, snd_cwnd):
8271 : 0 : SOCK_OPS_GET_TCP_SOCK_FIELD(snd_cwnd);
8272 : 0 : break;
8273 : : case offsetof(struct bpf_sock_ops, srtt_us):
8274 : 0 : SOCK_OPS_GET_TCP_SOCK_FIELD(srtt_us);
8275 : 0 : break;
8276 : : case offsetof(struct bpf_sock_ops, snd_ssthresh):
8277 : 0 : SOCK_OPS_GET_TCP_SOCK_FIELD(snd_ssthresh);
8278 : 0 : break;
8279 : : case offsetof(struct bpf_sock_ops, rcv_nxt):
8280 : 0 : SOCK_OPS_GET_TCP_SOCK_FIELD(rcv_nxt);
8281 : 0 : break;
8282 : : case offsetof(struct bpf_sock_ops, snd_nxt):
8283 : 0 : SOCK_OPS_GET_TCP_SOCK_FIELD(snd_nxt);
8284 : 0 : break;
8285 : : case offsetof(struct bpf_sock_ops, snd_una):
8286 : 0 : SOCK_OPS_GET_TCP_SOCK_FIELD(snd_una);
8287 : 0 : break;
8288 : : case offsetof(struct bpf_sock_ops, mss_cache):
8289 : 0 : SOCK_OPS_GET_TCP_SOCK_FIELD(mss_cache);
8290 : 0 : break;
8291 : : case offsetof(struct bpf_sock_ops, ecn_flags):
8292 : 0 : SOCK_OPS_GET_TCP_SOCK_FIELD(ecn_flags);
8293 : 0 : break;
8294 : : case offsetof(struct bpf_sock_ops, rate_delivered):
8295 : 0 : SOCK_OPS_GET_TCP_SOCK_FIELD(rate_delivered);
8296 : 0 : break;
8297 : : case offsetof(struct bpf_sock_ops, rate_interval_us):
8298 : 0 : SOCK_OPS_GET_TCP_SOCK_FIELD(rate_interval_us);
8299 : 0 : break;
8300 : : case offsetof(struct bpf_sock_ops, packets_out):
8301 : 0 : SOCK_OPS_GET_TCP_SOCK_FIELD(packets_out);
8302 : 0 : break;
8303 : : case offsetof(struct bpf_sock_ops, retrans_out):
8304 : 0 : SOCK_OPS_GET_TCP_SOCK_FIELD(retrans_out);
8305 : 0 : break;
8306 : : case offsetof(struct bpf_sock_ops, total_retrans):
8307 : 0 : SOCK_OPS_GET_TCP_SOCK_FIELD(total_retrans);
8308 : 0 : break;
8309 : : case offsetof(struct bpf_sock_ops, segs_in):
8310 : 0 : SOCK_OPS_GET_TCP_SOCK_FIELD(segs_in);
8311 : 0 : break;
8312 : : case offsetof(struct bpf_sock_ops, data_segs_in):
8313 : 0 : SOCK_OPS_GET_TCP_SOCK_FIELD(data_segs_in);
8314 : 0 : break;
8315 : : case offsetof(struct bpf_sock_ops, segs_out):
8316 : 0 : SOCK_OPS_GET_TCP_SOCK_FIELD(segs_out);
8317 : 0 : break;
8318 : : case offsetof(struct bpf_sock_ops, data_segs_out):
8319 : 0 : SOCK_OPS_GET_TCP_SOCK_FIELD(data_segs_out);
8320 : 0 : break;
8321 : : case offsetof(struct bpf_sock_ops, lost_out):
8322 : 0 : SOCK_OPS_GET_TCP_SOCK_FIELD(lost_out);
8323 : 0 : break;
8324 : : case offsetof(struct bpf_sock_ops, sacked_out):
8325 : 0 : SOCK_OPS_GET_TCP_SOCK_FIELD(sacked_out);
8326 : 0 : break;
8327 : : case offsetof(struct bpf_sock_ops, bytes_received):
8328 : 0 : SOCK_OPS_GET_TCP_SOCK_FIELD(bytes_received);
8329 : 0 : break;
8330 : : case offsetof(struct bpf_sock_ops, bytes_acked):
8331 : 0 : SOCK_OPS_GET_TCP_SOCK_FIELD(bytes_acked);
8332 : 0 : break;
8333 : : case offsetof(struct bpf_sock_ops, sk):
8334 [ # # # # : 0 : SOCK_OPS_GET_SK();
# # # # #
# # # #
# ]
8335 : : break;
8336 : : }
8337 : 0 : return insn - insn_buf;
8338 : : }
8339 : :
8340 : 0 : static u32 sk_skb_convert_ctx_access(enum bpf_access_type type,
8341 : : const struct bpf_insn *si,
8342 : : struct bpf_insn *insn_buf,
8343 : : struct bpf_prog *prog, u32 *target_size)
8344 : : {
8345 : : struct bpf_insn *insn = insn_buf;
8346 : : int off;
8347 : :
8348 [ # # ]: 0 : switch (si->off) {
8349 : : case offsetof(struct __sk_buff, data_end):
8350 : : off = si->off;
8351 : 0 : off -= offsetof(struct __sk_buff, data_end);
8352 : 0 : off += offsetof(struct sk_buff, cb);
8353 : 0 : off += offsetof(struct tcp_skb_cb, bpf.data_end);
8354 : 0 : *insn++ = BPF_LDX_MEM(BPF_SIZEOF(void *), si->dst_reg,
8355 : : si->src_reg, off);
8356 : : break;
8357 : : default:
8358 : 0 : return bpf_convert_ctx_access(type, si, insn_buf, prog,
8359 : : target_size);
8360 : : }
8361 : :
8362 : 0 : return insn - insn_buf;
8363 : : }
8364 : :
8365 : 0 : static u32 sk_msg_convert_ctx_access(enum bpf_access_type type,
8366 : : const struct bpf_insn *si,
8367 : : struct bpf_insn *insn_buf,
8368 : : struct bpf_prog *prog, u32 *target_size)
8369 : : {
8370 : : struct bpf_insn *insn = insn_buf;
8371 : : #if IS_ENABLED(CONFIG_IPV6)
8372 : : int off;
8373 : : #endif
8374 : :
8375 : : /* convert ctx uses the fact sg element is first in struct */
8376 : : BUILD_BUG_ON(offsetof(struct sk_msg, sg) != 0);
8377 : :
8378 [ # # # # : 0 : switch (si->off) {
# # # # #
# # ]
8379 : : case offsetof(struct sk_msg_md, data):
8380 : 0 : *insn++ = BPF_LDX_MEM(BPF_FIELD_SIZEOF(struct sk_msg, data),
8381 : : si->dst_reg, si->src_reg,
8382 : : offsetof(struct sk_msg, data));
8383 : 0 : break;
8384 : : case offsetof(struct sk_msg_md, data_end):
8385 : 0 : *insn++ = BPF_LDX_MEM(BPF_FIELD_SIZEOF(struct sk_msg, data_end),
8386 : : si->dst_reg, si->src_reg,
8387 : : offsetof(struct sk_msg, data_end));
8388 : 0 : break;
8389 : : case offsetof(struct sk_msg_md, family):
8390 : : BUILD_BUG_ON(FIELD_SIZEOF(struct sock_common, skc_family) != 2);
8391 : :
8392 : 0 : *insn++ = BPF_LDX_MEM(BPF_FIELD_SIZEOF(
8393 : : struct sk_msg, sk),
8394 : : si->dst_reg, si->src_reg,
8395 : : offsetof(struct sk_msg, sk));
8396 : 0 : *insn++ = BPF_LDX_MEM(BPF_H, si->dst_reg, si->dst_reg,
8397 : : offsetof(struct sock_common, skc_family));
8398 : 0 : break;
8399 : :
8400 : : case offsetof(struct sk_msg_md, remote_ip4):
8401 : : BUILD_BUG_ON(FIELD_SIZEOF(struct sock_common, skc_daddr) != 4);
8402 : :
8403 : 0 : *insn++ = BPF_LDX_MEM(BPF_FIELD_SIZEOF(
8404 : : struct sk_msg, sk),
8405 : : si->dst_reg, si->src_reg,
8406 : : offsetof(struct sk_msg, sk));
8407 : 0 : *insn++ = BPF_LDX_MEM(BPF_W, si->dst_reg, si->dst_reg,
8408 : : offsetof(struct sock_common, skc_daddr));
8409 : 0 : break;
8410 : :
8411 : : case offsetof(struct sk_msg_md, local_ip4):
8412 : : BUILD_BUG_ON(FIELD_SIZEOF(struct sock_common,
8413 : : skc_rcv_saddr) != 4);
8414 : :
8415 : 0 : *insn++ = BPF_LDX_MEM(BPF_FIELD_SIZEOF(
8416 : : struct sk_msg, sk),
8417 : : si->dst_reg, si->src_reg,
8418 : : offsetof(struct sk_msg, sk));
8419 : 0 : *insn++ = BPF_LDX_MEM(BPF_W, si->dst_reg, si->dst_reg,
8420 : : offsetof(struct sock_common,
8421 : : skc_rcv_saddr));
8422 : 0 : break;
8423 : :
8424 : : case offsetof(struct sk_msg_md, remote_ip6[0]) ...
8425 : : offsetof(struct sk_msg_md, remote_ip6[3]):
8426 : : #if IS_ENABLED(CONFIG_IPV6)
8427 : : BUILD_BUG_ON(FIELD_SIZEOF(struct sock_common,
8428 : : skc_v6_daddr.s6_addr32[0]) != 4);
8429 : :
8430 : : off = si->off;
8431 : 0 : off -= offsetof(struct sk_msg_md, remote_ip6[0]);
8432 : 0 : *insn++ = BPF_LDX_MEM(BPF_FIELD_SIZEOF(
8433 : : struct sk_msg, sk),
8434 : : si->dst_reg, si->src_reg,
8435 : : offsetof(struct sk_msg, sk));
8436 : 0 : *insn++ = BPF_LDX_MEM(BPF_W, si->dst_reg, si->dst_reg,
8437 : : offsetof(struct sock_common,
8438 : : skc_v6_daddr.s6_addr32[0]) +
8439 : : off);
8440 : : #else
8441 : : *insn++ = BPF_MOV32_IMM(si->dst_reg, 0);
8442 : : #endif
8443 : 0 : break;
8444 : :
8445 : : case offsetof(struct sk_msg_md, local_ip6[0]) ...
8446 : : offsetof(struct sk_msg_md, local_ip6[3]):
8447 : : #if IS_ENABLED(CONFIG_IPV6)
8448 : : BUILD_BUG_ON(FIELD_SIZEOF(struct sock_common,
8449 : : skc_v6_rcv_saddr.s6_addr32[0]) != 4);
8450 : :
8451 : : off = si->off;
8452 : 0 : off -= offsetof(struct sk_msg_md, local_ip6[0]);
8453 : 0 : *insn++ = BPF_LDX_MEM(BPF_FIELD_SIZEOF(
8454 : : struct sk_msg, sk),
8455 : : si->dst_reg, si->src_reg,
8456 : : offsetof(struct sk_msg, sk));
8457 : 0 : *insn++ = BPF_LDX_MEM(BPF_W, si->dst_reg, si->dst_reg,
8458 : : offsetof(struct sock_common,
8459 : : skc_v6_rcv_saddr.s6_addr32[0]) +
8460 : : off);
8461 : : #else
8462 : : *insn++ = BPF_MOV32_IMM(si->dst_reg, 0);
8463 : : #endif
8464 : 0 : break;
8465 : :
8466 : : case offsetof(struct sk_msg_md, remote_port):
8467 : : BUILD_BUG_ON(FIELD_SIZEOF(struct sock_common, skc_dport) != 2);
8468 : :
8469 : 0 : *insn++ = BPF_LDX_MEM(BPF_FIELD_SIZEOF(
8470 : : struct sk_msg, sk),
8471 : : si->dst_reg, si->src_reg,
8472 : : offsetof(struct sk_msg, sk));
8473 : 0 : *insn++ = BPF_LDX_MEM(BPF_H, si->dst_reg, si->dst_reg,
8474 : : offsetof(struct sock_common, skc_dport));
8475 : : #ifndef __BIG_ENDIAN_BITFIELD
8476 : 0 : *insn++ = BPF_ALU32_IMM(BPF_LSH, si->dst_reg, 16);
8477 : : #endif
8478 : 0 : break;
8479 : :
8480 : : case offsetof(struct sk_msg_md, local_port):
8481 : : BUILD_BUG_ON(FIELD_SIZEOF(struct sock_common, skc_num) != 2);
8482 : :
8483 : 0 : *insn++ = BPF_LDX_MEM(BPF_FIELD_SIZEOF(
8484 : : struct sk_msg, sk),
8485 : : si->dst_reg, si->src_reg,
8486 : : offsetof(struct sk_msg, sk));
8487 : 0 : *insn++ = BPF_LDX_MEM(BPF_H, si->dst_reg, si->dst_reg,
8488 : : offsetof(struct sock_common, skc_num));
8489 : 0 : break;
8490 : :
8491 : : case offsetof(struct sk_msg_md, size):
8492 : 0 : *insn++ = BPF_LDX_MEM(BPF_FIELD_SIZEOF(struct sk_msg_sg, size),
8493 : : si->dst_reg, si->src_reg,
8494 : : offsetof(struct sk_msg_sg, size));
8495 : 0 : break;
8496 : : }
8497 : :
8498 : 0 : return insn - insn_buf;
8499 : : }
8500 : :
8501 : : const struct bpf_verifier_ops sk_filter_verifier_ops = {
8502 : : .get_func_proto = sk_filter_func_proto,
8503 : : .is_valid_access = sk_filter_is_valid_access,
8504 : : .convert_ctx_access = bpf_convert_ctx_access,
8505 : : .gen_ld_abs = bpf_gen_ld_abs,
8506 : : };
8507 : :
8508 : : const struct bpf_prog_ops sk_filter_prog_ops = {
8509 : : .test_run = bpf_prog_test_run_skb,
8510 : : };
8511 : :
8512 : : const struct bpf_verifier_ops tc_cls_act_verifier_ops = {
8513 : : .get_func_proto = tc_cls_act_func_proto,
8514 : : .is_valid_access = tc_cls_act_is_valid_access,
8515 : : .convert_ctx_access = tc_cls_act_convert_ctx_access,
8516 : : .gen_prologue = tc_cls_act_prologue,
8517 : : .gen_ld_abs = bpf_gen_ld_abs,
8518 : : };
8519 : :
8520 : : const struct bpf_prog_ops tc_cls_act_prog_ops = {
8521 : : .test_run = bpf_prog_test_run_skb,
8522 : : };
8523 : :
8524 : : const struct bpf_verifier_ops xdp_verifier_ops = {
8525 : : .get_func_proto = xdp_func_proto,
8526 : : .is_valid_access = xdp_is_valid_access,
8527 : : .convert_ctx_access = xdp_convert_ctx_access,
8528 : : .gen_prologue = bpf_noop_prologue,
8529 : : };
8530 : :
8531 : : const struct bpf_prog_ops xdp_prog_ops = {
8532 : : .test_run = bpf_prog_test_run_xdp,
8533 : : };
8534 : :
8535 : : const struct bpf_verifier_ops cg_skb_verifier_ops = {
8536 : : .get_func_proto = cg_skb_func_proto,
8537 : : .is_valid_access = cg_skb_is_valid_access,
8538 : : .convert_ctx_access = bpf_convert_ctx_access,
8539 : : };
8540 : :
8541 : : const struct bpf_prog_ops cg_skb_prog_ops = {
8542 : : .test_run = bpf_prog_test_run_skb,
8543 : : };
8544 : :
8545 : : const struct bpf_verifier_ops lwt_in_verifier_ops = {
8546 : : .get_func_proto = lwt_in_func_proto,
8547 : : .is_valid_access = lwt_is_valid_access,
8548 : : .convert_ctx_access = bpf_convert_ctx_access,
8549 : : };
8550 : :
8551 : : const struct bpf_prog_ops lwt_in_prog_ops = {
8552 : : .test_run = bpf_prog_test_run_skb,
8553 : : };
8554 : :
8555 : : const struct bpf_verifier_ops lwt_out_verifier_ops = {
8556 : : .get_func_proto = lwt_out_func_proto,
8557 : : .is_valid_access = lwt_is_valid_access,
8558 : : .convert_ctx_access = bpf_convert_ctx_access,
8559 : : };
8560 : :
8561 : : const struct bpf_prog_ops lwt_out_prog_ops = {
8562 : : .test_run = bpf_prog_test_run_skb,
8563 : : };
8564 : :
8565 : : const struct bpf_verifier_ops lwt_xmit_verifier_ops = {
8566 : : .get_func_proto = lwt_xmit_func_proto,
8567 : : .is_valid_access = lwt_is_valid_access,
8568 : : .convert_ctx_access = bpf_convert_ctx_access,
8569 : : .gen_prologue = tc_cls_act_prologue,
8570 : : };
8571 : :
8572 : : const struct bpf_prog_ops lwt_xmit_prog_ops = {
8573 : : .test_run = bpf_prog_test_run_skb,
8574 : : };
8575 : :
8576 : : const struct bpf_verifier_ops lwt_seg6local_verifier_ops = {
8577 : : .get_func_proto = lwt_seg6local_func_proto,
8578 : : .is_valid_access = lwt_is_valid_access,
8579 : : .convert_ctx_access = bpf_convert_ctx_access,
8580 : : };
8581 : :
8582 : : const struct bpf_prog_ops lwt_seg6local_prog_ops = {
8583 : : .test_run = bpf_prog_test_run_skb,
8584 : : };
8585 : :
8586 : : const struct bpf_verifier_ops cg_sock_verifier_ops = {
8587 : : .get_func_proto = sock_filter_func_proto,
8588 : : .is_valid_access = sock_filter_is_valid_access,
8589 : : .convert_ctx_access = bpf_sock_convert_ctx_access,
8590 : : };
8591 : :
8592 : : const struct bpf_prog_ops cg_sock_prog_ops = {
8593 : : };
8594 : :
8595 : : const struct bpf_verifier_ops cg_sock_addr_verifier_ops = {
8596 : : .get_func_proto = sock_addr_func_proto,
8597 : : .is_valid_access = sock_addr_is_valid_access,
8598 : : .convert_ctx_access = sock_addr_convert_ctx_access,
8599 : : };
8600 : :
8601 : : const struct bpf_prog_ops cg_sock_addr_prog_ops = {
8602 : : };
8603 : :
8604 : : const struct bpf_verifier_ops sock_ops_verifier_ops = {
8605 : : .get_func_proto = sock_ops_func_proto,
8606 : : .is_valid_access = sock_ops_is_valid_access,
8607 : : .convert_ctx_access = sock_ops_convert_ctx_access,
8608 : : };
8609 : :
8610 : : const struct bpf_prog_ops sock_ops_prog_ops = {
8611 : : };
8612 : :
8613 : : const struct bpf_verifier_ops sk_skb_verifier_ops = {
8614 : : .get_func_proto = sk_skb_func_proto,
8615 : : .is_valid_access = sk_skb_is_valid_access,
8616 : : .convert_ctx_access = sk_skb_convert_ctx_access,
8617 : : .gen_prologue = sk_skb_prologue,
8618 : : };
8619 : :
8620 : : const struct bpf_prog_ops sk_skb_prog_ops = {
8621 : : };
8622 : :
8623 : : const struct bpf_verifier_ops sk_msg_verifier_ops = {
8624 : : .get_func_proto = sk_msg_func_proto,
8625 : : .is_valid_access = sk_msg_is_valid_access,
8626 : : .convert_ctx_access = sk_msg_convert_ctx_access,
8627 : : .gen_prologue = bpf_noop_prologue,
8628 : : };
8629 : :
8630 : : const struct bpf_prog_ops sk_msg_prog_ops = {
8631 : : };
8632 : :
8633 : : const struct bpf_verifier_ops flow_dissector_verifier_ops = {
8634 : : .get_func_proto = flow_dissector_func_proto,
8635 : : .is_valid_access = flow_dissector_is_valid_access,
8636 : : .convert_ctx_access = flow_dissector_convert_ctx_access,
8637 : : };
8638 : :
8639 : : const struct bpf_prog_ops flow_dissector_prog_ops = {
8640 : : .test_run = bpf_prog_test_run_flow_dissector,
8641 : : };
8642 : :
8643 : 0 : int sk_detach_filter(struct sock *sk)
8644 : : {
8645 : : int ret = -ENOENT;
8646 : : struct sk_filter *filter;
8647 : :
8648 [ # # ]: 0 : if (sock_flag(sk, SOCK_FILTER_LOCKED))
8649 : : return -EPERM;
8650 : :
8651 : 0 : filter = rcu_dereference_protected(sk->sk_filter,
8652 : : lockdep_sock_is_held(sk));
8653 [ # # ]: 0 : if (filter) {
8654 : : RCU_INIT_POINTER(sk->sk_filter, NULL);
8655 : 0 : sk_filter_uncharge(sk, filter);
8656 : : ret = 0;
8657 : : }
8658 : :
8659 : 0 : return ret;
8660 : : }
8661 : : EXPORT_SYMBOL_GPL(sk_detach_filter);
8662 : :
8663 : 0 : int sk_get_filter(struct sock *sk, struct sock_filter __user *ubuf,
8664 : : unsigned int len)
8665 : : {
8666 : : struct sock_fprog_kern *fprog;
8667 : : struct sk_filter *filter;
8668 : : int ret = 0;
8669 : :
8670 : : lock_sock(sk);
8671 : 0 : filter = rcu_dereference_protected(sk->sk_filter,
8672 : : lockdep_sock_is_held(sk));
8673 [ # # ]: 0 : if (!filter)
8674 : : goto out;
8675 : :
8676 : : /* We're copying the filter that has been originally attached,
8677 : : * so no conversion/decode needed anymore. eBPF programs that
8678 : : * have no original program cannot be dumped through this.
8679 : : */
8680 : : ret = -EACCES;
8681 : 0 : fprog = filter->prog->orig_prog;
8682 [ # # ]: 0 : if (!fprog)
8683 : : goto out;
8684 : :
8685 : 0 : ret = fprog->len;
8686 [ # # ]: 0 : if (!len)
8687 : : /* User space only enquires number of filter blocks. */
8688 : : goto out;
8689 : :
8690 : : ret = -EINVAL;
8691 [ # # ]: 0 : if (len < fprog->len)
8692 : : goto out;
8693 : :
8694 : : ret = -EFAULT;
8695 [ # # ]: 0 : if (copy_to_user(ubuf, fprog->filter, bpf_classic_proglen(fprog)))
8696 : : goto out;
8697 : :
8698 : : /* Instead of bytes, the API requests to return the number
8699 : : * of filter blocks.
8700 : : */
8701 : 0 : ret = fprog->len;
8702 : : out:
8703 : 0 : release_sock(sk);
8704 : 0 : return ret;
8705 : : }
8706 : :
8707 : : #ifdef CONFIG_INET
8708 : : struct sk_reuseport_kern {
8709 : : struct sk_buff *skb;
8710 : : struct sock *sk;
8711 : : struct sock *selected_sk;
8712 : : void *data_end;
8713 : : u32 hash;
8714 : : u32 reuseport_id;
8715 : : bool bind_inany;
8716 : : };
8717 : :
8718 : : static void bpf_init_reuseport_kern(struct sk_reuseport_kern *reuse_kern,
8719 : : struct sock_reuseport *reuse,
8720 : : struct sock *sk, struct sk_buff *skb,
8721 : : u32 hash)
8722 : : {
8723 : 0 : reuse_kern->skb = skb;
8724 : 0 : reuse_kern->sk = sk;
8725 : 0 : reuse_kern->selected_sk = NULL;
8726 : 0 : reuse_kern->data_end = skb->data + skb_headlen(skb);
8727 : 0 : reuse_kern->hash = hash;
8728 : 0 : reuse_kern->reuseport_id = reuse->reuseport_id;
8729 : 0 : reuse_kern->bind_inany = reuse->bind_inany;
8730 : : }
8731 : :
8732 : 0 : struct sock *bpf_run_sk_reuseport(struct sock_reuseport *reuse, struct sock *sk,
8733 : : struct bpf_prog *prog, struct sk_buff *skb,
8734 : : u32 hash)
8735 : : {
8736 : : struct sk_reuseport_kern reuse_kern;
8737 : : enum sk_action action;
8738 : :
8739 : : bpf_init_reuseport_kern(&reuse_kern, reuse, sk, skb, hash);
8740 [ # # ]: 0 : action = BPF_PROG_RUN(prog, &reuse_kern);
8741 : :
8742 [ # # ]: 0 : if (action == SK_PASS)
8743 : 0 : return reuse_kern.selected_sk;
8744 : : else
8745 : : return ERR_PTR(-ECONNREFUSED);
8746 : : }
8747 : :
8748 : 0 : BPF_CALL_4(sk_select_reuseport, struct sk_reuseport_kern *, reuse_kern,
8749 : : struct bpf_map *, map, void *, key, u32, flags)
8750 : : {
8751 : : struct sock_reuseport *reuse;
8752 : : struct sock *selected_sk;
8753 : :
8754 : 0 : selected_sk = map->ops->map_lookup_elem(map, key);
8755 [ # # ]: 0 : if (!selected_sk)
8756 : : return -ENOENT;
8757 : :
8758 : 0 : reuse = rcu_dereference(selected_sk->sk_reuseport_cb);
8759 [ # # ]: 0 : if (!reuse)
8760 : : /* selected_sk is unhashed (e.g. by close()) after the
8761 : : * above map_lookup_elem(). Treat selected_sk has already
8762 : : * been removed from the map.
8763 : : */
8764 : : return -ENOENT;
8765 : :
8766 [ # # ]: 0 : if (unlikely(reuse->reuseport_id != reuse_kern->reuseport_id)) {
8767 : : struct sock *sk;
8768 : :
8769 [ # # ]: 0 : if (unlikely(!reuse_kern->reuseport_id))
8770 : : /* There is a small race between adding the
8771 : : * sk to the map and setting the
8772 : : * reuse_kern->reuseport_id.
8773 : : * Treat it as the sk has not been added to
8774 : : * the bpf map yet.
8775 : : */
8776 : : return -ENOENT;
8777 : :
8778 : 0 : sk = reuse_kern->sk;
8779 [ # # ]: 0 : if (sk->sk_protocol != selected_sk->sk_protocol)
8780 : : return -EPROTOTYPE;
8781 [ # # ]: 0 : else if (sk->sk_family != selected_sk->sk_family)
8782 : : return -EAFNOSUPPORT;
8783 : :
8784 : : /* Catch all. Likely bound to a different sockaddr. */
8785 : : return -EBADFD;
8786 : : }
8787 : :
8788 : 0 : reuse_kern->selected_sk = selected_sk;
8789 : :
8790 : : return 0;
8791 : : }
8792 : :
8793 : : static const struct bpf_func_proto sk_select_reuseport_proto = {
8794 : : .func = sk_select_reuseport,
8795 : : .gpl_only = false,
8796 : : .ret_type = RET_INTEGER,
8797 : : .arg1_type = ARG_PTR_TO_CTX,
8798 : : .arg2_type = ARG_CONST_MAP_PTR,
8799 : : .arg3_type = ARG_PTR_TO_MAP_KEY,
8800 : : .arg4_type = ARG_ANYTHING,
8801 : : };
8802 : :
8803 : 0 : BPF_CALL_4(sk_reuseport_load_bytes,
8804 : : const struct sk_reuseport_kern *, reuse_kern, u32, offset,
8805 : : void *, to, u32, len)
8806 : : {
8807 : 0 : return ____bpf_skb_load_bytes(reuse_kern->skb, offset, to, len);
8808 : : }
8809 : :
8810 : : static const struct bpf_func_proto sk_reuseport_load_bytes_proto = {
8811 : : .func = sk_reuseport_load_bytes,
8812 : : .gpl_only = false,
8813 : : .ret_type = RET_INTEGER,
8814 : : .arg1_type = ARG_PTR_TO_CTX,
8815 : : .arg2_type = ARG_ANYTHING,
8816 : : .arg3_type = ARG_PTR_TO_UNINIT_MEM,
8817 : : .arg4_type = ARG_CONST_SIZE,
8818 : : };
8819 : :
8820 : 0 : BPF_CALL_5(sk_reuseport_load_bytes_relative,
8821 : : const struct sk_reuseport_kern *, reuse_kern, u32, offset,
8822 : : void *, to, u32, len, u32, start_header)
8823 : : {
8824 : 0 : return ____bpf_skb_load_bytes_relative(reuse_kern->skb, offset, to,
8825 : : len, start_header);
8826 : : }
8827 : :
8828 : : static const struct bpf_func_proto sk_reuseport_load_bytes_relative_proto = {
8829 : : .func = sk_reuseport_load_bytes_relative,
8830 : : .gpl_only = false,
8831 : : .ret_type = RET_INTEGER,
8832 : : .arg1_type = ARG_PTR_TO_CTX,
8833 : : .arg2_type = ARG_ANYTHING,
8834 : : .arg3_type = ARG_PTR_TO_UNINIT_MEM,
8835 : : .arg4_type = ARG_CONST_SIZE,
8836 : : .arg5_type = ARG_ANYTHING,
8837 : : };
8838 : :
8839 : : static const struct bpf_func_proto *
8840 : 0 : sk_reuseport_func_proto(enum bpf_func_id func_id,
8841 : : const struct bpf_prog *prog)
8842 : : {
8843 [ # # # # ]: 0 : switch (func_id) {
8844 : : case BPF_FUNC_sk_select_reuseport:
8845 : : return &sk_select_reuseport_proto;
8846 : : case BPF_FUNC_skb_load_bytes:
8847 : 0 : return &sk_reuseport_load_bytes_proto;
8848 : : case BPF_FUNC_skb_load_bytes_relative:
8849 : 0 : return &sk_reuseport_load_bytes_relative_proto;
8850 : : default:
8851 : 0 : return bpf_base_func_proto(func_id);
8852 : : }
8853 : : }
8854 : :
8855 : : static bool
8856 : 0 : sk_reuseport_is_valid_access(int off, int size,
8857 : : enum bpf_access_type type,
8858 : : const struct bpf_prog *prog,
8859 : : struct bpf_insn_access_aux *info)
8860 : : {
8861 : : const u32 size_default = sizeof(__u32);
8862 : :
8863 [ # # # # ]: 0 : if (off < 0 || off >= sizeof(struct sk_reuseport_md) ||
8864 [ # # ]: 0 : off % size || type != BPF_READ)
8865 : : return false;
8866 : :
8867 [ # # # # : 0 : switch (off) {
# # ]
8868 : : case offsetof(struct sk_reuseport_md, data):
8869 : 0 : info->reg_type = PTR_TO_PACKET;
8870 : 0 : return size == sizeof(__u64);
8871 : :
8872 : : case offsetof(struct sk_reuseport_md, data_end):
8873 : 0 : info->reg_type = PTR_TO_PACKET_END;
8874 : 0 : return size == sizeof(__u64);
8875 : :
8876 : : case offsetof(struct sk_reuseport_md, hash):
8877 : 0 : return size == size_default;
8878 : :
8879 : : /* Fields that allow narrowing */
8880 : : case bpf_ctx_range(struct sk_reuseport_md, eth_protocol):
8881 [ # # ]: 0 : if (size < FIELD_SIZEOF(struct sk_buff, protocol))
8882 : : return false;
8883 : : /* fall through */
8884 : : case bpf_ctx_range(struct sk_reuseport_md, ip_protocol):
8885 : : case bpf_ctx_range(struct sk_reuseport_md, bind_inany):
8886 : : case bpf_ctx_range(struct sk_reuseport_md, len):
8887 : : bpf_ctx_record_field_size(info, size_default);
8888 : 0 : return bpf_ctx_narrow_access_ok(off, size, size_default);
8889 : :
8890 : : default:
8891 : : return false;
8892 : : }
8893 : : }
8894 : :
8895 : : #define SK_REUSEPORT_LOAD_FIELD(F) ({ \
8896 : : *insn++ = BPF_LDX_MEM(BPF_FIELD_SIZEOF(struct sk_reuseport_kern, F), \
8897 : : si->dst_reg, si->src_reg, \
8898 : : bpf_target_off(struct sk_reuseport_kern, F, \
8899 : : FIELD_SIZEOF(struct sk_reuseport_kern, F), \
8900 : : target_size)); \
8901 : : })
8902 : :
8903 : : #define SK_REUSEPORT_LOAD_SKB_FIELD(SKB_FIELD) \
8904 : : SOCK_ADDR_LOAD_NESTED_FIELD(struct sk_reuseport_kern, \
8905 : : struct sk_buff, \
8906 : : skb, \
8907 : : SKB_FIELD)
8908 : :
8909 : : #define SK_REUSEPORT_LOAD_SK_FIELD_SIZE_OFF(SK_FIELD, BPF_SIZE, EXTRA_OFF) \
8910 : : SOCK_ADDR_LOAD_NESTED_FIELD_SIZE_OFF(struct sk_reuseport_kern, \
8911 : : struct sock, \
8912 : : sk, \
8913 : : SK_FIELD, BPF_SIZE, EXTRA_OFF)
8914 : :
8915 : 0 : static u32 sk_reuseport_convert_ctx_access(enum bpf_access_type type,
8916 : : const struct bpf_insn *si,
8917 : : struct bpf_insn *insn_buf,
8918 : : struct bpf_prog *prog,
8919 : : u32 *target_size)
8920 : : {
8921 : : struct bpf_insn *insn = insn_buf;
8922 : :
8923 [ # # # # : 0 : switch (si->off) {
# # # # ]
8924 : : case offsetof(struct sk_reuseport_md, data):
8925 : 0 : SK_REUSEPORT_LOAD_SKB_FIELD(data);
8926 : 0 : break;
8927 : :
8928 : : case offsetof(struct sk_reuseport_md, len):
8929 : 0 : SK_REUSEPORT_LOAD_SKB_FIELD(len);
8930 : 0 : break;
8931 : :
8932 : : case offsetof(struct sk_reuseport_md, eth_protocol):
8933 : 0 : SK_REUSEPORT_LOAD_SKB_FIELD(protocol);
8934 : 0 : break;
8935 : :
8936 : : case offsetof(struct sk_reuseport_md, ip_protocol):
8937 : : BUILD_BUG_ON(HWEIGHT32(SK_FL_PROTO_MASK) != BITS_PER_BYTE);
8938 : 0 : SK_REUSEPORT_LOAD_SK_FIELD_SIZE_OFF(__sk_flags_offset,
8939 : : BPF_W, 0);
8940 : 0 : *insn++ = BPF_ALU32_IMM(BPF_AND, si->dst_reg, SK_FL_PROTO_MASK);
8941 : 0 : *insn++ = BPF_ALU32_IMM(BPF_RSH, si->dst_reg,
8942 : : SK_FL_PROTO_SHIFT);
8943 : : /* SK_FL_PROTO_MASK and SK_FL_PROTO_SHIFT are endian
8944 : : * aware. No further narrowing or masking is needed.
8945 : : */
8946 : 0 : *target_size = 1;
8947 : 0 : break;
8948 : :
8949 : : case offsetof(struct sk_reuseport_md, data_end):
8950 : 0 : SK_REUSEPORT_LOAD_FIELD(data_end);
8951 : 0 : break;
8952 : :
8953 : : case offsetof(struct sk_reuseport_md, hash):
8954 : 0 : SK_REUSEPORT_LOAD_FIELD(hash);
8955 : 0 : break;
8956 : :
8957 : : case offsetof(struct sk_reuseport_md, bind_inany):
8958 : 0 : SK_REUSEPORT_LOAD_FIELD(bind_inany);
8959 : 0 : break;
8960 : : }
8961 : :
8962 : 0 : return insn - insn_buf;
8963 : : }
8964 : :
8965 : : const struct bpf_verifier_ops sk_reuseport_verifier_ops = {
8966 : : .get_func_proto = sk_reuseport_func_proto,
8967 : : .is_valid_access = sk_reuseport_is_valid_access,
8968 : : .convert_ctx_access = sk_reuseport_convert_ctx_access,
8969 : : };
8970 : :
8971 : : const struct bpf_prog_ops sk_reuseport_prog_ops = {
8972 : : };
8973 : : #endif /* CONFIG_INET */
|