1 | // SPDX-License-Identifier: GPL-2.0 |
2 | /* Copyright (c) 2021 Facebook */ |
3 | #include <vmlinux.h> |
4 | #include <bpf/bpf_helpers.h> |
5 | #include "../bpf_testmod/bpf_testmod_kfunc.h" |
6 | |
7 | SEC("tc" ) |
8 | int kfunc_call_test4(struct __sk_buff *skb) |
9 | { |
10 | struct bpf_sock *sk = skb->sk; |
11 | long tmp; |
12 | |
13 | if (!sk) |
14 | return -1; |
15 | |
16 | sk = bpf_sk_fullsock(sk); |
17 | if (!sk) |
18 | return -1; |
19 | |
20 | tmp = bpf_kfunc_call_test4(a: -3, b: -30, c: -200, d: -1000); |
21 | return (tmp >> 32) + tmp; |
22 | } |
23 | |
24 | SEC("tc" ) |
25 | int kfunc_call_test2(struct __sk_buff *skb) |
26 | { |
27 | struct bpf_sock *sk = skb->sk; |
28 | |
29 | if (!sk) |
30 | return -1; |
31 | |
32 | sk = bpf_sk_fullsock(sk); |
33 | if (!sk) |
34 | return -1; |
35 | |
36 | return bpf_kfunc_call_test2((struct sock *)sk, 1, 2); |
37 | } |
38 | |
39 | SEC("tc" ) |
40 | int kfunc_call_test1(struct __sk_buff *skb) |
41 | { |
42 | struct bpf_sock *sk = skb->sk; |
43 | __u64 a = 1ULL << 32; |
44 | __u32 ret; |
45 | |
46 | if (!sk) |
47 | return -1; |
48 | |
49 | sk = bpf_sk_fullsock(sk); |
50 | if (!sk) |
51 | return -1; |
52 | |
53 | a = bpf_kfunc_call_test1((struct sock *)sk, 1, a | 2, 3, a | 4); |
54 | ret = a >> 32; /* ret should be 2 */ |
55 | ret += (__u32)a; /* ret should be 12 */ |
56 | |
57 | return ret; |
58 | } |
59 | |
60 | SEC("tc" ) |
61 | int kfunc_call_test_ref_btf_id(struct __sk_buff *skb) |
62 | { |
63 | struct prog_test_ref_kfunc *pt; |
64 | unsigned long s = 0; |
65 | int ret = 0; |
66 | |
67 | pt = bpf_kfunc_call_test_acquire(scalar_ptr: &s); |
68 | if (pt) { |
69 | if (pt->a != 42 || pt->b != 108) |
70 | ret = -1; |
71 | bpf_kfunc_call_test_release(p: pt); |
72 | } |
73 | return ret; |
74 | } |
75 | |
76 | SEC("tc" ) |
77 | int kfunc_call_test_pass(struct __sk_buff *skb) |
78 | { |
79 | struct prog_test_pass1 p1 = {}; |
80 | struct prog_test_pass2 p2 = {}; |
81 | short a = 0; |
82 | __u64 b = 0; |
83 | long c = 0; |
84 | char d = 0; |
85 | int e = 0; |
86 | |
87 | bpf_kfunc_call_test_pass_ctx(skb); |
88 | bpf_kfunc_call_test_pass1(p: &p1); |
89 | bpf_kfunc_call_test_pass2(p: &p2); |
90 | |
91 | bpf_kfunc_call_test_mem_len_pass1(mem: &a, len: sizeof(a)); |
92 | bpf_kfunc_call_test_mem_len_pass1(&b, sizeof(b)); |
93 | bpf_kfunc_call_test_mem_len_pass1(mem: &c, len: sizeof(c)); |
94 | bpf_kfunc_call_test_mem_len_pass1(mem: &d, len: sizeof(d)); |
95 | bpf_kfunc_call_test_mem_len_pass1(mem: &e, len: sizeof(e)); |
96 | bpf_kfunc_call_test_mem_len_fail2(&b, -1); |
97 | |
98 | return 0; |
99 | } |
100 | |
101 | struct syscall_test_args { |
102 | __u8 data[16]; |
103 | size_t size; |
104 | }; |
105 | |
106 | SEC("syscall" ) |
107 | int kfunc_syscall_test(struct syscall_test_args *args) |
108 | { |
109 | const long size = args->size; |
110 | |
111 | if (size > sizeof(args->data)) |
112 | return -7; /* -E2BIG */ |
113 | |
114 | bpf_kfunc_call_test_mem_len_pass1(mem: &args->data, len: sizeof(args->data)); |
115 | bpf_kfunc_call_test_mem_len_pass1(mem: &args->data, len: sizeof(*args)); |
116 | bpf_kfunc_call_test_mem_len_pass1(mem: &args->data, len: size); |
117 | |
118 | return 0; |
119 | } |
120 | |
121 | SEC("syscall" ) |
122 | int kfunc_syscall_test_null(struct syscall_test_args *args) |
123 | { |
124 | /* Must be called with args as a NULL pointer |
125 | * we do not check for it to have the verifier consider that |
126 | * the pointer might not be null, and so we can load it. |
127 | * |
128 | * So the following can not be added: |
129 | * |
130 | * if (args) |
131 | * return -22; |
132 | */ |
133 | |
134 | bpf_kfunc_call_test_mem_len_pass1(mem: args, len: 0); |
135 | |
136 | return 0; |
137 | } |
138 | |
139 | SEC("tc" ) |
140 | int kfunc_call_test_get_mem(struct __sk_buff *skb) |
141 | { |
142 | struct prog_test_ref_kfunc *pt; |
143 | unsigned long s = 0; |
144 | int *p = NULL; |
145 | int ret = 0; |
146 | |
147 | pt = bpf_kfunc_call_test_acquire(scalar_ptr: &s); |
148 | if (pt) { |
149 | p = bpf_kfunc_call_test_get_rdwr_mem(p: pt, rdwr_buf_size: 2 * sizeof(int)); |
150 | if (p) { |
151 | p[0] = 42; |
152 | ret = p[1]; /* 108 */ |
153 | } else { |
154 | ret = -1; |
155 | } |
156 | |
157 | if (ret >= 0) { |
158 | p = bpf_kfunc_call_test_get_rdonly_mem(p: pt, rdonly_buf_size: 2 * sizeof(int)); |
159 | if (p) |
160 | ret = p[0]; /* 42 */ |
161 | else |
162 | ret = -1; |
163 | } |
164 | |
165 | bpf_kfunc_call_test_release(p: pt); |
166 | } |
167 | return ret; |
168 | } |
169 | |
170 | SEC("tc" ) |
171 | int kfunc_call_test_static_unused_arg(struct __sk_buff *skb) |
172 | { |
173 | |
174 | u32 expected = 5, actual; |
175 | |
176 | actual = bpf_kfunc_call_test_static_unused_arg(expected, 0xdeadbeef); |
177 | return actual != expected ? -1 : 0; |
178 | } |
179 | |
180 | char _license[] SEC("license" ) = "GPL" ; |
181 | |