File Index
Files and directories
Sign in
FILE

verifier_value_ptr_arith.c

File preview with syntax highlighting.

linux-6.19.14/tools/testing/selftests/bpf/progs/verifier_value_ptr_arith.c C
   1// SPDX-License-Identifier: GPL-2.0
   2/* Converted from tools/testing/selftests/bpf/verifier/value_ptr_arith.c */
   3
   4#include <linux/bpf.h>
   5#include <bpf/bpf_helpers.h>
   6#include <errno.h>
   7#include "bpf_misc.h"
   8
   9#define MAX_ENTRIES 11
  10
  11struct test_val {
  12	unsigned int index;
  13	int foo[MAX_ENTRIES];
  14};
  15
  16struct {
  17	__uint(type, BPF_MAP_TYPE_ARRAY);
  18	__uint(max_entries, 1);
  19	__type(key, int);
  20	__type(value, struct test_val);
  21} map_array_48b SEC(".maps");
  22
  23struct other_val {
  24	long long foo;
  25	long long bar;
  26};
  27
  28struct {
  29	__uint(type, BPF_MAP_TYPE_HASH);
  30	__uint(max_entries, 1);
  31	__type(key, long long);
  32	__type(value, struct other_val);
  33} map_hash_16b SEC(".maps");
  34
  35struct {
  36	__uint(type, BPF_MAP_TYPE_HASH);
  37	__uint(max_entries, 1);
  38	__type(key, long long);
  39	__type(value, struct test_val);
  40} map_hash_48b SEC(".maps");
  41
  42SEC("socket")
  43__description("map access: known scalar += value_ptr unknown vs const")
  44__success __failure_unpriv
  45__msg_unpriv("R1 tried to add from different maps, paths or scalars")
  46__retval(1)
  47__naked void value_ptr_unknown_vs_const(void)
  48{
  49	asm volatile ("					\
  50	r0 = *(u32*)(r1 + %[__sk_buff_len]);		\
  51	r1 = 0;						\
  52	*(u64*)(r10 - 8) = r1;				\
  53	r2 = r10;					\
  54	r2 += -8;					\
  55	if r0 == 1 goto l0_%=;				\
  56	r1 = %[map_hash_16b] ll;			\
  57	if r0 != 1 goto l1_%=;				\
  58l0_%=:	r1 = %[map_array_48b] ll;			\
  59l1_%=:	call %[bpf_map_lookup_elem];			\
  60	if r0 == 0 goto l2_%=;				\
  61	r4 = *(u8*)(r0 + 0);				\
  62	if r4 == 1 goto l3_%=;				\
  63	r1 = 6;						\
  64	r1 = -r1;					\
  65	r1 &= 0x7;					\
  66	goto l4_%=;					\
  67l3_%=:	r1 = 3;						\
  68l4_%=:	r1 += r0;					\
  69	r0 = *(u8*)(r1 + 0);				\
  70l2_%=:	r0 = 1;						\
  71	exit;						\
  72"	:
  73	: __imm(bpf_map_lookup_elem),
  74	  __imm_addr(map_array_48b),
  75	  __imm_addr(map_hash_16b),
  76	  __imm_const(__sk_buff_len, offsetof(struct __sk_buff, len))
  77	: __clobber_all);
  78}
  79
  80SEC("socket")
  81__description("map access: known scalar += value_ptr const vs unknown")
  82__success __failure_unpriv
  83__msg_unpriv("R1 tried to add from different maps, paths or scalars")
  84__retval(1)
  85__naked void value_ptr_const_vs_unknown(void)
  86{
  87	asm volatile ("					\
  88	r0 = *(u32*)(r1 + %[__sk_buff_len]);		\
  89	r1 = 0;						\
  90	*(u64*)(r10 - 8) = r1;				\
  91	r2 = r10;					\
  92	r2 += -8;					\
  93	if r0 == 1 goto l0_%=;				\
  94	r1 = %[map_hash_16b] ll;			\
  95	if r0 != 1 goto l1_%=;				\
  96l0_%=:	r1 = %[map_array_48b] ll;			\
  97l1_%=:	call %[bpf_map_lookup_elem];			\
  98	if r0 == 0 goto l2_%=;				\
  99	r4 = *(u8*)(r0 + 0);				\
 100	if r4 == 1 goto l3_%=;				\
 101	r1 = 3;						\
 102	goto l4_%=;					\
 103l3_%=:	r1 = 6;						\
 104	r1 = -r1;					\
 105	r1 &= 0x7;					\
 106l4_%=:	r1 += r0;					\
 107	r0 = *(u8*)(r1 + 0);				\
 108l2_%=:	r0 = 1;						\
 109	exit;						\
 110"	:
 111	: __imm(bpf_map_lookup_elem),
 112	  __imm_addr(map_array_48b),
 113	  __imm_addr(map_hash_16b),
 114	  __imm_const(__sk_buff_len, offsetof(struct __sk_buff, len))
 115	: __clobber_all);
 116}
 117
 118SEC("socket")
 119__description("map access: known scalar += value_ptr const vs const (ne)")
 120__success __failure_unpriv
 121__msg_unpriv("R1 tried to add from different maps, paths or scalars")
 122__retval(1)
 123__naked void ptr_const_vs_const_ne(void)
 124{
 125	asm volatile ("					\
 126	r0 = *(u32*)(r1 + %[__sk_buff_len]);		\
 127	r1 = 0;						\
 128	*(u64*)(r10 - 8) = r1;				\
 129	r2 = r10;					\
 130	r2 += -8;					\
 131	if r0 == 1 goto l0_%=;				\
 132	r1 = %[map_hash_16b] ll;			\
 133	if r0 != 1 goto l1_%=;				\
 134l0_%=:	r1 = %[map_array_48b] ll;			\
 135l1_%=:	call %[bpf_map_lookup_elem];			\
 136	if r0 == 0 goto l2_%=;				\
 137	r4 = *(u8*)(r0 + 0);				\
 138	if r4 == 1 goto l3_%=;				\
 139	r1 = 3;						\
 140	goto l4_%=;					\
 141l3_%=:	r1 = 5;						\
 142l4_%=:	r1 += r0;					\
 143	r0 = *(u8*)(r1 + 0);				\
 144l2_%=:	r0 = 1;						\
 145	exit;						\
 146"	:
 147	: __imm(bpf_map_lookup_elem),
 148	  __imm_addr(map_array_48b),
 149	  __imm_addr(map_hash_16b),
 150	  __imm_const(__sk_buff_len, offsetof(struct __sk_buff, len))
 151	: __clobber_all);
 152}
 153
 154SEC("socket")
 155__description("map access: known scalar += value_ptr const vs const (eq)")
 156__success __success_unpriv __retval(1)
 157__naked void ptr_const_vs_const_eq(void)
 158{
 159	asm volatile ("					\
 160	r0 = *(u32*)(r1 + %[__sk_buff_len]);		\
 161	r1 = 0;						\
 162	*(u64*)(r10 - 8) = r1;				\
 163	r2 = r10;					\
 164	r2 += -8;					\
 165	if r0 == 1 goto l0_%=;				\
 166	r1 = %[map_hash_16b] ll;			\
 167	if r0 != 1 goto l1_%=;				\
 168l0_%=:	r1 = %[map_array_48b] ll;			\
 169l1_%=:	call %[bpf_map_lookup_elem];			\
 170	if r0 == 0 goto l2_%=;				\
 171	r4 = *(u8*)(r0 + 0);				\
 172	if r4 == 1 goto l3_%=;				\
 173	r1 = 5;						\
 174	goto l4_%=;					\
 175l3_%=:	r1 = 5;						\
 176l4_%=:	r1 += r0;					\
 177	r0 = *(u8*)(r1 + 0);				\
 178l2_%=:	r0 = 1;						\
 179	exit;						\
 180"	:
 181	: __imm(bpf_map_lookup_elem),
 182	  __imm_addr(map_array_48b),
 183	  __imm_addr(map_hash_16b),
 184	  __imm_const(__sk_buff_len, offsetof(struct __sk_buff, len))
 185	: __clobber_all);
 186}
 187
 188SEC("socket")
 189__description("map access: known scalar += value_ptr unknown vs unknown (eq)")
 190__success __success_unpriv __retval(1)
 191__naked void ptr_unknown_vs_unknown_eq(void)
 192{
 193	asm volatile ("					\
 194	r0 = *(u32*)(r1 + %[__sk_buff_len]);		\
 195	r1 = 0;						\
 196	*(u64*)(r10 - 8) = r1;				\
 197	r2 = r10;					\
 198	r2 += -8;					\
 199	if r0 == 1 goto l0_%=;				\
 200	r1 = %[map_hash_16b] ll;			\
 201	if r0 != 1 goto l1_%=;				\
 202l0_%=:	r1 = %[map_array_48b] ll;			\
 203l1_%=:	call %[bpf_map_lookup_elem];			\
 204	if r0 == 0 goto l2_%=;				\
 205	r4 = *(u8*)(r0 + 0);				\
 206	if r4 == 1 goto l3_%=;				\
 207	r1 = 6;						\
 208	r1 = -r1;					\
 209	r1 &= 0x7;					\
 210	goto l4_%=;					\
 211l3_%=:	r1 = 6;						\
 212	r1 = -r1;					\
 213	r1 &= 0x7;					\
 214l4_%=:	r1 += r0;					\
 215	r0 = *(u8*)(r1 + 0);				\
 216l2_%=:	r0 = 1;						\
 217	exit;						\
 218"	:
 219	: __imm(bpf_map_lookup_elem),
 220	  __imm_addr(map_array_48b),
 221	  __imm_addr(map_hash_16b),
 222	  __imm_const(__sk_buff_len, offsetof(struct __sk_buff, len))
 223	: __clobber_all);
 224}
 225
 226SEC("socket")
 227__description("map access: known scalar += value_ptr unknown vs unknown (lt)")
 228__success __failure_unpriv
 229__msg_unpriv("R1 tried to add from different maps, paths or scalars")
 230__retval(1)
 231__naked void ptr_unknown_vs_unknown_lt(void)
 232{
 233	asm volatile ("					\
 234	r8 = r1;					\
 235	call %[bpf_get_prandom_u32];			\
 236	r9 = r0;					\
 237	r1 = r8;					\
 238	r0 = *(u32*)(r1 + %[__sk_buff_len]);		\
 239	r1 = 0;						\
 240	*(u64*)(r10 - 8) = r1;				\
 241	r2 = r10;					\
 242	r2 += -8;					\
 243	if r0 == 1 goto l0_%=;				\
 244	r1 = %[map_hash_16b] ll;			\
 245	if r0 != 1 goto l1_%=;				\
 246l0_%=:	r1 = %[map_array_48b] ll;			\
 247l1_%=:	call %[bpf_map_lookup_elem];			\
 248	if r0 == 0 goto l2_%=;				\
 249	r4 = *(u8*)(r0 + 0);				\
 250	if r4 == 1 goto l3_%=;				\
 251	r1 = 6;						\
 252	r1 = r9;					\
 253	r1 &= 0x3;					\
 254	goto l4_%=;					\
 255l3_%=:	r1 = 6;						\
 256	r1 = r9;					\
 257	r1 &= 0x7;					\
 258l4_%=:	r1 += r0;					\
 259	r0 = *(u8*)(r1 + 0);				\
 260l2_%=:	r0 = 1;						\
 261	exit;						\
 262"	:
 263	: __imm(bpf_map_lookup_elem),
 264	  __imm_addr(map_array_48b),
 265	  __imm_addr(map_hash_16b),
 266	  __imm_const(__sk_buff_len, offsetof(struct __sk_buff, len)),
 267	  __imm(bpf_get_prandom_u32)
 268	: __clobber_all);
 269}
 270
 271SEC("socket")
 272__description("map access: known scalar += value_ptr unknown vs unknown (gt)")
 273__success __failure_unpriv
 274__msg_unpriv("R1 tried to add from different maps, paths or scalars")
 275__retval(1)
 276__naked void ptr_unknown_vs_unknown_gt(void)
 277{
 278	asm volatile ("					\
 279	r8 = r1;					\
 280	call %[bpf_get_prandom_u32];			\
 281	r9 = r0;					\
 282	r1 = r8;					\
 283	r0 = *(u32*)(r1 + %[__sk_buff_len]);		\
 284	r1 = 0;						\
 285	*(u64*)(r10 - 8) = r1;				\
 286	r2 = r10;					\
 287	r2 += -8;					\
 288	if r0 == 1 goto l0_%=;				\
 289	r1 = %[map_hash_16b] ll;			\
 290	if r0 != 1 goto l1_%=;				\
 291l0_%=:	r1 = %[map_array_48b] ll;			\
 292l1_%=:	call %[bpf_map_lookup_elem];			\
 293	if r0 == 0 goto l2_%=;				\
 294	r4 = *(u8*)(r0 + 0);				\
 295	if r4 == 1 goto l3_%=;				\
 296	r1 = 6;						\
 297	r1 = r9;					\
 298	r1 &= 0x7;					\
 299	goto l4_%=;					\
 300l3_%=:	r1 = 6;						\
 301	r1 = r9;					\
 302	r1 &= 0x3;					\
 303l4_%=:	r1 += r0;					\
 304	r0 = *(u8*)(r1 + 0);				\
 305l2_%=:	r0 = 1;						\
 306	exit;						\
 307"	:
 308	: __imm(bpf_map_lookup_elem),
 309	  __imm_addr(map_array_48b),
 310	  __imm_addr(map_hash_16b),
 311	  __imm_const(__sk_buff_len, offsetof(struct __sk_buff, len)),
 312	  __imm(bpf_get_prandom_u32)
 313	: __clobber_all);
 314}
 315
 316SEC("socket")
 317__description("map access: known scalar += value_ptr from different maps")
 318__success __success_unpriv __retval(1)
 319__naked void value_ptr_from_different_maps(void)
 320{
 321	asm volatile ("					\
 322	r0 = *(u32*)(r1 + %[__sk_buff_len]);		\
 323	r1 = 0;						\
 324	*(u64*)(r10 - 8) = r1;				\
 325	r2 = r10;					\
 326	r2 += -8;					\
 327	if r0 == 1 goto l0_%=;				\
 328	r1 = %[map_hash_16b] ll;			\
 329	if r0 != 1 goto l1_%=;				\
 330l0_%=:	r1 = %[map_array_48b] ll;			\
 331l1_%=:	call %[bpf_map_lookup_elem];			\
 332	if r0 == 0 goto l2_%=;				\
 333	r1 = 4;						\
 334	r1 += r0;					\
 335	r0 = *(u8*)(r1 + 0);				\
 336l2_%=:	r0 = 1;						\
 337	exit;						\
 338"	:
 339	: __imm(bpf_map_lookup_elem),
 340	  __imm_addr(map_array_48b),
 341	  __imm_addr(map_hash_16b),
 342	  __imm_const(__sk_buff_len, offsetof(struct __sk_buff, len))
 343	: __clobber_all);
 344}
 345
 346SEC("socket")
 347__description("map access: value_ptr -= known scalar from different maps")
 348__success __failure_unpriv
 349__msg_unpriv("R0 min value is outside of the allowed memory range")
 350__retval(1)
 351__naked void known_scalar_from_different_maps(void)
 352{
 353	asm volatile ("					\
 354	r0 = *(u32*)(r1 + %[__sk_buff_len]);		\
 355	r1 = 0;						\
 356	*(u64*)(r10 - 8) = r1;				\
 357	r2 = r10;					\
 358	r2 += -8;					\
 359	if r0 == 1 goto l0_%=;				\
 360	r1 = %[map_hash_16b] ll;			\
 361	if r0 != 1 goto l1_%=;				\
 362l0_%=:	r1 = %[map_array_48b] ll;			\
 363l1_%=:	call %[bpf_map_lookup_elem];			\
 364	if r0 == 0 goto l2_%=;				\
 365	r1 = 4;						\
 366	r0 -= r1;					\
 367	r0 += r1;					\
 368	r0 = *(u8*)(r0 + 0);				\
 369l2_%=:	r0 = 1;						\
 370	exit;						\
 371"	:
 372	: __imm(bpf_map_lookup_elem),
 373	  __imm_addr(map_array_48b),
 374	  __imm_addr(map_hash_16b),
 375	  __imm_const(__sk_buff_len, offsetof(struct __sk_buff, len))
 376	: __clobber_all);
 377}
 378
 379SEC("socket")
 380__description("map access: known scalar += value_ptr from different maps, but same value properties")
 381__success __success_unpriv __retval(1)
 382__naked void maps_but_same_value_properties(void)
 383{
 384	asm volatile ("					\
 385	r0 = *(u32*)(r1 + %[__sk_buff_len]);		\
 386	r1 = 0;						\
 387	*(u64*)(r10 - 8) = r1;				\
 388	r2 = r10;					\
 389	r2 += -8;					\
 390	if r0 == 1 goto l0_%=;				\
 391	r1 = %[map_hash_48b] ll;			\
 392	if r0 != 1 goto l1_%=;				\
 393l0_%=:	r1 = %[map_array_48b] ll;			\
 394l1_%=:	call %[bpf_map_lookup_elem];			\
 395	if r0 == 0 goto l2_%=;				\
 396	r1 = 4;						\
 397	r1 += r0;					\
 398	r0 = *(u8*)(r1 + 0);				\
 399l2_%=:	r0 = 1;						\
 400	exit;						\
 401"	:
 402	: __imm(bpf_map_lookup_elem),
 403	  __imm_addr(map_array_48b),
 404	  __imm_addr(map_hash_48b),
 405	  __imm_const(__sk_buff_len, offsetof(struct __sk_buff, len))
 406	: __clobber_all);
 407}
 408
 409SEC("socket")
 410__description("map access: mixing value pointer and scalar, 1")
 411__success __failure_unpriv
 412__msg_unpriv("R2 tried to add from different maps, paths or scalars, pointer arithmetic with it prohibited for !root")
 413__retval(0)
 414__naked void value_pointer_and_scalar_1(void)
 415{
 416	asm volatile ("					\
 417	/* load map value pointer into r0 and r2 */	\
 418	r0 = 1;						\
 419	r1 = %[map_array_48b] ll;			\
 420	r2 = r10;					\
 421	r2 += -16;					\
 422	r6 = 0;						\
 423	*(u64*)(r10 - 16) = r6;				\
 424	call %[bpf_map_lookup_elem];			\
 425	if r0 != 0 goto l0_%=;				\
 426	exit;						\
 427l0_%=:	/* load some number from the map into r1 */	\
 428	r1 = *(u8*)(r0 + 0);				\
 429	/* depending on r1, branch: */			\
 430	if r1 != 0 goto l1_%=;				\
 431	/* branch A */					\
 432	r2 = r0;					\
 433	r3 = 0;						\
 434	goto l2_%=;					\
 435l1_%=:	/* branch B */					\
 436	r2 = 0;						\
 437	r3 = 0x100000;					\
 438l2_%=:	/* common instruction */			\
 439	r2 += r3;					\
 440	/* depending on r1, branch: */			\
 441	if r1 != 0 goto l3_%=;				\
 442	/* branch A */					\
 443	goto l4_%=;					\
 444l3_%=:	/* branch B */					\
 445	r0 = 0x13371337;				\
 446	/* verifier follows fall-through */		\
 447	/* unpriv: nospec (inserted to prevent `R2 pointer comparison prohibited`) */\
 448	if r2 != 0x100000 goto l4_%=;			\
 449	r0 = 0;						\
 450	exit;						\
 451l4_%=:	/* fake-dead code; targeted from branch A to	\
 452	 * prevent dead code sanitization		\
 453	 */						\
 454	r0 = *(u8*)(r0 + 0);				\
 455	r0 = 0;						\
 456	exit;						\
 457"	:
 458	: __imm(bpf_map_lookup_elem),
 459	  __imm_addr(map_array_48b)
 460	: __clobber_all);
 461}
 462
 463SEC("socket")
 464__description("map access: mixing value pointer and scalar, 2")
 465__success __failure_unpriv
 466__msg_unpriv("R2 tried to add from different maps, paths or scalars, pointer arithmetic with it prohibited for !root")
 467__retval(0)
 468__naked void value_pointer_and_scalar_2(void)
 469{
 470	asm volatile ("					\
 471	/* load map value pointer into r0 and r2 */	\
 472	r0 = 1;						\
 473	r1 = %[map_array_48b] ll;			\
 474	r2 = r10;					\
 475	r2 += -16;					\
 476	r6 = 0;						\
 477	*(u64*)(r10 - 16) = r6;				\
 478	call %[bpf_map_lookup_elem];			\
 479	if r0 != 0 goto l0_%=;				\
 480	exit;						\
 481l0_%=:	/* load some number from the map into r1 */	\
 482	r1 = *(u8*)(r0 + 0);				\
 483	/* depending on r1, branch: */			\
 484	if r1 == 0 goto l1_%=;				\
 485	/* branch A */					\
 486	r2 = 0;						\
 487	r3 = 0x100000;					\
 488	goto l2_%=;					\
 489l1_%=:	/* branch B */					\
 490	r2 = r0;					\
 491	r3 = 0;						\
 492l2_%=:	/* common instruction */			\
 493	r2 += r3;					\
 494	/* depending on r1, branch: */			\
 495	if r1 != 0 goto l3_%=;				\
 496	/* branch A */					\
 497	goto l4_%=;					\
 498l3_%=:	/* branch B */					\
 499	r0 = 0x13371337;				\
 500	/* verifier follows fall-through */		\
 501	if r2 != 0x100000 goto l4_%=;			\
 502	r0 = 0;						\
 503	exit;						\
 504l4_%=:	/* fake-dead code; targeted from branch A to	\
 505	 * prevent dead code sanitization, rejected	\
 506	 * via branch B however				\
 507	 */						\
 508	/* unpriv: nospec (inserted to prevent `R0 invalid mem access 'scalar'`) */\
 509	r0 = *(u8*)(r0 + 0);				\
 510	r0 = 0;						\
 511	exit;						\
 512"	:
 513	: __imm(bpf_map_lookup_elem),
 514	  __imm_addr(map_array_48b)
 515	: __clobber_all);
 516}
 517
 518SEC("socket")
 519__description("sanitation: alu with different scalars 1")
 520__success __success_unpriv __retval(0x100000)
 521__naked void alu_with_different_scalars_1(void)
 522{
 523	asm volatile ("					\
 524	r0 = 1;						\
 525	r1 = %[map_array_48b] ll;			\
 526	r2 = r10;					\
 527	r2 += -16;					\
 528	r6 = 0;						\
 529	*(u64*)(r10 - 16) = r6;				\
 530	call %[bpf_map_lookup_elem];			\
 531	if r0 != 0 goto l0_%=;				\
 532	exit;						\
 533l0_%=:	r1 = *(u32*)(r0 + 0);				\
 534	if r1 == 0 goto l1_%=;				\
 535	r2 = 0;						\
 536	r3 = 0x100000;					\
 537	goto l2_%=;					\
 538l1_%=:	r2 = 42;					\
 539	r3 = 0x100001;					\
 540l2_%=:	r2 += r3;					\
 541	r0 = r2;					\
 542	exit;						\
 543"	:
 544	: __imm(bpf_map_lookup_elem),
 545	  __imm_addr(map_array_48b)
 546	: __clobber_all);
 547}
 548
 549SEC("socket")
 550__description("sanitation: alu with different scalars 2")
 551__success __success_unpriv __retval(0)
 552__naked void alu_with_different_scalars_2(void)
 553{
 554	asm volatile ("					\
 555	r0 = 1;						\
 556	r1 = %[map_array_48b] ll;			\
 557	r6 = r1;					\
 558	r2 = r10;					\
 559	r2 += -16;					\
 560	r7 = 0;						\
 561	*(u64*)(r10 - 16) = r7;				\
 562	call %[bpf_map_delete_elem];			\
 563	r7 = r0;					\
 564	r1 = r6;					\
 565	r2 = r10;					\
 566	r2 += -16;					\
 567	call %[bpf_map_delete_elem];			\
 568	r6 = r0;					\
 569	r8 = r6;					\
 570	r8 += r7;					\
 571	r0 = r8;					\
 572	r0 += %[einval];				\
 573	r0 += %[einval];				\
 574	exit;						\
 575"	:
 576	: __imm(bpf_map_delete_elem),
 577	  __imm_addr(map_array_48b),
 578	  __imm_const(einval, EINVAL)
 579	: __clobber_all);
 580}
 581
 582SEC("socket")
 583__description("sanitation: alu with different scalars 3")
 584__success __success_unpriv __retval(0)
 585__naked void alu_with_different_scalars_3(void)
 586{
 587	asm volatile ("					\
 588	r0 = %[einval];					\
 589	r0 *= -1;					\
 590	r7 = r0;					\
 591	r0 = %[einval];					\
 592	r0 *= -1;					\
 593	r6 = r0;					\
 594	r8 = r6;					\
 595	r8 += r7;					\
 596	r0 = r8;					\
 597	r0 += %[einval];				\
 598	r0 += %[einval];				\
 599	exit;						\
 600"	:
 601	: __imm_const(einval, EINVAL)
 602	: __clobber_all);
 603}
 604
 605SEC("socket")
 606__description("map access: value_ptr += known scalar, upper oob arith, test 1")
 607__success __failure_unpriv
 608__msg_unpriv("R0 pointer arithmetic of map value goes out of range")
 609__retval(1)
 610__naked void upper_oob_arith_test_1(void)
 611{
 612	asm volatile ("					\
 613	r1 = 0;						\
 614	*(u64*)(r10 - 8) = r1;				\
 615	r2 = r10;					\
 616	r2 += -8;					\
 617	r1 = %[map_array_48b] ll;			\
 618	call %[bpf_map_lookup_elem];			\
 619	if r0 == 0 goto l0_%=;				\
 620	r1 = 48;					\
 621	r0 += r1;					\
 622	r0 -= r1;					\
 623	r0 = *(u8*)(r0 + 0);				\
 624l0_%=:	r0 = 1;						\
 625	exit;						\
 626"	:
 627	: __imm(bpf_map_lookup_elem),
 628	  __imm_addr(map_array_48b)
 629	: __clobber_all);
 630}
 631
 632SEC("socket")
 633__description("map access: value_ptr += known scalar, upper oob arith, test 2")
 634__success __failure_unpriv
 635__msg_unpriv("R0 pointer arithmetic of map value goes out of range")
 636__retval(1)
 637__naked void upper_oob_arith_test_2(void)
 638{
 639	asm volatile ("					\
 640	r1 = 0;						\
 641	*(u64*)(r10 - 8) = r1;				\
 642	r2 = r10;					\
 643	r2 += -8;					\
 644	r1 = %[map_array_48b] ll;			\
 645	call %[bpf_map_lookup_elem];			\
 646	if r0 == 0 goto l0_%=;				\
 647	r1 = 49;					\
 648	r0 += r1;					\
 649	r0 -= r1;					\
 650	r0 = *(u8*)(r0 + 0);				\
 651l0_%=:	r0 = 1;						\
 652	exit;						\
 653"	:
 654	: __imm(bpf_map_lookup_elem),
 655	  __imm_addr(map_array_48b)
 656	: __clobber_all);
 657}
 658
 659SEC("socket")
 660__description("map access: value_ptr += known scalar, upper oob arith, test 3")
 661__success __success_unpriv __retval(1)
 662__naked void upper_oob_arith_test_3(void)
 663{
 664	asm volatile ("					\
 665	r1 = 0;						\
 666	*(u64*)(r10 - 8) = r1;				\
 667	r2 = r10;					\
 668	r2 += -8;					\
 669	r1 = %[map_array_48b] ll;			\
 670	call %[bpf_map_lookup_elem];			\
 671	if r0 == 0 goto l0_%=;				\
 672	r1 = 47;					\
 673	r0 += r1;					\
 674	r0 -= r1;					\
 675	r0 = *(u8*)(r0 + 0);				\
 676l0_%=:	r0 = 1;						\
 677	exit;						\
 678"	:
 679	: __imm(bpf_map_lookup_elem),
 680	  __imm_addr(map_array_48b)
 681	: __clobber_all);
 682}
 683
 684SEC("socket")
 685__description("map access: value_ptr -= known scalar, lower oob arith, test 1")
 686__failure __msg("R0 min value is outside of the allowed memory range")
 687__failure_unpriv
 688__msg_unpriv("R0 pointer arithmetic of map value goes out of range")
 689__naked void lower_oob_arith_test_1(void)
 690{
 691	asm volatile ("					\
 692	r1 = 0;						\
 693	*(u64*)(r10 - 8) = r1;				\
 694	r2 = r10;					\
 695	r2 += -8;					\
 696	r1 = %[map_array_48b] ll;			\
 697	call %[bpf_map_lookup_elem];			\
 698	if r0 == 0 goto l0_%=;				\
 699	r1 = 47;					\
 700	r0 += r1;					\
 701	r1 = 48;					\
 702	r0 -= r1;					\
 703	r0 = *(u8*)(r0 + 0);				\
 704l0_%=:	r0 = 1;						\
 705	exit;						\
 706"	:
 707	: __imm(bpf_map_lookup_elem),
 708	  __imm_addr(map_array_48b)
 709	: __clobber_all);
 710}
 711
 712SEC("socket")
 713__description("map access: value_ptr -= known scalar, lower oob arith, test 2")
 714__success __failure_unpriv
 715__msg_unpriv("R0 pointer arithmetic of map value goes out of range")
 716__retval(1)
 717__naked void lower_oob_arith_test_2(void)
 718{
 719	asm volatile ("					\
 720	r1 = 0;						\
 721	*(u64*)(r10 - 8) = r1;				\
 722	r2 = r10;					\
 723	r2 += -8;					\
 724	r1 = %[map_array_48b] ll;			\
 725	call %[bpf_map_lookup_elem];			\
 726	if r0 == 0 goto l0_%=;				\
 727	r1 = 47;					\
 728	r0 += r1;					\
 729	r1 = 48;					\
 730	r0 -= r1;					\
 731	r1 = 1;						\
 732	r0 += r1;					\
 733	r0 = *(u8*)(r0 + 0);				\
 734l0_%=:	r0 = 1;						\
 735	exit;						\
 736"	:
 737	: __imm(bpf_map_lookup_elem),
 738	  __imm_addr(map_array_48b)
 739	: __clobber_all);
 740}
 741
 742SEC("socket")
 743__description("map access: value_ptr -= known scalar, lower oob arith, test 3")
 744__success __success_unpriv __retval(1)
 745__naked void lower_oob_arith_test_3(void)
 746{
 747	asm volatile ("					\
 748	r1 = 0;						\
 749	*(u64*)(r10 - 8) = r1;				\
 750	r2 = r10;					\
 751	r2 += -8;					\
 752	r1 = %[map_array_48b] ll;			\
 753	call %[bpf_map_lookup_elem];			\
 754	if r0 == 0 goto l0_%=;				\
 755	r1 = 47;					\
 756	r0 += r1;					\
 757	r1 = 47;					\
 758	r0 -= r1;					\
 759	r0 = *(u8*)(r0 + 0);				\
 760l0_%=:	r0 = 1;						\
 761	exit;						\
 762"	:
 763	: __imm(bpf_map_lookup_elem),
 764	  __imm_addr(map_array_48b)
 765	: __clobber_all);
 766}
 767
 768SEC("socket")
 769__description("map access: known scalar += value_ptr")
 770__success __success_unpriv __retval(1)
 771__naked void access_known_scalar_value_ptr_1(void)
 772{
 773	asm volatile ("					\
 774	r1 = 0;						\
 775	*(u64*)(r10 - 8) = r1;				\
 776	r2 = r10;					\
 777	r2 += -8;					\
 778	r1 = %[map_array_48b] ll;			\
 779	call %[bpf_map_lookup_elem];			\
 780	if r0 == 0 goto l0_%=;				\
 781	r1 = 4;						\
 782	r1 += r0;					\
 783	r0 = *(u8*)(r1 + 0);				\
 784l0_%=:	r0 = 1;						\
 785	exit;						\
 786"	:
 787	: __imm(bpf_map_lookup_elem),
 788	  __imm_addr(map_array_48b)
 789	: __clobber_all);
 790}
 791
 792SEC("socket")
 793__description("map access: value_ptr += known scalar, 1")
 794__success __success_unpriv __retval(1)
 795__naked void value_ptr_known_scalar_1(void)
 796{
 797	asm volatile ("					\
 798	r1 = 0;						\
 799	*(u64*)(r10 - 8) = r1;				\
 800	r2 = r10;					\
 801	r2 += -8;					\
 802	r1 = %[map_array_48b] ll;			\
 803	call %[bpf_map_lookup_elem];			\
 804	if r0 == 0 goto l0_%=;				\
 805	r1 = 4;						\
 806	r0 += r1;					\
 807	r1 = *(u8*)(r0 + 0);				\
 808l0_%=:	r0 = 1;						\
 809	exit;						\
 810"	:
 811	: __imm(bpf_map_lookup_elem),
 812	  __imm_addr(map_array_48b)
 813	: __clobber_all);
 814}
 815
 816SEC("socket")
 817__description("map access: value_ptr += known scalar, 2")
 818__failure __msg("invalid access to map value")
 819__failure_unpriv
 820__naked void value_ptr_known_scalar_2_1(void)
 821{
 822	asm volatile ("					\
 823	r1 = 0;						\
 824	*(u64*)(r10 - 8) = r1;				\
 825	r2 = r10;					\
 826	r2 += -8;					\
 827	r1 = %[map_array_48b] ll;			\
 828	call %[bpf_map_lookup_elem];			\
 829	if r0 == 0 goto l0_%=;				\
 830	r1 = 49;					\
 831	r0 += r1;					\
 832	r1 = *(u8*)(r0 + 0);				\
 833l0_%=:	r0 = 1;						\
 834	exit;						\
 835"	:
 836	: __imm(bpf_map_lookup_elem),
 837	  __imm_addr(map_array_48b)
 838	: __clobber_all);
 839}
 840
 841SEC("socket")
 842__description("map access: value_ptr += known scalar, 3")
 843__failure __msg("invalid access to map value")
 844__failure_unpriv
 845__naked void value_ptr_known_scalar_3(void)
 846{
 847	asm volatile ("					\
 848	r1 = 0;						\
 849	*(u64*)(r10 - 8) = r1;				\
 850	r2 = r10;					\
 851	r2 += -8;					\
 852	r1 = %[map_array_48b] ll;			\
 853	call %[bpf_map_lookup_elem];			\
 854	if r0 == 0 goto l0_%=;				\
 855	r1 = -1;					\
 856	r0 += r1;					\
 857	r1 = *(u8*)(r0 + 0);				\
 858l0_%=:	r0 = 1;						\
 859	exit;						\
 860"	:
 861	: __imm(bpf_map_lookup_elem),
 862	  __imm_addr(map_array_48b)
 863	: __clobber_all);
 864}
 865
 866SEC("socket")
 867__description("map access: value_ptr += known scalar, 4")
 868__success __success_unpriv __retval(1)
 869__naked void value_ptr_known_scalar_4(void)
 870{
 871	asm volatile ("					\
 872	r1 = 0;						\
 873	*(u64*)(r10 - 8) = r1;				\
 874	r2 = r10;					\
 875	r2 += -8;					\
 876	r1 = %[map_array_48b] ll;			\
 877	call %[bpf_map_lookup_elem];			\
 878	if r0 == 0 goto l0_%=;				\
 879	r1 = 5;						\
 880	r0 += r1;					\
 881	r1 = -2;					\
 882	r0 += r1;					\
 883	r1 = -1;					\
 884	r0 += r1;					\
 885	r1 = *(u8*)(r0 + 0);				\
 886l0_%=:	r0 = 1;						\
 887	exit;						\
 888"	:
 889	: __imm(bpf_map_lookup_elem),
 890	  __imm_addr(map_array_48b)
 891	: __clobber_all);
 892}
 893
 894SEC("socket")
 895__description("map access: value_ptr += known scalar, 5")
 896__success __success_unpriv __retval(0xabcdef12)
 897__naked void value_ptr_known_scalar_5(void)
 898{
 899	asm volatile ("					\
 900	r1 = 0;						\
 901	*(u64*)(r10 - 8) = r1;				\
 902	r2 = r10;					\
 903	r2 += -8;					\
 904	r1 = %[map_array_48b] ll;			\
 905	call %[bpf_map_lookup_elem];			\
 906	if r0 == 0 goto l0_%=;				\
 907	r1 = %[__imm_0];				\
 908	r1 += r0;					\
 909	r0 = *(u32*)(r1 + 0);				\
 910l0_%=:	exit;						\
 911"	:
 912	: __imm(bpf_map_lookup_elem),
 913	  __imm_addr(map_array_48b),
 914	  __imm_const(__imm_0, (6 + 1) * sizeof(int))
 915	: __clobber_all);
 916}
 917
 918SEC("socket")
 919__description("map access: value_ptr += known scalar, 6")
 920__success __success_unpriv __retval(0xabcdef12)
 921__naked void value_ptr_known_scalar_6(void)
 922{
 923	asm volatile ("					\
 924	r1 = 0;						\
 925	*(u64*)(r10 - 8) = r1;				\
 926	r2 = r10;					\
 927	r2 += -8;					\
 928	r1 = %[map_array_48b] ll;			\
 929	call %[bpf_map_lookup_elem];			\
 930	if r0 == 0 goto l0_%=;				\
 931	r1 = %[__imm_0];				\
 932	r0 += r1;					\
 933	r1 = %[__imm_1];				\
 934	r0 += r1;					\
 935	r0 = *(u32*)(r0 + 0);				\
 936l0_%=:	exit;						\
 937"	:
 938	: __imm(bpf_map_lookup_elem),
 939	  __imm_addr(map_array_48b),
 940	  __imm_const(__imm_0, (3 + 1) * sizeof(int)),
 941	  __imm_const(__imm_1, 3 * sizeof(int))
 942	: __clobber_all);
 943}
 944
 945SEC("socket")
 946__description("map access: value_ptr += N, value_ptr -= N known scalar")
 947__success __success_unpriv __retval(0x12345678)
 948__naked void value_ptr_n_known_scalar(void)
 949{
 950	asm volatile ("					\
 951	r1 = 0;						\
 952	*(u64*)(r10 - 8) = r1;				\
 953	r2 = r10;					\
 954	r2 += -8;					\
 955	r1 = %[map_array_48b] ll;			\
 956	call %[bpf_map_lookup_elem];			\
 957	if r0 == 0 goto l0_%=;				\
 958	w1 = 0x12345678;				\
 959	*(u32*)(r0 + 0) = r1;				\
 960	r0 += 2;					\
 961	r1 = 2;						\
 962	r0 -= r1;					\
 963	r0 = *(u32*)(r0 + 0);				\
 964l0_%=:	exit;						\
 965"	:
 966	: __imm(bpf_map_lookup_elem),
 967	  __imm_addr(map_array_48b)
 968	: __clobber_all);
 969}
 970
 971SEC("socket")
 972__description("map access: unknown scalar += value_ptr, 1")
 973__success __success_unpriv __retval(1)
 974__naked void unknown_scalar_value_ptr_1(void)
 975{
 976	asm volatile ("					\
 977	r1 = 0;						\
 978	*(u64*)(r10 - 8) = r1;				\
 979	r2 = r10;					\
 980	r2 += -8;					\
 981	r1 = %[map_array_48b] ll;			\
 982	call %[bpf_map_lookup_elem];			\
 983	if r0 == 0 goto l0_%=;				\
 984	r1 = *(u8*)(r0 + 0);				\
 985	r1 &= 0xf;					\
 986	r1 += r0;					\
 987	r0 = *(u8*)(r1 + 0);				\
 988l0_%=:	r0 = 1;						\
 989	exit;						\
 990"	:
 991	: __imm(bpf_map_lookup_elem),
 992	  __imm_addr(map_array_48b)
 993	: __clobber_all);
 994}
 995
 996SEC("socket")
 997__description("map access: unknown scalar += value_ptr, 2")
 998__success __success_unpriv __retval(0xabcdef12) __flag(BPF_F_ANY_ALIGNMENT)
 999__naked void unknown_scalar_value_ptr_2(void)
1000{
1001	asm volatile ("					\
1002	r1 = 0;						\
1003	*(u64*)(r10 - 8) = r1;				\
1004	r2 = r10;					\
1005	r2 += -8;					\
1006	r1 = %[map_array_48b] ll;			\
1007	call %[bpf_map_lookup_elem];			\
1008	if r0 == 0 goto l0_%=;				\
1009	r1 = *(u32*)(r0 + 0);				\
1010	r1 &= 31;					\
1011	r1 += r0;					\
1012	r0 = *(u32*)(r1 + 0);				\
1013l0_%=:	exit;						\
1014"	:
1015	: __imm(bpf_map_lookup_elem),
1016	  __imm_addr(map_array_48b)
1017	: __clobber_all);
1018}
1019
1020SEC("socket")
1021__description("map access: unknown scalar += value_ptr, 3")
1022__success __failure_unpriv
1023__msg_unpriv("R0 pointer arithmetic of map value goes out of range")
1024__retval(0xabcdef12) __flag(BPF_F_ANY_ALIGNMENT)
1025__naked void unknown_scalar_value_ptr_3(void)
1026{
1027	asm volatile ("					\
1028	r1 = 0;						\
1029	*(u64*)(r10 - 8) = r1;				\
1030	r2 = r10;					\
1031	r2 += -8;					\
1032	r1 = %[map_array_48b] ll;			\
1033	call %[bpf_map_lookup_elem];			\
1034	if r0 == 0 goto l0_%=;				\
1035	r1 = -1;					\
1036	r0 += r1;					\
1037	r1 = 1;						\
1038	r0 += r1;					\
1039	r1 = *(u32*)(r0 + 0);				\
1040	r1 &= 31;					\
1041	r1 += r0;					\
1042	r0 = *(u32*)(r1 + 0);				\
1043l0_%=:	exit;						\
1044"	:
1045	: __imm(bpf_map_lookup_elem),
1046	  __imm_addr(map_array_48b)
1047	: __clobber_all);
1048}
1049
1050SEC("socket")
1051__description("map access: unknown scalar += value_ptr, 4")
1052__failure __msg("R1 max value is outside of the allowed memory range")
1053__msg_unpriv("R1 pointer arithmetic of map value goes out of range")
1054__flag(BPF_F_ANY_ALIGNMENT)
1055__naked void unknown_scalar_value_ptr_4(void)
1056{
1057	asm volatile ("					\
1058	r1 = 0;						\
1059	*(u64*)(r10 - 8) = r1;				\
1060	r2 = r10;					\
1061	r2 += -8;					\
1062	r1 = %[map_array_48b] ll;			\
1063	call %[bpf_map_lookup_elem];			\
1064	if r0 == 0 goto l0_%=;				\
1065	r1 = 19;					\
1066	r0 += r1;					\
1067	r1 = *(u32*)(r0 + 0);				\
1068	r1 &= 31;					\
1069	r1 += r0;					\
1070	r0 = *(u32*)(r1 + 0);				\
1071l0_%=:	exit;						\
1072"	:
1073	: __imm(bpf_map_lookup_elem),
1074	  __imm_addr(map_array_48b)
1075	: __clobber_all);
1076}
1077
1078SEC("socket")
1079__description("map access: value_ptr += unknown scalar, 1")
1080__success __success_unpriv __retval(1)
1081__naked void value_ptr_unknown_scalar_1(void)
1082{
1083	asm volatile ("					\
1084	r1 = 0;						\
1085	*(u64*)(r10 - 8) = r1;				\
1086	r2 = r10;					\
1087	r2 += -8;					\
1088	r1 = %[map_array_48b] ll;			\
1089	call %[bpf_map_lookup_elem];			\
1090	if r0 == 0 goto l0_%=;				\
1091	r1 = *(u8*)(r0 + 0);				\
1092	r1 &= 0xf;					\
1093	r0 += r1;					\
1094	r1 = *(u8*)(r0 + 0);				\
1095l0_%=:	r0 = 1;						\
1096	exit;						\
1097"	:
1098	: __imm(bpf_map_lookup_elem),
1099	  __imm_addr(map_array_48b)
1100	: __clobber_all);
1101}
1102
1103SEC("socket")
1104__description("map access: value_ptr += unknown scalar, 2")
1105__success __success_unpriv __retval(0xabcdef12) __flag(BPF_F_ANY_ALIGNMENT)
1106__naked void value_ptr_unknown_scalar_2_1(void)
1107{
1108	asm volatile ("					\
1109	r1 = 0;						\
1110	*(u64*)(r10 - 8) = r1;				\
1111	r2 = r10;					\
1112	r2 += -8;					\
1113	r1 = %[map_array_48b] ll;			\
1114	call %[bpf_map_lookup_elem];			\
1115	if r0 == 0 goto l0_%=;				\
1116	r1 = *(u32*)(r0 + 0);				\
1117	r1 &= 31;					\
1118	r0 += r1;					\
1119	r0 = *(u32*)(r0 + 0);				\
1120l0_%=:	exit;						\
1121"	:
1122	: __imm(bpf_map_lookup_elem),
1123	  __imm_addr(map_array_48b)
1124	: __clobber_all);
1125}
1126
1127SEC("socket")
1128__description("map access: value_ptr += unknown scalar, 3")
1129__success __success_unpriv __retval(1)
1130__naked void value_ptr_unknown_scalar_3(void)
1131{
1132	asm volatile ("					\
1133	r1 = 0;						\
1134	*(u64*)(r10 - 8) = r1;				\
1135	r2 = r10;					\
1136	r2 += -8;					\
1137	r1 = %[map_array_48b] ll;			\
1138	call %[bpf_map_lookup_elem];			\
1139	if r0 == 0 goto l0_%=;				\
1140	r1 = *(u64*)(r0 + 0);				\
1141	r2 = *(u64*)(r0 + 8);				\
1142	r3 = *(u64*)(r0 + 16);				\
1143	r1 &= 0xf;					\
1144	r3 &= 1;					\
1145	r3 |= 1;					\
1146	if r2 > r3 goto l0_%=;				\
1147	r0 += r3;					\
1148	r0 = *(u8*)(r0 + 0);				\
1149	r0 = 1;						\
1150l1_%=:	exit;						\
1151l0_%=:	r0 = 2;						\
1152	goto l1_%=;					\
1153"	:
1154	: __imm(bpf_map_lookup_elem),
1155	  __imm_addr(map_array_48b)
1156	: __clobber_all);
1157}
1158
1159SEC("socket")
1160__description("map access: value_ptr += value_ptr")
1161__failure __msg("R0 pointer += pointer prohibited")
1162__failure_unpriv
1163__naked void access_value_ptr_value_ptr_1(void)
1164{
1165	asm volatile ("					\
1166	r1 = 0;						\
1167	*(u64*)(r10 - 8) = r1;				\
1168	r2 = r10;					\
1169	r2 += -8;					\
1170	r1 = %[map_array_48b] ll;			\
1171	call %[bpf_map_lookup_elem];			\
1172	if r0 == 0 goto l0_%=;				\
1173	r0 += r0;					\
1174	r1 = *(u8*)(r0 + 0);				\
1175l0_%=:	r0 = 1;						\
1176	exit;						\
1177"	:
1178	: __imm(bpf_map_lookup_elem),
1179	  __imm_addr(map_array_48b)
1180	: __clobber_all);
1181}
1182
1183SEC("socket")
1184__description("map access: known scalar -= value_ptr")
1185__failure __msg("R1 tried to subtract pointer from scalar")
1186__failure_unpriv
1187__naked void access_known_scalar_value_ptr_2(void)
1188{
1189	asm volatile ("					\
1190	r1 = 0;						\
1191	*(u64*)(r10 - 8) = r1;				\
1192	r2 = r10;					\
1193	r2 += -8;					\
1194	r1 = %[map_array_48b] ll;			\
1195	call %[bpf_map_lookup_elem];			\
1196	if r0 == 0 goto l0_%=;				\
1197	r1 = 4;						\
1198	r1 -= r0;					\
1199	r0 = *(u8*)(r1 + 0);				\
1200l0_%=:	r0 = 1;						\
1201	exit;						\
1202"	:
1203	: __imm(bpf_map_lookup_elem),
1204	  __imm_addr(map_array_48b)
1205	: __clobber_all);
1206}
1207
1208SEC("socket")
1209__description("map access: value_ptr -= known scalar")
1210__failure __msg("R0 min value is outside of the allowed memory range")
1211__failure_unpriv
1212__naked void access_value_ptr_known_scalar(void)
1213{
1214	asm volatile ("					\
1215	r1 = 0;						\
1216	*(u64*)(r10 - 8) = r1;				\
1217	r2 = r10;					\
1218	r2 += -8;					\
1219	r1 = %[map_array_48b] ll;			\
1220	call %[bpf_map_lookup_elem];			\
1221	if r0 == 0 goto l0_%=;				\
1222	r1 = 4;						\
1223	r0 -= r1;					\
1224	r1 = *(u8*)(r0 + 0);				\
1225l0_%=:	r0 = 1;						\
1226	exit;						\
1227"	:
1228	: __imm(bpf_map_lookup_elem),
1229	  __imm_addr(map_array_48b)
1230	: __clobber_all);
1231}
1232
1233SEC("socket")
1234__description("map access: value_ptr -= known scalar, 2")
1235__success __success_unpriv __retval(1)
1236__naked void value_ptr_known_scalar_2_2(void)
1237{
1238	asm volatile ("					\
1239	r1 = 0;						\
1240	*(u64*)(r10 - 8) = r1;				\
1241	r2 = r10;					\
1242	r2 += -8;					\
1243	r1 = %[map_array_48b] ll;			\
1244	call %[bpf_map_lookup_elem];			\
1245	if r0 == 0 goto l0_%=;				\
1246	r1 = 6;						\
1247	r2 = 4;						\
1248	r0 += r1;					\
1249	r0 -= r2;					\
1250	r1 = *(u8*)(r0 + 0);				\
1251l0_%=:	r0 = 1;						\
1252	exit;						\
1253"	:
1254	: __imm(bpf_map_lookup_elem),
1255	  __imm_addr(map_array_48b)
1256	: __clobber_all);
1257}
1258
1259SEC("socket")
1260__description("map access: unknown scalar -= value_ptr")
1261__failure __msg("R1 tried to subtract pointer from scalar")
1262__failure_unpriv
1263__naked void access_unknown_scalar_value_ptr(void)
1264{
1265	asm volatile ("					\
1266	r1 = 0;						\
1267	*(u64*)(r10 - 8) = r1;				\
1268	r2 = r10;					\
1269	r2 += -8;					\
1270	r1 = %[map_array_48b] ll;			\
1271	call %[bpf_map_lookup_elem];			\
1272	if r0 == 0 goto l0_%=;				\
1273	r1 = *(u8*)(r0 + 0);				\
1274	r1 &= 0xf;					\
1275	r1 -= r0;					\
1276	r0 = *(u8*)(r1 + 0);				\
1277l0_%=:	r0 = 1;						\
1278	exit;						\
1279"	:
1280	: __imm(bpf_map_lookup_elem),
1281	  __imm_addr(map_array_48b)
1282	: __clobber_all);
1283}
1284
1285SEC("socket")
1286__description("map access: value_ptr -= unknown scalar")
1287__failure __msg("R0 min value is negative")
1288__failure_unpriv
1289__naked void access_value_ptr_unknown_scalar(void)
1290{
1291	asm volatile ("					\
1292	r1 = 0;						\
1293	*(u64*)(r10 - 8) = r1;				\
1294	r2 = r10;					\
1295	r2 += -8;					\
1296	r1 = %[map_array_48b] ll;			\
1297	call %[bpf_map_lookup_elem];			\
1298	if r0 == 0 goto l0_%=;				\
1299	r1 = *(u8*)(r0 + 0);				\
1300	r1 &= 0xf;					\
1301	r0 -= r1;					\
1302	r1 = *(u8*)(r0 + 0);				\
1303l0_%=:	r0 = 1;						\
1304	exit;						\
1305"	:
1306	: __imm(bpf_map_lookup_elem),
1307	  __imm_addr(map_array_48b)
1308	: __clobber_all);
1309}
1310
1311SEC("socket")
1312__description("map access: value_ptr -= unknown scalar, 2")
1313__success __success_unpriv
1314__retval(1)
1315#ifdef SPEC_V1
1316__xlated_unpriv("r1 &= 7")
1317__xlated_unpriv("nospec") /* inserted to prevent `R0 pointer arithmetic of map value goes out of range` */
1318__xlated_unpriv("r0 -= r1")
1319#endif
1320__naked void value_ptr_unknown_scalar_2_2(void)
1321{
1322	asm volatile ("					\
1323	r1 = 0;						\
1324	*(u64*)(r10 - 8) = r1;				\
1325	r2 = r10;					\
1326	r2 += -8;					\
1327	r1 = %[map_array_48b] ll;			\
1328	call %[bpf_map_lookup_elem];			\
1329	if r0 == 0 goto l0_%=;				\
1330	r1 = *(u8*)(r0 + 0);				\
1331	r1 &= 0xf;					\
1332	r1 |= 0x7;					\
1333	r0 += r1;					\
1334	r1 = *(u8*)(r0 + 0);				\
1335	r1 &= 0x7;					\
1336	r0 -= r1;					\
1337	r1 = *(u8*)(r0 + 0);				\
1338l0_%=:	r0 = 1;						\
1339	exit;						\
1340"	:
1341	: __imm(bpf_map_lookup_elem),
1342	  __imm_addr(map_array_48b)
1343	: __clobber_all);
1344}
1345
1346SEC("socket")
1347__description("map access: value_ptr -= value_ptr")
1348__failure __msg("R0 invalid mem access 'scalar'")
1349__msg_unpriv("R0 pointer -= pointer prohibited")
1350__naked void access_value_ptr_value_ptr_2(void)
1351{
1352	asm volatile ("					\
1353	r1 = 0;						\
1354	*(u64*)(r10 - 8) = r1;				\
1355	r2 = r10;					\
1356	r2 += -8;					\
1357	r1 = %[map_array_48b] ll;			\
1358	call %[bpf_map_lookup_elem];			\
1359	if r0 == 0 goto l0_%=;				\
1360	r0 -= r0;					\
1361	r1 = *(u8*)(r0 + 0);				\
1362l0_%=:	r0 = 1;						\
1363	exit;						\
1364"	:
1365	: __imm(bpf_map_lookup_elem),
1366	  __imm_addr(map_array_48b)
1367	: __clobber_all);
1368}
1369
1370SEC("socket")
1371__description("map access: trying to leak tainted dst reg")
1372__failure __msg("math between map_value pointer and 4294967295 is not allowed")
1373__failure_unpriv
1374__naked void to_leak_tainted_dst_reg(void)
1375{
1376	asm volatile ("					\
1377	r0 = 0;						\
1378	r1 = 0;						\
1379	*(u64*)(r10 - 8) = r1;				\
1380	r2 = r10;					\
1381	r2 += -8;					\
1382	r1 = %[map_array_48b] ll;			\
1383	call %[bpf_map_lookup_elem];			\
1384	if r0 != 0 goto l0_%=;				\
1385	exit;						\
1386l0_%=:	r2 = r0;					\
1387	w1 = 0xFFFFFFFF;				\
1388	w1 = w1;					\
1389	r2 -= r1;					\
1390	*(u64*)(r0 + 0) = r2;				\
1391	r0 = 0;						\
1392	exit;						\
1393"	:
1394	: __imm(bpf_map_lookup_elem),
1395	  __imm_addr(map_array_48b)
1396	: __clobber_all);
1397}
1398
1399SEC("tc")
1400__description("32bit pkt_ptr -= scalar")
1401__success __retval(0) __flag(BPF_F_ANY_ALIGNMENT)
1402__naked void _32bit_pkt_ptr_scalar(void)
1403{
1404	asm volatile ("					\
1405	r8 = *(u32*)(r1 + %[__sk_buff_data_end]);	\
1406	r7 = *(u32*)(r1 + %[__sk_buff_data]);		\
1407	r6 = r7;					\
1408	r6 += 40;					\
1409	if r6 > r8 goto l0_%=;				\
1410	w4 = w7;					\
1411	w6 -= w4;					\
1412l0_%=:	r0 = 0;						\
1413	exit;						\
1414"	:
1415	: __imm_const(__sk_buff_data, offsetof(struct __sk_buff, data)),
1416	  __imm_const(__sk_buff_data_end, offsetof(struct __sk_buff, data_end))
1417	: __clobber_all);
1418}
1419
1420SEC("tc")
1421__description("32bit scalar -= pkt_ptr")
1422__success __retval(0) __flag(BPF_F_ANY_ALIGNMENT)
1423__naked void _32bit_scalar_pkt_ptr(void)
1424{
1425	asm volatile ("					\
1426	r8 = *(u32*)(r1 + %[__sk_buff_data_end]);	\
1427	r7 = *(u32*)(r1 + %[__sk_buff_data]);		\
1428	r6 = r7;					\
1429	r6 += 40;					\
1430	if r6 > r8 goto l0_%=;				\
1431	w4 = w6;					\
1432	w4 -= w7;					\
1433l0_%=:	r0 = 0;						\
1434	exit;						\
1435"	:
1436	: __imm_const(__sk_buff_data, offsetof(struct __sk_buff, data)),
1437	  __imm_const(__sk_buff_data_end, offsetof(struct __sk_buff, data_end))
1438	: __clobber_all);
1439}
1440
1441char _license[] SEC("license") = "GPL";
~/ Read-only file preview.