All of lore.kernel.org
 help / color / mirror / Atom feed
From: Yuqi Xu <xuyuqiabc@gmail.com>
To: bpf@vger.kernel.org
Cc: Vadim Fedorenko <vadim.fedorenko@linux.dev>,
	Alexei Starovoitov <ast@kernel.org>,
	Daniel Borkmann <daniel@iogearbox.net>,
	Andrii Nakryiko <andrii@kernel.org>,
	Eduard Zingerman <eddyz87@gmail.com>,
	Kumar Kartikeya Dwivedi <memxor@gmail.com>,
	Martin KaFai Lau <martin.lau@linux.dev>,
	Song Liu <song@kernel.org>,
	Yonghong Song <yonghong.song@linux.dev>,
	Jiri Olsa <jolsa@kernel.org>,
	Emil Tsalapatis <emil@etsalapatis.com>,
	Ihor Solodrai <ihor.solodrai@linux.dev>,
	stable@vger.kernel.org, Vega <vega@nebusec.ai>,
	Ren Wei <weir@nebusec.ai>,
	xuyq21@lenovo.com
Subject: Re: [PATCH bpf 1/1] bpf: crypto: check params size before reading reserved fields
Date: Sun, 20 Sep 2026 15:24:41 +0800	[thread overview]
Message-ID: <20260920072441.60435-1-xuyuqiabc@gmail.com> (raw)
In-Reply-To: <4f3ab4b03e79017e215521743996555439bf0bb3.1789802413.git.xuyuqiabc@gmail.com>

Hi all,

This note is about a Sashiko finding on the already-applied patch
(a11212910cf0); that review was not posted to the list.  The note
below is analysis only; I am not asking to change the merged patch.

> The `algo` string in `struct bpf_crypto_params` is not checked for
> null-termination before being passed to the crypto API. A BPF program
> can fill this array and subsequent fields with non-null bytes, causing
> `vsnprintf` in `request_module` to read out-of-bounds, potentially
> resulting in a kernel panic or leaking kernel memory to user-space.
> locations: kernel/bpf/crypto.c:165 `bpf_crypto_ctx_create`;
> kernel/bpf/crypto.c:185

This is a valid finding.  It is also pre-existing and independent of the
params__sz out-of-bounds read that this patch fixes.

The kfunc's __sz annotation only bounds-checks the buffer: the verifier
calls check_mem_size_reg() on the params / params__sz pair and checks
that params__sz bytes of the pointer are readable.  It neither zeroes
nor NUL-terminates the buffer.  After the size check in
bpf_crypto_ctx_create(), params__sz == sizeof(struct bpf_crypto_params)
== 408, so algo[] (offset 16, 128 bytes, kernel/bpf/crypto.c:33) lies
inside the validated region, but nothing guarantees a NUL anywhere in
it.  A program can pass reserved[0] = reserved[1] = 0 (which the
function requires) and fill algo[] and the trailing fields with non-NUL
bytes.

type->has_algo(params->algo) (kernel/bpf/crypto.c:165) then reaches an
unbounded read:

  bpf_crypto_lskcipher_has_algo()
    crypto_has_skcipher()          crypto/skcipher.c:666
      crypto_type_has_alg()        crypto/algapi.c:1039
        crypto_find_alg()          crypto/api.c:535
          crypto_alg_mod_lookup()  crypto/api.c:338
            crypto_larval_lookup()  crypto/api.c:290
              request_module("crypto-%s", name)   crypto/api.c:303
                vsnprintf(module_name, MODULE_NAME_LEN, fmt, args)
                                                  kernel/module/kmod.c:150

The "%s" conversion has no precision, so vsnprintf() does a plain
strlen() on name; it keeps reading through key[], key_len and authsize
and past the 408-byte region that the verifier validated, until it finds
a zero byte.  KASAN reports a slab-out-of-bounds read if the object ends
before the next zero.  That is the extent of the bug: the OOB is only
that strlen()/string_nocheck walk past the 408-byte region.  An
unterminated algo makes vsnprintf()'s "%s" read unbounded, but when the
return value is >= MODULE_NAME_LEN, kmod.c returns -ENAMETOOLONG and
does not reach call_modprobe() or the usermode helper.

The finding also cites kernel/bpf/crypto.c:185.  That line is a blank
line, not a second use of algo; if (!ctx) after kzalloc is at 181.
The nearby second use of params->algo is type->alloc_tfm() at 187;
185 is a near miss for that line.  A 128-byte all-non-NUL algo cannot
match any already-loaded cra_name, so has_algo() returns false,
bpf_crypto_ctx_create() sets -EOPNOTSUPP, and type->alloc_tfm() is
not reached.

This is only reachable from BPF_PROG_TYPE_SYSCALL (the
crypt_init_kfunc_set registration at kernel/bpf/crypto.c:393), which
requires CAP_BPF, so it is not an unprivileged attack.  Still, the
verifier-validated buffer is the trust boundary, and reading past it is
a bug regardless.

Relationship to this patch: the patch only moves the params__sz
comparison ahead of the reserved[] reads.  The algo[] termination
problem exists identically before and after it, so it is a separate root
cause and is neither fixed nor worsened here.

A follow-up would validate that the strings are terminated before
handing them to the crypto API, for example:

  if (strnlen(params->algo, sizeof(params->algo)) == sizeof(params->algo) ||
      strnlen(params->type, sizeof(params->type)) == sizeof(params->type)) {
          *err = -EINVAL;
          return NULL;
  }

(memchr(params->algo, '\0', sizeof(params->algo)) is equivalent.)
params is const, so writing
params->algo[sizeof(params->algo) - 1] = '\0' would modify the
caller's buffer; explicitly rejecting an unterminated name is cleaner
than silently truncating it.  params->type[] is only compared with
strcmp() against the short, NUL-terminated registered type names, so
it cannot drive the unbounded read, but validating both keeps them
consistent.

That would be a separate patch (Fixes: 3e1c6f35409f), not a change to
the already-merged commit.  Happy to send it if you want it.

Thanks,
Yuqi Xu

  parent reply	other threads:[~2026-09-20  7:25 UTC|newest]

Thread overview: 5+ messages / expand[flat|nested]  mbox.gz  Atom feed  top
2026-09-19  8:45 [PATCH bpf 0/1] bpf: crypto: check params size before reading reserved fields Yuqi Xu
2026-09-19  8:45 ` [PATCH bpf 1/1] " Yuqi Xu
2026-09-19 18:17   ` Alexei Starovoitov
2026-09-20  7:24   ` Yuqi Xu [this message]
2026-09-19 23:30 ` [PATCH bpf 0/1] " patchwork-bot+netdevbpf

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=20260920072441.60435-1-xuyuqiabc@gmail.com \
    --to=xuyuqiabc@gmail.com \
    --cc=andrii@kernel.org \
    --cc=ast@kernel.org \
    --cc=bpf@vger.kernel.org \
    --cc=daniel@iogearbox.net \
    --cc=eddyz87@gmail.com \
    --cc=emil@etsalapatis.com \
    --cc=ihor.solodrai@linux.dev \
    --cc=jolsa@kernel.org \
    --cc=martin.lau@linux.dev \
    --cc=memxor@gmail.com \
    --cc=song@kernel.org \
    --cc=stable@vger.kernel.org \
    --cc=vadim.fedorenko@linux.dev \
    --cc=vega@nebusec.ai \
    --cc=weir@nebusec.ai \
    --cc=xuyq21@lenovo.com \
    --cc=yonghong.song@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.