Skip to content

Commit 6715df8

Browse files
eddyz87Alexei Starovoitov
authored andcommitted
bpf: Allow reads from uninit stack
This commits updates the following functions to allow reads from uninitialized stack locations when env->allow_uninit_stack option is enabled: - check_stack_read_fixed_off() - check_stack_range_initialized(), called from: - check_stack_read_var_off() - check_helper_mem_access() Such change allows to relax logic in stacksafe() to treat STACK_MISC and STACK_INVALID in a same way and make the following stack slot configurations equivalent: | Cached state | Current state | | stack slot | stack slot | |------------------+------------------| | STACK_INVALID or | STACK_INVALID or | | STACK_MISC | STACK_SPILL or | | | STACK_MISC or | | | STACK_ZERO or | | | STACK_DYNPTR | This leads to significant verification speed gains (see below). The idea was suggested by Andrii Nakryiko [1] and initial patch was created by Alexei Starovoitov [2]. Currently the env->allow_uninit_stack is allowed for programs loaded by users with CAP_PERFMON or CAP_SYS_ADMIN capabilities. A number of test cases from verifier/*.c were expecting uninitialized stack access to be an error. These test cases were updated to execute in unprivileged mode (thus preserving the tests). The test progs/test_global_func10.c expected "invalid indirect read from stack" error message because of the access to uninitialized memory region. This error is no longer possible in privileged mode. The test is updated to provoke an error "invalid indirect access to stack" because of access to invalid stack address (such error is not verified by progs/test_global_func*.c series of tests). The following tests had to be removed because these can't be made unprivileged: - verifier/sock.c: - "sk_storage_get(map, skb->sk, &stack_value, 1): partially init stack_value" BPF_PROG_TYPE_SCHED_CLS programs are not executed in unprivileged mode. - verifier/var_off.c: - "indirect variable-offset stack access, max_off+size > max_initialized" - "indirect variable-offset stack access, uninitialized" These tests verify that access to uninitialized stack values is detected when stack offset is not a constant. However, variable stack access is prohibited in unprivileged mode, thus these tests are no longer valid. * * * Here is veristat log comparing this patch with current master on a set of selftest binaries listed in tools/testing/selftests/bpf/veristat.cfg and cilium BPF binaries (see [3]): $ ./veristat -e file,prog,states -C -f 'states_pct<-30' master.log current.log File Program States (A) States (B) States (DIFF) -------------------------- -------------------------- ---------- ---------- ---------------- bpf_host.o tail_handle_ipv6_from_host 349 244 -105 (-30.09%) bpf_host.o tail_handle_nat_fwd_ipv4 1320 895 -425 (-32.20%) bpf_lxc.o tail_handle_nat_fwd_ipv4 1320 895 -425 (-32.20%) bpf_sock.o cil_sock4_connect 70 48 -22 (-31.43%) bpf_sock.o cil_sock4_sendmsg 68 46 -22 (-32.35%) bpf_xdp.o tail_handle_nat_fwd_ipv4 1554 803 -751 (-48.33%) bpf_xdp.o tail_lb_ipv4 6457 2473 -3984 (-61.70%) bpf_xdp.o tail_lb_ipv6 7249 3908 -3341 (-46.09%) pyperf600_bpf_loop.bpf.o on_event 287 145 -142 (-49.48%) strobemeta.bpf.o on_event 15915 4772 -11143 (-70.02%) strobemeta_nounroll2.bpf.o on_event 17087 3820 -13267 (-77.64%) xdp_synproxy_kern.bpf.o syncookie_tc 21271 6635 -14636 (-68.81%) xdp_synproxy_kern.bpf.o syncookie_xdp 23122 6024 -17098 (-73.95%) -------------------------- -------------------------- ---------- ---------- ---------------- Note: I limited selection by states_pct<-30%. Inspection of differences in pyperf600_bpf_loop behavior shows that the following patch for the test removes almost all differences: - a/tools/testing/selftests/bpf/progs/pyperf.h + b/tools/testing/selftests/bpf/progs/pyperf.h @ -266,8 +266,8 @ int __on_event(struct bpf_raw_tracepoint_args *ctx) } if (event->pthread_match || !pidData->use_tls) { - void* frame_ptr; - FrameData frame; + void* frame_ptr = 0; + FrameData frame = {}; Symbol sym = {}; int cur_cpu = bpf_get_smp_processor_id(); W/o this patch the difference comes from the following pattern (for different variables): static bool get_frame_data(... FrameData *frame ...) { ... bpf_probe_read_user(&frame->f_code, ...); if (!frame->f_code) return false; ... bpf_probe_read_user(&frame->co_name, ...); if (frame->co_name) ...; } int __on_event(struct bpf_raw_tracepoint_args *ctx) { FrameData frame; ... get_frame_data(... &frame ...) // indirectly via a bpf_loop & callback ... } SEC("raw_tracepoint/kfree_skb") int on_event(struct bpf_raw_tracepoint_args* ctx) { ... ret |= __on_event(ctx); ret |= __on_event(ctx); ... } With regards to value `frame->co_name` the following is important: - Because of the conditional `if (!frame->f_code)` each call to __on_event() produces two states, one with `frame->co_name` marked as STACK_MISC, another with it as is (and marked STACK_INVALID on a first call). - The call to bpf_probe_read_user() does not mark stack slots corresponding to `&frame->co_name` as REG_LIVE_WRITTEN but it marks these slots as BPF_MISC, this happens because of the following loop in the check_helper_call(): for (i = 0; i < meta.access_size; i++) { err = check_mem_access(env, insn_idx, meta.regno, i, BPF_B, BPF_WRITE, -1, false); if (err) return err; } Note the size of the write, it is a one byte write for each byte touched by a helper. The BPF_B write does not lead to write marks for the target stack slot. - Which means that w/o this patch when second __on_event() call is verified `if (frame->co_name)` will propagate read marks first to a stack slot with STACK_MISC marks and second to a stack slot with STACK_INVALID marks and these states would be considered different. [1] https://lore.kernel.org/bpf/CAEf4BzY3e+ZuC6HUa8dCiUovQRg2SzEk7M-dSkqNZyn=xEmnPA@mail.gmail.com/ [2] https://lore.kernel.org/bpf/CAADnVQKs2i1iuZ5SUGuJtxWVfGYR9kDgYKhq3rNV+kBLQCu7rA@mail.gmail.com/ [3] git@github.com:anakryiko/cilium.git Suggested-by: Andrii Nakryiko <andrii@kernel.org> Co-developed-by: Alexei Starovoitov <ast@kernel.org> Signed-off-by: Eduard Zingerman <eddyz87@gmail.com> Acked-by: Andrii Nakryiko <andrii@kernel.org> Link: https://lore.kernel.org/r/20230219200427.606541-2-eddyz87@gmail.com Signed-off-by: Alexei Starovoitov <ast@kernel.org>
1 parent 5b7c4ca commit 6715df8

File tree

9 files changed

+108
-136
lines changed

9 files changed

+108
-136
lines changed

kernel/bpf/verifier.c

Lines changed: 10 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -3826,6 +3826,8 @@ static int check_stack_read_fixed_off(struct bpf_verifier_env *env,
38263826
continue;
38273827
if (type == STACK_MISC)
38283828
continue;
3829+
if (type == STACK_INVALID && env->allow_uninit_stack)
3830+
continue;
38293831
verbose(env, "invalid read from stack off %d+%d size %d\n",
38303832
off, i, size);
38313833
return -EACCES;
@@ -3863,6 +3865,8 @@ static int check_stack_read_fixed_off(struct bpf_verifier_env *env,
38633865
continue;
38643866
if (type == STACK_ZERO)
38653867
continue;
3868+
if (type == STACK_INVALID && env->allow_uninit_stack)
3869+
continue;
38663870
verbose(env, "invalid read from stack off %d+%d size %d\n",
38673871
off, i, size);
38683872
return -EACCES;
@@ -5754,7 +5758,8 @@ static int check_stack_range_initialized(
57545758
stype = &state->stack[spi].slot_type[slot % BPF_REG_SIZE];
57555759
if (*stype == STACK_MISC)
57565760
goto mark;
5757-
if (*stype == STACK_ZERO) {
5761+
if ((*stype == STACK_ZERO) ||
5762+
(*stype == STACK_INVALID && env->allow_uninit_stack)) {
57585763
if (clobber) {
57595764
/* helper can write anything into the stack */
57605765
*stype = STACK_MISC;
@@ -13936,6 +13941,10 @@ static bool stacksafe(struct bpf_verifier_env *env, struct bpf_func_state *old,
1393613941
if (old->stack[spi].slot_type[i % BPF_REG_SIZE] == STACK_INVALID)
1393713942
continue;
1393813943

13944+
if (env->allow_uninit_stack &&
13945+
old->stack[spi].slot_type[i % BPF_REG_SIZE] == STACK_MISC)
13946+
continue;
13947+
1393913948
/* explored stack has more populated slots than current stack
1394013949
* and these slots were used
1394113950
*/

tools/testing/selftests/bpf/progs/test_global_func10.c

Lines changed: 4 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -5,12 +5,12 @@
55
#include "bpf_misc.h"
66

77
struct Small {
8-
int x;
8+
long x;
99
};
1010

1111
struct Big {
12-
int x;
13-
int y;
12+
long x;
13+
long y;
1414
};
1515

1616
__noinline int foo(const struct Big *big)
@@ -22,7 +22,7 @@ __noinline int foo(const struct Big *big)
2222
}
2323

2424
SEC("cgroup_skb/ingress")
25-
__failure __msg("invalid indirect read from stack")
25+
__failure __msg("invalid indirect access to stack")
2626
int global_func10(struct __sk_buff *skb)
2727
{
2828
const struct Small small = {.x = skb->len };

tools/testing/selftests/bpf/verifier/calls.c

Lines changed: 8 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -2221,19 +2221,22 @@
22212221
* that fp-8 stack slot was unused in the fall-through
22222222
* branch and will accept the program incorrectly
22232223
*/
2224-
BPF_JMP_IMM(BPF_JGT, BPF_REG_1, 2, 2),
2224+
BPF_EMIT_CALL(BPF_FUNC_get_prandom_u32),
2225+
BPF_JMP_IMM(BPF_JGT, BPF_REG_0, 2, 2),
22252226
BPF_ST_MEM(BPF_DW, BPF_REG_10, -8, 0),
22262227
BPF_JMP_IMM(BPF_JA, 0, 0, 0),
22272228
BPF_MOV64_REG(BPF_REG_2, BPF_REG_10),
22282229
BPF_ALU64_IMM(BPF_ADD, BPF_REG_2, -8),
22292230
BPF_LD_MAP_FD(BPF_REG_1, 0),
22302231
BPF_RAW_INSN(BPF_JMP | BPF_CALL, 0, 0, 0, BPF_FUNC_map_lookup_elem),
2232+
BPF_MOV64_IMM(BPF_REG_0, 0),
22312233
BPF_EXIT_INSN(),
22322234
},
2233-
.fixup_map_hash_48b = { 6 },
2234-
.errstr = "invalid indirect read from stack R2 off -8+0 size 8",
2235-
.result = REJECT,
2236-
.prog_type = BPF_PROG_TYPE_XDP,
2235+
.fixup_map_hash_48b = { 7 },
2236+
.errstr_unpriv = "invalid indirect read from stack R2 off -8+0 size 8",
2237+
.result_unpriv = REJECT,
2238+
/* in privileged mode reads from uninitialized stack locations are permitted */
2239+
.result = ACCEPT,
22372240
},
22382241
{
22392242
"calls: ctx read at start of subprog",

tools/testing/selftests/bpf/verifier/helper_access_var_len.c

Lines changed: 69 additions & 35 deletions
Original file line numberDiff line numberDiff line change
@@ -29,19 +29,30 @@
2929
{
3030
"helper access to variable memory: stack, bitwise AND, zero included",
3131
.insns = {
32-
BPF_LDX_MEM(BPF_DW, BPF_REG_2, BPF_REG_1, 8),
33-
BPF_MOV64_REG(BPF_REG_1, BPF_REG_10),
34-
BPF_ALU64_IMM(BPF_ADD, BPF_REG_1, -64),
35-
BPF_STX_MEM(BPF_DW, BPF_REG_1, BPF_REG_2, -128),
36-
BPF_LDX_MEM(BPF_DW, BPF_REG_2, BPF_REG_1, -128),
37-
BPF_ALU64_IMM(BPF_AND, BPF_REG_2, 64),
38-
BPF_MOV64_IMM(BPF_REG_3, 0),
39-
BPF_EMIT_CALL(BPF_FUNC_probe_read_kernel),
32+
/* set max stack size */
33+
BPF_ST_MEM(BPF_DW, BPF_REG_10, -128, 0),
34+
/* set r3 to a random value */
35+
BPF_EMIT_CALL(BPF_FUNC_get_prandom_u32),
36+
BPF_MOV64_REG(BPF_REG_3, BPF_REG_0),
37+
/* use bitwise AND to limit r3 range to [0, 64] */
38+
BPF_ALU64_IMM(BPF_AND, BPF_REG_3, 64),
39+
BPF_LD_MAP_FD(BPF_REG_1, 0),
40+
BPF_MOV64_REG(BPF_REG_2, BPF_REG_10),
41+
BPF_ALU64_IMM(BPF_ADD, BPF_REG_2, -64),
42+
BPF_MOV64_IMM(BPF_REG_4, 0),
43+
/* Call bpf_ringbuf_output(), it is one of a few helper functions with
44+
* ARG_CONST_SIZE_OR_ZERO parameter allowed in unpriv mode.
45+
* For unpriv this should signal an error, because memory at &fp[-64] is
46+
* not initialized.
47+
*/
48+
BPF_EMIT_CALL(BPF_FUNC_ringbuf_output),
4049
BPF_EXIT_INSN(),
4150
},
42-
.errstr = "invalid indirect read from stack R1 off -64+0 size 64",
43-
.result = REJECT,
44-
.prog_type = BPF_PROG_TYPE_TRACEPOINT,
51+
.fixup_map_ringbuf = { 4 },
52+
.errstr_unpriv = "invalid indirect read from stack R2 off -64+0 size 64",
53+
.result_unpriv = REJECT,
54+
/* in privileged mode reads from uninitialized stack locations are permitted */
55+
.result = ACCEPT,
4556
},
4657
{
4758
"helper access to variable memory: stack, bitwise AND + JMP, wrong max",
@@ -183,20 +194,31 @@
183194
{
184195
"helper access to variable memory: stack, JMP, no min check",
185196
.insns = {
186-
BPF_LDX_MEM(BPF_DW, BPF_REG_2, BPF_REG_1, 8),
187-
BPF_MOV64_REG(BPF_REG_1, BPF_REG_10),
188-
BPF_ALU64_IMM(BPF_ADD, BPF_REG_1, -64),
189-
BPF_STX_MEM(BPF_DW, BPF_REG_1, BPF_REG_2, -128),
190-
BPF_LDX_MEM(BPF_DW, BPF_REG_2, BPF_REG_1, -128),
191-
BPF_JMP_IMM(BPF_JGT, BPF_REG_2, 64, 3),
192-
BPF_MOV64_IMM(BPF_REG_3, 0),
193-
BPF_EMIT_CALL(BPF_FUNC_probe_read_kernel),
197+
/* set max stack size */
198+
BPF_ST_MEM(BPF_DW, BPF_REG_10, -128, 0),
199+
/* set r3 to a random value */
200+
BPF_EMIT_CALL(BPF_FUNC_get_prandom_u32),
201+
BPF_MOV64_REG(BPF_REG_3, BPF_REG_0),
202+
/* use JMP to limit r3 range to [0, 64] */
203+
BPF_JMP_IMM(BPF_JGT, BPF_REG_3, 64, 6),
204+
BPF_LD_MAP_FD(BPF_REG_1, 0),
205+
BPF_MOV64_REG(BPF_REG_2, BPF_REG_10),
206+
BPF_ALU64_IMM(BPF_ADD, BPF_REG_2, -64),
207+
BPF_MOV64_IMM(BPF_REG_4, 0),
208+
/* Call bpf_ringbuf_output(), it is one of a few helper functions with
209+
* ARG_CONST_SIZE_OR_ZERO parameter allowed in unpriv mode.
210+
* For unpriv this should signal an error, because memory at &fp[-64] is
211+
* not initialized.
212+
*/
213+
BPF_EMIT_CALL(BPF_FUNC_ringbuf_output),
194214
BPF_MOV64_IMM(BPF_REG_0, 0),
195215
BPF_EXIT_INSN(),
196216
},
197-
.errstr = "invalid indirect read from stack R1 off -64+0 size 64",
198-
.result = REJECT,
199-
.prog_type = BPF_PROG_TYPE_TRACEPOINT,
217+
.fixup_map_ringbuf = { 4 },
218+
.errstr_unpriv = "invalid indirect read from stack R2 off -64+0 size 64",
219+
.result_unpriv = REJECT,
220+
/* in privileged mode reads from uninitialized stack locations are permitted */
221+
.result = ACCEPT,
200222
},
201223
{
202224
"helper access to variable memory: stack, JMP (signed), no min check",
@@ -564,29 +586,41 @@
564586
{
565587
"helper access to variable memory: 8 bytes leak",
566588
.insns = {
567-
BPF_LDX_MEM(BPF_DW, BPF_REG_2, BPF_REG_1, 8),
568-
BPF_MOV64_REG(BPF_REG_1, BPF_REG_10),
569-
BPF_ALU64_IMM(BPF_ADD, BPF_REG_1, -64),
589+
/* set max stack size */
590+
BPF_ST_MEM(BPF_DW, BPF_REG_10, -128, 0),
591+
/* set r3 to a random value */
592+
BPF_EMIT_CALL(BPF_FUNC_get_prandom_u32),
593+
BPF_MOV64_REG(BPF_REG_3, BPF_REG_0),
594+
BPF_LD_MAP_FD(BPF_REG_1, 0),
595+
BPF_MOV64_REG(BPF_REG_2, BPF_REG_10),
596+
BPF_ALU64_IMM(BPF_ADD, BPF_REG_2, -64),
570597
BPF_MOV64_IMM(BPF_REG_0, 0),
571598
BPF_STX_MEM(BPF_DW, BPF_REG_10, BPF_REG_0, -64),
572599
BPF_STX_MEM(BPF_DW, BPF_REG_10, BPF_REG_0, -56),
573600
BPF_STX_MEM(BPF_DW, BPF_REG_10, BPF_REG_0, -48),
574601
BPF_STX_MEM(BPF_DW, BPF_REG_10, BPF_REG_0, -40),
602+
/* Note: fp[-32] left uninitialized */
575603
BPF_STX_MEM(BPF_DW, BPF_REG_10, BPF_REG_0, -24),
576604
BPF_STX_MEM(BPF_DW, BPF_REG_10, BPF_REG_0, -16),
577605
BPF_STX_MEM(BPF_DW, BPF_REG_10, BPF_REG_0, -8),
578-
BPF_STX_MEM(BPF_DW, BPF_REG_10, BPF_REG_2, -128),
579-
BPF_LDX_MEM(BPF_DW, BPF_REG_2, BPF_REG_10, -128),
580-
BPF_ALU64_IMM(BPF_AND, BPF_REG_2, 63),
581-
BPF_ALU64_IMM(BPF_ADD, BPF_REG_2, 1),
582-
BPF_MOV64_IMM(BPF_REG_3, 0),
583-
BPF_EMIT_CALL(BPF_FUNC_probe_read_kernel),
584-
BPF_LDX_MEM(BPF_DW, BPF_REG_1, BPF_REG_10, -16),
606+
/* Limit r3 range to [1, 64] */
607+
BPF_ALU64_IMM(BPF_AND, BPF_REG_3, 63),
608+
BPF_ALU64_IMM(BPF_ADD, BPF_REG_3, 1),
609+
BPF_MOV64_IMM(BPF_REG_4, 0),
610+
/* Call bpf_ringbuf_output(), it is one of a few helper functions with
611+
* ARG_CONST_SIZE_OR_ZERO parameter allowed in unpriv mode.
612+
* For unpriv this should signal an error, because memory region [1, 64]
613+
* at &fp[-64] is not fully initialized.
614+
*/
615+
BPF_EMIT_CALL(BPF_FUNC_ringbuf_output),
616+
BPF_MOV64_IMM(BPF_REG_0, 0),
585617
BPF_EXIT_INSN(),
586618
},
587-
.errstr = "invalid indirect read from stack R1 off -64+32 size 64",
588-
.result = REJECT,
589-
.prog_type = BPF_PROG_TYPE_TRACEPOINT,
619+
.fixup_map_ringbuf = { 3 },
620+
.errstr_unpriv = "invalid indirect read from stack R2 off -64+32 size 64",
621+
.result_unpriv = REJECT,
622+
/* in privileged mode reads from uninitialized stack locations are permitted */
623+
.result = ACCEPT,
590624
},
591625
{
592626
"helper access to variable memory: 8 bytes no leak (init memory)",

tools/testing/selftests/bpf/verifier/int_ptr.c

Lines changed: 5 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -54,12 +54,13 @@
5454
/* bpf_strtoul() */
5555
BPF_EMIT_CALL(BPF_FUNC_strtoul),
5656

57-
BPF_MOV64_IMM(BPF_REG_0, 1),
57+
BPF_MOV64_IMM(BPF_REG_0, 0),
5858
BPF_EXIT_INSN(),
5959
},
60-
.result = REJECT,
61-
.prog_type = BPF_PROG_TYPE_CGROUP_SYSCTL,
62-
.errstr = "invalid indirect read from stack R4 off -16+4 size 8",
60+
.result_unpriv = REJECT,
61+
.errstr_unpriv = "invalid indirect read from stack R4 off -16+4 size 8",
62+
/* in privileged mode reads from uninitialized stack locations are permitted */
63+
.result = ACCEPT,
6364
},
6465
{
6566
"ARG_PTR_TO_LONG misaligned",

tools/testing/selftests/bpf/verifier/search_pruning.c

Lines changed: 8 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -128,9 +128,10 @@
128128
BPF_EXIT_INSN(),
129129
},
130130
.fixup_map_hash_8b = { 3 },
131-
.errstr = "invalid read from stack off -16+0 size 8",
132-
.result = REJECT,
133-
.prog_type = BPF_PROG_TYPE_TRACEPOINT,
131+
.errstr_unpriv = "invalid read from stack off -16+0 size 8",
132+
.result_unpriv = REJECT,
133+
/* in privileged mode reads from uninitialized stack locations are permitted */
134+
.result = ACCEPT,
134135
},
135136
{
136137
"precision tracking for u32 spill/fill",
@@ -258,6 +259,8 @@
258259
BPF_EXIT_INSN(),
259260
},
260261
.flags = BPF_F_TEST_STATE_FREQ,
261-
.errstr = "invalid read from stack off -8+1 size 8",
262-
.result = REJECT,
262+
.errstr_unpriv = "invalid read from stack off -8+1 size 8",
263+
.result_unpriv = REJECT,
264+
/* in privileged mode reads from uninitialized stack locations are permitted */
265+
.result = ACCEPT,
263266
},

tools/testing/selftests/bpf/verifier/sock.c

Lines changed: 0 additions & 27 deletions
Original file line numberDiff line numberDiff line change
@@ -530,33 +530,6 @@
530530
.prog_type = BPF_PROG_TYPE_SCHED_CLS,
531531
.result = ACCEPT,
532532
},
533-
{
534-
"sk_storage_get(map, skb->sk, &stack_value, 1): partially init stack_value",
535-
.insns = {
536-
BPF_MOV64_IMM(BPF_REG_2, 0),
537-
BPF_STX_MEM(BPF_W, BPF_REG_10, BPF_REG_2, -8),
538-
BPF_LDX_MEM(BPF_DW, BPF_REG_1, BPF_REG_1, offsetof(struct __sk_buff, sk)),
539-
BPF_JMP_IMM(BPF_JNE, BPF_REG_1, 0, 2),
540-
BPF_MOV64_IMM(BPF_REG_0, 0),
541-
BPF_EXIT_INSN(),
542-
BPF_EMIT_CALL(BPF_FUNC_sk_fullsock),
543-
BPF_JMP_IMM(BPF_JNE, BPF_REG_0, 0, 2),
544-
BPF_MOV64_IMM(BPF_REG_0, 0),
545-
BPF_EXIT_INSN(),
546-
BPF_MOV64_IMM(BPF_REG_4, 1),
547-
BPF_MOV64_REG(BPF_REG_3, BPF_REG_10),
548-
BPF_ALU64_IMM(BPF_ADD, BPF_REG_3, -8),
549-
BPF_MOV64_REG(BPF_REG_2, BPF_REG_0),
550-
BPF_LD_MAP_FD(BPF_REG_1, 0),
551-
BPF_EMIT_CALL(BPF_FUNC_sk_storage_get),
552-
BPF_MOV64_IMM(BPF_REG_0, 0),
553-
BPF_EXIT_INSN(),
554-
},
555-
.fixup_sk_storage_map = { 14 },
556-
.prog_type = BPF_PROG_TYPE_SCHED_CLS,
557-
.result = REJECT,
558-
.errstr = "invalid indirect read from stack",
559-
},
560533
{
561534
"bpf_map_lookup_elem(smap, &key)",
562535
.insns = {

tools/testing/selftests/bpf/verifier/spill_fill.c

Lines changed: 4 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -171,9 +171,10 @@
171171
BPF_MOV64_IMM(BPF_REG_0, 0),
172172
BPF_EXIT_INSN(),
173173
},
174-
.result = REJECT,
175-
.errstr = "invalid read from stack off -4+0 size 4",
176-
.prog_type = BPF_PROG_TYPE_SCHED_CLS,
174+
.result_unpriv = REJECT,
175+
.errstr_unpriv = "invalid read from stack off -4+0 size 4",
176+
/* in privileged mode reads from uninitialized stack locations are permitted */
177+
.result = ACCEPT,
177178
},
178179
{
179180
"Spill a u32 const scalar. Refill as u16. Offset to skb->data",

tools/testing/selftests/bpf/verifier/var_off.c

Lines changed: 0 additions & 52 deletions
Original file line numberDiff line numberDiff line change
@@ -212,31 +212,6 @@
212212
.result = REJECT,
213213
.prog_type = BPF_PROG_TYPE_LWT_IN,
214214
},
215-
{
216-
"indirect variable-offset stack access, max_off+size > max_initialized",
217-
.insns = {
218-
/* Fill only the second from top 8 bytes of the stack. */
219-
BPF_ST_MEM(BPF_DW, BPF_REG_10, -16, 0),
220-
/* Get an unknown value. */
221-
BPF_LDX_MEM(BPF_W, BPF_REG_2, BPF_REG_1, 0),
222-
/* Make it small and 4-byte aligned. */
223-
BPF_ALU64_IMM(BPF_AND, BPF_REG_2, 4),
224-
BPF_ALU64_IMM(BPF_SUB, BPF_REG_2, 16),
225-
/* Add it to fp. We now have either fp-12 or fp-16, but we don't know
226-
* which. fp-12 size 8 is partially uninitialized stack.
227-
*/
228-
BPF_ALU64_REG(BPF_ADD, BPF_REG_2, BPF_REG_10),
229-
/* Dereference it indirectly. */
230-
BPF_LD_MAP_FD(BPF_REG_1, 0),
231-
BPF_EMIT_CALL(BPF_FUNC_map_lookup_elem),
232-
BPF_MOV64_IMM(BPF_REG_0, 0),
233-
BPF_EXIT_INSN(),
234-
},
235-
.fixup_map_hash_8b = { 5 },
236-
.errstr = "invalid indirect read from stack R2 var_off",
237-
.result = REJECT,
238-
.prog_type = BPF_PROG_TYPE_LWT_IN,
239-
},
240215
{
241216
"indirect variable-offset stack access, min_off < min_initialized",
242217
.insns = {
@@ -289,33 +264,6 @@
289264
.result = ACCEPT,
290265
.prog_type = BPF_PROG_TYPE_CGROUP_SKB,
291266
},
292-
{
293-
"indirect variable-offset stack access, uninitialized",
294-
.insns = {
295-
BPF_MOV64_IMM(BPF_REG_2, 6),
296-
BPF_MOV64_IMM(BPF_REG_3, 28),
297-
/* Fill the top 16 bytes of the stack. */
298-
BPF_ST_MEM(BPF_W, BPF_REG_10, -16, 0),
299-
BPF_ST_MEM(BPF_DW, BPF_REG_10, -8, 0),
300-
/* Get an unknown value. */
301-
BPF_LDX_MEM(BPF_W, BPF_REG_4, BPF_REG_1, 0),
302-
/* Make it small and 4-byte aligned. */
303-
BPF_ALU64_IMM(BPF_AND, BPF_REG_4, 4),
304-
BPF_ALU64_IMM(BPF_SUB, BPF_REG_4, 16),
305-
/* Add it to fp. We now have either fp-12 or fp-16, we don't know
306-
* which, but either way it points to initialized stack.
307-
*/
308-
BPF_ALU64_REG(BPF_ADD, BPF_REG_4, BPF_REG_10),
309-
BPF_MOV64_IMM(BPF_REG_5, 8),
310-
/* Dereference it indirectly. */
311-
BPF_EMIT_CALL(BPF_FUNC_getsockopt),
312-
BPF_MOV64_IMM(BPF_REG_0, 0),
313-
BPF_EXIT_INSN(),
314-
},
315-
.errstr = "invalid indirect read from stack R4 var_off",
316-
.result = REJECT,
317-
.prog_type = BPF_PROG_TYPE_SOCK_OPS,
318-
},
319267
{
320268
"indirect variable-offset stack access, ok",
321269
.insns = {

0 commit comments

Comments
 (0)