From: sashiko-bot@kernel.org
To: "Daniel Borkmann" <daniel@iogearbox.net>
Cc: bpf@vger.kernel.org
Subject: Re: [PATCH bpf-next v2 1/5] bpf: Verify signed loader metadata at load time
Date: Wed, 24 Jun 2026 14:48:03 +0000 [thread overview]
Message-ID: <20260624144803.7AADB1F000E9@smtp.kernel.org> (raw)
In-Reply-To: <20260624140301.93421-2-daniel@iogearbox.net>
Thank you for your contribution! Sashiko AI review found 1 potential issue(s) to consider:
- [High] TOCTOU race in BPF signed program verification allows bypassing signature via concurrent modification of user-space fd_array.
--
commit e61d684bd0467f62e035ea0592a8066b9c7246fb
Author: Daniel Borkmann <daniel@iogearbox.net>
bpf: Verify signed loader metadata at load time
This patch modifies the BPF verifier to perform integrity checking of a signed
program's metadata array maps before the LSM admission hook fires. It achieves
this by resolving the maps from the fd_array, folding their frozen contents
into the signature verification process, and validating the map count.
Link: https://lore.kernel.org/bpf/CAHC9VhSDkwGgPfrBUh7EgBKEJj_JjnY68c0YAmuuLT_i--GskQ@mail.gmail.com [0]
Link: https://lore.kernel.org/bpf/2f71d6c03698eb17d51f7247efde777627ee578a.camel@HansenPartnership.com [1]
Link: https://lore.kernel.org/lkml/ecf0521ed302db672672ebfbc670ecfba36a6e00.camel@HansenPartnership.com [2]
Link: https://lore.kernel.org/bpf/88703f00d5b7a779728451008626efa45e42db3d.camel@HansenPartnership.com [3]
> diff --git a/kernel/bpf/verifier.c b/kernel/bpf/verifier.c
> index 2abc79dbf281c..9cd2b62da3803 100644
> --- a/kernel/bpf/verifier.c
> +++ b/kernel/bpf/verifier.c
[ ... ]
> @@ -19895,11 +19895,28 @@ int bpf_check(struct bpf_prog **prog, union bpf_attr *attr, bpfptr_t uattr,
> ret = bpf_vlog_init(&env->log, attr_log->level, attr_log->ubuf, attr_log->size);
> if (ret)
> goto err_unlock;
> + if (env->check_signature) {
> + ret = bpf_prog_calc_tag(env->prog);
> + if (ret < 0)
> + goto skip_full_check;
> + }
>
> ret = process_fd_array(env, attr, uattr);
> if (ret)
> goto skip_full_check;
>
> + if (env->check_signature) {
> + ret = bpf_prog_verify_signature(env, attr, uattr.is_kernel);
> + if (ret)
> + goto skip_full_check;
> + signed_map_cnt = env->used_map_cnt;
> + }
[ ... ]
> @@ -19966,7 +19966,14 @@ int bpf_check(struct bpf_prog **prog, union bpf_attr *attr, bpfptr_t uattr,
> ret = check_and_resolve_insns(env);
> if (ret < 0)
> goto skip_full_check;
> -
> + if (env->prog->aux->sig.verdict == BPF_SIG_VERIFIED &&
> + (env->used_map_cnt != signed_map_cnt || env->used_btf_cnt)) {
[Severity: High]
Is there a TOCTOU race with how fd_array is processed between these checks?
If an attacker concurrently modifies the fd_array in user memory after
process_fd_array() runs but before check_and_resolve_insns() reads it again:
1. process_fd_array() reads the array from user space and populates
env->used_maps with MAP_A and MAP_B.
2. bpf_prog_verify_signature() successfully verifies the signature over
these specific maps, and signed_map_cnt is set to 2.
3. The attacker modifies the user-space fd_array memory (e.g., swapping the
FDs for MAP_A and MAP_B, or duplicating MAP_B).
4. check_and_resolve_insns() reads the modified fd_array from user space
again via copy_from_bpfptr_offset(&fd, env->fd_array, ...) and binds the
swapped maps to the program's pseudo instructions.
5. This final integrity check (env->used_map_cnt != signed_map_cnt) still
passes because the total map count remains unchanged, but the
cryptographic bindings have been completely bypassed.
Would it be safer to cache the fd_array in kernel memory during the initial
process_fd_array() call so that check_and_resolve_insns() does not need to
read from user space a second time?
> + verbose(env, "signed program uses %s not covered by the signature\n",
> + env->used_map_cnt != signed_map_cnt ?
> + (env->used_btf_cnt ? "maps and BTF" : "maps") : "BTF");
> + ret = -EACCES;
> + goto skip_full_check;
> + }
--
Sashiko AI review · https://sashiko.dev/#/patchset/20260624140301.93421-1-daniel@iogearbox.net?part=1
next prev parent reply other threads:[~2026-06-24 14:48 UTC|newest]
Thread overview: 20+ messages / expand[flat|nested] mbox.gz Atom feed top
2026-06-24 14:02 [PATCH bpf-next v2 0/5] Verify BPF signed loader at load time Daniel Borkmann
2026-06-24 14:02 ` [PATCH bpf-next v2 1/5] bpf: Verify signed loader metadata " Daniel Borkmann
2026-06-24 14:48 ` sashiko-bot [this message]
2026-06-24 15:32 ` Daniel Borkmann
2026-06-24 15:12 ` Paul Moore
2026-06-24 15:37 ` Daniel Borkmann
2026-06-24 18:42 ` Paul Moore
2026-06-25 20:37 ` Daniel Borkmann
2026-06-26 0:59 ` Paul Moore
2026-06-26 1:16 ` Alexei Starovoitov
2026-06-26 1:38 ` Paul Moore
2026-06-26 1:44 ` Alexei Starovoitov
2026-06-26 2:01 ` Paul Moore
2026-06-26 22:01 ` KP Singh
2026-06-27 1:32 ` Paul Moore
2026-06-24 15:17 ` bot+bpf-ci
2026-06-24 14:02 ` [PATCH bpf-next v2 2/5] libbpf: Drop in-loader metadata check for load-time verification Daniel Borkmann
2026-06-24 14:02 ` [PATCH bpf-next v2 3/5] bpftool: Cover loader metadata with the program signature Daniel Borkmann
2026-06-24 14:03 ` [PATCH bpf-next v2 4/5] selftests/bpf: Verify load-time signed loader metadata Daniel Borkmann
2026-06-24 14:03 ` [PATCH bpf-next v2 5/5] Documentation/bpf: Add BPF signing and enforcement doc Daniel Borkmann
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=20260624144803.7AADB1F000E9@smtp.kernel.org \
--to=sashiko-bot@kernel.org \
--cc=bpf@vger.kernel.org \
--cc=daniel@iogearbox.net \
--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.