162306a36Sopenharmony_ci// SPDX-License-Identifier: GPL-2.0 262306a36Sopenharmony_ci/* Copyright (c) 2023 Meta Platforms, Inc. and affiliates. */ 362306a36Sopenharmony_ci 462306a36Sopenharmony_ci#include <stdbool.h> 562306a36Sopenharmony_ci#include <linux/bpf.h> 662306a36Sopenharmony_ci#include <bpf/bpf_helpers.h> 762306a36Sopenharmony_ci#include "bpf_misc.h" 862306a36Sopenharmony_ci 962306a36Sopenharmony_ci#define ARRAY_SIZE(x) (sizeof(x) / sizeof((x)[0])) 1062306a36Sopenharmony_ci 1162306a36Sopenharmony_cistatic volatile int zero = 0; 1262306a36Sopenharmony_ci 1362306a36Sopenharmony_ciint my_pid; 1462306a36Sopenharmony_ciint arr[256]; 1562306a36Sopenharmony_ciint small_arr[16] SEC(".data.small_arr"); 1662306a36Sopenharmony_ci 1762306a36Sopenharmony_cistruct { 1862306a36Sopenharmony_ci __uint(type, BPF_MAP_TYPE_HASH); 1962306a36Sopenharmony_ci __uint(max_entries, 10); 2062306a36Sopenharmony_ci __type(key, int); 2162306a36Sopenharmony_ci __type(value, int); 2262306a36Sopenharmony_ci} amap SEC(".maps"); 2362306a36Sopenharmony_ci 2462306a36Sopenharmony_ci#ifdef REAL_TEST 2562306a36Sopenharmony_ci#define MY_PID_GUARD() if (my_pid != (bpf_get_current_pid_tgid() >> 32)) return 0 2662306a36Sopenharmony_ci#else 2762306a36Sopenharmony_ci#define MY_PID_GUARD() ({ }) 2862306a36Sopenharmony_ci#endif 2962306a36Sopenharmony_ci 3062306a36Sopenharmony_ciSEC("?raw_tp") 3162306a36Sopenharmony_ci__failure __msg("math between map_value pointer and register with unbounded min value is not allowed") 3262306a36Sopenharmony_ciint iter_err_unsafe_c_loop(const void *ctx) 3362306a36Sopenharmony_ci{ 3462306a36Sopenharmony_ci struct bpf_iter_num it; 3562306a36Sopenharmony_ci int *v, i = zero; /* obscure initial value of i */ 3662306a36Sopenharmony_ci 3762306a36Sopenharmony_ci MY_PID_GUARD(); 3862306a36Sopenharmony_ci 3962306a36Sopenharmony_ci bpf_iter_num_new(&it, 0, 1000); 4062306a36Sopenharmony_ci while ((v = bpf_iter_num_next(&it))) { 4162306a36Sopenharmony_ci i++; 4262306a36Sopenharmony_ci } 4362306a36Sopenharmony_ci bpf_iter_num_destroy(&it); 4462306a36Sopenharmony_ci 4562306a36Sopenharmony_ci small_arr[i] = 123; /* invalid */ 4662306a36Sopenharmony_ci 4762306a36Sopenharmony_ci return 0; 4862306a36Sopenharmony_ci} 4962306a36Sopenharmony_ci 5062306a36Sopenharmony_ciSEC("?raw_tp") 5162306a36Sopenharmony_ci__failure __msg("unbounded memory access") 5262306a36Sopenharmony_ciint iter_err_unsafe_asm_loop(const void *ctx) 5362306a36Sopenharmony_ci{ 5462306a36Sopenharmony_ci struct bpf_iter_num it; 5562306a36Sopenharmony_ci 5662306a36Sopenharmony_ci MY_PID_GUARD(); 5762306a36Sopenharmony_ci 5862306a36Sopenharmony_ci asm volatile ( 5962306a36Sopenharmony_ci "r6 = %[zero];" /* iteration counter */ 6062306a36Sopenharmony_ci "r1 = %[it];" /* iterator state */ 6162306a36Sopenharmony_ci "r2 = 0;" 6262306a36Sopenharmony_ci "r3 = 1000;" 6362306a36Sopenharmony_ci "r4 = 1;" 6462306a36Sopenharmony_ci "call %[bpf_iter_num_new];" 6562306a36Sopenharmony_ci "loop:" 6662306a36Sopenharmony_ci "r1 = %[it];" 6762306a36Sopenharmony_ci "call %[bpf_iter_num_next];" 6862306a36Sopenharmony_ci "if r0 == 0 goto out;" 6962306a36Sopenharmony_ci "r6 += 1;" 7062306a36Sopenharmony_ci "goto loop;" 7162306a36Sopenharmony_ci "out:" 7262306a36Sopenharmony_ci "r1 = %[it];" 7362306a36Sopenharmony_ci "call %[bpf_iter_num_destroy];" 7462306a36Sopenharmony_ci "r1 = %[small_arr];" 7562306a36Sopenharmony_ci "r2 = r6;" 7662306a36Sopenharmony_ci "r2 <<= 2;" 7762306a36Sopenharmony_ci "r1 += r2;" 7862306a36Sopenharmony_ci "*(u32 *)(r1 + 0) = r6;" /* invalid */ 7962306a36Sopenharmony_ci : 8062306a36Sopenharmony_ci : [it]"r"(&it), 8162306a36Sopenharmony_ci [small_arr]"p"(small_arr), 8262306a36Sopenharmony_ci [zero]"p"(zero), 8362306a36Sopenharmony_ci __imm(bpf_iter_num_new), 8462306a36Sopenharmony_ci __imm(bpf_iter_num_next), 8562306a36Sopenharmony_ci __imm(bpf_iter_num_destroy) 8662306a36Sopenharmony_ci : __clobber_common, "r6" 8762306a36Sopenharmony_ci ); 8862306a36Sopenharmony_ci 8962306a36Sopenharmony_ci return 0; 9062306a36Sopenharmony_ci} 9162306a36Sopenharmony_ci 9262306a36Sopenharmony_ciSEC("raw_tp") 9362306a36Sopenharmony_ci__success 9462306a36Sopenharmony_ciint iter_while_loop(const void *ctx) 9562306a36Sopenharmony_ci{ 9662306a36Sopenharmony_ci struct bpf_iter_num it; 9762306a36Sopenharmony_ci int *v; 9862306a36Sopenharmony_ci 9962306a36Sopenharmony_ci MY_PID_GUARD(); 10062306a36Sopenharmony_ci 10162306a36Sopenharmony_ci bpf_iter_num_new(&it, 0, 3); 10262306a36Sopenharmony_ci while ((v = bpf_iter_num_next(&it))) { 10362306a36Sopenharmony_ci bpf_printk("ITER_BASIC: E1 VAL: v=%d", *v); 10462306a36Sopenharmony_ci } 10562306a36Sopenharmony_ci bpf_iter_num_destroy(&it); 10662306a36Sopenharmony_ci 10762306a36Sopenharmony_ci return 0; 10862306a36Sopenharmony_ci} 10962306a36Sopenharmony_ci 11062306a36Sopenharmony_ciSEC("raw_tp") 11162306a36Sopenharmony_ci__success 11262306a36Sopenharmony_ciint iter_while_loop_auto_cleanup(const void *ctx) 11362306a36Sopenharmony_ci{ 11462306a36Sopenharmony_ci __attribute__((cleanup(bpf_iter_num_destroy))) struct bpf_iter_num it; 11562306a36Sopenharmony_ci int *v; 11662306a36Sopenharmony_ci 11762306a36Sopenharmony_ci MY_PID_GUARD(); 11862306a36Sopenharmony_ci 11962306a36Sopenharmony_ci bpf_iter_num_new(&it, 0, 3); 12062306a36Sopenharmony_ci while ((v = bpf_iter_num_next(&it))) { 12162306a36Sopenharmony_ci bpf_printk("ITER_BASIC: E1 VAL: v=%d", *v); 12262306a36Sopenharmony_ci } 12362306a36Sopenharmony_ci /* (!) no explicit bpf_iter_num_destroy() */ 12462306a36Sopenharmony_ci 12562306a36Sopenharmony_ci return 0; 12662306a36Sopenharmony_ci} 12762306a36Sopenharmony_ci 12862306a36Sopenharmony_ciSEC("raw_tp") 12962306a36Sopenharmony_ci__success 13062306a36Sopenharmony_ciint iter_for_loop(const void *ctx) 13162306a36Sopenharmony_ci{ 13262306a36Sopenharmony_ci struct bpf_iter_num it; 13362306a36Sopenharmony_ci int *v; 13462306a36Sopenharmony_ci 13562306a36Sopenharmony_ci MY_PID_GUARD(); 13662306a36Sopenharmony_ci 13762306a36Sopenharmony_ci bpf_iter_num_new(&it, 5, 10); 13862306a36Sopenharmony_ci for (v = bpf_iter_num_next(&it); v; v = bpf_iter_num_next(&it)) { 13962306a36Sopenharmony_ci bpf_printk("ITER_BASIC: E2 VAL: v=%d", *v); 14062306a36Sopenharmony_ci } 14162306a36Sopenharmony_ci bpf_iter_num_destroy(&it); 14262306a36Sopenharmony_ci 14362306a36Sopenharmony_ci return 0; 14462306a36Sopenharmony_ci} 14562306a36Sopenharmony_ci 14662306a36Sopenharmony_ciSEC("raw_tp") 14762306a36Sopenharmony_ci__success 14862306a36Sopenharmony_ciint iter_bpf_for_each_macro(const void *ctx) 14962306a36Sopenharmony_ci{ 15062306a36Sopenharmony_ci int *v; 15162306a36Sopenharmony_ci 15262306a36Sopenharmony_ci MY_PID_GUARD(); 15362306a36Sopenharmony_ci 15462306a36Sopenharmony_ci bpf_for_each(num, v, 5, 10) { 15562306a36Sopenharmony_ci bpf_printk("ITER_BASIC: E2 VAL: v=%d", *v); 15662306a36Sopenharmony_ci } 15762306a36Sopenharmony_ci 15862306a36Sopenharmony_ci return 0; 15962306a36Sopenharmony_ci} 16062306a36Sopenharmony_ci 16162306a36Sopenharmony_ciSEC("raw_tp") 16262306a36Sopenharmony_ci__success 16362306a36Sopenharmony_ciint iter_bpf_for_macro(const void *ctx) 16462306a36Sopenharmony_ci{ 16562306a36Sopenharmony_ci int i; 16662306a36Sopenharmony_ci 16762306a36Sopenharmony_ci MY_PID_GUARD(); 16862306a36Sopenharmony_ci 16962306a36Sopenharmony_ci bpf_for(i, 5, 10) { 17062306a36Sopenharmony_ci bpf_printk("ITER_BASIC: E2 VAL: v=%d", i); 17162306a36Sopenharmony_ci } 17262306a36Sopenharmony_ci 17362306a36Sopenharmony_ci return 0; 17462306a36Sopenharmony_ci} 17562306a36Sopenharmony_ci 17662306a36Sopenharmony_ciSEC("raw_tp") 17762306a36Sopenharmony_ci__success 17862306a36Sopenharmony_ciint iter_pragma_unroll_loop(const void *ctx) 17962306a36Sopenharmony_ci{ 18062306a36Sopenharmony_ci struct bpf_iter_num it; 18162306a36Sopenharmony_ci int *v, i; 18262306a36Sopenharmony_ci 18362306a36Sopenharmony_ci MY_PID_GUARD(); 18462306a36Sopenharmony_ci 18562306a36Sopenharmony_ci bpf_iter_num_new(&it, 0, 2); 18662306a36Sopenharmony_ci#pragma nounroll 18762306a36Sopenharmony_ci for (i = 0; i < 3; i++) { 18862306a36Sopenharmony_ci v = bpf_iter_num_next(&it); 18962306a36Sopenharmony_ci bpf_printk("ITER_BASIC: E3 VAL: i=%d v=%d", i, v ? *v : -1); 19062306a36Sopenharmony_ci } 19162306a36Sopenharmony_ci bpf_iter_num_destroy(&it); 19262306a36Sopenharmony_ci 19362306a36Sopenharmony_ci return 0; 19462306a36Sopenharmony_ci} 19562306a36Sopenharmony_ci 19662306a36Sopenharmony_ciSEC("raw_tp") 19762306a36Sopenharmony_ci__success 19862306a36Sopenharmony_ciint iter_manual_unroll_loop(const void *ctx) 19962306a36Sopenharmony_ci{ 20062306a36Sopenharmony_ci struct bpf_iter_num it; 20162306a36Sopenharmony_ci int *v; 20262306a36Sopenharmony_ci 20362306a36Sopenharmony_ci MY_PID_GUARD(); 20462306a36Sopenharmony_ci 20562306a36Sopenharmony_ci bpf_iter_num_new(&it, 100, 200); 20662306a36Sopenharmony_ci v = bpf_iter_num_next(&it); 20762306a36Sopenharmony_ci bpf_printk("ITER_BASIC: E4 VAL: v=%d", v ? *v : -1); 20862306a36Sopenharmony_ci v = bpf_iter_num_next(&it); 20962306a36Sopenharmony_ci bpf_printk("ITER_BASIC: E4 VAL: v=%d", v ? *v : -1); 21062306a36Sopenharmony_ci v = bpf_iter_num_next(&it); 21162306a36Sopenharmony_ci bpf_printk("ITER_BASIC: E4 VAL: v=%d", v ? *v : -1); 21262306a36Sopenharmony_ci v = bpf_iter_num_next(&it); 21362306a36Sopenharmony_ci bpf_printk("ITER_BASIC: E4 VAL: v=%d\n", v ? *v : -1); 21462306a36Sopenharmony_ci bpf_iter_num_destroy(&it); 21562306a36Sopenharmony_ci 21662306a36Sopenharmony_ci return 0; 21762306a36Sopenharmony_ci} 21862306a36Sopenharmony_ci 21962306a36Sopenharmony_ciSEC("raw_tp") 22062306a36Sopenharmony_ci__success 22162306a36Sopenharmony_ciint iter_multiple_sequential_loops(const void *ctx) 22262306a36Sopenharmony_ci{ 22362306a36Sopenharmony_ci struct bpf_iter_num it; 22462306a36Sopenharmony_ci int *v, i; 22562306a36Sopenharmony_ci 22662306a36Sopenharmony_ci MY_PID_GUARD(); 22762306a36Sopenharmony_ci 22862306a36Sopenharmony_ci bpf_iter_num_new(&it, 0, 3); 22962306a36Sopenharmony_ci while ((v = bpf_iter_num_next(&it))) { 23062306a36Sopenharmony_ci bpf_printk("ITER_BASIC: E1 VAL: v=%d", *v); 23162306a36Sopenharmony_ci } 23262306a36Sopenharmony_ci bpf_iter_num_destroy(&it); 23362306a36Sopenharmony_ci 23462306a36Sopenharmony_ci bpf_iter_num_new(&it, 5, 10); 23562306a36Sopenharmony_ci for (v = bpf_iter_num_next(&it); v; v = bpf_iter_num_next(&it)) { 23662306a36Sopenharmony_ci bpf_printk("ITER_BASIC: E2 VAL: v=%d", *v); 23762306a36Sopenharmony_ci } 23862306a36Sopenharmony_ci bpf_iter_num_destroy(&it); 23962306a36Sopenharmony_ci 24062306a36Sopenharmony_ci bpf_iter_num_new(&it, 0, 2); 24162306a36Sopenharmony_ci#pragma nounroll 24262306a36Sopenharmony_ci for (i = 0; i < 3; i++) { 24362306a36Sopenharmony_ci v = bpf_iter_num_next(&it); 24462306a36Sopenharmony_ci bpf_printk("ITER_BASIC: E3 VAL: i=%d v=%d", i, v ? *v : -1); 24562306a36Sopenharmony_ci } 24662306a36Sopenharmony_ci bpf_iter_num_destroy(&it); 24762306a36Sopenharmony_ci 24862306a36Sopenharmony_ci bpf_iter_num_new(&it, 100, 200); 24962306a36Sopenharmony_ci v = bpf_iter_num_next(&it); 25062306a36Sopenharmony_ci bpf_printk("ITER_BASIC: E4 VAL: v=%d", v ? *v : -1); 25162306a36Sopenharmony_ci v = bpf_iter_num_next(&it); 25262306a36Sopenharmony_ci bpf_printk("ITER_BASIC: E4 VAL: v=%d", v ? *v : -1); 25362306a36Sopenharmony_ci v = bpf_iter_num_next(&it); 25462306a36Sopenharmony_ci bpf_printk("ITER_BASIC: E4 VAL: v=%d", v ? *v : -1); 25562306a36Sopenharmony_ci v = bpf_iter_num_next(&it); 25662306a36Sopenharmony_ci bpf_printk("ITER_BASIC: E4 VAL: v=%d\n", v ? *v : -1); 25762306a36Sopenharmony_ci bpf_iter_num_destroy(&it); 25862306a36Sopenharmony_ci 25962306a36Sopenharmony_ci return 0; 26062306a36Sopenharmony_ci} 26162306a36Sopenharmony_ci 26262306a36Sopenharmony_ciSEC("raw_tp") 26362306a36Sopenharmony_ci__success 26462306a36Sopenharmony_ciint iter_limit_cond_break_loop(const void *ctx) 26562306a36Sopenharmony_ci{ 26662306a36Sopenharmony_ci struct bpf_iter_num it; 26762306a36Sopenharmony_ci int *v, i = 0, sum = 0; 26862306a36Sopenharmony_ci 26962306a36Sopenharmony_ci MY_PID_GUARD(); 27062306a36Sopenharmony_ci 27162306a36Sopenharmony_ci bpf_iter_num_new(&it, 0, 10); 27262306a36Sopenharmony_ci while ((v = bpf_iter_num_next(&it))) { 27362306a36Sopenharmony_ci bpf_printk("ITER_SIMPLE: i=%d v=%d", i, *v); 27462306a36Sopenharmony_ci sum += *v; 27562306a36Sopenharmony_ci 27662306a36Sopenharmony_ci i++; 27762306a36Sopenharmony_ci if (i > 3) 27862306a36Sopenharmony_ci break; 27962306a36Sopenharmony_ci } 28062306a36Sopenharmony_ci bpf_iter_num_destroy(&it); 28162306a36Sopenharmony_ci 28262306a36Sopenharmony_ci bpf_printk("ITER_SIMPLE: sum=%d\n", sum); 28362306a36Sopenharmony_ci 28462306a36Sopenharmony_ci return 0; 28562306a36Sopenharmony_ci} 28662306a36Sopenharmony_ci 28762306a36Sopenharmony_ciSEC("raw_tp") 28862306a36Sopenharmony_ci__success 28962306a36Sopenharmony_ciint iter_obfuscate_counter(const void *ctx) 29062306a36Sopenharmony_ci{ 29162306a36Sopenharmony_ci struct bpf_iter_num it; 29262306a36Sopenharmony_ci int *v, sum = 0; 29362306a36Sopenharmony_ci /* Make i's initial value unknowable for verifier to prevent it from 29462306a36Sopenharmony_ci * pruning if/else branch inside the loop body and marking i as precise. 29562306a36Sopenharmony_ci */ 29662306a36Sopenharmony_ci int i = zero; 29762306a36Sopenharmony_ci 29862306a36Sopenharmony_ci MY_PID_GUARD(); 29962306a36Sopenharmony_ci 30062306a36Sopenharmony_ci bpf_iter_num_new(&it, 0, 10); 30162306a36Sopenharmony_ci while ((v = bpf_iter_num_next(&it))) { 30262306a36Sopenharmony_ci int x; 30362306a36Sopenharmony_ci 30462306a36Sopenharmony_ci i += 1; 30562306a36Sopenharmony_ci 30662306a36Sopenharmony_ci /* If we initialized i as `int i = 0;` above, verifier would 30762306a36Sopenharmony_ci * track that i becomes 1 on first iteration after increment 30862306a36Sopenharmony_ci * above, and here verifier would eagerly prune else branch 30962306a36Sopenharmony_ci * and mark i as precise, ruining open-coded iterator logic 31062306a36Sopenharmony_ci * completely, as each next iteration would have a different 31162306a36Sopenharmony_ci * *precise* value of i, and thus there would be no 31262306a36Sopenharmony_ci * convergence of state. This would result in reaching maximum 31362306a36Sopenharmony_ci * instruction limit, no matter what the limit is. 31462306a36Sopenharmony_ci */ 31562306a36Sopenharmony_ci if (i == 1) 31662306a36Sopenharmony_ci x = 123; 31762306a36Sopenharmony_ci else 31862306a36Sopenharmony_ci x = i * 3 + 1; 31962306a36Sopenharmony_ci 32062306a36Sopenharmony_ci bpf_printk("ITER_OBFUSCATE_COUNTER: i=%d v=%d x=%d", i, *v, x); 32162306a36Sopenharmony_ci 32262306a36Sopenharmony_ci sum += x; 32362306a36Sopenharmony_ci } 32462306a36Sopenharmony_ci bpf_iter_num_destroy(&it); 32562306a36Sopenharmony_ci 32662306a36Sopenharmony_ci bpf_printk("ITER_OBFUSCATE_COUNTER: sum=%d\n", sum); 32762306a36Sopenharmony_ci 32862306a36Sopenharmony_ci return 0; 32962306a36Sopenharmony_ci} 33062306a36Sopenharmony_ci 33162306a36Sopenharmony_ciSEC("raw_tp") 33262306a36Sopenharmony_ci__success 33362306a36Sopenharmony_ciint iter_search_loop(const void *ctx) 33462306a36Sopenharmony_ci{ 33562306a36Sopenharmony_ci struct bpf_iter_num it; 33662306a36Sopenharmony_ci int *v, *elem = NULL; 33762306a36Sopenharmony_ci bool found = false; 33862306a36Sopenharmony_ci 33962306a36Sopenharmony_ci MY_PID_GUARD(); 34062306a36Sopenharmony_ci 34162306a36Sopenharmony_ci bpf_iter_num_new(&it, 0, 10); 34262306a36Sopenharmony_ci 34362306a36Sopenharmony_ci while ((v = bpf_iter_num_next(&it))) { 34462306a36Sopenharmony_ci bpf_printk("ITER_SEARCH_LOOP: v=%d", *v); 34562306a36Sopenharmony_ci 34662306a36Sopenharmony_ci if (*v == 2) { 34762306a36Sopenharmony_ci found = true; 34862306a36Sopenharmony_ci elem = v; 34962306a36Sopenharmony_ci barrier_var(elem); 35062306a36Sopenharmony_ci } 35162306a36Sopenharmony_ci } 35262306a36Sopenharmony_ci 35362306a36Sopenharmony_ci /* should fail to verify if bpf_iter_num_destroy() is here */ 35462306a36Sopenharmony_ci 35562306a36Sopenharmony_ci if (found) 35662306a36Sopenharmony_ci /* here found element will be wrong, we should have copied 35762306a36Sopenharmony_ci * value to a variable, but here we want to make sure we can 35862306a36Sopenharmony_ci * access memory after the loop anyways 35962306a36Sopenharmony_ci */ 36062306a36Sopenharmony_ci bpf_printk("ITER_SEARCH_LOOP: FOUND IT = %d!\n", *elem); 36162306a36Sopenharmony_ci else 36262306a36Sopenharmony_ci bpf_printk("ITER_SEARCH_LOOP: NOT FOUND IT!\n"); 36362306a36Sopenharmony_ci 36462306a36Sopenharmony_ci bpf_iter_num_destroy(&it); 36562306a36Sopenharmony_ci 36662306a36Sopenharmony_ci return 0; 36762306a36Sopenharmony_ci} 36862306a36Sopenharmony_ci 36962306a36Sopenharmony_ciSEC("raw_tp") 37062306a36Sopenharmony_ci__success 37162306a36Sopenharmony_ciint iter_array_fill(const void *ctx) 37262306a36Sopenharmony_ci{ 37362306a36Sopenharmony_ci int sum, i; 37462306a36Sopenharmony_ci 37562306a36Sopenharmony_ci MY_PID_GUARD(); 37662306a36Sopenharmony_ci 37762306a36Sopenharmony_ci bpf_for(i, 0, ARRAY_SIZE(arr)) { 37862306a36Sopenharmony_ci arr[i] = i * 2; 37962306a36Sopenharmony_ci } 38062306a36Sopenharmony_ci 38162306a36Sopenharmony_ci sum = 0; 38262306a36Sopenharmony_ci bpf_for(i, 0, ARRAY_SIZE(arr)) { 38362306a36Sopenharmony_ci sum += arr[i]; 38462306a36Sopenharmony_ci } 38562306a36Sopenharmony_ci 38662306a36Sopenharmony_ci bpf_printk("ITER_ARRAY_FILL: sum=%d (should be %d)\n", sum, 255 * 256); 38762306a36Sopenharmony_ci 38862306a36Sopenharmony_ci return 0; 38962306a36Sopenharmony_ci} 39062306a36Sopenharmony_ci 39162306a36Sopenharmony_cistatic int arr2d[4][5]; 39262306a36Sopenharmony_cistatic int arr2d_row_sums[4]; 39362306a36Sopenharmony_cistatic int arr2d_col_sums[5]; 39462306a36Sopenharmony_ci 39562306a36Sopenharmony_ciSEC("raw_tp") 39662306a36Sopenharmony_ci__success 39762306a36Sopenharmony_ciint iter_nested_iters(const void *ctx) 39862306a36Sopenharmony_ci{ 39962306a36Sopenharmony_ci int sum, row, col; 40062306a36Sopenharmony_ci 40162306a36Sopenharmony_ci MY_PID_GUARD(); 40262306a36Sopenharmony_ci 40362306a36Sopenharmony_ci bpf_for(row, 0, ARRAY_SIZE(arr2d)) { 40462306a36Sopenharmony_ci bpf_for( col, 0, ARRAY_SIZE(arr2d[0])) { 40562306a36Sopenharmony_ci arr2d[row][col] = row * col; 40662306a36Sopenharmony_ci } 40762306a36Sopenharmony_ci } 40862306a36Sopenharmony_ci 40962306a36Sopenharmony_ci /* zero-initialize sums */ 41062306a36Sopenharmony_ci sum = 0; 41162306a36Sopenharmony_ci bpf_for(row, 0, ARRAY_SIZE(arr2d)) { 41262306a36Sopenharmony_ci arr2d_row_sums[row] = 0; 41362306a36Sopenharmony_ci } 41462306a36Sopenharmony_ci bpf_for(col, 0, ARRAY_SIZE(arr2d[0])) { 41562306a36Sopenharmony_ci arr2d_col_sums[col] = 0; 41662306a36Sopenharmony_ci } 41762306a36Sopenharmony_ci 41862306a36Sopenharmony_ci /* calculate sums */ 41962306a36Sopenharmony_ci bpf_for(row, 0, ARRAY_SIZE(arr2d)) { 42062306a36Sopenharmony_ci bpf_for(col, 0, ARRAY_SIZE(arr2d[0])) { 42162306a36Sopenharmony_ci sum += arr2d[row][col]; 42262306a36Sopenharmony_ci arr2d_row_sums[row] += arr2d[row][col]; 42362306a36Sopenharmony_ci arr2d_col_sums[col] += arr2d[row][col]; 42462306a36Sopenharmony_ci } 42562306a36Sopenharmony_ci } 42662306a36Sopenharmony_ci 42762306a36Sopenharmony_ci bpf_printk("ITER_NESTED_ITERS: total sum=%d", sum); 42862306a36Sopenharmony_ci bpf_for(row, 0, ARRAY_SIZE(arr2d)) { 42962306a36Sopenharmony_ci bpf_printk("ITER_NESTED_ITERS: row #%d sum=%d", row, arr2d_row_sums[row]); 43062306a36Sopenharmony_ci } 43162306a36Sopenharmony_ci bpf_for(col, 0, ARRAY_SIZE(arr2d[0])) { 43262306a36Sopenharmony_ci bpf_printk("ITER_NESTED_ITERS: col #%d sum=%d%s", 43362306a36Sopenharmony_ci col, arr2d_col_sums[col], 43462306a36Sopenharmony_ci col == ARRAY_SIZE(arr2d[0]) - 1 ? "\n" : ""); 43562306a36Sopenharmony_ci } 43662306a36Sopenharmony_ci 43762306a36Sopenharmony_ci return 0; 43862306a36Sopenharmony_ci} 43962306a36Sopenharmony_ci 44062306a36Sopenharmony_ciSEC("raw_tp") 44162306a36Sopenharmony_ci__success 44262306a36Sopenharmony_ciint iter_nested_deeply_iters(const void *ctx) 44362306a36Sopenharmony_ci{ 44462306a36Sopenharmony_ci int sum = 0; 44562306a36Sopenharmony_ci 44662306a36Sopenharmony_ci MY_PID_GUARD(); 44762306a36Sopenharmony_ci 44862306a36Sopenharmony_ci bpf_repeat(10) { 44962306a36Sopenharmony_ci bpf_repeat(10) { 45062306a36Sopenharmony_ci bpf_repeat(10) { 45162306a36Sopenharmony_ci bpf_repeat(10) { 45262306a36Sopenharmony_ci bpf_repeat(10) { 45362306a36Sopenharmony_ci sum += 1; 45462306a36Sopenharmony_ci } 45562306a36Sopenharmony_ci } 45662306a36Sopenharmony_ci } 45762306a36Sopenharmony_ci } 45862306a36Sopenharmony_ci /* validate that we can break from inside bpf_repeat() */ 45962306a36Sopenharmony_ci break; 46062306a36Sopenharmony_ci } 46162306a36Sopenharmony_ci 46262306a36Sopenharmony_ci return sum; 46362306a36Sopenharmony_ci} 46462306a36Sopenharmony_ci 46562306a36Sopenharmony_cistatic __noinline void fill_inner_dimension(int row) 46662306a36Sopenharmony_ci{ 46762306a36Sopenharmony_ci int col; 46862306a36Sopenharmony_ci 46962306a36Sopenharmony_ci bpf_for(col, 0, ARRAY_SIZE(arr2d[0])) { 47062306a36Sopenharmony_ci arr2d[row][col] = row * col; 47162306a36Sopenharmony_ci } 47262306a36Sopenharmony_ci} 47362306a36Sopenharmony_ci 47462306a36Sopenharmony_cistatic __noinline int sum_inner_dimension(int row) 47562306a36Sopenharmony_ci{ 47662306a36Sopenharmony_ci int sum = 0, col; 47762306a36Sopenharmony_ci 47862306a36Sopenharmony_ci bpf_for(col, 0, ARRAY_SIZE(arr2d[0])) { 47962306a36Sopenharmony_ci sum += arr2d[row][col]; 48062306a36Sopenharmony_ci arr2d_row_sums[row] += arr2d[row][col]; 48162306a36Sopenharmony_ci arr2d_col_sums[col] += arr2d[row][col]; 48262306a36Sopenharmony_ci } 48362306a36Sopenharmony_ci 48462306a36Sopenharmony_ci return sum; 48562306a36Sopenharmony_ci} 48662306a36Sopenharmony_ci 48762306a36Sopenharmony_ciSEC("raw_tp") 48862306a36Sopenharmony_ci__success 48962306a36Sopenharmony_ciint iter_subprog_iters(const void *ctx) 49062306a36Sopenharmony_ci{ 49162306a36Sopenharmony_ci int sum, row, col; 49262306a36Sopenharmony_ci 49362306a36Sopenharmony_ci MY_PID_GUARD(); 49462306a36Sopenharmony_ci 49562306a36Sopenharmony_ci bpf_for(row, 0, ARRAY_SIZE(arr2d)) { 49662306a36Sopenharmony_ci fill_inner_dimension(row); 49762306a36Sopenharmony_ci } 49862306a36Sopenharmony_ci 49962306a36Sopenharmony_ci /* zero-initialize sums */ 50062306a36Sopenharmony_ci sum = 0; 50162306a36Sopenharmony_ci bpf_for(row, 0, ARRAY_SIZE(arr2d)) { 50262306a36Sopenharmony_ci arr2d_row_sums[row] = 0; 50362306a36Sopenharmony_ci } 50462306a36Sopenharmony_ci bpf_for(col, 0, ARRAY_SIZE(arr2d[0])) { 50562306a36Sopenharmony_ci arr2d_col_sums[col] = 0; 50662306a36Sopenharmony_ci } 50762306a36Sopenharmony_ci 50862306a36Sopenharmony_ci /* calculate sums */ 50962306a36Sopenharmony_ci bpf_for(row, 0, ARRAY_SIZE(arr2d)) { 51062306a36Sopenharmony_ci sum += sum_inner_dimension(row); 51162306a36Sopenharmony_ci } 51262306a36Sopenharmony_ci 51362306a36Sopenharmony_ci bpf_printk("ITER_SUBPROG_ITERS: total sum=%d", sum); 51462306a36Sopenharmony_ci bpf_for(row, 0, ARRAY_SIZE(arr2d)) { 51562306a36Sopenharmony_ci bpf_printk("ITER_SUBPROG_ITERS: row #%d sum=%d", 51662306a36Sopenharmony_ci row, arr2d_row_sums[row]); 51762306a36Sopenharmony_ci } 51862306a36Sopenharmony_ci bpf_for(col, 0, ARRAY_SIZE(arr2d[0])) { 51962306a36Sopenharmony_ci bpf_printk("ITER_SUBPROG_ITERS: col #%d sum=%d%s", 52062306a36Sopenharmony_ci col, arr2d_col_sums[col], 52162306a36Sopenharmony_ci col == ARRAY_SIZE(arr2d[0]) - 1 ? "\n" : ""); 52262306a36Sopenharmony_ci } 52362306a36Sopenharmony_ci 52462306a36Sopenharmony_ci return 0; 52562306a36Sopenharmony_ci} 52662306a36Sopenharmony_ci 52762306a36Sopenharmony_cistruct { 52862306a36Sopenharmony_ci __uint(type, BPF_MAP_TYPE_ARRAY); 52962306a36Sopenharmony_ci __type(key, int); 53062306a36Sopenharmony_ci __type(value, int); 53162306a36Sopenharmony_ci __uint(max_entries, 1000); 53262306a36Sopenharmony_ci} arr_map SEC(".maps"); 53362306a36Sopenharmony_ci 53462306a36Sopenharmony_ciSEC("?raw_tp") 53562306a36Sopenharmony_ci__failure __msg("invalid mem access 'scalar'") 53662306a36Sopenharmony_ciint iter_err_too_permissive1(const void *ctx) 53762306a36Sopenharmony_ci{ 53862306a36Sopenharmony_ci int *map_val = NULL; 53962306a36Sopenharmony_ci int key = 0; 54062306a36Sopenharmony_ci 54162306a36Sopenharmony_ci MY_PID_GUARD(); 54262306a36Sopenharmony_ci 54362306a36Sopenharmony_ci map_val = bpf_map_lookup_elem(&arr_map, &key); 54462306a36Sopenharmony_ci if (!map_val) 54562306a36Sopenharmony_ci return 0; 54662306a36Sopenharmony_ci 54762306a36Sopenharmony_ci bpf_repeat(1000000) { 54862306a36Sopenharmony_ci map_val = NULL; 54962306a36Sopenharmony_ci } 55062306a36Sopenharmony_ci 55162306a36Sopenharmony_ci *map_val = 123; 55262306a36Sopenharmony_ci 55362306a36Sopenharmony_ci return 0; 55462306a36Sopenharmony_ci} 55562306a36Sopenharmony_ci 55662306a36Sopenharmony_ciSEC("?raw_tp") 55762306a36Sopenharmony_ci__failure __msg("invalid mem access 'map_value_or_null'") 55862306a36Sopenharmony_ciint iter_err_too_permissive2(const void *ctx) 55962306a36Sopenharmony_ci{ 56062306a36Sopenharmony_ci int *map_val = NULL; 56162306a36Sopenharmony_ci int key = 0; 56262306a36Sopenharmony_ci 56362306a36Sopenharmony_ci MY_PID_GUARD(); 56462306a36Sopenharmony_ci 56562306a36Sopenharmony_ci map_val = bpf_map_lookup_elem(&arr_map, &key); 56662306a36Sopenharmony_ci if (!map_val) 56762306a36Sopenharmony_ci return 0; 56862306a36Sopenharmony_ci 56962306a36Sopenharmony_ci bpf_repeat(1000000) { 57062306a36Sopenharmony_ci map_val = bpf_map_lookup_elem(&arr_map, &key); 57162306a36Sopenharmony_ci } 57262306a36Sopenharmony_ci 57362306a36Sopenharmony_ci *map_val = 123; 57462306a36Sopenharmony_ci 57562306a36Sopenharmony_ci return 0; 57662306a36Sopenharmony_ci} 57762306a36Sopenharmony_ci 57862306a36Sopenharmony_ciSEC("?raw_tp") 57962306a36Sopenharmony_ci__failure __msg("invalid mem access 'map_value_or_null'") 58062306a36Sopenharmony_ciint iter_err_too_permissive3(const void *ctx) 58162306a36Sopenharmony_ci{ 58262306a36Sopenharmony_ci int *map_val = NULL; 58362306a36Sopenharmony_ci int key = 0; 58462306a36Sopenharmony_ci bool found = false; 58562306a36Sopenharmony_ci 58662306a36Sopenharmony_ci MY_PID_GUARD(); 58762306a36Sopenharmony_ci 58862306a36Sopenharmony_ci bpf_repeat(1000000) { 58962306a36Sopenharmony_ci map_val = bpf_map_lookup_elem(&arr_map, &key); 59062306a36Sopenharmony_ci found = true; 59162306a36Sopenharmony_ci } 59262306a36Sopenharmony_ci 59362306a36Sopenharmony_ci if (found) 59462306a36Sopenharmony_ci *map_val = 123; 59562306a36Sopenharmony_ci 59662306a36Sopenharmony_ci return 0; 59762306a36Sopenharmony_ci} 59862306a36Sopenharmony_ci 59962306a36Sopenharmony_ciSEC("raw_tp") 60062306a36Sopenharmony_ci__success 60162306a36Sopenharmony_ciint iter_tricky_but_fine(const void *ctx) 60262306a36Sopenharmony_ci{ 60362306a36Sopenharmony_ci int *map_val = NULL; 60462306a36Sopenharmony_ci int key = 0; 60562306a36Sopenharmony_ci bool found = false; 60662306a36Sopenharmony_ci 60762306a36Sopenharmony_ci MY_PID_GUARD(); 60862306a36Sopenharmony_ci 60962306a36Sopenharmony_ci bpf_repeat(1000000) { 61062306a36Sopenharmony_ci map_val = bpf_map_lookup_elem(&arr_map, &key); 61162306a36Sopenharmony_ci if (map_val) { 61262306a36Sopenharmony_ci found = true; 61362306a36Sopenharmony_ci break; 61462306a36Sopenharmony_ci } 61562306a36Sopenharmony_ci } 61662306a36Sopenharmony_ci 61762306a36Sopenharmony_ci if (found) 61862306a36Sopenharmony_ci *map_val = 123; 61962306a36Sopenharmony_ci 62062306a36Sopenharmony_ci return 0; 62162306a36Sopenharmony_ci} 62262306a36Sopenharmony_ci 62362306a36Sopenharmony_ci#define __bpf_memzero(p, sz) bpf_probe_read_kernel((p), (sz), 0) 62462306a36Sopenharmony_ci 62562306a36Sopenharmony_ciSEC("raw_tp") 62662306a36Sopenharmony_ci__success 62762306a36Sopenharmony_ciint iter_stack_array_loop(const void *ctx) 62862306a36Sopenharmony_ci{ 62962306a36Sopenharmony_ci long arr1[16], arr2[16], sum = 0; 63062306a36Sopenharmony_ci int i; 63162306a36Sopenharmony_ci 63262306a36Sopenharmony_ci MY_PID_GUARD(); 63362306a36Sopenharmony_ci 63462306a36Sopenharmony_ci /* zero-init arr1 and arr2 in such a way that verifier doesn't know 63562306a36Sopenharmony_ci * it's all zeros; if we don't do that, we'll make BPF verifier track 63662306a36Sopenharmony_ci * all combination of zero/non-zero stack slots for arr1/arr2, which 63762306a36Sopenharmony_ci * will lead to O(2^(ARRAY_SIZE(arr1)+ARRAY_SIZE(arr2))) different 63862306a36Sopenharmony_ci * states 63962306a36Sopenharmony_ci */ 64062306a36Sopenharmony_ci __bpf_memzero(arr1, sizeof(arr1)); 64162306a36Sopenharmony_ci __bpf_memzero(arr2, sizeof(arr1)); 64262306a36Sopenharmony_ci 64362306a36Sopenharmony_ci /* validate that we can break and continue when using bpf_for() */ 64462306a36Sopenharmony_ci bpf_for(i, 0, ARRAY_SIZE(arr1)) { 64562306a36Sopenharmony_ci if (i & 1) { 64662306a36Sopenharmony_ci arr1[i] = i; 64762306a36Sopenharmony_ci continue; 64862306a36Sopenharmony_ci } else { 64962306a36Sopenharmony_ci arr2[i] = i; 65062306a36Sopenharmony_ci break; 65162306a36Sopenharmony_ci } 65262306a36Sopenharmony_ci } 65362306a36Sopenharmony_ci 65462306a36Sopenharmony_ci bpf_for(i, 0, ARRAY_SIZE(arr1)) { 65562306a36Sopenharmony_ci sum += arr1[i] + arr2[i]; 65662306a36Sopenharmony_ci } 65762306a36Sopenharmony_ci 65862306a36Sopenharmony_ci return sum; 65962306a36Sopenharmony_ci} 66062306a36Sopenharmony_ci 66162306a36Sopenharmony_cistatic __noinline void fill(struct bpf_iter_num *it, int *arr, __u32 n, int mul) 66262306a36Sopenharmony_ci{ 66362306a36Sopenharmony_ci int *t, i; 66462306a36Sopenharmony_ci 66562306a36Sopenharmony_ci while ((t = bpf_iter_num_next(it))) { 66662306a36Sopenharmony_ci i = *t; 66762306a36Sopenharmony_ci if (i >= n) 66862306a36Sopenharmony_ci break; 66962306a36Sopenharmony_ci arr[i] = i * mul; 67062306a36Sopenharmony_ci } 67162306a36Sopenharmony_ci} 67262306a36Sopenharmony_ci 67362306a36Sopenharmony_cistatic __noinline int sum(struct bpf_iter_num *it, int *arr, __u32 n) 67462306a36Sopenharmony_ci{ 67562306a36Sopenharmony_ci int *t, i, sum = 0;; 67662306a36Sopenharmony_ci 67762306a36Sopenharmony_ci while ((t = bpf_iter_num_next(it))) { 67862306a36Sopenharmony_ci i = *t; 67962306a36Sopenharmony_ci if (i >= n) 68062306a36Sopenharmony_ci break; 68162306a36Sopenharmony_ci sum += arr[i]; 68262306a36Sopenharmony_ci } 68362306a36Sopenharmony_ci 68462306a36Sopenharmony_ci return sum; 68562306a36Sopenharmony_ci} 68662306a36Sopenharmony_ci 68762306a36Sopenharmony_ciSEC("raw_tp") 68862306a36Sopenharmony_ci__success 68962306a36Sopenharmony_ciint iter_pass_iter_ptr_to_subprog(const void *ctx) 69062306a36Sopenharmony_ci{ 69162306a36Sopenharmony_ci int arr1[16], arr2[32]; 69262306a36Sopenharmony_ci struct bpf_iter_num it; 69362306a36Sopenharmony_ci int n, sum1, sum2; 69462306a36Sopenharmony_ci 69562306a36Sopenharmony_ci MY_PID_GUARD(); 69662306a36Sopenharmony_ci 69762306a36Sopenharmony_ci /* fill arr1 */ 69862306a36Sopenharmony_ci n = ARRAY_SIZE(arr1); 69962306a36Sopenharmony_ci bpf_iter_num_new(&it, 0, n); 70062306a36Sopenharmony_ci fill(&it, arr1, n, 2); 70162306a36Sopenharmony_ci bpf_iter_num_destroy(&it); 70262306a36Sopenharmony_ci 70362306a36Sopenharmony_ci /* fill arr2 */ 70462306a36Sopenharmony_ci n = ARRAY_SIZE(arr2); 70562306a36Sopenharmony_ci bpf_iter_num_new(&it, 0, n); 70662306a36Sopenharmony_ci fill(&it, arr2, n, 10); 70762306a36Sopenharmony_ci bpf_iter_num_destroy(&it); 70862306a36Sopenharmony_ci 70962306a36Sopenharmony_ci /* sum arr1 */ 71062306a36Sopenharmony_ci n = ARRAY_SIZE(arr1); 71162306a36Sopenharmony_ci bpf_iter_num_new(&it, 0, n); 71262306a36Sopenharmony_ci sum1 = sum(&it, arr1, n); 71362306a36Sopenharmony_ci bpf_iter_num_destroy(&it); 71462306a36Sopenharmony_ci 71562306a36Sopenharmony_ci /* sum arr2 */ 71662306a36Sopenharmony_ci n = ARRAY_SIZE(arr2); 71762306a36Sopenharmony_ci bpf_iter_num_new(&it, 0, n); 71862306a36Sopenharmony_ci sum2 = sum(&it, arr2, n); 71962306a36Sopenharmony_ci bpf_iter_num_destroy(&it); 72062306a36Sopenharmony_ci 72162306a36Sopenharmony_ci bpf_printk("sum1=%d, sum2=%d", sum1, sum2); 72262306a36Sopenharmony_ci 72362306a36Sopenharmony_ci return 0; 72462306a36Sopenharmony_ci} 72562306a36Sopenharmony_ci 72662306a36Sopenharmony_ciSEC("?raw_tp") 72762306a36Sopenharmony_ci__failure 72862306a36Sopenharmony_ci__msg("R1 type=scalar expected=fp") 72962306a36Sopenharmony_ci__naked int delayed_read_mark(void) 73062306a36Sopenharmony_ci{ 73162306a36Sopenharmony_ci /* This is equivalent to C program below. 73262306a36Sopenharmony_ci * The call to bpf_iter_num_next() is reachable with r7 values &fp[-16] and 0xdead. 73362306a36Sopenharmony_ci * State with r7=&fp[-16] is visited first and follows r6 != 42 ... continue branch. 73462306a36Sopenharmony_ci * At this point iterator next() call is reached with r7 that has no read mark. 73562306a36Sopenharmony_ci * Loop body with r7=0xdead would only be visited if verifier would decide to continue 73662306a36Sopenharmony_ci * with second loop iteration. Absence of read mark on r7 might affect state 73762306a36Sopenharmony_ci * equivalent logic used for iterator convergence tracking. 73862306a36Sopenharmony_ci * 73962306a36Sopenharmony_ci * r7 = &fp[-16] 74062306a36Sopenharmony_ci * fp[-16] = 0 74162306a36Sopenharmony_ci * r6 = bpf_get_prandom_u32() 74262306a36Sopenharmony_ci * bpf_iter_num_new(&fp[-8], 0, 10) 74362306a36Sopenharmony_ci * while (bpf_iter_num_next(&fp[-8])) { 74462306a36Sopenharmony_ci * r6++ 74562306a36Sopenharmony_ci * if (r6 != 42) { 74662306a36Sopenharmony_ci * r7 = 0xdead 74762306a36Sopenharmony_ci * continue; 74862306a36Sopenharmony_ci * } 74962306a36Sopenharmony_ci * bpf_probe_read_user(r7, 8, 0xdeadbeef); // this is not safe 75062306a36Sopenharmony_ci * } 75162306a36Sopenharmony_ci * bpf_iter_num_destroy(&fp[-8]) 75262306a36Sopenharmony_ci * return 0 75362306a36Sopenharmony_ci */ 75462306a36Sopenharmony_ci asm volatile ( 75562306a36Sopenharmony_ci "r7 = r10;" 75662306a36Sopenharmony_ci "r7 += -16;" 75762306a36Sopenharmony_ci "r0 = 0;" 75862306a36Sopenharmony_ci "*(u64 *)(r7 + 0) = r0;" 75962306a36Sopenharmony_ci "call %[bpf_get_prandom_u32];" 76062306a36Sopenharmony_ci "r6 = r0;" 76162306a36Sopenharmony_ci "r1 = r10;" 76262306a36Sopenharmony_ci "r1 += -8;" 76362306a36Sopenharmony_ci "r2 = 0;" 76462306a36Sopenharmony_ci "r3 = 10;" 76562306a36Sopenharmony_ci "call %[bpf_iter_num_new];" 76662306a36Sopenharmony_ci "1:" 76762306a36Sopenharmony_ci "r1 = r10;" 76862306a36Sopenharmony_ci "r1 += -8;" 76962306a36Sopenharmony_ci "call %[bpf_iter_num_next];" 77062306a36Sopenharmony_ci "if r0 == 0 goto 2f;" 77162306a36Sopenharmony_ci "r6 += 1;" 77262306a36Sopenharmony_ci "if r6 != 42 goto 3f;" 77362306a36Sopenharmony_ci "r7 = 0xdead;" 77462306a36Sopenharmony_ci "goto 1b;" 77562306a36Sopenharmony_ci "3:" 77662306a36Sopenharmony_ci "r1 = r7;" 77762306a36Sopenharmony_ci "r2 = 8;" 77862306a36Sopenharmony_ci "r3 = 0xdeadbeef;" 77962306a36Sopenharmony_ci "call %[bpf_probe_read_user];" 78062306a36Sopenharmony_ci "goto 1b;" 78162306a36Sopenharmony_ci "2:" 78262306a36Sopenharmony_ci "r1 = r10;" 78362306a36Sopenharmony_ci "r1 += -8;" 78462306a36Sopenharmony_ci "call %[bpf_iter_num_destroy];" 78562306a36Sopenharmony_ci "r0 = 0;" 78662306a36Sopenharmony_ci "exit;" 78762306a36Sopenharmony_ci : 78862306a36Sopenharmony_ci : __imm(bpf_get_prandom_u32), 78962306a36Sopenharmony_ci __imm(bpf_iter_num_new), 79062306a36Sopenharmony_ci __imm(bpf_iter_num_next), 79162306a36Sopenharmony_ci __imm(bpf_iter_num_destroy), 79262306a36Sopenharmony_ci __imm(bpf_probe_read_user) 79362306a36Sopenharmony_ci : __clobber_all 79462306a36Sopenharmony_ci ); 79562306a36Sopenharmony_ci} 79662306a36Sopenharmony_ci 79762306a36Sopenharmony_ciSEC("?raw_tp") 79862306a36Sopenharmony_ci__failure 79962306a36Sopenharmony_ci__msg("math between fp pointer and register with unbounded") 80062306a36Sopenharmony_ci__naked int delayed_precision_mark(void) 80162306a36Sopenharmony_ci{ 80262306a36Sopenharmony_ci /* This is equivalent to C program below. 80362306a36Sopenharmony_ci * The test is similar to delayed_iter_mark but verifies that incomplete 80462306a36Sopenharmony_ci * precision don't fool verifier. 80562306a36Sopenharmony_ci * The call to bpf_iter_num_next() is reachable with r7 values -16 and -32. 80662306a36Sopenharmony_ci * State with r7=-16 is visited first and follows r6 != 42 ... continue branch. 80762306a36Sopenharmony_ci * At this point iterator next() call is reached with r7 that has no read 80862306a36Sopenharmony_ci * and precision marks. 80962306a36Sopenharmony_ci * Loop body with r7=-32 would only be visited if verifier would decide to continue 81062306a36Sopenharmony_ci * with second loop iteration. Absence of precision mark on r7 might affect state 81162306a36Sopenharmony_ci * equivalent logic used for iterator convergence tracking. 81262306a36Sopenharmony_ci * 81362306a36Sopenharmony_ci * r8 = 0 81462306a36Sopenharmony_ci * fp[-16] = 0 81562306a36Sopenharmony_ci * r7 = -16 81662306a36Sopenharmony_ci * r6 = bpf_get_prandom_u32() 81762306a36Sopenharmony_ci * bpf_iter_num_new(&fp[-8], 0, 10) 81862306a36Sopenharmony_ci * while (bpf_iter_num_next(&fp[-8])) { 81962306a36Sopenharmony_ci * if (r6 != 42) { 82062306a36Sopenharmony_ci * r7 = -32 82162306a36Sopenharmony_ci * r6 = bpf_get_prandom_u32() 82262306a36Sopenharmony_ci * continue; 82362306a36Sopenharmony_ci * } 82462306a36Sopenharmony_ci * r0 = r10 82562306a36Sopenharmony_ci * r0 += r7 82662306a36Sopenharmony_ci * r8 = *(u64 *)(r0 + 0) // this is not safe 82762306a36Sopenharmony_ci * r6 = bpf_get_prandom_u32() 82862306a36Sopenharmony_ci * } 82962306a36Sopenharmony_ci * bpf_iter_num_destroy(&fp[-8]) 83062306a36Sopenharmony_ci * return r8 83162306a36Sopenharmony_ci */ 83262306a36Sopenharmony_ci asm volatile ( 83362306a36Sopenharmony_ci "r8 = 0;" 83462306a36Sopenharmony_ci "*(u64 *)(r10 - 16) = r8;" 83562306a36Sopenharmony_ci "r7 = -16;" 83662306a36Sopenharmony_ci "call %[bpf_get_prandom_u32];" 83762306a36Sopenharmony_ci "r6 = r0;" 83862306a36Sopenharmony_ci "r1 = r10;" 83962306a36Sopenharmony_ci "r1 += -8;" 84062306a36Sopenharmony_ci "r2 = 0;" 84162306a36Sopenharmony_ci "r3 = 10;" 84262306a36Sopenharmony_ci "call %[bpf_iter_num_new];" 84362306a36Sopenharmony_ci "1:" 84462306a36Sopenharmony_ci "r1 = r10;" 84562306a36Sopenharmony_ci "r1 += -8;\n" 84662306a36Sopenharmony_ci "call %[bpf_iter_num_next];" 84762306a36Sopenharmony_ci "if r0 == 0 goto 2f;" 84862306a36Sopenharmony_ci "if r6 != 42 goto 3f;" 84962306a36Sopenharmony_ci "r7 = -32;" 85062306a36Sopenharmony_ci "call %[bpf_get_prandom_u32];" 85162306a36Sopenharmony_ci "r6 = r0;" 85262306a36Sopenharmony_ci "goto 1b;\n" 85362306a36Sopenharmony_ci "3:" 85462306a36Sopenharmony_ci "r0 = r10;" 85562306a36Sopenharmony_ci "r0 += r7;" 85662306a36Sopenharmony_ci "r8 = *(u64 *)(r0 + 0);" 85762306a36Sopenharmony_ci "call %[bpf_get_prandom_u32];" 85862306a36Sopenharmony_ci "r6 = r0;" 85962306a36Sopenharmony_ci "goto 1b;\n" 86062306a36Sopenharmony_ci "2:" 86162306a36Sopenharmony_ci "r1 = r10;" 86262306a36Sopenharmony_ci "r1 += -8;" 86362306a36Sopenharmony_ci "call %[bpf_iter_num_destroy];" 86462306a36Sopenharmony_ci "r0 = r8;" 86562306a36Sopenharmony_ci "exit;" 86662306a36Sopenharmony_ci : 86762306a36Sopenharmony_ci : __imm(bpf_get_prandom_u32), 86862306a36Sopenharmony_ci __imm(bpf_iter_num_new), 86962306a36Sopenharmony_ci __imm(bpf_iter_num_next), 87062306a36Sopenharmony_ci __imm(bpf_iter_num_destroy), 87162306a36Sopenharmony_ci __imm(bpf_probe_read_user) 87262306a36Sopenharmony_ci : __clobber_all 87362306a36Sopenharmony_ci ); 87462306a36Sopenharmony_ci} 87562306a36Sopenharmony_ci 87662306a36Sopenharmony_ciSEC("?raw_tp") 87762306a36Sopenharmony_ci__failure 87862306a36Sopenharmony_ci__msg("math between fp pointer and register with unbounded") 87962306a36Sopenharmony_ci__flag(BPF_F_TEST_STATE_FREQ) 88062306a36Sopenharmony_ci__naked int loop_state_deps1(void) 88162306a36Sopenharmony_ci{ 88262306a36Sopenharmony_ci /* This is equivalent to C program below. 88362306a36Sopenharmony_ci * 88462306a36Sopenharmony_ci * The case turns out to be tricky in a sense that: 88562306a36Sopenharmony_ci * - states with c=-25 are explored only on a second iteration 88662306a36Sopenharmony_ci * of the outer loop; 88762306a36Sopenharmony_ci * - states with read+precise mark on c are explored only on 88862306a36Sopenharmony_ci * second iteration of the inner loop and in a state which 88962306a36Sopenharmony_ci * is pushed to states stack first. 89062306a36Sopenharmony_ci * 89162306a36Sopenharmony_ci * Depending on the details of iterator convergence logic 89262306a36Sopenharmony_ci * verifier might stop states traversal too early and miss 89362306a36Sopenharmony_ci * unsafe c=-25 memory access. 89462306a36Sopenharmony_ci * 89562306a36Sopenharmony_ci * j = iter_new(); // fp[-16] 89662306a36Sopenharmony_ci * a = 0; // r6 89762306a36Sopenharmony_ci * b = 0; // r7 89862306a36Sopenharmony_ci * c = -24; // r8 89962306a36Sopenharmony_ci * while (iter_next(j)) { 90062306a36Sopenharmony_ci * i = iter_new(); // fp[-8] 90162306a36Sopenharmony_ci * a = 0; // r6 90262306a36Sopenharmony_ci * b = 0; // r7 90362306a36Sopenharmony_ci * while (iter_next(i)) { 90462306a36Sopenharmony_ci * if (a == 1) { 90562306a36Sopenharmony_ci * a = 0; 90662306a36Sopenharmony_ci * b = 1; 90762306a36Sopenharmony_ci * } else if (a == 0) { 90862306a36Sopenharmony_ci * a = 1; 90962306a36Sopenharmony_ci * if (random() == 42) 91062306a36Sopenharmony_ci * continue; 91162306a36Sopenharmony_ci * if (b == 1) { 91262306a36Sopenharmony_ci * *(r10 + c) = 7; // this is not safe 91362306a36Sopenharmony_ci * iter_destroy(i); 91462306a36Sopenharmony_ci * iter_destroy(j); 91562306a36Sopenharmony_ci * return; 91662306a36Sopenharmony_ci * } 91762306a36Sopenharmony_ci * } 91862306a36Sopenharmony_ci * } 91962306a36Sopenharmony_ci * iter_destroy(i); 92062306a36Sopenharmony_ci * a = 0; 92162306a36Sopenharmony_ci * b = 0; 92262306a36Sopenharmony_ci * c = -25; 92362306a36Sopenharmony_ci * } 92462306a36Sopenharmony_ci * iter_destroy(j); 92562306a36Sopenharmony_ci * return; 92662306a36Sopenharmony_ci */ 92762306a36Sopenharmony_ci asm volatile ( 92862306a36Sopenharmony_ci "r1 = r10;" 92962306a36Sopenharmony_ci "r1 += -16;" 93062306a36Sopenharmony_ci "r2 = 0;" 93162306a36Sopenharmony_ci "r3 = 10;" 93262306a36Sopenharmony_ci "call %[bpf_iter_num_new];" 93362306a36Sopenharmony_ci "r6 = 0;" 93462306a36Sopenharmony_ci "r7 = 0;" 93562306a36Sopenharmony_ci "r8 = -24;" 93662306a36Sopenharmony_ci "j_loop_%=:" 93762306a36Sopenharmony_ci "r1 = r10;" 93862306a36Sopenharmony_ci "r1 += -16;" 93962306a36Sopenharmony_ci "call %[bpf_iter_num_next];" 94062306a36Sopenharmony_ci "if r0 == 0 goto j_loop_end_%=;" 94162306a36Sopenharmony_ci "r1 = r10;" 94262306a36Sopenharmony_ci "r1 += -8;" 94362306a36Sopenharmony_ci "r2 = 0;" 94462306a36Sopenharmony_ci "r3 = 10;" 94562306a36Sopenharmony_ci "call %[bpf_iter_num_new];" 94662306a36Sopenharmony_ci "r6 = 0;" 94762306a36Sopenharmony_ci "r7 = 0;" 94862306a36Sopenharmony_ci "i_loop_%=:" 94962306a36Sopenharmony_ci "r1 = r10;" 95062306a36Sopenharmony_ci "r1 += -8;" 95162306a36Sopenharmony_ci "call %[bpf_iter_num_next];" 95262306a36Sopenharmony_ci "if r0 == 0 goto i_loop_end_%=;" 95362306a36Sopenharmony_ci "check_one_r6_%=:" 95462306a36Sopenharmony_ci "if r6 != 1 goto check_zero_r6_%=;" 95562306a36Sopenharmony_ci "r6 = 0;" 95662306a36Sopenharmony_ci "r7 = 1;" 95762306a36Sopenharmony_ci "goto i_loop_%=;" 95862306a36Sopenharmony_ci "check_zero_r6_%=:" 95962306a36Sopenharmony_ci "if r6 != 0 goto i_loop_%=;" 96062306a36Sopenharmony_ci "r6 = 1;" 96162306a36Sopenharmony_ci "call %[bpf_get_prandom_u32];" 96262306a36Sopenharmony_ci "if r0 != 42 goto check_one_r7_%=;" 96362306a36Sopenharmony_ci "goto i_loop_%=;" 96462306a36Sopenharmony_ci "check_one_r7_%=:" 96562306a36Sopenharmony_ci "if r7 != 1 goto i_loop_%=;" 96662306a36Sopenharmony_ci "r0 = r10;" 96762306a36Sopenharmony_ci "r0 += r8;" 96862306a36Sopenharmony_ci "r1 = 7;" 96962306a36Sopenharmony_ci "*(u64 *)(r0 + 0) = r1;" 97062306a36Sopenharmony_ci "r1 = r10;" 97162306a36Sopenharmony_ci "r1 += -8;" 97262306a36Sopenharmony_ci "call %[bpf_iter_num_destroy];" 97362306a36Sopenharmony_ci "r1 = r10;" 97462306a36Sopenharmony_ci "r1 += -16;" 97562306a36Sopenharmony_ci "call %[bpf_iter_num_destroy];" 97662306a36Sopenharmony_ci "r0 = 0;" 97762306a36Sopenharmony_ci "exit;" 97862306a36Sopenharmony_ci "i_loop_end_%=:" 97962306a36Sopenharmony_ci "r1 = r10;" 98062306a36Sopenharmony_ci "r1 += -8;" 98162306a36Sopenharmony_ci "call %[bpf_iter_num_destroy];" 98262306a36Sopenharmony_ci "r6 = 0;" 98362306a36Sopenharmony_ci "r7 = 0;" 98462306a36Sopenharmony_ci "r8 = -25;" 98562306a36Sopenharmony_ci "goto j_loop_%=;" 98662306a36Sopenharmony_ci "j_loop_end_%=:" 98762306a36Sopenharmony_ci "r1 = r10;" 98862306a36Sopenharmony_ci "r1 += -16;" 98962306a36Sopenharmony_ci "call %[bpf_iter_num_destroy];" 99062306a36Sopenharmony_ci "r0 = 0;" 99162306a36Sopenharmony_ci "exit;" 99262306a36Sopenharmony_ci : 99362306a36Sopenharmony_ci : __imm(bpf_get_prandom_u32), 99462306a36Sopenharmony_ci __imm(bpf_iter_num_new), 99562306a36Sopenharmony_ci __imm(bpf_iter_num_next), 99662306a36Sopenharmony_ci __imm(bpf_iter_num_destroy) 99762306a36Sopenharmony_ci : __clobber_all 99862306a36Sopenharmony_ci ); 99962306a36Sopenharmony_ci} 100062306a36Sopenharmony_ci 100162306a36Sopenharmony_ciSEC("?raw_tp") 100262306a36Sopenharmony_ci__failure 100362306a36Sopenharmony_ci__msg("math between fp pointer and register with unbounded") 100462306a36Sopenharmony_ci__flag(BPF_F_TEST_STATE_FREQ) 100562306a36Sopenharmony_ci__naked int loop_state_deps2(void) 100662306a36Sopenharmony_ci{ 100762306a36Sopenharmony_ci /* This is equivalent to C program below. 100862306a36Sopenharmony_ci * 100962306a36Sopenharmony_ci * The case turns out to be tricky in a sense that: 101062306a36Sopenharmony_ci * - states with read+precise mark on c are explored only on a second 101162306a36Sopenharmony_ci * iteration of the first inner loop and in a state which is pushed to 101262306a36Sopenharmony_ci * states stack first. 101362306a36Sopenharmony_ci * - states with c=-25 are explored only on a second iteration of the 101462306a36Sopenharmony_ci * second inner loop and in a state which is pushed to states stack 101562306a36Sopenharmony_ci * first. 101662306a36Sopenharmony_ci * 101762306a36Sopenharmony_ci * Depending on the details of iterator convergence logic 101862306a36Sopenharmony_ci * verifier might stop states traversal too early and miss 101962306a36Sopenharmony_ci * unsafe c=-25 memory access. 102062306a36Sopenharmony_ci * 102162306a36Sopenharmony_ci * j = iter_new(); // fp[-16] 102262306a36Sopenharmony_ci * a = 0; // r6 102362306a36Sopenharmony_ci * b = 0; // r7 102462306a36Sopenharmony_ci * c = -24; // r8 102562306a36Sopenharmony_ci * while (iter_next(j)) { 102662306a36Sopenharmony_ci * i = iter_new(); // fp[-8] 102762306a36Sopenharmony_ci * a = 0; // r6 102862306a36Sopenharmony_ci * b = 0; // r7 102962306a36Sopenharmony_ci * while (iter_next(i)) { 103062306a36Sopenharmony_ci * if (a == 1) { 103162306a36Sopenharmony_ci * a = 0; 103262306a36Sopenharmony_ci * b = 1; 103362306a36Sopenharmony_ci * } else if (a == 0) { 103462306a36Sopenharmony_ci * a = 1; 103562306a36Sopenharmony_ci * if (random() == 42) 103662306a36Sopenharmony_ci * continue; 103762306a36Sopenharmony_ci * if (b == 1) { 103862306a36Sopenharmony_ci * *(r10 + c) = 7; // this is not safe 103962306a36Sopenharmony_ci * iter_destroy(i); 104062306a36Sopenharmony_ci * iter_destroy(j); 104162306a36Sopenharmony_ci * return; 104262306a36Sopenharmony_ci * } 104362306a36Sopenharmony_ci * } 104462306a36Sopenharmony_ci * } 104562306a36Sopenharmony_ci * iter_destroy(i); 104662306a36Sopenharmony_ci * i = iter_new(); // fp[-8] 104762306a36Sopenharmony_ci * a = 0; // r6 104862306a36Sopenharmony_ci * b = 0; // r7 104962306a36Sopenharmony_ci * while (iter_next(i)) { 105062306a36Sopenharmony_ci * if (a == 1) { 105162306a36Sopenharmony_ci * a = 0; 105262306a36Sopenharmony_ci * b = 1; 105362306a36Sopenharmony_ci * } else if (a == 0) { 105462306a36Sopenharmony_ci * a = 1; 105562306a36Sopenharmony_ci * if (random() == 42) 105662306a36Sopenharmony_ci * continue; 105762306a36Sopenharmony_ci * if (b == 1) { 105862306a36Sopenharmony_ci * a = 0; 105962306a36Sopenharmony_ci * c = -25; 106062306a36Sopenharmony_ci * } 106162306a36Sopenharmony_ci * } 106262306a36Sopenharmony_ci * } 106362306a36Sopenharmony_ci * iter_destroy(i); 106462306a36Sopenharmony_ci * } 106562306a36Sopenharmony_ci * iter_destroy(j); 106662306a36Sopenharmony_ci * return; 106762306a36Sopenharmony_ci */ 106862306a36Sopenharmony_ci asm volatile ( 106962306a36Sopenharmony_ci "r1 = r10;" 107062306a36Sopenharmony_ci "r1 += -16;" 107162306a36Sopenharmony_ci "r2 = 0;" 107262306a36Sopenharmony_ci "r3 = 10;" 107362306a36Sopenharmony_ci "call %[bpf_iter_num_new];" 107462306a36Sopenharmony_ci "r6 = 0;" 107562306a36Sopenharmony_ci "r7 = 0;" 107662306a36Sopenharmony_ci "r8 = -24;" 107762306a36Sopenharmony_ci "j_loop_%=:" 107862306a36Sopenharmony_ci "r1 = r10;" 107962306a36Sopenharmony_ci "r1 += -16;" 108062306a36Sopenharmony_ci "call %[bpf_iter_num_next];" 108162306a36Sopenharmony_ci "if r0 == 0 goto j_loop_end_%=;" 108262306a36Sopenharmony_ci 108362306a36Sopenharmony_ci /* first inner loop */ 108462306a36Sopenharmony_ci "r1 = r10;" 108562306a36Sopenharmony_ci "r1 += -8;" 108662306a36Sopenharmony_ci "r2 = 0;" 108762306a36Sopenharmony_ci "r3 = 10;" 108862306a36Sopenharmony_ci "call %[bpf_iter_num_new];" 108962306a36Sopenharmony_ci "r6 = 0;" 109062306a36Sopenharmony_ci "r7 = 0;" 109162306a36Sopenharmony_ci "i_loop_%=:" 109262306a36Sopenharmony_ci "r1 = r10;" 109362306a36Sopenharmony_ci "r1 += -8;" 109462306a36Sopenharmony_ci "call %[bpf_iter_num_next];" 109562306a36Sopenharmony_ci "if r0 == 0 goto i_loop_end_%=;" 109662306a36Sopenharmony_ci "check_one_r6_%=:" 109762306a36Sopenharmony_ci "if r6 != 1 goto check_zero_r6_%=;" 109862306a36Sopenharmony_ci "r6 = 0;" 109962306a36Sopenharmony_ci "r7 = 1;" 110062306a36Sopenharmony_ci "goto i_loop_%=;" 110162306a36Sopenharmony_ci "check_zero_r6_%=:" 110262306a36Sopenharmony_ci "if r6 != 0 goto i_loop_%=;" 110362306a36Sopenharmony_ci "r6 = 1;" 110462306a36Sopenharmony_ci "call %[bpf_get_prandom_u32];" 110562306a36Sopenharmony_ci "if r0 != 42 goto check_one_r7_%=;" 110662306a36Sopenharmony_ci "goto i_loop_%=;" 110762306a36Sopenharmony_ci "check_one_r7_%=:" 110862306a36Sopenharmony_ci "if r7 != 1 goto i_loop_%=;" 110962306a36Sopenharmony_ci "r0 = r10;" 111062306a36Sopenharmony_ci "r0 += r8;" 111162306a36Sopenharmony_ci "r1 = 7;" 111262306a36Sopenharmony_ci "*(u64 *)(r0 + 0) = r1;" 111362306a36Sopenharmony_ci "r1 = r10;" 111462306a36Sopenharmony_ci "r1 += -8;" 111562306a36Sopenharmony_ci "call %[bpf_iter_num_destroy];" 111662306a36Sopenharmony_ci "r1 = r10;" 111762306a36Sopenharmony_ci "r1 += -16;" 111862306a36Sopenharmony_ci "call %[bpf_iter_num_destroy];" 111962306a36Sopenharmony_ci "r0 = 0;" 112062306a36Sopenharmony_ci "exit;" 112162306a36Sopenharmony_ci "i_loop_end_%=:" 112262306a36Sopenharmony_ci "r1 = r10;" 112362306a36Sopenharmony_ci "r1 += -8;" 112462306a36Sopenharmony_ci "call %[bpf_iter_num_destroy];" 112562306a36Sopenharmony_ci 112662306a36Sopenharmony_ci /* second inner loop */ 112762306a36Sopenharmony_ci "r1 = r10;" 112862306a36Sopenharmony_ci "r1 += -8;" 112962306a36Sopenharmony_ci "r2 = 0;" 113062306a36Sopenharmony_ci "r3 = 10;" 113162306a36Sopenharmony_ci "call %[bpf_iter_num_new];" 113262306a36Sopenharmony_ci "r6 = 0;" 113362306a36Sopenharmony_ci "r7 = 0;" 113462306a36Sopenharmony_ci "i2_loop_%=:" 113562306a36Sopenharmony_ci "r1 = r10;" 113662306a36Sopenharmony_ci "r1 += -8;" 113762306a36Sopenharmony_ci "call %[bpf_iter_num_next];" 113862306a36Sopenharmony_ci "if r0 == 0 goto i2_loop_end_%=;" 113962306a36Sopenharmony_ci "check2_one_r6_%=:" 114062306a36Sopenharmony_ci "if r6 != 1 goto check2_zero_r6_%=;" 114162306a36Sopenharmony_ci "r6 = 0;" 114262306a36Sopenharmony_ci "r7 = 1;" 114362306a36Sopenharmony_ci "goto i2_loop_%=;" 114462306a36Sopenharmony_ci "check2_zero_r6_%=:" 114562306a36Sopenharmony_ci "if r6 != 0 goto i2_loop_%=;" 114662306a36Sopenharmony_ci "r6 = 1;" 114762306a36Sopenharmony_ci "call %[bpf_get_prandom_u32];" 114862306a36Sopenharmony_ci "if r0 != 42 goto check2_one_r7_%=;" 114962306a36Sopenharmony_ci "goto i2_loop_%=;" 115062306a36Sopenharmony_ci "check2_one_r7_%=:" 115162306a36Sopenharmony_ci "if r7 != 1 goto i2_loop_%=;" 115262306a36Sopenharmony_ci "r6 = 0;" 115362306a36Sopenharmony_ci "r8 = -25;" 115462306a36Sopenharmony_ci "goto i2_loop_%=;" 115562306a36Sopenharmony_ci "i2_loop_end_%=:" 115662306a36Sopenharmony_ci "r1 = r10;" 115762306a36Sopenharmony_ci "r1 += -8;" 115862306a36Sopenharmony_ci "call %[bpf_iter_num_destroy];" 115962306a36Sopenharmony_ci 116062306a36Sopenharmony_ci "r6 = 0;" 116162306a36Sopenharmony_ci "r7 = 0;" 116262306a36Sopenharmony_ci "goto j_loop_%=;" 116362306a36Sopenharmony_ci "j_loop_end_%=:" 116462306a36Sopenharmony_ci "r1 = r10;" 116562306a36Sopenharmony_ci "r1 += -16;" 116662306a36Sopenharmony_ci "call %[bpf_iter_num_destroy];" 116762306a36Sopenharmony_ci "r0 = 0;" 116862306a36Sopenharmony_ci "exit;" 116962306a36Sopenharmony_ci : 117062306a36Sopenharmony_ci : __imm(bpf_get_prandom_u32), 117162306a36Sopenharmony_ci __imm(bpf_iter_num_new), 117262306a36Sopenharmony_ci __imm(bpf_iter_num_next), 117362306a36Sopenharmony_ci __imm(bpf_iter_num_destroy) 117462306a36Sopenharmony_ci : __clobber_all 117562306a36Sopenharmony_ci ); 117662306a36Sopenharmony_ci} 117762306a36Sopenharmony_ci 117862306a36Sopenharmony_ciSEC("?raw_tp") 117962306a36Sopenharmony_ci__success 118062306a36Sopenharmony_ci__naked int triple_continue(void) 118162306a36Sopenharmony_ci{ 118262306a36Sopenharmony_ci /* This is equivalent to C program below. 118362306a36Sopenharmony_ci * High branching factor of the loop body turned out to be 118462306a36Sopenharmony_ci * problematic for one of the iterator convergence tracking 118562306a36Sopenharmony_ci * algorithms explored. 118662306a36Sopenharmony_ci * 118762306a36Sopenharmony_ci * r6 = bpf_get_prandom_u32() 118862306a36Sopenharmony_ci * bpf_iter_num_new(&fp[-8], 0, 10) 118962306a36Sopenharmony_ci * while (bpf_iter_num_next(&fp[-8])) { 119062306a36Sopenharmony_ci * if (bpf_get_prandom_u32() != 42) 119162306a36Sopenharmony_ci * continue; 119262306a36Sopenharmony_ci * if (bpf_get_prandom_u32() != 42) 119362306a36Sopenharmony_ci * continue; 119462306a36Sopenharmony_ci * if (bpf_get_prandom_u32() != 42) 119562306a36Sopenharmony_ci * continue; 119662306a36Sopenharmony_ci * r0 += 0; 119762306a36Sopenharmony_ci * } 119862306a36Sopenharmony_ci * bpf_iter_num_destroy(&fp[-8]) 119962306a36Sopenharmony_ci * return 0 120062306a36Sopenharmony_ci */ 120162306a36Sopenharmony_ci asm volatile ( 120262306a36Sopenharmony_ci "r1 = r10;" 120362306a36Sopenharmony_ci "r1 += -8;" 120462306a36Sopenharmony_ci "r2 = 0;" 120562306a36Sopenharmony_ci "r3 = 10;" 120662306a36Sopenharmony_ci "call %[bpf_iter_num_new];" 120762306a36Sopenharmony_ci "loop_%=:" 120862306a36Sopenharmony_ci "r1 = r10;" 120962306a36Sopenharmony_ci "r1 += -8;" 121062306a36Sopenharmony_ci "call %[bpf_iter_num_next];" 121162306a36Sopenharmony_ci "if r0 == 0 goto loop_end_%=;" 121262306a36Sopenharmony_ci "call %[bpf_get_prandom_u32];" 121362306a36Sopenharmony_ci "if r0 != 42 goto loop_%=;" 121462306a36Sopenharmony_ci "call %[bpf_get_prandom_u32];" 121562306a36Sopenharmony_ci "if r0 != 42 goto loop_%=;" 121662306a36Sopenharmony_ci "call %[bpf_get_prandom_u32];" 121762306a36Sopenharmony_ci "if r0 != 42 goto loop_%=;" 121862306a36Sopenharmony_ci "r0 += 0;" 121962306a36Sopenharmony_ci "goto loop_%=;" 122062306a36Sopenharmony_ci "loop_end_%=:" 122162306a36Sopenharmony_ci "r1 = r10;" 122262306a36Sopenharmony_ci "r1 += -8;" 122362306a36Sopenharmony_ci "call %[bpf_iter_num_destroy];" 122462306a36Sopenharmony_ci "r0 = 0;" 122562306a36Sopenharmony_ci "exit;" 122662306a36Sopenharmony_ci : 122762306a36Sopenharmony_ci : __imm(bpf_get_prandom_u32), 122862306a36Sopenharmony_ci __imm(bpf_iter_num_new), 122962306a36Sopenharmony_ci __imm(bpf_iter_num_next), 123062306a36Sopenharmony_ci __imm(bpf_iter_num_destroy) 123162306a36Sopenharmony_ci : __clobber_all 123262306a36Sopenharmony_ci ); 123362306a36Sopenharmony_ci} 123462306a36Sopenharmony_ci 123562306a36Sopenharmony_ciSEC("?raw_tp") 123662306a36Sopenharmony_ci__success 123762306a36Sopenharmony_ci__naked int widen_spill(void) 123862306a36Sopenharmony_ci{ 123962306a36Sopenharmony_ci /* This is equivalent to C program below. 124062306a36Sopenharmony_ci * The counter is stored in fp[-16], if this counter is not widened 124162306a36Sopenharmony_ci * verifier states representing loop iterations would never converge. 124262306a36Sopenharmony_ci * 124362306a36Sopenharmony_ci * fp[-16] = 0 124462306a36Sopenharmony_ci * bpf_iter_num_new(&fp[-8], 0, 10) 124562306a36Sopenharmony_ci * while (bpf_iter_num_next(&fp[-8])) { 124662306a36Sopenharmony_ci * r0 = fp[-16]; 124762306a36Sopenharmony_ci * r0 += 1; 124862306a36Sopenharmony_ci * fp[-16] = r0; 124962306a36Sopenharmony_ci * } 125062306a36Sopenharmony_ci * bpf_iter_num_destroy(&fp[-8]) 125162306a36Sopenharmony_ci * return 0 125262306a36Sopenharmony_ci */ 125362306a36Sopenharmony_ci asm volatile ( 125462306a36Sopenharmony_ci "r0 = 0;" 125562306a36Sopenharmony_ci "*(u64 *)(r10 - 16) = r0;" 125662306a36Sopenharmony_ci "r1 = r10;" 125762306a36Sopenharmony_ci "r1 += -8;" 125862306a36Sopenharmony_ci "r2 = 0;" 125962306a36Sopenharmony_ci "r3 = 10;" 126062306a36Sopenharmony_ci "call %[bpf_iter_num_new];" 126162306a36Sopenharmony_ci "loop_%=:" 126262306a36Sopenharmony_ci "r1 = r10;" 126362306a36Sopenharmony_ci "r1 += -8;" 126462306a36Sopenharmony_ci "call %[bpf_iter_num_next];" 126562306a36Sopenharmony_ci "if r0 == 0 goto loop_end_%=;" 126662306a36Sopenharmony_ci "r0 = *(u64 *)(r10 - 16);" 126762306a36Sopenharmony_ci "r0 += 1;" 126862306a36Sopenharmony_ci "*(u64 *)(r10 - 16) = r0;" 126962306a36Sopenharmony_ci "goto loop_%=;" 127062306a36Sopenharmony_ci "loop_end_%=:" 127162306a36Sopenharmony_ci "r1 = r10;" 127262306a36Sopenharmony_ci "r1 += -8;" 127362306a36Sopenharmony_ci "call %[bpf_iter_num_destroy];" 127462306a36Sopenharmony_ci "r0 = 0;" 127562306a36Sopenharmony_ci "exit;" 127662306a36Sopenharmony_ci : 127762306a36Sopenharmony_ci : __imm(bpf_iter_num_new), 127862306a36Sopenharmony_ci __imm(bpf_iter_num_next), 127962306a36Sopenharmony_ci __imm(bpf_iter_num_destroy) 128062306a36Sopenharmony_ci : __clobber_all 128162306a36Sopenharmony_ci ); 128262306a36Sopenharmony_ci} 128362306a36Sopenharmony_ci 128462306a36Sopenharmony_ciSEC("raw_tp") 128562306a36Sopenharmony_ci__success 128662306a36Sopenharmony_ci__naked int checkpoint_states_deletion(void) 128762306a36Sopenharmony_ci{ 128862306a36Sopenharmony_ci /* This is equivalent to C program below. 128962306a36Sopenharmony_ci * 129062306a36Sopenharmony_ci * int *a, *b, *c, *d, *e, *f; 129162306a36Sopenharmony_ci * int i, sum = 0; 129262306a36Sopenharmony_ci * bpf_for(i, 0, 10) { 129362306a36Sopenharmony_ci * a = bpf_map_lookup_elem(&amap, &i); 129462306a36Sopenharmony_ci * b = bpf_map_lookup_elem(&amap, &i); 129562306a36Sopenharmony_ci * c = bpf_map_lookup_elem(&amap, &i); 129662306a36Sopenharmony_ci * d = bpf_map_lookup_elem(&amap, &i); 129762306a36Sopenharmony_ci * e = bpf_map_lookup_elem(&amap, &i); 129862306a36Sopenharmony_ci * f = bpf_map_lookup_elem(&amap, &i); 129962306a36Sopenharmony_ci * if (a) sum += 1; 130062306a36Sopenharmony_ci * if (b) sum += 1; 130162306a36Sopenharmony_ci * if (c) sum += 1; 130262306a36Sopenharmony_ci * if (d) sum += 1; 130362306a36Sopenharmony_ci * if (e) sum += 1; 130462306a36Sopenharmony_ci * if (f) sum += 1; 130562306a36Sopenharmony_ci * } 130662306a36Sopenharmony_ci * return 0; 130762306a36Sopenharmony_ci * 130862306a36Sopenharmony_ci * The body of the loop spawns multiple simulation paths 130962306a36Sopenharmony_ci * with different combination of NULL/non-NULL information for a/b/c/d/e/f. 131062306a36Sopenharmony_ci * Each combination is unique from states_equal() point of view. 131162306a36Sopenharmony_ci * Explored states checkpoint is created after each iterator next call. 131262306a36Sopenharmony_ci * Iterator convergence logic expects that eventually current state 131362306a36Sopenharmony_ci * would get equal to one of the explored states and thus loop 131462306a36Sopenharmony_ci * exploration would be finished (at-least for a specific path). 131562306a36Sopenharmony_ci * Verifier evicts explored states with high miss to hit ratio 131662306a36Sopenharmony_ci * to to avoid comparing current state with too many explored 131762306a36Sopenharmony_ci * states per instruction. 131862306a36Sopenharmony_ci * This test is designed to "stress test" eviction policy defined using formula: 131962306a36Sopenharmony_ci * 132062306a36Sopenharmony_ci * sl->miss_cnt > sl->hit_cnt * N + N // if true sl->state is evicted 132162306a36Sopenharmony_ci * 132262306a36Sopenharmony_ci * Currently N is set to 64, which allows for 6 variables in this test. 132362306a36Sopenharmony_ci */ 132462306a36Sopenharmony_ci asm volatile ( 132562306a36Sopenharmony_ci "r6 = 0;" /* a */ 132662306a36Sopenharmony_ci "r7 = 0;" /* b */ 132762306a36Sopenharmony_ci "r8 = 0;" /* c */ 132862306a36Sopenharmony_ci "*(u64 *)(r10 - 24) = r6;" /* d */ 132962306a36Sopenharmony_ci "*(u64 *)(r10 - 32) = r6;" /* e */ 133062306a36Sopenharmony_ci "*(u64 *)(r10 - 40) = r6;" /* f */ 133162306a36Sopenharmony_ci "r9 = 0;" /* sum */ 133262306a36Sopenharmony_ci "r1 = r10;" 133362306a36Sopenharmony_ci "r1 += -8;" 133462306a36Sopenharmony_ci "r2 = 0;" 133562306a36Sopenharmony_ci "r3 = 10;" 133662306a36Sopenharmony_ci "call %[bpf_iter_num_new];" 133762306a36Sopenharmony_ci "loop_%=:" 133862306a36Sopenharmony_ci "r1 = r10;" 133962306a36Sopenharmony_ci "r1 += -8;" 134062306a36Sopenharmony_ci "call %[bpf_iter_num_next];" 134162306a36Sopenharmony_ci "if r0 == 0 goto loop_end_%=;" 134262306a36Sopenharmony_ci 134362306a36Sopenharmony_ci "*(u64 *)(r10 - 16) = r0;" 134462306a36Sopenharmony_ci 134562306a36Sopenharmony_ci "r1 = %[amap] ll;" 134662306a36Sopenharmony_ci "r2 = r10;" 134762306a36Sopenharmony_ci "r2 += -16;" 134862306a36Sopenharmony_ci "call %[bpf_map_lookup_elem];" 134962306a36Sopenharmony_ci "r6 = r0;" 135062306a36Sopenharmony_ci 135162306a36Sopenharmony_ci "r1 = %[amap] ll;" 135262306a36Sopenharmony_ci "r2 = r10;" 135362306a36Sopenharmony_ci "r2 += -16;" 135462306a36Sopenharmony_ci "call %[bpf_map_lookup_elem];" 135562306a36Sopenharmony_ci "r7 = r0;" 135662306a36Sopenharmony_ci 135762306a36Sopenharmony_ci "r1 = %[amap] ll;" 135862306a36Sopenharmony_ci "r2 = r10;" 135962306a36Sopenharmony_ci "r2 += -16;" 136062306a36Sopenharmony_ci "call %[bpf_map_lookup_elem];" 136162306a36Sopenharmony_ci "r8 = r0;" 136262306a36Sopenharmony_ci 136362306a36Sopenharmony_ci "r1 = %[amap] ll;" 136462306a36Sopenharmony_ci "r2 = r10;" 136562306a36Sopenharmony_ci "r2 += -16;" 136662306a36Sopenharmony_ci "call %[bpf_map_lookup_elem];" 136762306a36Sopenharmony_ci "*(u64 *)(r10 - 24) = r0;" 136862306a36Sopenharmony_ci 136962306a36Sopenharmony_ci "r1 = %[amap] ll;" 137062306a36Sopenharmony_ci "r2 = r10;" 137162306a36Sopenharmony_ci "r2 += -16;" 137262306a36Sopenharmony_ci "call %[bpf_map_lookup_elem];" 137362306a36Sopenharmony_ci "*(u64 *)(r10 - 32) = r0;" 137462306a36Sopenharmony_ci 137562306a36Sopenharmony_ci "r1 = %[amap] ll;" 137662306a36Sopenharmony_ci "r2 = r10;" 137762306a36Sopenharmony_ci "r2 += -16;" 137862306a36Sopenharmony_ci "call %[bpf_map_lookup_elem];" 137962306a36Sopenharmony_ci "*(u64 *)(r10 - 40) = r0;" 138062306a36Sopenharmony_ci 138162306a36Sopenharmony_ci "if r6 == 0 goto +1;" 138262306a36Sopenharmony_ci "r9 += 1;" 138362306a36Sopenharmony_ci "if r7 == 0 goto +1;" 138462306a36Sopenharmony_ci "r9 += 1;" 138562306a36Sopenharmony_ci "if r8 == 0 goto +1;" 138662306a36Sopenharmony_ci "r9 += 1;" 138762306a36Sopenharmony_ci "r0 = *(u64 *)(r10 - 24);" 138862306a36Sopenharmony_ci "if r0 == 0 goto +1;" 138962306a36Sopenharmony_ci "r9 += 1;" 139062306a36Sopenharmony_ci "r0 = *(u64 *)(r10 - 32);" 139162306a36Sopenharmony_ci "if r0 == 0 goto +1;" 139262306a36Sopenharmony_ci "r9 += 1;" 139362306a36Sopenharmony_ci "r0 = *(u64 *)(r10 - 40);" 139462306a36Sopenharmony_ci "if r0 == 0 goto +1;" 139562306a36Sopenharmony_ci "r9 += 1;" 139662306a36Sopenharmony_ci 139762306a36Sopenharmony_ci "goto loop_%=;" 139862306a36Sopenharmony_ci "loop_end_%=:" 139962306a36Sopenharmony_ci "r1 = r10;" 140062306a36Sopenharmony_ci "r1 += -8;" 140162306a36Sopenharmony_ci "call %[bpf_iter_num_destroy];" 140262306a36Sopenharmony_ci "r0 = 0;" 140362306a36Sopenharmony_ci "exit;" 140462306a36Sopenharmony_ci : 140562306a36Sopenharmony_ci : __imm(bpf_map_lookup_elem), 140662306a36Sopenharmony_ci __imm(bpf_iter_num_new), 140762306a36Sopenharmony_ci __imm(bpf_iter_num_next), 140862306a36Sopenharmony_ci __imm(bpf_iter_num_destroy), 140962306a36Sopenharmony_ci __imm_addr(amap) 141062306a36Sopenharmony_ci : __clobber_all 141162306a36Sopenharmony_ci ); 141262306a36Sopenharmony_ci} 141362306a36Sopenharmony_ci 141462306a36Sopenharmony_cichar _license[] SEC("license") = "GPL"; 1415