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("socket") 9 __success 10 __retval(0) 11 int ldx_is_ok_bad_addr(void *ctx) 12 { 13 char *p; 14 15 if (!bpf_core_enum_value_exists(enum bpf_features, BPF_FEAT_RDONLY_CAST_TO_VOID)) 16 return 42; 17 18 p = bpf_rdonly_cast(0, 0); 19 return p[0x7fff]; 20 } 21 22 SEC("socket") 23 __success 24 __retval(1) 25 int ldx_is_ok_good_addr(void *ctx) 26 { 27 int v, *p; 28 29 v = 1; 30 p = bpf_rdonly_cast(&v, 0); 31 return *p; 32 } 33 34 SEC("socket") 35 __success 36 int offset_not_tracked(void *ctx) 37 { 38 int *p, i, s; 39 40 p = bpf_rdonly_cast(0, 0); 41 s = 0; 42 bpf_for(i, 0, 1000 * 1000 * 1000) { 43 p++; 44 s += *p; 45 } 46 return s; 47 } 48 49 SEC("socket") 50 __failure 51 __msg("cannot write into rdonly_untrusted_mem") 52 int stx_not_ok(void *ctx) 53 { 54 int v, *p; 55 56 v = 1; 57 p = bpf_rdonly_cast(&v, 0); 58 *p = 1; 59 return 0; 60 } 61 62 SEC("socket") 63 __failure 64 __msg("cannot write into rdonly_untrusted_mem") 65 int atomic_not_ok(void *ctx) 66 { 67 int v, *p; 68 69 v = 1; 70 p = bpf_rdonly_cast(&v, 0); 71 __sync_fetch_and_add(p, 1); 72 return 0; 73 } 74 75 SEC("socket") 76 __failure 77 __msg("cannot write into rdonly_untrusted_mem") 78 int atomic_rmw_not_ok(void *ctx) 79 { 80 long v, *p; 81 82 v = 1; 83 p = bpf_rdonly_cast(&v, 0); 84 return __sync_val_compare_and_swap(p, 0, 42); 85 } 86 87 SEC("socket") 88 __failure 89 __msg("invalid access to memory, mem_size=0 off=0 size=4") 90 __msg("R1 min value is outside of the allowed memory range") 91 int kfunc_param_not_ok(void *ctx) 92 { 93 int *p; 94 95 p = bpf_rdonly_cast(0, 0); 96 bpf_kfunc_trusted_num_test(p); 97 return 0; 98 } 99 100 SEC("?fentry.s/" SYS_PREFIX "sys_getpgid") 101 __failure 102 __msg("R1 type=rdonly_untrusted_mem expected=") 103 int helper_param_not_ok(void *ctx) 104 { 105 char *p; 106 107 p = bpf_rdonly_cast(0, 0); 108 /* 109 * Any helper with ARG_CONST_SIZE_OR_ZERO constraint will do, 110 * the most permissive constraint 111 */ 112 bpf_copy_from_user(p, 0, (void *)42); 113 return 0; 114 } 115 116 static __noinline u64 *get_some_addr(void) 117 { 118 if (bpf_get_prandom_u32()) 119 return bpf_rdonly_cast(0, bpf_core_type_id_kernel(struct sock)); 120 else 121 return bpf_rdonly_cast(0, 0); 122 } 123 124 SEC("socket") 125 __success 126 __retval(0) 127 int mixed_mem_type(void *ctx) 128 { 129 u64 *p; 130 131 /* Try to avoid compiler hoisting load to if branches by using __noinline func. */ 132 p = get_some_addr(); 133 return *p; 134 } 135 136 __attribute__((__aligned__(8))) 137 u8 global[] = { 138 0x11, 0x22, 0x33, 0x44, 139 0x55, 0x66, 0x77, 0x88, 140 0x99 141 }; 142 143 __always_inline 144 static u64 combine(void *p) 145 { 146 u64 acc; 147 148 acc = 0; 149 #if __BYTE_ORDER__ == __ORDER_LITTLE_ENDIAN__ 150 acc |= (*(u64 *)p >> 56) << 24; 151 acc |= (*(u32 *)p >> 24) << 16; 152 acc |= (*(u16 *)p >> 8) << 8; 153 acc |= *(u8 *)p; 154 #else 155 acc |= (*(u64 *)p & 0xff) << 24; 156 acc |= (*(u32 *)p & 0xff) << 16; 157 acc |= (*(u16 *)p & 0xff) << 8; 158 acc |= *(u8 *)p; 159 #endif 160 return acc; 161 } 162 163 SEC("socket") 164 __retval(0x88442211) 165 int diff_size_access(void *ctx) 166 { 167 return combine(bpf_rdonly_cast(&global, 0)); 168 } 169 170 SEC("socket") 171 __retval(0x99553322) 172 int misaligned_access(void *ctx) 173 { 174 return combine(bpf_rdonly_cast(&global, 0) + 1); 175 } 176 177 __weak int return_one(void) 178 { 179 return 1; 180 } 181 182 SEC("socket") 183 __success 184 __retval(1) 185 int null_check(void *ctx) 186 { 187 int *p; 188 189 p = bpf_rdonly_cast(0, 0); 190 if (p == 0) 191 /* make this a function call to avoid compiler 192 * moving r0 assignment before check. 193 */ 194 return return_one(); 195 return 0; 196 } 197 198 char _license[] SEC("license") = "GPL"; 199