Linux kernel mirror (for testing) git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git
kernel os linux
1
fork

Configure Feed

Select the types of activity you want to include in your feed.

Merge branch 'security-propagate-caller-information-in-bpf-hooks'

Blaise Boscaccy says:

====================
While trying to implement an eBPF gatekeeper program, we ran into an
issue whereas the LSM hooks are missing some relevant data.

Certain subcommands passed to the bpf() syscall can be invoked from
either the kernel or userspace. Additionally, some fields in the
bpf_attr struct contain pointers, and depending on where the
subcommand was invoked, they could point to either user or kernel
memory. One example of this is the bpf_prog_load subcommand and its
fd_array. This data is made available and used by the verifier but not
made available to the LSM subsystem. This patchset simply exposes that
information to applicable LSM hooks.

Change list:
- v6 -> v7
- use gettid/pid in lieu of getpid/tgid in test condition
- v5 -> v6
- fix regression caused by is_kernel renaming
- simplify test logic
- v4 -> v5
- merge v4 selftest breakout patch back into a single patch
- change "is_kernel" to "kernel"
- add selftest using new kernel flag
- v3 -> v4
- split out selftest changes into a separate patch
- v2 -> v3
- reorder params so that the new boolean flag is the last param
- fixup function signatures in bpf selftests
- v1 -> v2
- Pass a boolean flag in lieu of bpfptr_t

Revisions:
- v6
https://lore.kernel.org/bpf/20250308013314.719150-1-bboscaccy@linux.microsoft.com/
- v5
https://lore.kernel.org/bpf/20250307213651.3065714-1-bboscaccy@linux.microsoft.com/
- v4
https://lore.kernel.org/bpf/20250304203123.3935371-1-bboscaccy@linux.microsoft.com/
- v3
https://lore.kernel.org/bpf/20250303222416.3909228-1-bboscaccy@linux.microsoft.com/
- v2
https://lore.kernel.org/bpf/20250228165322.3121535-1-bboscaccy@linux.microsoft.com/
- v1
https://lore.kernel.org/bpf/20250226003055.1654837-1-bboscaccy@linux.microsoft.com/
====================

Link: https://patch.msgid.link/20250310221737.821889-1-bboscaccy@linux.microsoft.com
Signed-off-by: Alexei Starovoitov <ast@kernel.org>

+108 -33
+3 -3
include/linux/lsm_hook_defs.h
··· 426 426 #endif /* CONFIG_AUDIT */ 427 427 428 428 #ifdef CONFIG_BPF_SYSCALL 429 - LSM_HOOK(int, 0, bpf, int cmd, union bpf_attr *attr, unsigned int size) 429 + LSM_HOOK(int, 0, bpf, int cmd, union bpf_attr *attr, unsigned int size, bool kernel) 430 430 LSM_HOOK(int, 0, bpf_map, struct bpf_map *map, fmode_t fmode) 431 431 LSM_HOOK(int, 0, bpf_prog, struct bpf_prog *prog) 432 432 LSM_HOOK(int, 0, bpf_map_create, struct bpf_map *map, union bpf_attr *attr, 433 - struct bpf_token *token) 433 + struct bpf_token *token, bool kernel) 434 434 LSM_HOOK(void, LSM_RET_VOID, bpf_map_free, struct bpf_map *map) 435 435 LSM_HOOK(int, 0, bpf_prog_load, struct bpf_prog *prog, union bpf_attr *attr, 436 - struct bpf_token *token) 436 + struct bpf_token *token, bool kernel) 437 437 LSM_HOOK(void, LSM_RET_VOID, bpf_prog_free, struct bpf_prog *prog) 438 438 LSM_HOOK(int, 0, bpf_token_create, struct bpf_token *token, union bpf_attr *attr, 439 439 const struct path *path)
+6 -6
include/linux/security.h
··· 2249 2249 struct bpf_prog; 2250 2250 struct bpf_token; 2251 2251 #ifdef CONFIG_SECURITY 2252 - extern int security_bpf(int cmd, union bpf_attr *attr, unsigned int size); 2252 + extern int security_bpf(int cmd, union bpf_attr *attr, unsigned int size, bool kernel); 2253 2253 extern int security_bpf_map(struct bpf_map *map, fmode_t fmode); 2254 2254 extern int security_bpf_prog(struct bpf_prog *prog); 2255 2255 extern int security_bpf_map_create(struct bpf_map *map, union bpf_attr *attr, 2256 - struct bpf_token *token); 2256 + struct bpf_token *token, bool kernel); 2257 2257 extern void security_bpf_map_free(struct bpf_map *map); 2258 2258 extern int security_bpf_prog_load(struct bpf_prog *prog, union bpf_attr *attr, 2259 - struct bpf_token *token); 2259 + struct bpf_token *token, bool kernel); 2260 2260 extern void security_bpf_prog_free(struct bpf_prog *prog); 2261 2261 extern int security_bpf_token_create(struct bpf_token *token, union bpf_attr *attr, 2262 2262 const struct path *path); ··· 2265 2265 extern int security_bpf_token_capable(const struct bpf_token *token, int cap); 2266 2266 #else 2267 2267 static inline int security_bpf(int cmd, union bpf_attr *attr, 2268 - unsigned int size) 2268 + unsigned int size, bool kernel) 2269 2269 { 2270 2270 return 0; 2271 2271 } ··· 2281 2281 } 2282 2282 2283 2283 static inline int security_bpf_map_create(struct bpf_map *map, union bpf_attr *attr, 2284 - struct bpf_token *token) 2284 + struct bpf_token *token, bool kernel) 2285 2285 { 2286 2286 return 0; 2287 2287 } ··· 2290 2290 { } 2291 2291 2292 2292 static inline int security_bpf_prog_load(struct bpf_prog *prog, union bpf_attr *attr, 2293 - struct bpf_token *token) 2293 + struct bpf_token *token, bool kernel) 2294 2294 { 2295 2295 return 0; 2296 2296 }
+5 -5
kernel/bpf/syscall.c
··· 1315 1315 1316 1316 #define BPF_MAP_CREATE_LAST_FIELD map_token_fd 1317 1317 /* called via syscall */ 1318 - static int map_create(union bpf_attr *attr) 1318 + static int map_create(union bpf_attr *attr, bool kernel) 1319 1319 { 1320 1320 const struct bpf_map_ops *ops; 1321 1321 struct bpf_token *token = NULL; ··· 1505 1505 attr->btf_vmlinux_value_type_id; 1506 1506 } 1507 1507 1508 - err = security_bpf_map_create(map, attr, token); 1508 + err = security_bpf_map_create(map, attr, token, kernel); 1509 1509 if (err) 1510 1510 goto free_map_sec; 1511 1511 ··· 2942 2942 if (err < 0) 2943 2943 goto free_prog; 2944 2944 2945 - err = security_bpf_prog_load(prog, attr, token); 2945 + err = security_bpf_prog_load(prog, attr, token, uattr.is_kernel); 2946 2946 if (err) 2947 2947 goto free_prog_sec; 2948 2948 ··· 5767 5767 if (copy_from_bpfptr(&attr, uattr, size) != 0) 5768 5768 return -EFAULT; 5769 5769 5770 - err = security_bpf(cmd, &attr, size); 5770 + err = security_bpf(cmd, &attr, size, uattr.is_kernel); 5771 5771 if (err < 0) 5772 5772 return err; 5773 5773 5774 5774 switch (cmd) { 5775 5775 case BPF_MAP_CREATE: 5776 - err = map_create(&attr); 5776 + err = map_create(&attr, uattr.is_kernel); 5777 5777 break; 5778 5778 case BPF_MAP_LOOKUP_ELEM: 5779 5779 err = map_lookup_elem(&attr);
+9 -6
security/security.c
··· 5627 5627 * @cmd: command 5628 5628 * @attr: bpf attribute 5629 5629 * @size: size 5630 + * @kernel: whether or not call originated from kernel 5630 5631 * 5631 5632 * Do a initial check for all bpf syscalls after the attribute is copied into 5632 5633 * the kernel. The actual security module can implement their own rules to ··· 5635 5634 * 5636 5635 * Return: Returns 0 if permission is granted. 5637 5636 */ 5638 - int security_bpf(int cmd, union bpf_attr *attr, unsigned int size) 5637 + int security_bpf(int cmd, union bpf_attr *attr, unsigned int size, bool kernel) 5639 5638 { 5640 - return call_int_hook(bpf, cmd, attr, size); 5639 + return call_int_hook(bpf, cmd, attr, size, kernel); 5641 5640 } 5642 5641 5643 5642 /** ··· 5674 5673 * @map: BPF map object 5675 5674 * @attr: BPF syscall attributes used to create BPF map 5676 5675 * @token: BPF token used to grant user access 5676 + * @kernel: whether or not call originated from kernel 5677 5677 * 5678 5678 * Do a check when the kernel creates a new BPF map. This is also the 5679 5679 * point where LSM blob is allocated for LSMs that need them. ··· 5682 5680 * Return: Returns 0 on success, error on failure. 5683 5681 */ 5684 5682 int security_bpf_map_create(struct bpf_map *map, union bpf_attr *attr, 5685 - struct bpf_token *token) 5683 + struct bpf_token *token, bool kernel) 5686 5684 { 5687 - return call_int_hook(bpf_map_create, map, attr, token); 5685 + return call_int_hook(bpf_map_create, map, attr, token, kernel); 5688 5686 } 5689 5687 5690 5688 /** ··· 5692 5690 * @prog: BPF program object 5693 5691 * @attr: BPF syscall attributes used to create BPF program 5694 5692 * @token: BPF token used to grant user access to BPF subsystem 5693 + * @kernel: whether or not call originated from kernel 5695 5694 * 5696 5695 * Perform an access control check when the kernel loads a BPF program and 5697 5696 * allocates associated BPF program object. This hook is also responsible for ··· 5701 5698 * Return: Returns 0 on success, error on failure. 5702 5699 */ 5703 5700 int security_bpf_prog_load(struct bpf_prog *prog, union bpf_attr *attr, 5704 - struct bpf_token *token) 5701 + struct bpf_token *token, bool kernel) 5705 5702 { 5706 - return call_int_hook(bpf_prog_load, prog, attr, token); 5703 + return call_int_hook(bpf_prog_load, prog, attr, token, kernel); 5707 5704 } 5708 5705 5709 5706 /**
+3 -3
security/selinux/hooks.c
··· 6866 6866 6867 6867 #ifdef CONFIG_BPF_SYSCALL 6868 6868 static int selinux_bpf(int cmd, union bpf_attr *attr, 6869 - unsigned int size) 6869 + unsigned int size, bool kernel) 6870 6870 { 6871 6871 u32 sid = current_sid(); 6872 6872 int ret; ··· 6953 6953 } 6954 6954 6955 6955 static int selinux_bpf_map_create(struct bpf_map *map, union bpf_attr *attr, 6956 - struct bpf_token *token) 6956 + struct bpf_token *token, bool kernel) 6957 6957 { 6958 6958 struct bpf_security_struct *bpfsec; 6959 6959 ··· 6976 6976 } 6977 6977 6978 6978 static int selinux_bpf_prog_load(struct bpf_prog *prog, union bpf_attr *attr, 6979 - struct bpf_token *token) 6979 + struct bpf_token *token, bool kernel) 6980 6980 { 6981 6981 struct bpf_security_struct *bpfsec; 6982 6982
+43
tools/testing/selftests/bpf/prog_tests/kernel_flag.c
··· 1 + // SPDX-License-Identifier: GPL-2.0 2 + /* Copyright (c) 2025 Microsoft */ 3 + #include <test_progs.h> 4 + #include "kfunc_call_test.skel.h" 5 + #include "kfunc_call_test.lskel.h" 6 + #include "test_kernel_flag.skel.h" 7 + 8 + void test_kernel_flag(void) 9 + { 10 + struct test_kernel_flag *lsm_skel; 11 + struct kfunc_call_test *skel = NULL; 12 + struct kfunc_call_test_lskel *lskel = NULL; 13 + int ret; 14 + 15 + lsm_skel = test_kernel_flag__open_and_load(); 16 + if (!ASSERT_OK_PTR(lsm_skel, "lsm_skel")) 17 + return; 18 + 19 + lsm_skel->bss->monitored_tid = gettid(); 20 + 21 + ret = test_kernel_flag__attach(lsm_skel); 22 + if (!ASSERT_OK(ret, "test_kernel_flag__attach")) 23 + goto close_prog; 24 + 25 + /* Test with skel. This should pass the gatekeeper */ 26 + skel = kfunc_call_test__open_and_load(); 27 + if (!ASSERT_OK_PTR(skel, "skel")) 28 + goto close_prog; 29 + 30 + /* Test with lskel. This should fail due to blocking kernel-based bpf() invocations */ 31 + lskel = kfunc_call_test_lskel__open_and_load(); 32 + if (!ASSERT_ERR_PTR(lskel, "lskel")) 33 + goto close_prog; 34 + 35 + close_prog: 36 + if (skel) 37 + kfunc_call_test__destroy(skel); 38 + if (lskel) 39 + kfunc_call_test_lskel__destroy(lskel); 40 + 41 + lsm_skel->bss->monitored_tid = 0; 42 + test_kernel_flag__destroy(lsm_skel); 43 + }
+2 -1
tools/testing/selftests/bpf/progs/rcu_read_lock.c
··· 242 242 } 243 243 244 244 SEC("?lsm.s/bpf") 245 - int BPF_PROG(inproper_sleepable_kfunc, int cmd, union bpf_attr *attr, unsigned int size) 245 + int BPF_PROG(inproper_sleepable_kfunc, int cmd, union bpf_attr *attr, unsigned int size, 246 + bool kernel) 246 247 { 247 248 struct bpf_key *bkey; 248 249
+2 -2
tools/testing/selftests/bpf/progs/test_cgroup1_hierarchy.c
··· 51 51 } 52 52 53 53 SEC("lsm/bpf") 54 - int BPF_PROG(lsm_run, int cmd, union bpf_attr *attr, unsigned int size) 54 + int BPF_PROG(lsm_run, int cmd, union bpf_attr *attr, unsigned int size, bool kernel) 55 55 { 56 56 return bpf_link_create_verify(cmd); 57 57 } 58 58 59 59 SEC("lsm.s/bpf") 60 - int BPF_PROG(lsm_s_run, int cmd, union bpf_attr *attr, unsigned int size) 60 + int BPF_PROG(lsm_s_run, int cmd, union bpf_attr *attr, unsigned int size, bool kernel) 61 61 { 62 62 return bpf_link_create_verify(cmd); 63 63 }
+28
tools/testing/selftests/bpf/progs/test_kernel_flag.c
··· 1 + // SPDX-License-Identifier: GPL-2.0 2 + 3 + /* 4 + * Copyright (C) 2025 Microsoft Corporation 5 + * 6 + * Author: Blaise Boscaccy <bboscaccy@linux.microsoft.com> 7 + */ 8 + 9 + #include "vmlinux.h" 10 + #include <errno.h> 11 + #include <bpf/bpf_helpers.h> 12 + #include <bpf/bpf_tracing.h> 13 + 14 + char _license[] SEC("license") = "GPL"; 15 + 16 + __u32 monitored_tid; 17 + 18 + SEC("lsm.s/bpf") 19 + int BPF_PROG(bpf, int cmd, union bpf_attr *attr, unsigned int size, bool kernel) 20 + { 21 + __u32 tid; 22 + 23 + tid = bpf_get_current_pid_tgid() & 0xFFFFFFFF; 24 + if (!kernel || tid != monitored_tid) 25 + return 0; 26 + else 27 + return -EINVAL; 28 + }
+3 -3
tools/testing/selftests/bpf/progs/test_kfunc_dynptr_param.c
··· 36 36 37 37 SEC("?lsm.s/bpf") 38 38 __failure __msg("cannot pass in dynptr at an offset=-8") 39 - int BPF_PROG(not_valid_dynptr, int cmd, union bpf_attr *attr, unsigned int size) 39 + int BPF_PROG(not_valid_dynptr, int cmd, union bpf_attr *attr, unsigned int size, bool kernel) 40 40 { 41 41 unsigned long val; 42 42 ··· 46 46 47 47 SEC("?lsm.s/bpf") 48 48 __failure __msg("arg#0 expected pointer to stack or const struct bpf_dynptr") 49 - int BPF_PROG(not_ptr_to_stack, int cmd, union bpf_attr *attr, unsigned int size) 49 + int BPF_PROG(not_ptr_to_stack, int cmd, union bpf_attr *attr, unsigned int size, bool kernel) 50 50 { 51 51 unsigned long val = 0; 52 52 ··· 55 55 } 56 56 57 57 SEC("lsm.s/bpf") 58 - int BPF_PROG(dynptr_data_null, int cmd, union bpf_attr *attr, unsigned int size) 58 + int BPF_PROG(dynptr_data_null, int cmd, union bpf_attr *attr, unsigned int size, bool kernel) 59 59 { 60 60 struct bpf_key *trusted_keyring; 61 61 struct bpf_dynptr ptr;
+1 -1
tools/testing/selftests/bpf/progs/test_lookup_key.c
··· 23 23 extern void bpf_key_put(struct bpf_key *key) __ksym; 24 24 25 25 SEC("lsm.s/bpf") 26 - int BPF_PROG(bpf, int cmd, union bpf_attr *attr, unsigned int size) 26 + int BPF_PROG(bpf, int cmd, union bpf_attr *attr, unsigned int size, bool kernel) 27 27 { 28 28 struct bpf_key *bkey; 29 29 __u32 pid;
+1 -1
tools/testing/selftests/bpf/progs/test_ptr_untrusted.c
··· 7 7 char tp_name[128]; 8 8 9 9 SEC("lsm.s/bpf") 10 - int BPF_PROG(lsm_run, int cmd, union bpf_attr *attr, unsigned int size) 10 + int BPF_PROG(lsm_run, int cmd, union bpf_attr *attr, unsigned int size, bool kernel) 11 11 { 12 12 switch (cmd) { 13 13 case BPF_RAW_TRACEPOINT_OPEN:
+1 -1
tools/testing/selftests/bpf/progs/test_task_under_cgroup.c
··· 49 49 } 50 50 51 51 SEC("lsm.s/bpf") 52 - int BPF_PROG(lsm_run, int cmd, union bpf_attr *attr, unsigned int size) 52 + int BPF_PROG(lsm_run, int cmd, union bpf_attr *attr, unsigned int size, bool kernel) 53 53 { 54 54 struct cgroup *cgrp = NULL; 55 55 struct task_struct *task;
+1 -1
tools/testing/selftests/bpf/progs/test_verify_pkcs7_sig.c
··· 37 37 char _license[] SEC("license") = "GPL"; 38 38 39 39 SEC("lsm.s/bpf") 40 - int BPF_PROG(bpf, int cmd, union bpf_attr *attr, unsigned int size) 40 + int BPF_PROG(bpf, int cmd, union bpf_attr *attr, unsigned int size, bool kernel) 41 41 { 42 42 struct bpf_dynptr data_ptr, sig_ptr; 43 43 struct data *data_val;