mirror of
https://github.com/torvalds/linux.git
synced 2026-05-31 10:33:41 +02:00
Merge branch 'allow-fixed-offsets-for-ptr_to_ctx'
Kumar Kartikeya Dwivedi says: ==================== Allow fixed offsets for PTR_TO_CTX Enable pointer modification with constant offsets accumulated in the register for PTR_TO_CTX for programs where it won't be rewritten. See patches for details. ==================== Link: https://patch.msgid.link/20260227005725.1247305-1-memxor@gmail.com Signed-off-by: Alexei Starovoitov <ast@kernel.org>
This commit is contained in:
commit
b000044809
|
|
@ -7752,6 +7752,11 @@ static int check_mem_access(struct bpf_verifier_env *env, int insn_idx, u32 regn
|
|||
if (!err && value_regno >= 0 && (t == BPF_READ || rdonly_mem))
|
||||
mark_reg_unknown(env, regs, value_regno);
|
||||
} else if (reg->type == PTR_TO_CTX) {
|
||||
/*
|
||||
* Program types that don't rewrite ctx accesses can safely
|
||||
* dereference ctx pointers with fixed offsets.
|
||||
*/
|
||||
bool fixed_off_ok = !env->ops->convert_ctx_access;
|
||||
struct bpf_retval_range range;
|
||||
struct bpf_insn_access_aux info = {
|
||||
.reg_type = SCALAR_VALUE,
|
||||
|
|
@ -7765,10 +7770,16 @@ static int check_mem_access(struct bpf_verifier_env *env, int insn_idx, u32 regn
|
|||
return -EACCES;
|
||||
}
|
||||
|
||||
err = check_ptr_off_reg(env, reg, regno);
|
||||
err = __check_ptr_off_reg(env, reg, regno, fixed_off_ok);
|
||||
if (err < 0)
|
||||
return err;
|
||||
|
||||
/*
|
||||
* Fold the register's constant offset into the insn offset so
|
||||
* that is_valid_access() sees the true effective offset.
|
||||
*/
|
||||
if (fixed_off_ok)
|
||||
off += reg->var_off.value;
|
||||
err = check_ctx_access(env, insn_idx, off, size, t, &info);
|
||||
if (err)
|
||||
verbose_linfo(env, insn_idx, "; ");
|
||||
|
|
|
|||
|
|
@ -292,4 +292,80 @@ padding_access("cgroup/post_bind4", bpf_sock, dst_port, 2);
|
|||
__failure __msg("invalid bpf_context access")
|
||||
padding_access("sk_reuseport", sk_reuseport_md, hash, 4);
|
||||
|
||||
SEC("syscall")
|
||||
__description("syscall: write to ctx with fixed offset")
|
||||
__success
|
||||
__naked void syscall_ctx_fixed_off_write(void)
|
||||
{
|
||||
asm volatile (" \
|
||||
r0 = 0; \
|
||||
*(u32*)(r1 + 0) = r0; \
|
||||
r1 += 4; \
|
||||
*(u32*)(r1 + 0) = r0; \
|
||||
exit; \
|
||||
" ::: __clobber_all);
|
||||
}
|
||||
|
||||
/*
|
||||
* Test that program types without convert_ctx_access can dereference
|
||||
* their ctx pointer after adding a fixed offset. Variable and negative
|
||||
* offsets should still be rejected.
|
||||
*/
|
||||
#define no_rewrite_ctx_access(type, name, off, ld_op) \
|
||||
SEC(type) \
|
||||
__description(type ": read ctx at fixed offset") \
|
||||
__success \
|
||||
__naked void no_rewrite_##name##_fixed(void) \
|
||||
{ \
|
||||
asm volatile (" \
|
||||
r1 += %[__off]; \
|
||||
r0 = *(" #ld_op " *)(r1 + 0); \
|
||||
r0 = 0; \
|
||||
exit;" \
|
||||
: \
|
||||
: __imm_const(__off, off) \
|
||||
: __clobber_all); \
|
||||
} \
|
||||
SEC(type) \
|
||||
__description(type ": reject variable offset ctx access") \
|
||||
__failure __msg("variable ctx access var_off=") \
|
||||
__naked void no_rewrite_##name##_var(void) \
|
||||
{ \
|
||||
asm volatile (" \
|
||||
r6 = r1; \
|
||||
call %[bpf_get_prandom_u32]; \
|
||||
r1 = r6; \
|
||||
r0 &= 4; \
|
||||
r1 += r0; \
|
||||
r0 = *(" #ld_op " *)(r1 + 0); \
|
||||
r0 = 0; \
|
||||
exit;" \
|
||||
: \
|
||||
: __imm(bpf_get_prandom_u32) \
|
||||
: __clobber_all); \
|
||||
} \
|
||||
SEC(type) \
|
||||
__description(type ": reject negative offset ctx access") \
|
||||
__failure __msg("negative offset ctx ptr") \
|
||||
__naked void no_rewrite_##name##_neg(void) \
|
||||
{ \
|
||||
asm volatile (" \
|
||||
r1 += %[__neg_off]; \
|
||||
r0 = *(" #ld_op " *)(r1 + 0); \
|
||||
r0 = 0; \
|
||||
exit;" \
|
||||
: \
|
||||
: __imm_const(__neg_off, -(off)) \
|
||||
: __clobber_all); \
|
||||
}
|
||||
|
||||
no_rewrite_ctx_access("syscall", syscall, 4, u32);
|
||||
no_rewrite_ctx_access("kprobe", kprobe, 8, u64);
|
||||
no_rewrite_ctx_access("tracepoint", tp, 8, u64);
|
||||
no_rewrite_ctx_access("raw_tp", raw_tp, 8, u64);
|
||||
no_rewrite_ctx_access("raw_tracepoint.w", raw_tp_w, 8, u64);
|
||||
no_rewrite_ctx_access("fentry/bpf_modify_return_test", fentry, 8, u64);
|
||||
no_rewrite_ctx_access("cgroup/dev", cgroup_dev, 4, u32);
|
||||
no_rewrite_ctx_access("netfilter", netfilter, offsetof(struct bpf_nf_ctx, skb), u64);
|
||||
|
||||
char _license[] SEC("license") = "GPL";
|
||||
|
|
|
|||
Loading…
Reference in New Issue
Block a user