]> git.ipfire.org Git - thirdparty/linux.git/commitdiff
bpf: annotate file argument as __nullable in bpf_lsm_mmap_file
authorMatt Bobrowski <mattbobrowski@google.com>
Tue, 16 Dec 2025 13:29:59 +0000 (13:29 +0000)
committerAlexei Starovoitov <ast@kernel.org>
Sun, 21 Dec 2025 18:56:33 +0000 (10:56 -0800)
As reported in [0], anonymous memory mappings are not backed by a
struct file instance. Consequently, the struct file pointer passed to
the security_mmap_file() LSM hook is NULL in such cases.

The BPF verifier is currently unaware of this, allowing BPF LSM
programs to dereference this struct file pointer without needing to
perform an explicit NULL check. This leads to potential NULL pointer
dereference and a kernel crash.

Add a strong override for bpf_lsm_mmap_file() which annotates the
struct file pointer parameter with the __nullable suffix. This
explicitly informs the BPF verifier that this pointer (PTR_MAYBE_NULL)
can be NULL, forcing BPF LSM programs to perform a check on it before
dereferencing it.

[0] https://lore.kernel.org/bpf/5e460d3c.4c3e9.19adde547d8.Coremail.kaiyanm@hust.edu.cn/

Reported-by: Kaiyan Mei <M202472210@hust.edu.cn>
Reported-by: Yinhao Hu <dddddd@hust.edu.cn>
Reviewed-by: Dongliang Mu <dzm91@hust.edu.cn>
Closes: https://lore.kernel.org/bpf/5e460d3c.4c3e9.19adde547d8.Coremail.kaiyanm@hust.edu.cn/
Signed-off-by: Matt Bobrowski <mattbobrowski@google.com>
Acked-by: Song Liu <song@kernel.org>
Link: https://lore.kernel.org/r/20251216133000.3690723-1-mattbobrowski@google.com
Signed-off-by: Alexei Starovoitov <ast@kernel.org>
MAINTAINERS
kernel/bpf/Makefile
kernel/bpf/bpf_lsm.c
kernel/bpf/bpf_lsm_proto.c [new file with mode: 0644]

index cb1898a85b050a3fd8cef0b3fb8afd3a7c6e5055..e7027fba97db2c64f473018d7c522be22def7476 100644 (file)
@@ -4848,6 +4848,7 @@ S:        Maintained
 F:     Documentation/bpf/prog_lsm.rst
 F:     include/linux/bpf_lsm.h
 F:     kernel/bpf/bpf_lsm.c
+F:     kernel/bpf/bpf_lsm_proto.c
 F:     kernel/trace/bpf_trace.c
 F:     security/bpf/
 
index 232cbc97434db921d573cfc9573cba388a0ad348..79cf22860a99ba31a9daf08a29de0f3a162ba89f 100644 (file)
@@ -42,7 +42,17 @@ endif
 ifeq ($(CONFIG_BPF_JIT),y)
 obj-$(CONFIG_BPF_SYSCALL) += bpf_struct_ops.o
 obj-$(CONFIG_BPF_SYSCALL) += cpumask.o
-obj-${CONFIG_BPF_LSM} += bpf_lsm.o
+# bpf_lsm_proto.o must precede bpf_lsm.o. The current pahole logic
+# deduplicates function prototypes within
+# btf_encoder__add_saved_func() by keeping the first instance seen. We
+# need the function prototype(s) in bpf_lsm_proto.o to take precedence
+# over those within bpf_lsm.o. Having bpf_lsm_proto.o precede
+# bpf_lsm.o ensures its DWARF CU is processed early, forcing the
+# generated BTF to contain the overrides.
+#
+# Notably, this is a temporary workaround whilst the deduplication
+# semantics within pahole are revisited accordingly.
+obj-${CONFIG_BPF_LSM} += bpf_lsm_proto.o bpf_lsm.o
 endif
 ifneq ($(CONFIG_CRYPTO),)
 obj-$(CONFIG_BPF_SYSCALL) += crypto.o
index 7cb6e8d4282cb13f92e268461e69670392cae36b..0c4a0c8e6f703e3da82aa641b06fa0f2ba43dc98 100644 (file)
 #include <linux/bpf-cgroup.h>
 
 /* For every LSM hook that allows attachment of BPF programs, declare a nop
- * function where a BPF program can be attached.
+ * function where a BPF program can be attached. Notably, we qualify each with
+ * weak linkage such that strong overrides can be implemented if need be.
  */
 #define LSM_HOOK(RET, DEFAULT, NAME, ...)      \
-noinline RET bpf_lsm_##NAME(__VA_ARGS__)       \
+__weak noinline RET bpf_lsm_##NAME(__VA_ARGS__)        \
 {                                              \
        return DEFAULT;                         \
 }
diff --git a/kernel/bpf/bpf_lsm_proto.c b/kernel/bpf/bpf_lsm_proto.c
new file mode 100644 (file)
index 0000000..44a54fd
--- /dev/null
@@ -0,0 +1,19 @@
+// SPDX-License-Identifier: GPL-2.0
+/*
+ * Copyright 2025 Google LLC.
+ */
+
+#include <linux/fs.h>
+#include <linux/bpf_lsm.h>
+
+/*
+ * Strong definition of the mmap_file() BPF LSM hook. The __nullable suffix on
+ * the struct file pointer parameter name marks it as PTR_MAYBE_NULL. This
+ * explicitly enforces that BPF LSM programs check for NULL before attempting to
+ * dereference it.
+ */
+int bpf_lsm_mmap_file(struct file *file__nullable, unsigned long reqprot,
+                     unsigned long prot, unsigned long flags)
+{
+       return 0;
+}