All of lore.kernel.org
 help / color / mirror / Atom feed
From: sashiko-bot@kernel.org
To: "Alexei Starovoitov" <alexei.starovoitov@gmail.com>, bpf@vger.kernel.org
Subject: Re: [PATCH bpf-next 26/38] bpf: Assume no bounds for a writable tp with tail calls
Date: Sat, 17 Oct 2026 02:05:48 +0000	[thread overview]
Message-ID: <sashiko-outbox-175187@kernel.org> (raw)
In-Reply-To: <20261017012451.364800-18-alexei.starovoitov@gmail.com>

Thank you for your contribution! Sashiko AI review found 1 potential issue(s) to consider:
- [High] bpf: max_tp_access check bypassed via BPF_PROG_TYPE_EXT on writable raw tp
--

commit 467f1021d59430c1b54a88fe6072cc36e60eb149
Author: Josef Bacik <josef@toxicpanda.com>

bpf: Assume no bounds for a writable tp with tail calls

This commit sets max_tp_access to U32_MAX when a
BPF_PROG_TYPE_RAW_TRACEPOINT_WRITABLE program performs a tail call,
preventing it from attaching to a writable raw tracepoint and tail-calling a
program that accesses beyond the tracepoint buffer bounds.

> diff --git a/kernel/bpf/fixups.c b/kernel/bpf/fixups.c
> index 002c3935a8eb0..fe59e3114d828 100644
> --- a/kernel/bpf/fixups.c
> +++ b/kernel/bpf/fixups.c
> @@ -2153,6 +2153,8 @@ int bpf_do_misc_fixups(struct bpf_verifier_env *env)
>  			prog->aux->max_pkt_offset = MAX_PACKET_OFF;
>  			prog->aux->max_rdonly_access = U32_MAX;
>  			prog->aux->max_rdwr_access = U32_MAX;
> +			if (prog->type == BPF_PROG_TYPE_RAW_TRACEPOINT_WRITABLE)
> +				prog->aux->max_tp_access = U32_MAX;

[Severity: High]
Can the max_tp_access check still be bypassed using a BPF_PROG_TYPE_EXT
(freplace) program attached to a BPF_PROG_TYPE_RAW_TRACEPOINT_WRITABLE
target program?

A target program (tgt_prog) of type BPF_PROG_TYPE_RAW_TRACEPOINT_WRITABLE
with prototype int prog(struct bpf_raw_tracepoint_args *ctx) (or a global
subprogram taking struct bpf_raw_tracepoint_args *ctx) that does not access
ctx->args[0] or call bpf_tail_call() is loaded with
tgt_prog->aux->max_tp_access == 0. Because
find_canonical_prog_ctx_type(BPF_PROG_TYPE_RAW_TRACEPOINT_WRITABLE) resolves
to struct bpf_raw_tracepoint_args, btf_prepare_func_args() marks its BTF
signature as reliable.

When attaching tgt_prog, bpf_probe_register() in kernel/trace/bpf_trace.c
only validates max_tp_access on the root attached program:

kernel/trace/bpf_trace.c:bpf_probe_register() {
    ...
	if (prog->aux->max_tp_access > btp->writable_size)
		return -EINVAL;
    ...
}

This succeeds for any raw tracepoint (even when btp->writable_size is 0)
since tgt_prog->aux->max_tp_access is 0.

Meanwhile, a BPF_PROG_TYPE_EXT program (ext_prog) targeting tgt_prog or its
global subprogram passes bpf_check_attach_target(), inherits
raw_tracepoint_writable_verifier_ops in check_attach_btf_id(), and has its
struct bpf_raw_tracepoint_args *ctx argument typed as PTR_TO_CTX in
btf_prepare_func_args():

kernel/bpf/verifier.c:check_attach_btf_id() {
    ...
	if (tgt_prog && prog->type == BPF_PROG_TYPE_EXT) {
		/* to make freplace equivalent to their targets, they need to
		 * inherit env->ops and expected_attach_type for the rest of the
		 * verification
		 */
		env->ops = bpf_verifier_ops[tgt_prog->type];
		prog->expected_attach_type = tgt_prog->expected_attach_type;
	}
    ...
}

In bpf_do_misc_fixups(), the check added here tests
prog->type == BPF_PROG_TYPE_RAW_TRACEPOINT_WRITABLE rather than
resolve_prog_type(prog), so it does not match when ext_prog
(prog->type == BPF_PROG_TYPE_EXT) calls bpf_tail_call() (which is permitted
when the replaced function has changes_pkt_data set, such as via
bpf_dynptr_write() or bpf_dynptr_memset() on a local dynptr, or when
CONFIG_NET=n). However, __bpf_prog_map_compatible() in kernel/bpf/core.c
uses resolve_prog_type(fp):

kernel/bpf/core.c:__bpf_prog_map_compatible() {
    ...
	enum bpf_prog_type prog_type = resolve_prog_type(fp);
    ...
}

This allows ext_prog to tail-call into a BPF_MAP_TYPE_PROG_ARRAY of
BPF_PROG_TYPE_RAW_TRACEPOINT_WRITABLE programs that read and write past
btp->writable_size.

Furthermore, even if ext_prog directly accesses ctx->args[0] (which
raw_tp_writable_prog_is_valid_access() types as PTR_TO_TP_BUFFER) or has
ext_prog->aux->max_tp_access set to U32_MAX, check_tp_buffer_access() only
updates ext_prog->aux->max_tp_access, which is never validated against
btp->writable_size or propagated to tgt_prog.

Should BPF_PROG_TYPE_EXT programs be disallowed from targeting
BPF_PROG_TYPE_RAW_TRACEPOINT_WRITABLE programs (similar to how iterator
programs reject extensions in commit "bpf: Don't take an extension for an
iterator program")?

>  
>  			/* mark bpf_tail_call as different opcode to avoid
>  			 * conditional branch in the interpreter for every normal

-- 
Sashiko AI review · https://sashiko.dev/#/patchset/20261017012058.355787-1-alexei.starovoitov@gmail.com?part=26

  reply	other threads:[~2026-10-17  2:05 UTC|newest]

Thread overview: 51+ messages / expand[flat|nested]  mbox.gz  Atom feed  top
2026-10-17  1:20 [PATCH bpf-next 00/38] bpf: Memory safety, lifetime and locking fixes Alexei Starovoitov
2026-10-17  1:20 ` [PATCH bpf-next 01/38] bpf: use the frame mem type in devmap egress XDP Alexei Starovoitov
2026-10-17  1:20 ` [PATCH bpf-next 02/38] bpf: forbid sleeping in hash map for_each callbacks Alexei Starovoitov
2026-10-17  1:20 ` [PATCH bpf-next 03/38] bpf: don't leak the inode when token creation fails Alexei Starovoitov
2026-10-17  1:20 ` [PATCH bpf-next 04/38] bpf: don't hand out a linked element as extra element Alexei Starovoitov
2026-10-17  1:45   ` sashiko-bot
2026-10-17  1:52   ` bot+bpf-ci
2026-10-17  1:20 ` [PATCH bpf-next 05/38] bpf: reject sleepable programs for task_vma iterator Alexei Starovoitov
2026-10-17  1:20 ` [PATCH bpf-next 06/38] bpf: forbid sleeping in bpf_find_vma() callbacks Alexei Starovoitov
2026-10-17  1:20 ` [PATCH bpf-next 07/38] bpf: look at all 64 bits of a BPF_JSET mask on 32-bit Alexei Starovoitov
2026-10-17  1:20 ` [PATCH bpf-next 08/38] bpf: don't let bpf_skb_adjust_room() use up the MSS Alexei Starovoitov
2026-10-17  1:51   ` sashiko-bot
2026-10-17  1:24 ` [PATCH bpf-next 09/38] bpf: Read the probe of a perf event under event_mutex Alexei Starovoitov
2026-10-17  1:24 ` [PATCH bpf-next 10/38] bpf: Don't saturate owner_refcnt on the last unpin Alexei Starovoitov
2026-10-17  1:24 ` [PATCH bpf-next 11/38] bpf: Validate the SRH which End.DT6 uncovers in End.BPF Alexei Starovoitov
2026-10-17  1:24 ` [PATCH bpf-next 12/38] bpf: Pull the inner header for End.DT6 " Alexei Starovoitov
2026-10-17  1:24 ` [PATCH bpf-next 13/38] bpf: Update the SRH state if End.B6 fails late Alexei Starovoitov
2026-10-17  1:24 ` [PATCH bpf-next 14/38] bpf: Clear sk_refcnt of a clone before its storage is linked Alexei Starovoitov
2026-10-17  1:24 ` [PATCH bpf-next 15/38] bpf: Fix NULL deref in the sk_storage map iterator Alexei Starovoitov
2026-10-17  1:24 ` [PATCH bpf-next 16/38] bpf: Hold the socket " Alexei Starovoitov
2026-10-17  2:02   ` bot+bpf-ci
2026-10-17  1:24 ` [PATCH bpf-next 17/38] bpf: Bound the nesting that the BTF show code follows Alexei Starovoitov
2026-10-17  1:46   ` sashiko-bot
2026-10-17  1:24 ` [PATCH bpf-next 18/38] bpf: Check the new program of an iterator link update Alexei Starovoitov
2026-10-17  1:24 ` [PATCH bpf-next 19/38] bpf: Fix stale offload->prog pointer after realloc Alexei Starovoitov
2026-10-17  1:45   ` sashiko-bot
2026-10-17  1:52   ` bot+bpf-ci
2026-10-17  1:24 ` [PATCH bpf-next 20/38] bpf: Don't bind a program to a netdev that goes away Alexei Starovoitov
2026-10-17  1:24 ` [PATCH bpf-next 21/38] bpf: Keep a program until its bpf_wq callback has ended Alexei Starovoitov
2026-10-17  1:24 ` [PATCH bpf-next 22/38] bpf: Count sleepable callbacks as sleepable map users Alexei Starovoitov
2026-10-17  1:24 ` [PATCH bpf-next 23/38] bpf: Check the maps that sleepable callbacks use Alexei Starovoitov
2026-10-17  1:58   ` sashiko-bot
2026-10-17  1:24 ` [PATCH bpf-next 24/38] bpf: Assume no bounds for buffers behind a tail call Alexei Starovoitov
2026-10-17  1:24 ` [PATCH bpf-next 25/38] bpf: Don't take an extension for an iterator program Alexei Starovoitov
2026-10-17  1:24 ` [PATCH bpf-next 26/38] bpf: Assume no bounds for a writable tp with tail calls Alexei Starovoitov
2026-10-17  2:05   ` sashiko-bot [this message]
2026-10-17  1:24 ` [PATCH bpf-next 27/38] bpf: Keep iterator programs off special map fields Alexei Starovoitov
2026-10-17  1:24 ` [PATCH bpf-next 28/38] bpf: Free what map_free() unlinks for sleepable readers Alexei Starovoitov
2026-10-17  1:24 ` [PATCH bpf-next 29/38] bpf: Keep values of a dead owner for sleepable programs Alexei Starovoitov
2026-10-17  2:10   ` sashiko-bot
2026-10-17  1:24 ` [PATCH bpf-next 30/38] bpf: Keep the symbols of a program until it has ended Alexei Starovoitov
2026-10-17  1:24 ` [PATCH bpf-next 31/38] bpf: Use the socket of a sk_lookup test run under RCU Alexei Starovoitov
2026-10-17  1:24 ` [PATCH bpf-next 32/38] bpf, cpumap: Hold the device of frames in the queue Alexei Starovoitov
2026-10-17  1:24 ` [PATCH bpf-next 33/38] bpf: Drop packet pointers behind kfuncs writing an skb Alexei Starovoitov
2026-10-17  2:10   ` sashiko-bot
2026-10-17  1:24 ` [PATCH bpf-next 34/38] bpf: Let bpf_dynptr_write() mark a global function Alexei Starovoitov
2026-10-17  1:24 ` [PATCH bpf-next 35/38] bpf: Don't take a dynptr argument for a local dynptr Alexei Starovoitov
2026-10-17  1:24 ` [PATCH bpf-next 36/38] bpf: Follow the head if an skb is written from a slice Alexei Starovoitov
2026-10-17  2:05   ` sashiko-bot
2026-10-17  1:24 ` [PATCH bpf-next 37/38] bpf: Use memmove() to store bytes in an skb Alexei Starovoitov
2026-10-17  1:24 ` [PATCH bpf-next 38/38] bpf: Refuse packet slices for packet-changing helpers Alexei Starovoitov

Reply instructions:

You may reply publicly to this message via plain-text email
using any one of the following methods:

* Save the following mbox file, import it into your mail client,
  and reply-to-all from there: mbox

  Avoid top-posting and favor interleaved quoting:
  https://en.wikipedia.org/wiki/Posting_style#Interleaved_style

* Reply using the --to, --cc, and --in-reply-to
  switches of git-send-email(1):

  git send-email \
    --in-reply-to=sashiko-outbox-175187@kernel.org \
    --to=sashiko-bot@kernel.org \
    --cc=alexei.starovoitov@gmail.com \
    --cc=bpf@vger.kernel.org \
    --cc=sashiko-reviews@lists.linux.dev \
    /path/to/YOUR_REPLY

  https://kernel.org/pub/software/scm/git/docs/git-send-email.html

* If your mail client supports setting the In-Reply-To header
  via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line before the message body.
This is an external index of several public inboxes,
see mirroring instructions on how to clone and mirror
all data and code used by this external index.