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 'add-bpf-lsm-return-value-range-check-bpf-part'

Xu Kuohai says:

====================
Add BPF LSM return value range check, BPF part

From: Xu Kuohai <xukuohai@huawei.com>

LSM BPF prog may make kernel panic when returning an unexpected value,
such as returning positive value on hook file_alloc_security.

To fix it, series [1] refactored LSM hook return values and added
BPF return value check on top of that. Since the refactoring of LSM
hooks and checking BPF prog return value patches is not closely related,
this series separates BPF-related patches from [1].

v2:
- Update Shung-Hsi's patch with [3]

v1: https://lore.kernel.org/bpf/20240719081749.769748-1-xukuohai@huaweicloud.com/

Changes to [1]:

1. Extend LSM disabled list to include hooks refactored in [1] to avoid
dependency on the hooks return value refactoring patches.

2. Replace the special case patch for bitwise AND on [-1, 0] with Shung-Hsi's
general bitwise AND improvement patch [2].

3. Remove unused patches.

[1] https://lore.kernel.org/bpf/20240711111908.3817636-1-xukuohai@huaweicloud.com
https://lore.kernel.org/bpf/20240711113828.3818398-1-xukuohai@huaweicloud.com

[2] https://lore.kernel.org/bpf/ykuhustu7vt2ilwhl32kj655xfdgdlm2xkl5rff6tw2ycksovp@ss2n4gpjysnw

[3] https://lore.kernel.org/bpf/20240719081702.137173-1-shung-hsi.yu@suse.com/

Shung-Hsi Yu (1):
bpf, verifier: improve signed ranges inference for BPF_AND
====================

Link: https://lore.kernel.org/r/20240719110059.797546-1-xukuohai@huaweicloud.com
Signed-off-by: Alexei Starovoitov <ast@kernel.org>
Signed-off-by: Andrii Nakryiko <andrii@kernel.org>

authored by

Alexei Starovoitov and committed by
Andrii Nakryiko
02d9fe1c e2854bc3

+427 -27
+2
include/linux/bpf.h
··· 294 294 * same prog type, JITed flag and xdp_has_frags flag. 295 295 */ 296 296 struct { 297 + const struct btf_type *attach_func_proto; 297 298 spinlock_t lock; 298 299 enum bpf_prog_type type; 299 300 bool jited; ··· 928 927 }; 929 928 }; 930 929 struct bpf_verifier_log *log; /* for verbose logs */ 930 + bool is_retval; /* is accessing function return value ? */ 931 931 }; 932 932 933 933 static inline void
+8
include/linux/bpf_lsm.h
··· 9 9 10 10 #include <linux/sched.h> 11 11 #include <linux/bpf.h> 12 + #include <linux/bpf_verifier.h> 12 13 #include <linux/lsm_hooks.h> 13 14 14 15 #ifdef CONFIG_BPF_LSM ··· 46 45 47 46 void bpf_lsm_find_cgroup_shim(const struct bpf_prog *prog, bpf_func_t *bpf_func); 48 47 48 + int bpf_lsm_get_retval_range(const struct bpf_prog *prog, 49 + struct bpf_retval_range *range); 49 50 #else /* !CONFIG_BPF_LSM */ 50 51 51 52 static inline bool bpf_lsm_is_sleepable_hook(u32 btf_id) ··· 81 78 { 82 79 } 83 80 81 + static inline int bpf_lsm_get_retval_range(const struct bpf_prog *prog, 82 + struct bpf_retval_range *range) 83 + { 84 + return -EOPNOTSUPP; 85 + } 84 86 #endif /* CONFIG_BPF_LSM */ 85 87 86 88 #endif /* _LINUX_BPF_LSM_H */
+62 -3
kernel/bpf/bpf_lsm.c
··· 11 11 #include <linux/lsm_hooks.h> 12 12 #include <linux/bpf_lsm.h> 13 13 #include <linux/kallsyms.h> 14 - #include <linux/bpf_verifier.h> 15 14 #include <net/bpf_sk_storage.h> 16 15 #include <linux/bpf_local_storage.h> 17 16 #include <linux/btf_ids.h> ··· 34 35 #include <linux/lsm_hook_defs.h> 35 36 #undef LSM_HOOK 36 37 BTF_SET_END(bpf_lsm_hooks) 38 + 39 + BTF_SET_START(bpf_lsm_disabled_hooks) 40 + BTF_ID(func, bpf_lsm_vm_enough_memory) 41 + BTF_ID(func, bpf_lsm_inode_need_killpriv) 42 + BTF_ID(func, bpf_lsm_inode_getsecurity) 43 + BTF_ID(func, bpf_lsm_inode_listsecurity) 44 + BTF_ID(func, bpf_lsm_inode_copy_up_xattr) 45 + BTF_ID(func, bpf_lsm_getselfattr) 46 + BTF_ID(func, bpf_lsm_getprocattr) 47 + BTF_ID(func, bpf_lsm_setprocattr) 48 + #ifdef CONFIG_KEYS 49 + BTF_ID(func, bpf_lsm_key_getsecurity) 50 + #endif 51 + #ifdef CONFIG_AUDIT 52 + BTF_ID(func, bpf_lsm_audit_rule_match) 53 + #endif 54 + BTF_ID(func, bpf_lsm_ismaclabel) 55 + BTF_SET_END(bpf_lsm_disabled_hooks) 37 56 38 57 /* List of LSM hooks that should operate on 'current' cgroup regardless 39 58 * of function signature. ··· 114 97 int bpf_lsm_verify_prog(struct bpf_verifier_log *vlog, 115 98 const struct bpf_prog *prog) 116 99 { 100 + u32 btf_id = prog->aux->attach_btf_id; 101 + const char *func_name = prog->aux->attach_func_name; 102 + 117 103 if (!prog->gpl_compatible) { 118 104 bpf_log(vlog, 119 105 "LSM programs must have a GPL compatible license\n"); 120 106 return -EINVAL; 121 107 } 122 108 123 - if (!btf_id_set_contains(&bpf_lsm_hooks, prog->aux->attach_btf_id)) { 109 + if (btf_id_set_contains(&bpf_lsm_disabled_hooks, btf_id)) { 110 + bpf_log(vlog, "attach_btf_id %u points to disabled hook %s\n", 111 + btf_id, func_name); 112 + return -EINVAL; 113 + } 114 + 115 + if (!btf_id_set_contains(&bpf_lsm_hooks, btf_id)) { 124 116 bpf_log(vlog, "attach_btf_id %u points to wrong type name %s\n", 125 - prog->aux->attach_btf_id, prog->aux->attach_func_name); 117 + btf_id, func_name); 126 118 return -EINVAL; 127 119 } 128 120 ··· 416 390 .get_func_proto = bpf_lsm_func_proto, 417 391 .is_valid_access = btf_ctx_access, 418 392 }; 393 + 394 + /* hooks return 0 or 1 */ 395 + BTF_SET_START(bool_lsm_hooks) 396 + #ifdef CONFIG_SECURITY_NETWORK_XFRM 397 + BTF_ID(func, bpf_lsm_xfrm_state_pol_flow_match) 398 + #endif 399 + #ifdef CONFIG_AUDIT 400 + BTF_ID(func, bpf_lsm_audit_rule_known) 401 + #endif 402 + BTF_ID(func, bpf_lsm_inode_xattr_skipcap) 403 + BTF_SET_END(bool_lsm_hooks) 404 + 405 + int bpf_lsm_get_retval_range(const struct bpf_prog *prog, 406 + struct bpf_retval_range *retval_range) 407 + { 408 + /* no return value range for void hooks */ 409 + if (!prog->aux->attach_func_proto->type) 410 + return -EINVAL; 411 + 412 + if (btf_id_set_contains(&bool_lsm_hooks, prog->aux->attach_btf_id)) { 413 + retval_range->minval = 0; 414 + retval_range->maxval = 1; 415 + } else { 416 + /* All other available LSM hooks, except task_prctl, return 0 417 + * on success and negative error code on failure. 418 + * To keep things simple, we only allow bpf progs to return 0 419 + * or negative errno for task_prctl too. 420 + */ 421 + retval_range->minval = -MAX_ERRNO; 422 + retval_range->maxval = 0; 423 + } 424 + return 0; 425 + }
+4 -1
kernel/bpf/btf.c
··· 6416 6416 6417 6417 if (arg == nr_args) { 6418 6418 switch (prog->expected_attach_type) { 6419 - case BPF_LSM_CGROUP: 6420 6419 case BPF_LSM_MAC: 6420 + /* mark we are accessing the return value */ 6421 + info->is_retval = true; 6422 + fallthrough; 6423 + case BPF_LSM_CGROUP: 6421 6424 case BPF_TRACE_FEXIT: 6422 6425 /* When LSM programs are attached to void LSM hooks 6423 6426 * they use FEXIT trampolines and when attached to
+18 -3
kernel/bpf/core.c
··· 2302 2302 { 2303 2303 enum bpf_prog_type prog_type = resolve_prog_type(fp); 2304 2304 bool ret; 2305 + struct bpf_prog_aux *aux = fp->aux; 2305 2306 2306 2307 if (fp->kprobe_override) 2307 2308 return false; ··· 2312 2311 * in the case of devmap and cpumap). Until device checks 2313 2312 * are implemented, prohibit adding dev-bound programs to program maps. 2314 2313 */ 2315 - if (bpf_prog_is_dev_bound(fp->aux)) 2314 + if (bpf_prog_is_dev_bound(aux)) 2316 2315 return false; 2317 2316 2318 2317 spin_lock(&map->owner.lock); ··· 2322 2321 */ 2323 2322 map->owner.type = prog_type; 2324 2323 map->owner.jited = fp->jited; 2325 - map->owner.xdp_has_frags = fp->aux->xdp_has_frags; 2324 + map->owner.xdp_has_frags = aux->xdp_has_frags; 2325 + map->owner.attach_func_proto = aux->attach_func_proto; 2326 2326 ret = true; 2327 2327 } else { 2328 2328 ret = map->owner.type == prog_type && 2329 2329 map->owner.jited == fp->jited && 2330 - map->owner.xdp_has_frags == fp->aux->xdp_has_frags; 2330 + map->owner.xdp_has_frags == aux->xdp_has_frags; 2331 + if (ret && 2332 + map->owner.attach_func_proto != aux->attach_func_proto) { 2333 + switch (prog_type) { 2334 + case BPF_PROG_TYPE_TRACING: 2335 + case BPF_PROG_TYPE_LSM: 2336 + case BPF_PROG_TYPE_EXT: 2337 + case BPF_PROG_TYPE_STRUCT_OPS: 2338 + ret = false; 2339 + break; 2340 + default: 2341 + break; 2342 + } 2343 + } 2331 2344 } 2332 2345 spin_unlock(&map->owner.lock); 2333 2346
+62 -14
kernel/bpf/verifier.c
··· 2334 2334 __mark_reg_unknown(env, regs + regno); 2335 2335 } 2336 2336 2337 + static int __mark_reg_s32_range(struct bpf_verifier_env *env, 2338 + struct bpf_reg_state *regs, 2339 + u32 regno, 2340 + s32 s32_min, 2341 + s32 s32_max) 2342 + { 2343 + struct bpf_reg_state *reg = regs + regno; 2344 + 2345 + reg->s32_min_value = max_t(s32, reg->s32_min_value, s32_min); 2346 + reg->s32_max_value = min_t(s32, reg->s32_max_value, s32_max); 2347 + 2348 + reg->smin_value = max_t(s64, reg->smin_value, s32_min); 2349 + reg->smax_value = min_t(s64, reg->smax_value, s32_max); 2350 + 2351 + reg_bounds_sync(reg); 2352 + 2353 + return reg_bounds_sanity_check(env, reg, "s32_range"); 2354 + } 2355 + 2337 2356 static void __mark_reg_not_init(const struct bpf_verifier_env *env, 2338 2357 struct bpf_reg_state *reg) 2339 2358 { ··· 5626 5607 /* check access to 'struct bpf_context' fields. Supports fixed offsets only */ 5627 5608 static int check_ctx_access(struct bpf_verifier_env *env, int insn_idx, int off, int size, 5628 5609 enum bpf_access_type t, enum bpf_reg_type *reg_type, 5629 - struct btf **btf, u32 *btf_id) 5610 + struct btf **btf, u32 *btf_id, bool *is_retval) 5630 5611 { 5631 5612 struct bpf_insn_access_aux info = { 5632 5613 .reg_type = *reg_type, 5633 5614 .log = &env->log, 5615 + .is_retval = false, 5634 5616 }; 5635 5617 5636 5618 if (env->ops->is_valid_access && ··· 5644 5624 * type of narrower access. 5645 5625 */ 5646 5626 *reg_type = info.reg_type; 5627 + *is_retval = info.is_retval; 5647 5628 5648 5629 if (base_type(*reg_type) == PTR_TO_BTF_ID) { 5649 5630 *btf = info.btf; ··· 6813 6792 return grow_stack_state(env, state, -min_off /* size */); 6814 6793 } 6815 6794 6795 + static bool get_func_retval_range(struct bpf_prog *prog, 6796 + struct bpf_retval_range *range) 6797 + { 6798 + if (prog->type == BPF_PROG_TYPE_LSM && 6799 + prog->expected_attach_type == BPF_LSM_MAC && 6800 + !bpf_lsm_get_retval_range(prog, range)) { 6801 + return true; 6802 + } 6803 + return false; 6804 + } 6805 + 6816 6806 /* check whether memory at (regno + off) is accessible for t = (read | write) 6817 6807 * if t==write, value_regno is a register which value is stored into memory 6818 6808 * if t==read, value_regno is a register which will receive the value from memory ··· 6928 6896 if (!err && value_regno >= 0 && (t == BPF_READ || rdonly_mem)) 6929 6897 mark_reg_unknown(env, regs, value_regno); 6930 6898 } else if (reg->type == PTR_TO_CTX) { 6899 + bool is_retval = false; 6900 + struct bpf_retval_range range; 6931 6901 enum bpf_reg_type reg_type = SCALAR_VALUE; 6932 6902 struct btf *btf = NULL; 6933 6903 u32 btf_id = 0; ··· 6945 6911 return err; 6946 6912 6947 6913 err = check_ctx_access(env, insn_idx, off, size, t, &reg_type, &btf, 6948 - &btf_id); 6914 + &btf_id, &is_retval); 6949 6915 if (err) 6950 6916 verbose_linfo(env, insn_idx, "; "); 6951 6917 if (!err && t == BPF_READ && value_regno >= 0) { ··· 6954 6920 * case, we know the offset is zero. 6955 6921 */ 6956 6922 if (reg_type == SCALAR_VALUE) { 6957 - mark_reg_unknown(env, regs, value_regno); 6923 + if (is_retval && get_func_retval_range(env->prog, &range)) { 6924 + err = __mark_reg_s32_range(env, regs, value_regno, 6925 + range.minval, range.maxval); 6926 + if (err) 6927 + return err; 6928 + } else { 6929 + mark_reg_unknown(env, regs, value_regno); 6930 + } 6958 6931 } else { 6959 6932 mark_reg_known_zero(env, regs, 6960 6933 value_regno); ··· 9984 9943 return is_rbtree_lock_required_kfunc(kfunc_btf_id); 9985 9944 } 9986 9945 9987 - static bool retval_range_within(struct bpf_retval_range range, const struct bpf_reg_state *reg) 9946 + static bool retval_range_within(struct bpf_retval_range range, const struct bpf_reg_state *reg, 9947 + bool return_32bit) 9988 9948 { 9989 - return range.minval <= reg->smin_value && reg->smax_value <= range.maxval; 9949 + if (return_32bit) 9950 + return range.minval <= reg->s32_min_value && reg->s32_max_value <= range.maxval; 9951 + else 9952 + return range.minval <= reg->smin_value && reg->smax_value <= range.maxval; 9990 9953 } 9991 9954 9992 9955 static int prepare_func_exit(struct bpf_verifier_env *env, int *insn_idx) ··· 10027 9982 if (err) 10028 9983 return err; 10029 9984 10030 - /* enforce R0 return value range */ 10031 - if (!retval_range_within(callee->callback_ret_range, r0)) { 9985 + /* enforce R0 return value range, and bpf_callback_t returns 64bit */ 9986 + if (!retval_range_within(callee->callback_ret_range, r0, false)) { 10032 9987 verbose_invalid_scalar(env, r0, callee->callback_ret_range, 10033 9988 "At callback return", "R0"); 10034 9989 return -EINVAL; ··· 15702 15657 int err; 15703 15658 struct bpf_func_state *frame = env->cur_state->frame[0]; 15704 15659 const bool is_subprog = frame->subprogno; 15660 + bool return_32bit = false; 15705 15661 15706 15662 /* LSM and struct_ops func-ptr's return type could be "void" */ 15707 15663 if (!is_subprog || frame->in_exception_callback_fn) { ··· 15808 15762 15809 15763 case BPF_PROG_TYPE_LSM: 15810 15764 if (env->prog->expected_attach_type != BPF_LSM_CGROUP) { 15811 - /* Regular BPF_PROG_TYPE_LSM programs can return 15812 - * any value. 15813 - */ 15814 - return 0; 15815 - } 15816 - if (!env->prog->aux->attach_func_proto->type) { 15765 + /* no range found, any return value is allowed */ 15766 + if (!get_func_retval_range(env->prog, &range)) 15767 + return 0; 15768 + /* no restricted range, any return value is allowed */ 15769 + if (range.minval == S32_MIN && range.maxval == S32_MAX) 15770 + return 0; 15771 + return_32bit = true; 15772 + } else if (!env->prog->aux->attach_func_proto->type) { 15817 15773 /* Make sure programs that attach to void 15818 15774 * hooks don't try to modify return value. 15819 15775 */ ··· 15845 15797 if (err) 15846 15798 return err; 15847 15799 15848 - if (!retval_range_within(range, reg)) { 15800 + if (!retval_range_within(range, reg, return_32bit)) { 15849 15801 verbose_invalid_scalar(env, reg, range, exit_ctx, reg_name); 15850 15802 if (!is_subprog && 15851 15803 prog->expected_attach_type == BPF_LSM_CGROUP &&
+45 -1
tools/testing/selftests/bpf/prog_tests/test_lsm.c
··· 12 12 #include <stdlib.h> 13 13 14 14 #include "lsm.skel.h" 15 + #include "lsm_tailcall.skel.h" 15 16 16 17 char *CMD_ARGS[] = {"true", NULL}; 17 18 ··· 96 95 return 0; 97 96 } 98 97 99 - void test_test_lsm(void) 98 + static void test_lsm_basic(void) 100 99 { 101 100 struct lsm *skel = NULL; 102 101 int err; ··· 114 113 115 114 close_prog: 116 115 lsm__destroy(skel); 116 + } 117 + 118 + static void test_lsm_tailcall(void) 119 + { 120 + struct lsm_tailcall *skel = NULL; 121 + int map_fd, prog_fd; 122 + int err, key; 123 + 124 + skel = lsm_tailcall__open_and_load(); 125 + if (!ASSERT_OK_PTR(skel, "lsm_tailcall__skel_load")) 126 + goto close_prog; 127 + 128 + map_fd = bpf_map__fd(skel->maps.jmp_table); 129 + if (CHECK_FAIL(map_fd < 0)) 130 + goto close_prog; 131 + 132 + prog_fd = bpf_program__fd(skel->progs.lsm_file_permission_prog); 133 + if (CHECK_FAIL(prog_fd < 0)) 134 + goto close_prog; 135 + 136 + key = 0; 137 + err = bpf_map_update_elem(map_fd, &key, &prog_fd, BPF_ANY); 138 + if (CHECK_FAIL(!err)) 139 + goto close_prog; 140 + 141 + prog_fd = bpf_program__fd(skel->progs.lsm_file_alloc_security_prog); 142 + if (CHECK_FAIL(prog_fd < 0)) 143 + goto close_prog; 144 + 145 + err = bpf_map_update_elem(map_fd, &key, &prog_fd, BPF_ANY); 146 + if (CHECK_FAIL(err)) 147 + goto close_prog; 148 + 149 + close_prog: 150 + lsm_tailcall__destroy(skel); 151 + } 152 + 153 + void test_test_lsm(void) 154 + { 155 + if (test__start_subtest("lsm_basic")) 156 + test_lsm_basic(); 157 + if (test__start_subtest("lsm_tailcall")) 158 + test_lsm_tailcall(); 117 159 }
+2
tools/testing/selftests/bpf/prog_tests/verifier.c
··· 88 88 #include "verifier_xdp.skel.h" 89 89 #include "verifier_xdp_direct_packet_access.skel.h" 90 90 #include "verifier_bits_iter.skel.h" 91 + #include "verifier_lsm.skel.h" 91 92 92 93 #define MAX_ENTRIES 11 93 94 ··· 207 206 void test_verifier_xdp(void) { RUN(verifier_xdp); } 208 207 void test_verifier_xdp_direct_packet_access(void) { RUN(verifier_xdp_direct_packet_access); } 209 208 void test_verifier_bits_iter(void) { RUN(verifier_bits_iter); } 209 + void test_verifier_lsm(void) { RUN(verifier_lsm); } 210 210 211 211 static int init_test_val_map(struct bpf_object *obj, char *map_name) 212 212 {
+10
tools/testing/selftests/bpf/progs/err.h
··· 5 5 #define MAX_ERRNO 4095 6 6 #define IS_ERR_VALUE(x) (unsigned long)(void *)(x) >= (unsigned long)-MAX_ERRNO 7 7 8 + #define __STR(x) #x 9 + 10 + #define set_if_not_errno_or_zero(x, y) \ 11 + ({ \ 12 + asm volatile ("if %0 s< -4095 goto +1\n" \ 13 + "if %0 s<= 0 goto +1\n" \ 14 + "%0 = " __STR(y) "\n" \ 15 + : "+r"(x)); \ 16 + }) 17 + 8 18 static inline int IS_ERR_OR_NULL(const void *ptr) 9 19 { 10 20 return !ptr || IS_ERR_VALUE((unsigned long)ptr);
+34
tools/testing/selftests/bpf/progs/lsm_tailcall.c
··· 1 + // SPDX-License-Identifier: GPL-2.0 2 + /* Copyright (c) 2024 Huawei Technologies Co., Ltd */ 3 + 4 + #include "vmlinux.h" 5 + #include <errno.h> 6 + #include <bpf/bpf_helpers.h> 7 + 8 + char _license[] SEC("license") = "GPL"; 9 + 10 + struct { 11 + __uint(type, BPF_MAP_TYPE_PROG_ARRAY); 12 + __uint(max_entries, 1); 13 + __uint(key_size, sizeof(__u32)); 14 + __uint(value_size, sizeof(__u32)); 15 + } jmp_table SEC(".maps"); 16 + 17 + SEC("lsm/file_permission") 18 + int lsm_file_permission_prog(void *ctx) 19 + { 20 + return 0; 21 + } 22 + 23 + SEC("lsm/file_alloc_security") 24 + int lsm_file_alloc_security_prog(void *ctx) 25 + { 26 + return 0; 27 + } 28 + 29 + SEC("lsm/file_alloc_security") 30 + int lsm_file_alloc_security_entry(void *ctx) 31 + { 32 + bpf_tail_call_static(ctx, &jmp_table, 0); 33 + return 0; 34 + }
+4
tools/testing/selftests/bpf/progs/test_sig_in_xattr.c
··· 6 6 #include <bpf/bpf_helpers.h> 7 7 #include <bpf/bpf_tracing.h> 8 8 #include "bpf_kfuncs.h" 9 + #include "err.h" 9 10 10 11 char _license[] SEC("license") = "GPL"; 11 12 ··· 80 79 ret = bpf_verify_pkcs7_signature(&digest_ptr, &sig_ptr, trusted_keyring); 81 80 82 81 bpf_key_put(trusted_keyring); 82 + 83 + set_if_not_errno_or_zero(ret, -EFAULT); 84 + 83 85 return ret; 84 86 }
+6 -2
tools/testing/selftests/bpf/progs/test_verify_pkcs7_sig.c
··· 11 11 #include <bpf/bpf_helpers.h> 12 12 #include <bpf/bpf_tracing.h> 13 13 #include "bpf_kfuncs.h" 14 + #include "err.h" 14 15 15 16 #define MAX_DATA_SIZE (1024 * 1024) 16 17 #define MAX_SIG_SIZE 1024 ··· 56 55 57 56 ret = bpf_probe_read_kernel(&value, sizeof(value), &attr->value); 58 57 if (ret) 59 - return ret; 58 + goto out; 60 59 61 60 ret = bpf_copy_from_user(data_val, sizeof(struct data), 62 61 (void *)(unsigned long)value); 63 62 if (ret) 64 - return ret; 63 + goto out; 65 64 66 65 if (data_val->data_len > sizeof(data_val->data)) 67 66 return -EINVAL; ··· 84 83 ret = bpf_verify_pkcs7_signature(&data_ptr, &sig_ptr, trusted_keyring); 85 84 86 85 bpf_key_put(trusted_keyring); 86 + 87 + out: 88 + set_if_not_errno_or_zero(ret, -EFAULT); 87 89 88 90 return ret; 89 91 }
+2 -2
tools/testing/selftests/bpf/progs/token_lsm.c
··· 8 8 char _license[] SEC("license") = "GPL"; 9 9 10 10 int my_pid; 11 - bool reject_capable; 12 - bool reject_cmd; 11 + int reject_capable; 12 + int reject_cmd; 13 13 14 14 SEC("lsm/bpf_token_capable") 15 15 int BPF_PROG(token_capable, struct bpf_token *token, int cap)
+6 -1
tools/testing/selftests/bpf/progs/verifier_global_subprogs.c
··· 7 7 #include "bpf_misc.h" 8 8 #include "xdp_metadata.h" 9 9 #include "bpf_kfuncs.h" 10 + #include "err.h" 10 11 11 12 /* The compiler may be able to detect the access to uninitialized 12 13 memory in the routines performing out of bound memory accesses and ··· 332 331 __success __log_level(2) 333 332 int BPF_PROG(arg_tag_ctx_lsm) 334 333 { 335 - return tracing_subprog_void(ctx) + tracing_subprog_u64(ctx); 334 + int ret; 335 + 336 + ret = tracing_subprog_void(ctx) + tracing_subprog_u64(ctx); 337 + set_if_not_errno_or_zero(ret, -1); 338 + return ret; 336 339 } 337 340 338 341 SEC("?struct_ops/test_1")
+162
tools/testing/selftests/bpf/progs/verifier_lsm.c
··· 1 + // SPDX-License-Identifier: GPL-2.0 2 + 3 + #include <linux/bpf.h> 4 + #include <bpf/bpf_helpers.h> 5 + #include "bpf_misc.h" 6 + 7 + SEC("lsm/file_alloc_security") 8 + __description("lsm bpf prog with -4095~0 retval. test 1") 9 + __success 10 + __naked int errno_zero_retval_test1(void *ctx) 11 + { 12 + asm volatile ( 13 + "r0 = 0;" 14 + "exit;" 15 + ::: __clobber_all); 16 + } 17 + 18 + SEC("lsm/file_alloc_security") 19 + __description("lsm bpf prog with -4095~0 retval. test 2") 20 + __success 21 + __naked int errno_zero_retval_test2(void *ctx) 22 + { 23 + asm volatile ( 24 + "r0 = -4095;" 25 + "exit;" 26 + ::: __clobber_all); 27 + } 28 + 29 + SEC("lsm/file_mprotect") 30 + __description("lsm bpf prog with -4095~0 retval. test 4") 31 + __failure __msg("R0 has smin=-4096 smax=-4096 should have been in [-4095, 0]") 32 + __naked int errno_zero_retval_test4(void *ctx) 33 + { 34 + asm volatile ( 35 + "r0 = -4096;" 36 + "exit;" 37 + ::: __clobber_all); 38 + } 39 + 40 + SEC("lsm/file_mprotect") 41 + __description("lsm bpf prog with -4095~0 retval. test 5") 42 + __failure __msg("R0 has smin=4096 smax=4096 should have been in [-4095, 0]") 43 + __naked int errno_zero_retval_test5(void *ctx) 44 + { 45 + asm volatile ( 46 + "r0 = 4096;" 47 + "exit;" 48 + ::: __clobber_all); 49 + } 50 + 51 + SEC("lsm/file_mprotect") 52 + __description("lsm bpf prog with -4095~0 retval. test 6") 53 + __failure __msg("R0 has smin=1 smax=1 should have been in [-4095, 0]") 54 + __naked int errno_zero_retval_test6(void *ctx) 55 + { 56 + asm volatile ( 57 + "r0 = 1;" 58 + "exit;" 59 + ::: __clobber_all); 60 + } 61 + 62 + SEC("lsm/audit_rule_known") 63 + __description("lsm bpf prog with bool retval. test 1") 64 + __success 65 + __naked int bool_retval_test1(void *ctx) 66 + { 67 + asm volatile ( 68 + "r0 = 1;" 69 + "exit;" 70 + ::: __clobber_all); 71 + } 72 + 73 + SEC("lsm/audit_rule_known") 74 + __description("lsm bpf prog with bool retval. test 2") 75 + __success 76 + __success 77 + __naked int bool_retval_test2(void *ctx) 78 + { 79 + asm volatile ( 80 + "r0 = 0;" 81 + "exit;" 82 + ::: __clobber_all); 83 + } 84 + 85 + SEC("lsm/audit_rule_known") 86 + __description("lsm bpf prog with bool retval. test 3") 87 + __failure __msg("R0 has smin=-1 smax=-1 should have been in [0, 1]") 88 + __naked int bool_retval_test3(void *ctx) 89 + { 90 + asm volatile ( 91 + "r0 = -1;" 92 + "exit;" 93 + ::: __clobber_all); 94 + } 95 + 96 + SEC("lsm/audit_rule_known") 97 + __description("lsm bpf prog with bool retval. test 4") 98 + __failure __msg("R0 has smin=2 smax=2 should have been in [0, 1]") 99 + __naked int bool_retval_test4(void *ctx) 100 + { 101 + asm volatile ( 102 + "r0 = 2;" 103 + "exit;" 104 + ::: __clobber_all); 105 + } 106 + 107 + SEC("lsm/file_free_security") 108 + __success 109 + __description("lsm bpf prog with void retval. test 1") 110 + __naked int void_retval_test1(void *ctx) 111 + { 112 + asm volatile ( 113 + "r0 = -4096;" 114 + "exit;" 115 + ::: __clobber_all); 116 + } 117 + 118 + SEC("lsm/file_free_security") 119 + __success 120 + __description("lsm bpf prog with void retval. test 2") 121 + __naked int void_retval_test2(void *ctx) 122 + { 123 + asm volatile ( 124 + "r0 = 4096;" 125 + "exit;" 126 + ::: __clobber_all); 127 + } 128 + 129 + SEC("lsm/getprocattr") 130 + __description("lsm disabled hook: getprocattr") 131 + __failure __msg("points to disabled hook") 132 + __naked int disabled_hook_test1(void *ctx) 133 + { 134 + asm volatile ( 135 + "r0 = 0;" 136 + "exit;" 137 + ::: __clobber_all); 138 + } 139 + 140 + SEC("lsm/setprocattr") 141 + __description("lsm disabled hook: setprocattr") 142 + __failure __msg("points to disabled hook") 143 + __naked int disabled_hook_test2(void *ctx) 144 + { 145 + asm volatile ( 146 + "r0 = 0;" 147 + "exit;" 148 + ::: __clobber_all); 149 + } 150 + 151 + SEC("lsm/ismaclabel") 152 + __description("lsm disabled hook: ismaclabel") 153 + __failure __msg("points to disabled hook") 154 + __naked int disabled_hook_test3(void *ctx) 155 + { 156 + asm volatile ( 157 + "r0 = 0;" 158 + "exit;" 159 + ::: __clobber_all); 160 + } 161 + 162 + char _license[] SEC("license") = "GPL";