mirror of https://lore.kernel.org/lkml/
 help / color / mirror / Atom feed
* [PATCH bpf] bpf, lsm: Mark backing_file_alloc/free LSM hooks as untrusted
@ 2026-11-11 20:35 Sergei Nizovtsev
  0 siblings, 0 replies; only message in thread
From: Sergei Nizovtsev @ 2026-11-11 20:35 UTC (permalink / raw)
  To: bpf
  Cc: linux-security-module, Sergei Nizovtsev, stable, KP Singh,
	Matt Bobrowski, Alexei Starovoitov, Daniel Borkmann,
	Andrii Nakryiko, Eduard Zingerman, Kumar Kartikeya Dwivedi,
	Martin KaFai Lau, Song Liu, Yonghong Song, Jiri Olsa,
	Emil Tsalapatis, Ihor Solodrai, Serge Hallyn, Amir Goldstein,
	Paul Moore, Christian Brauner, linux-kernel

The backing_file_alloc and backing_file_free LSM hooks get the backing
file as "struct file *backing_file", but its f_path is not populated
while they run:

 - security_backing_file_alloc() is called from init_backing_file() in
   alloc_empty_backing_file(), before vfs_open() sets f_path, so
   backing_file->f_path.dentry is NULL;
 - security_backing_file_free() can run for a backing file whose open
   failed and whose f_path was already cleared.

Neither hook is listed in untrusted_lsm_hooks, so bpf_lsm_is_trusted()
lets BPF LSM programs use the argument as a trusted pointer.  A program
attached to lsm/backing_file_alloc can pass &backing_file->f_path to the
trusted-args kfunc bpf_path_d_path(), and d_path() dereferences the NULL
dentry on the first open of a file on overlayfs:

  extern int bpf_path_d_path(const struct path *path, char *buf,
                             size_t sz) __ksym;
  char buf[256];

  SEC("lsm/backing_file_alloc")
  int BPF_PROG(poc, struct file *backing_file,
               const struct file *user_file)
  {
          bpf_path_d_path(&backing_file->f_path, buf, sizeof(buf));
          return 0;
  }

  # bpftool prog load poc.bpf.o /sys/fs/bpf/poc autoattach
  # cat <any file on an overlayfs mount>

  Oops: general protection fault, probably for non-canonical address 0xdffffc000000000c: 0000 [#1] SMP KASAN NOPTI
  KASAN: null-ptr-deref in range [0x0000000000000060-0x0000000000000067]
  RIP: 0010:d_path+0xb4/0x810
  Call Trace:
   bpf_path_d_path+0x26/0x70
   bpf_prog_f8f2e241d4ff7217_poc+0x33/0x37
   bpf_trampoline_6442521065+0x61/0xf9
   security_backing_file_alloc+0x78/0xe0
   alloc_empty_backing_file+0xf0/0x170
   backing_file_open+0xfd/0x290
   ovl_open_realfile+0x1ed/0x270
   ovl_open+0x1a9/0x2f0
   do_dentry_open+0x404/0x1280
   vfs_open_consume+0xba/0x4b0
   path_openat+0xc4f/0x1f60

Add both hooks to untrusted_lsm_hooks, next to file_alloc_security and
file_free_security, which are listed there for the same reason.  The
program above is then rejected at load time with "R1 must be referenced
or trusted".

Fixes: 6af36aeb147a ("lsm: add backing_file LSM hooks")
Cc: stable@vger.kernel.org
Assisted-by: Claude:claude-fable-5-2
Signed-off-by: Sergei Nizovtsev <snizovtsev@cloudlinux.com>
---
Tested on bpf.git master (475a0cfd02f1) under virtme-ng with KASAN: the
reproducer oopses without the patch and fails to load with it. Only the
backing_file_alloc case was reproduced; backing_file_free is from code
reading.

 kernel/bpf/bpf_lsm.c | 2 ++
 1 file changed, 2 insertions(+)

diff --git a/kernel/bpf/bpf_lsm.c b/kernel/bpf/bpf_lsm.c
index f58dce888ff4a..f39a3766f2245 100644
--- a/kernel/bpf/bpf_lsm.c
+++ b/kernel/bpf/bpf_lsm.c
@@ -411,6 +411,8 @@ BTF_ID(func, bpf_lsm_bpf_map_free)
 BTF_ID(func, bpf_lsm_bpf_prog_free)
 BTF_ID(func, bpf_lsm_file_alloc_security)
 BTF_ID(func, bpf_lsm_file_free_security)
+BTF_ID(func, bpf_lsm_backing_file_alloc)
+BTF_ID(func, bpf_lsm_backing_file_free)
 #ifdef CONFIG_SECURITY_NETWORK
 BTF_ID(func, bpf_lsm_sk_alloc_security)
 BTF_ID(func, bpf_lsm_sk_free_security)
-- 
2.56.0


^ permalink raw reply	[flat|nested] only message in thread

only message in thread, other threads:[~2026-11-11 20:36 UTC | newest]

Thread overview: (only message) (download: mbox.gz / follow: Atom feed)
-- links below jump to the message on this page --
2026-11-11 20:35 [PATCH bpf] bpf, lsm: Mark backing_file_alloc/free LSM hooks as untrusted Sergei Nizovtsev

This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox

all inboxes | Powered by JetHome®