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 | struct syscall_test_args { |
8 | __u8 data[16]; |
9 | size_t size; |
10 | }; |
11 | |
12 | SEC("?syscall" ) |
13 | int kfunc_syscall_test_fail(struct syscall_test_args *args) |
14 | { |
15 | bpf_kfunc_call_test_mem_len_pass1(mem: &args->data, len: sizeof(*args) + 1); |
16 | |
17 | return 0; |
18 | } |
19 | |
20 | SEC("?syscall" ) |
21 | int kfunc_syscall_test_null_fail(struct syscall_test_args *args) |
22 | { |
23 | /* Must be called with args as a NULL pointer |
24 | * we do not check for it to have the verifier consider that |
25 | * the pointer might not be null, and so we can load it. |
26 | * |
27 | * So the following can not be added: |
28 | * |
29 | * if (args) |
30 | * return -22; |
31 | */ |
32 | |
33 | bpf_kfunc_call_test_mem_len_pass1(mem: args, len: sizeof(*args)); |
34 | |
35 | return 0; |
36 | } |
37 | |
38 | SEC("?tc" ) |
39 | int kfunc_call_test_get_mem_fail_rdonly(struct __sk_buff *skb) |
40 | { |
41 | struct prog_test_ref_kfunc *pt; |
42 | unsigned long s = 0; |
43 | int *p = NULL; |
44 | int ret = 0; |
45 | |
46 | pt = bpf_kfunc_call_test_acquire(scalar_ptr: &s); |
47 | if (pt) { |
48 | p = bpf_kfunc_call_test_get_rdonly_mem(p: pt, rdonly_buf_size: 2 * sizeof(int)); |
49 | if (p) |
50 | p[0] = 42; /* this is a read-only buffer, so -EACCES */ |
51 | else |
52 | ret = -1; |
53 | |
54 | bpf_kfunc_call_test_release(p: pt); |
55 | } |
56 | return ret; |
57 | } |
58 | |
59 | SEC("?tc" ) |
60 | int kfunc_call_test_get_mem_fail_use_after_free(struct __sk_buff *skb) |
61 | { |
62 | struct prog_test_ref_kfunc *pt; |
63 | unsigned long s = 0; |
64 | int *p = NULL; |
65 | int ret = 0; |
66 | |
67 | pt = bpf_kfunc_call_test_acquire(scalar_ptr: &s); |
68 | if (pt) { |
69 | p = bpf_kfunc_call_test_get_rdwr_mem(p: pt, rdwr_buf_size: 2 * sizeof(int)); |
70 | if (p) { |
71 | p[0] = 42; |
72 | ret = p[1]; /* 108 */ |
73 | } else { |
74 | ret = -1; |
75 | } |
76 | |
77 | bpf_kfunc_call_test_release(p: pt); |
78 | } |
79 | if (p) |
80 | ret = p[0]; /* p is not valid anymore */ |
81 | |
82 | return ret; |
83 | } |
84 | |
85 | SEC("?tc" ) |
86 | int kfunc_call_test_get_mem_fail_oob(struct __sk_buff *skb) |
87 | { |
88 | struct prog_test_ref_kfunc *pt; |
89 | unsigned long s = 0; |
90 | int *p = NULL; |
91 | int ret = 0; |
92 | |
93 | pt = bpf_kfunc_call_test_acquire(scalar_ptr: &s); |
94 | if (pt) { |
95 | p = bpf_kfunc_call_test_get_rdonly_mem(p: pt, rdonly_buf_size: 2 * sizeof(int)); |
96 | if (p) |
97 | ret = p[2 * sizeof(int)]; /* oob access, so -EACCES */ |
98 | else |
99 | ret = -1; |
100 | |
101 | bpf_kfunc_call_test_release(p: pt); |
102 | } |
103 | return ret; |
104 | } |
105 | |
106 | int not_const_size = 2 * sizeof(int); |
107 | |
108 | SEC("?tc" ) |
109 | int kfunc_call_test_get_mem_fail_not_const(struct __sk_buff *skb) |
110 | { |
111 | struct prog_test_ref_kfunc *pt; |
112 | unsigned long s = 0; |
113 | int *p = NULL; |
114 | int ret = 0; |
115 | |
116 | pt = bpf_kfunc_call_test_acquire(scalar_ptr: &s); |
117 | if (pt) { |
118 | p = bpf_kfunc_call_test_get_rdonly_mem(p: pt, rdonly_buf_size: not_const_size); /* non const size, -EINVAL */ |
119 | if (p) |
120 | ret = p[0]; |
121 | else |
122 | ret = -1; |
123 | |
124 | bpf_kfunc_call_test_release(p: pt); |
125 | } |
126 | return ret; |
127 | } |
128 | |
129 | SEC("?tc" ) |
130 | int kfunc_call_test_mem_acquire_fail(struct __sk_buff *skb) |
131 | { |
132 | struct prog_test_ref_kfunc *pt; |
133 | unsigned long s = 0; |
134 | int *p = NULL; |
135 | int ret = 0; |
136 | |
137 | pt = bpf_kfunc_call_test_acquire(scalar_ptr: &s); |
138 | if (pt) { |
139 | /* we are failing on this one, because we are not acquiring a PTR_TO_BTF_ID (a struct ptr) */ |
140 | p = bpf_kfunc_call_test_acq_rdonly_mem(p: pt, rdonly_buf_size: 2 * sizeof(int)); |
141 | if (p) |
142 | ret = p[0]; |
143 | else |
144 | ret = -1; |
145 | |
146 | bpf_kfunc_call_int_mem_release(p); |
147 | |
148 | bpf_kfunc_call_test_release(p: pt); |
149 | } |
150 | return ret; |
151 | } |
152 | |
153 | char _license[] SEC("license" ) = "GPL" ; |
154 | |