Insert a nospec before the access to prevent it from ever using a index that is subject to speculative scalar-confusion. Signed-off-by: Luis Gerhorst <luis.gerhorst@xxxxxx> Acked-by: Henriette Herzog <henriette.herzog@xxxxxx> Cc: Maximilian Ott <ott@xxxxxxxxx> Cc: Milan Stephan <milan.stephan@xxxxxx> --- kernel/bpf/verifier.c | 15 ++++++++------- 1 file changed, 8 insertions(+), 7 deletions(-) diff --git a/kernel/bpf/verifier.c b/kernel/bpf/verifier.c index aee49f8da0c1..06c2f929d602 100644 --- a/kernel/bpf/verifier.c +++ b/kernel/bpf/verifier.c @@ -7638,6 +7638,8 @@ static int check_atomic(struct bpf_verifier_env *env, int insn_idx, struct bpf_i return 0; } +static struct bpf_insn_aux_data *cur_aux(struct bpf_verifier_env *env); + /* When register 'regno' is used to read the stack (either directly or through * a helper function) make sure that it's within stack boundary and, depending * on the access type and privileges, that all elements of the stack are @@ -7677,18 +7679,17 @@ static int check_stack_range_initialized( if (tnum_is_const(reg->var_off)) { min_off = max_off = reg->var_off.value + off; } else { - /* Variable offset is prohibited for unprivileged mode for + /* Variable offset requires a nospec for unprivileged mode for * simplicity since it requires corresponding support in * Spectre masking for stack ALU. * See also retrieve_ptr_limit(). */ if (!env->bypass_spec_v1) { - char tn_buf[48]; - - tnum_strn(tn_buf, sizeof(tn_buf), reg->var_off); - verbose(env, "R%d variable offset stack access prohibited for !root, var_off=%s\n", - regno, tn_buf); - return -EACCES; + /* Allow the access, but prevent it from using a + * speculative offset using a nospec before the + * dereference op. + */ + cur_aux(env)->nospec = true; } /* Only initialized buffer on stack is allowed to be accessed * with variable offset. With uninitialized buffer it's hard to -- 2.48.1