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 8 SEC("tp_btf/sys_enter") 9 __success 10 __log_level(2) 11 __msg("r8 = *(u64 *)(r7 +0) ; R7_w=ptr_nameidata(off={{[0-9]+}}) R8_w=rdonly_untrusted_mem(sz=0)") 12 __msg("r9 = *(u8 *)(r8 +0) ; R8_w=rdonly_untrusted_mem(sz=0) R9_w=scalar") 13 int 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 39 SEC("socket") 40 __success 41 __retval(0) 42 int 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 53 SEC("socket") 54 __success 55 __retval(1) 56 int 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 65 SEC("socket") 66 __success 67 int 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 80 SEC("socket") 81 __failure 82 __msg("cannot write into rdonly_untrusted_mem") 83 int 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 93 SEC("socket") 94 __failure 95 __msg("cannot write into rdonly_untrusted_mem") 96 int 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 106 SEC("socket") 107 __failure 108 __msg("cannot write into rdonly_untrusted_mem") 109 int 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 118 SEC("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") 122 int 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 131 SEC("?fentry.s/" SYS_PREFIX "sys_getpgid") 132 __failure 133 __msg("R1 type=rdonly_untrusted_mem expected=") 134 int 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 147 static __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 155 SEC("socket") 156 __success 157 __retval(0) 158 int 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))) 168 u8 global[] = { 169 0x11, 0x22, 0x33, 0x44, 170 0x55, 0x66, 0x77, 0x88, 171 0x99 172 }; 173 174 __always_inline 175 static 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 194 SEC("socket") 195 __retval(0x88442211) 196 int diff_size_access(void *ctx) 197 { 198 return combine(bpf_rdonly_cast(&global, 0)); 199 } 200 201 SEC("socket") 202 __retval(0x99553322) 203 int 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 213 SEC("socket") 214 __success 215 __retval(1) 216 int 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 229 char _license[] SEC("license") = "GPL"; 230