selftests/bpf: Fix erroneous bitmask operation
[platform/kernel/linux-rpi.git] / tools / testing / selftests / bpf / progs / sockopt_multi.c
1 // SPDX-License-Identifier: GPL-2.0
2 #include <netinet/in.h>
3 #include <linux/bpf.h>
4 #include <bpf/bpf_helpers.h>
5
6 char _license[] SEC("license") = "GPL";
7
8 __u32 page_size = 0;
9
10 SEC("cgroup/getsockopt")
11 int _getsockopt_child(struct bpf_sockopt *ctx)
12 {
13         __u8 *optval_end = ctx->optval_end;
14         __u8 *optval = ctx->optval;
15
16         if (ctx->level != SOL_IP || ctx->optname != IP_TOS)
17                 goto out;
18
19         if (optval + 1 > optval_end)
20                 return 0; /* EPERM, bounds check */
21
22         if (optval[0] != 0x80)
23                 return 0; /* EPERM, unexpected optval from the kernel */
24
25         ctx->retval = 0; /* Reset system call return value to zero */
26
27         optval[0] = 0x90;
28         ctx->optlen = 1;
29
30         return 1;
31
32 out:
33         /* optval larger than PAGE_SIZE use kernel's buffer. */
34         if (ctx->optlen > page_size)
35                 ctx->optlen = 0;
36         return 1;
37 }
38
39 SEC("cgroup/getsockopt")
40 int _getsockopt_parent(struct bpf_sockopt *ctx)
41 {
42         __u8 *optval_end = ctx->optval_end;
43         __u8 *optval = ctx->optval;
44
45         if (ctx->level != SOL_IP || ctx->optname != IP_TOS)
46                 goto out;
47
48         if (optval + 1 > optval_end)
49                 return 0; /* EPERM, bounds check */
50
51         if (optval[0] != 0x90)
52                 return 0; /* EPERM, unexpected optval from the kernel */
53
54         ctx->retval = 0; /* Reset system call return value to zero */
55
56         optval[0] = 0xA0;
57         ctx->optlen = 1;
58
59         return 1;
60
61 out:
62         /* optval larger than PAGE_SIZE use kernel's buffer. */
63         if (ctx->optlen > page_size)
64                 ctx->optlen = 0;
65         return 1;
66 }
67
68 SEC("cgroup/setsockopt")
69 int _setsockopt(struct bpf_sockopt *ctx)
70 {
71         __u8 *optval_end = ctx->optval_end;
72         __u8 *optval = ctx->optval;
73
74         if (ctx->level != SOL_IP || ctx->optname != IP_TOS)
75                 goto out;
76
77         if (optval + 1 > optval_end)
78                 return 0; /* EPERM, bounds check */
79
80         optval[0] += 0x10;
81         ctx->optlen = 1;
82
83         return 1;
84
85 out:
86         /* optval larger than PAGE_SIZE use kernel's buffer. */
87         if (ctx->optlen > page_size)
88                 ctx->optlen = 0;
89         return 1;
90 }