File Index
Files and directories
Sign in
FILE

mem_rdonly_untrusted.c

File preview with syntax highlighting.

linux-6.19.14/tools/testing/selftests/bpf/progs/mem_rdonly_untrusted.c C
  1// SPDX-License-Identifier: GPL-2.0
  2
  3#include <vmlinux.h>
  4#include <bpf/bpf_core_read.h>
  5#include "bpf_misc.h"
  6#include "../test_kmods/bpf_testmod_kfunc.h"
  7
  8SEC("tp_btf/sys_enter")
  9__success
 10__log_level(2)
 11__msg("r8 = *(u64 *)(r7 +0)          ; R7=ptr_nameidata(off={{[0-9]+}}) R8=rdonly_untrusted_mem(sz=0)")
 12__msg("r9 = *(u8 *)(r8 +0)           ; R8=rdonly_untrusted_mem(sz=0) R9=scalar")
 13int btf_id_to_ptr_mem(void *ctx)
 14{
 15	struct task_struct *task;
 16	struct nameidata *idata;
 17	u64 ret, off;
 18
 19	task = bpf_get_current_task_btf();
 20	idata = task->nameidata;
 21	off = bpf_core_field_offset(struct nameidata, pathname);
 22	/*
 23	 * asm block to have reliable match target for __msg, equivalent of:
 24	 *   ret = task->nameidata->pathname[0];
 25	 */
 26	asm volatile (
 27	"r7 = %[idata];"
 28	"r7 += %[off];"
 29	"r8 = *(u64 *)(r7 + 0);"
 30	"r9 = *(u8 *)(r8 + 0);"
 31	"%[ret] = r9;"
 32	: [ret]"=r"(ret)
 33	: [idata]"r"(idata),
 34	  [off]"r"(off)
 35	: "r7", "r8", "r9");
 36	return ret;
 37}
 38
 39SEC("socket")
 40__success
 41__retval(0)
 42int ldx_is_ok_bad_addr(void *ctx)
 43{
 44	char *p;
 45
 46	if (!bpf_core_enum_value_exists(enum bpf_features, BPF_FEAT_RDONLY_CAST_TO_VOID))
 47		return 42;
 48
 49	p = bpf_rdonly_cast(0, 0);
 50	return p[0x7fff];
 51}
 52
 53SEC("socket")
 54__success
 55__retval(1)
 56int ldx_is_ok_good_addr(void *ctx)
 57{
 58	int v, *p;
 59
 60	v = 1;
 61	p = bpf_rdonly_cast(&v, 0);
 62	return *p;
 63}
 64
 65SEC("socket")
 66__success
 67int offset_not_tracked(void *ctx)
 68{
 69	int *p, i, s;
 70
 71	p = bpf_rdonly_cast(0, 0);
 72	s = 0;
 73	bpf_for(i, 0, 1000 * 1000 * 1000) {
 74		p++;
 75		s += *p;
 76	}
 77	return s;
 78}
 79
 80SEC("socket")
 81__failure
 82__msg("cannot write into rdonly_untrusted_mem")
 83int stx_not_ok(void *ctx)
 84{
 85	int v, *p;
 86
 87	v = 1;
 88	p = bpf_rdonly_cast(&v, 0);
 89	*p = 1;
 90	return 0;
 91}
 92
 93SEC("socket")
 94__failure
 95__msg("cannot write into rdonly_untrusted_mem")
 96int atomic_not_ok(void *ctx)
 97{
 98	int v, *p;
 99
100	v = 1;
101	p = bpf_rdonly_cast(&v, 0);
102	__sync_fetch_and_add(p, 1);
103	return 0;
104}
105
106SEC("socket")
107__failure
108__msg("cannot write into rdonly_untrusted_mem")
109int atomic_rmw_not_ok(void *ctx)
110{
111	long v, *p;
112
113	v = 1;
114	p = bpf_rdonly_cast(&v, 0);
115	return __sync_val_compare_and_swap(p, 0, 42);
116}
117
118SEC("socket")
119__failure
120__msg("invalid access to memory, mem_size=0 off=0 size=4")
121__msg("R1 min value is outside of the allowed memory range")
122int kfunc_param_not_ok(void *ctx)
123{
124	int *p;
125
126	p = bpf_rdonly_cast(0, 0);
127	bpf_kfunc_trusted_num_test(p);
128	return 0;
129}
130
131SEC("?fentry.s/" SYS_PREFIX "sys_getpgid")
132__failure
133__msg("R1 type=rdonly_untrusted_mem expected=")
134int helper_param_not_ok(void *ctx)
135{
136	char *p;
137
138	p = bpf_rdonly_cast(0, 0);
139	/*
140	 * Any helper with ARG_CONST_SIZE_OR_ZERO constraint will do,
141	 * the most permissive constraint
142	 */
143	bpf_copy_from_user(p, 0, (void *)42);
144	return 0;
145}
146
147static __noinline u64 *get_some_addr(void)
148{
149	if (bpf_get_prandom_u32())
150		return bpf_rdonly_cast(0, bpf_core_type_id_kernel(struct sock));
151	else
152		return bpf_rdonly_cast(0, 0);
153}
154
155SEC("socket")
156__success
157__retval(0)
158int mixed_mem_type(void *ctx)
159{
160	u64 *p;
161
162	/* Try to avoid compiler hoisting load to if branches by using __noinline func. */
163	p = get_some_addr();
164	return *p;
165}
166
167__attribute__((__aligned__(8)))
168u8 global[] = {
169	0x11, 0x22, 0x33, 0x44,
170	0x55, 0x66, 0x77, 0x88,
171	0x99
172};
173
174__always_inline
175static u64 combine(void *p)
176{
177	u64 acc;
178
179	acc = 0;
180#if __BYTE_ORDER__ == __ORDER_LITTLE_ENDIAN__
181	acc |= (*(u64 *)p >> 56) << 24;
182	acc |= (*(u32 *)p >> 24) << 16;
183	acc |= (*(u16 *)p >> 8)  << 8;
184	acc |= *(u8 *)p;
185#else
186	acc |= (*(u64 *)p & 0xff) << 24;
187	acc |= (*(u32 *)p & 0xff) << 16;
188	acc |= (*(u16 *)p & 0xff) << 8;
189	acc |= *(u8 *)p;
190#endif
191	return acc;
192}
193
194SEC("socket")
195__retval(0x88442211)
196int diff_size_access(void *ctx)
197{
198	return combine(bpf_rdonly_cast(&global, 0));
199}
200
201SEC("socket")
202__retval(0x99553322)
203int misaligned_access(void *ctx)
204{
205	return combine(bpf_rdonly_cast(&global, 0) + 1);
206}
207
208__weak int return_one(void)
209{
210	return 1;
211}
212
213SEC("socket")
214__success
215__retval(1)
216int null_check(void *ctx)
217{
218	int *p;
219
220	p = bpf_rdonly_cast(0, 0);
221	if (p == 0)
222		/* make this a function call to avoid compiler
223		 * moving r0 assignment before check.
224		 */
225		return return_one();
226	return 0;
227}
228
229char _license[] SEC("license") = "GPL";
~/ Read-only file preview.