Linux kernel mirror (for testing) git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git
kernel os linux
1
fork

Configure Feed

Select the types of activity you want to include in your feed.

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>

+88 -1
+12 -1
kernel/bpf/verifier.c
··· 7752 7752 if (!err && value_regno >= 0 && (t == BPF_READ || rdonly_mem)) 7753 7753 mark_reg_unknown(env, regs, value_regno); 7754 7754 } else if (reg->type == PTR_TO_CTX) { 7755 + /* 7756 + * Program types that don't rewrite ctx accesses can safely 7757 + * dereference ctx pointers with fixed offsets. 7758 + */ 7759 + bool fixed_off_ok = !env->ops->convert_ctx_access; 7755 7760 struct bpf_retval_range range; 7756 7761 struct bpf_insn_access_aux info = { 7757 7762 .reg_type = SCALAR_VALUE, ··· 7770 7765 return -EACCES; 7771 7766 } 7772 7767 7773 - err = check_ptr_off_reg(env, reg, regno); 7768 + err = __check_ptr_off_reg(env, reg, regno, fixed_off_ok); 7774 7769 if (err < 0) 7775 7770 return err; 7776 7771 7772 + /* 7773 + * Fold the register's constant offset into the insn offset so 7774 + * that is_valid_access() sees the true effective offset. 7775 + */ 7776 + if (fixed_off_ok) 7777 + off += reg->var_off.value; 7777 7778 err = check_ctx_access(env, insn_idx, off, size, t, &info); 7778 7779 if (err) 7779 7780 verbose_linfo(env, insn_idx, "; ");
+76
tools/testing/selftests/bpf/progs/verifier_ctx.c
··· 292 292 __failure __msg("invalid bpf_context access") 293 293 padding_access("sk_reuseport", sk_reuseport_md, hash, 4); 294 294 295 + SEC("syscall") 296 + __description("syscall: write to ctx with fixed offset") 297 + __success 298 + __naked void syscall_ctx_fixed_off_write(void) 299 + { 300 + asm volatile (" \ 301 + r0 = 0; \ 302 + *(u32*)(r1 + 0) = r0; \ 303 + r1 += 4; \ 304 + *(u32*)(r1 + 0) = r0; \ 305 + exit; \ 306 + " ::: __clobber_all); 307 + } 308 + 309 + /* 310 + * Test that program types without convert_ctx_access can dereference 311 + * their ctx pointer after adding a fixed offset. Variable and negative 312 + * offsets should still be rejected. 313 + */ 314 + #define no_rewrite_ctx_access(type, name, off, ld_op) \ 315 + SEC(type) \ 316 + __description(type ": read ctx at fixed offset") \ 317 + __success \ 318 + __naked void no_rewrite_##name##_fixed(void) \ 319 + { \ 320 + asm volatile (" \ 321 + r1 += %[__off]; \ 322 + r0 = *(" #ld_op " *)(r1 + 0); \ 323 + r0 = 0; \ 324 + exit;" \ 325 + : \ 326 + : __imm_const(__off, off) \ 327 + : __clobber_all); \ 328 + } \ 329 + SEC(type) \ 330 + __description(type ": reject variable offset ctx access") \ 331 + __failure __msg("variable ctx access var_off=") \ 332 + __naked void no_rewrite_##name##_var(void) \ 333 + { \ 334 + asm volatile (" \ 335 + r6 = r1; \ 336 + call %[bpf_get_prandom_u32]; \ 337 + r1 = r6; \ 338 + r0 &= 4; \ 339 + r1 += r0; \ 340 + r0 = *(" #ld_op " *)(r1 + 0); \ 341 + r0 = 0; \ 342 + exit;" \ 343 + : \ 344 + : __imm(bpf_get_prandom_u32) \ 345 + : __clobber_all); \ 346 + } \ 347 + SEC(type) \ 348 + __description(type ": reject negative offset ctx access") \ 349 + __failure __msg("negative offset ctx ptr") \ 350 + __naked void no_rewrite_##name##_neg(void) \ 351 + { \ 352 + asm volatile (" \ 353 + r1 += %[__neg_off]; \ 354 + r0 = *(" #ld_op " *)(r1 + 0); \ 355 + r0 = 0; \ 356 + exit;" \ 357 + : \ 358 + : __imm_const(__neg_off, -(off)) \ 359 + : __clobber_all); \ 360 + } 361 + 362 + no_rewrite_ctx_access("syscall", syscall, 4, u32); 363 + no_rewrite_ctx_access("kprobe", kprobe, 8, u64); 364 + no_rewrite_ctx_access("tracepoint", tp, 8, u64); 365 + no_rewrite_ctx_access("raw_tp", raw_tp, 8, u64); 366 + no_rewrite_ctx_access("raw_tracepoint.w", raw_tp_w, 8, u64); 367 + no_rewrite_ctx_access("fentry/bpf_modify_return_test", fentry, 8, u64); 368 + no_rewrite_ctx_access("cgroup/dev", cgroup_dev, 4, u32); 369 + no_rewrite_ctx_access("netfilter", netfilter, offsetof(struct bpf_nf_ctx, skb), u64); 370 + 295 371 char _license[] SEC("license") = "GPL";