From mboxrd@z Thu Jan 1 00:00:00 1970 Received: from 66-220-155-178.mail-mxout.facebook.com (66-220-155-178.mail-mxout.facebook.com [66.220.155.178]) (using TLSv1.2 with cipher ECDHE-RSA-AES128-GCM-SHA256 (128/128 bits)) (No client certificate requested) by smtp.subspace.kernel.org (Postfix) with ESMTPS id 584FD3382CB for ; Tue, 13 Oct 2026 00:35:01 +0000 (UTC) Authentication-Results: smtp.subspace.kernel.org; arc=none smtp.client-ip=66.220.155.178 ARC-Seal:i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1791851702; cv=none; b=Cfv/n6pLoPJtaoTOVkJGd8jygYk8Y0RTdwT2FP6ZQpeYT9uzpOo5D8a35tlk1iUGOubtgrQLZngyFLnf5IE5U4k5cgW+YLdoXdKlDwhgtJdErjmIyPJsjju2hYPcyHYn4hufbfgiYBF/oG+NoMufrShS6kRknh5vMTgb+fwtdiw= ARC-Message-Signature:i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1791851702; c=relaxed/simple; bh=4g1B4i4yPpBPj7Ktq86GeimEMK3G4dboTnZfITcJVxw=; h=From:To:Cc:Subject:Date:Message-ID:In-Reply-To:References: MIME-Version; b=ICwo2K+ra2+temZEQ/uB/WVE26VaPfSzo2P1sJ/SjeVGhlaBmu15G9Ukz3zkSGDu1ILVQNPHPZU9OTQo0u9gcln+QWZn9rfuI5B8JA8wobp9vbyS+zjUevzi5JCNLWITwII3tgiK+GbXm295wvQg/2syNCb7BIEz0CR7mH3K28s= ARC-Authentication-Results:i=1; smtp.subspace.kernel.org; dmarc=fail (p=none dis=none) header.from=linux.dev; spf=fail smtp.mailfrom=linux.dev; arc=none smtp.client-ip=66.220.155.178 Authentication-Results: smtp.subspace.kernel.org; dmarc=fail (p=none dis=none) header.from=linux.dev Authentication-Results: smtp.subspace.kernel.org; spf=fail smtp.mailfrom=linux.dev Received: by devvm16039.vll0.facebook.com (Postfix, from userid 128203) id BCA0E30D78EBD5; Mon, 12 Oct 2026 17:34:49 -0700 (PDT) From: Yonghong Song To: bpf@vger.kernel.org Cc: Alexei Starovoitov , Andrii Nakryiko , Daniel Borkmann , Eduard Zingerman , kernel-team@fb.com Subject: [PATCH bpf-next v2 04/11] bpf: Describe a BPF function to its trampoline as one u64 per slot Date: Mon, 12 Oct 2026 17:34:49 -0700 Message-ID: <20261013003449.1857106-1-yonghong.song@linux.dev> X-Mailer: git-send-email 2.53.0 In-Reply-To: <20261013003429.1853052-1-yonghong.song@linux.dev> References: <20261013003429.1853052-1-yonghong.song@linux.dev> Precedence: bulk X-Mailing-List: bpf@vger.kernel.org List-Id: List-Subscribe: List-Unsubscribe: MIME-Version: 1.0 Content-Transfer-Encoding: quoted-printable A trampoline on a BPF function, fentry, fexit or fsession attached through attach_prog_fd, takes the function's arguments from where BPF code left them. A call from one BPF function to another passes slot N where the kernel convention passes its Nth u64 argument, in a register or a stack slot, whatever the types of the arguments: the x86-64, arm64 and riscv JITs all place a stack argument that way. The model of the function, distilled from its BTF, still carries those types, so each arch places the arguments by its own rules for them. For a 16-byte argument at an odd slot, such as s in u64 f(u64 a, struct { __int128 v; } s, u64 b) the arm64 trampoline reads s from x2 and x3, where the caller left it in x1 and x2, and b from x4. And an x86-64 trampoline puts a 16-byte argument at slot 6 wholly on the stack, while BPF code splits it between r9 and the stack. Rewrite the model of a target program's function in bpf_check_attach_target() as one u64 argument per argument slot. Every convention places N u64 arguments in slot order, so all of the above take them from where BPF code put them, and no arch has to know that the function is a BPF one. The model no longer gives the size and flags of each argument, so an arch that sign-extends a narrow signed argument, or clears the unused bytes of a narrow stack argument, for the program does not do that for a BPF function any more: the program gets the eightbyte BPF code passed, as it does on x86-64, and fexit hands it back unchanged. Fixes: afdbb4cdd3d2 ("bpf, arm64: Place trampoline arguments by the arm64= calling convention") Fixes: 4dd676ca5b7a ("bpf: Support by-value struct arguments up to 16 byt= es") Signed-off-by: Yonghong Song --- kernel/bpf/verifier.c | 31 +++++++++++++++++++++++++++++++ 1 file changed, 31 insertions(+) diff --git a/kernel/bpf/verifier.c b/kernel/bpf/verifier.c index 2f190abe3448..c7af14a3f0e8 100644 --- a/kernel/bpf/verifier.c +++ b/kernel/bpf/verifier.c @@ -22002,6 +22002,32 @@ static bool attach_uses_trampoline_retval(enum b= pf_attach_type type) } } =20 +/* + * BPF code passes argument slot N where the kernel convention passes it= s Nth + * u64 argument, so describe a BPF function to its trampoline as one u64= per + * slot, and every arch places its arguments right. + */ +static int flatten_bpf_func_model(struct bpf_verifier_log *log, const ch= ar *tname, + struct btf_func_model *m) +{ + u32 i, nslots =3D 0; + + for (i =3D 0; i < m->nr_args; i++) + nslots +=3D btf_func_model_arg_slots(m, i); + if (nslots > MAX_BPF_FUNC_ARGS) { + bpf_log(log, "The function %s has %u argument slots. Too many.\n", + tname, nslots); + return -EINVAL; + } + + for (i =3D 0; i < nslots; i++) { + m->arg_size[i] =3D sizeof(u64); + m->arg_flags[i] =3D 0; + } + m->nr_args =3D nslots; + return 0; +} + int bpf_check_attach_target(struct bpf_verifier_log *log, const struct bpf_prog *prog, const struct bpf_prog *tgt_prog, @@ -22275,6 +22301,11 @@ int bpf_check_attach_target(struct bpf_verifier_= log *log, ret =3D btf_distill_func_proto(log, btf, t, tname, &tgt_info->fmodel); if (ret < 0) return ret; + if (tgt_prog) { + ret =3D flatten_bpf_func_model(log, tname, &tgt_info->fmodel); + if (ret < 0) + return ret; + } =20 if (tgt_info->fmodel.ret_size > 8 && attach_uses_trampoline_retval(prog->expected_attach_type)) { --=20 2.53.0-Meta