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 'handle-possible-null-trusted-raw_tp-arguments'

Kumar Kartikeya Dwivedi says:

====================
Handle possible NULL trusted raw_tp arguments

More context is available in [0], but the TLDR; is that the verifier
incorrectly assumes that any raw tracepoint argument will always be
non-NULL. This means that even when users correctly check possible NULL
arguments, the verifier can remove the NULL check due to incorrect
knowledge of the NULL-ness of the pointer. Secondly, kernel helpers or
kfuncs taking these trusted tracepoint arguments incorrectly assume that
all arguments will always be valid non-NULL.

In this set, we mark raw_tp arguments as PTR_MAYBE_NULL on top of
PTR_TRUSTED, but special case their behavior when dereferencing them or
pointer arithmetic over them is involved. When passing trusted args to
helpers or kfuncs, raw_tp programs are permitted to pass possibly NULL
pointers in such cases.

Any loads into such maybe NULL trusted PTR_TO_BTF_ID is promoted to a
PROBE_MEM load to handle emanating page faults. The verifier will ensure
NULL checks on such pointers are preserved and do not lead to dead code
elimination.

This new behavior is not applied when ref_obj_id is non-zero, as those
pointers do not belong to raw_tp arguments, but instead acquired
objects.

Since helpers and kfuncs already require attention for PTR_TO_BTF_ID
(non-trusted) pointers, we do not implement any protection for such
cases in this patch set, and leave it as future work for an upcoming
series.

A selftest is included with this patch set to verify the new behavior,
and it crashes the kernel without the first patch.

[0]: https://lore.kernel.org/bpf/CAADnVQLMPPavJQR6JFsi3dtaaLHB816JN4HCV_TFWohJ61D+wQ@mail.gmail.com

Changelog:
----------
v2 -> v3
v2: https://lore.kernel.org/bpf/20241103184144.3765700-1-memxor@gmail.com

* Fix lenient check around check_ptr_to_btf_access allowing any
PTR_TO_BTF_ID with PTR_MAYBE_NULL to be deref'd.
* Add Juri and Jiri's Tested-by, Reviewed-by resp.

v1 -> v2
v1: https://lore.kernel.org/bpf/20241101000017.3424165-1-memxor@gmail.com

* Add patch to clean up users of gettid (Andrii)
* Avoid nested blocks in sefltest (Andrii)
* Prevent code motion optimization in selftest using barrier()
====================

Link: https://lore.kernel.org/r/20241104171959.2938862-1-memxor@gmail.com
Signed-off-by: Alexei Starovoitov <ast@kernel.org>

+187 -31
+6
include/linux/bpf.h
··· 3495 3495 return prog->aux->func_idx != 0; 3496 3496 } 3497 3497 3498 + static inline bool bpf_prog_is_raw_tp(const struct bpf_prog *prog) 3499 + { 3500 + return prog->type == BPF_PROG_TYPE_TRACING && 3501 + prog->expected_attach_type == BPF_TRACE_RAW_TP; 3502 + } 3503 + 3498 3504 #endif /* _LINUX_BPF_H */
+4 -1
kernel/bpf/btf.c
··· 6588 6588 if (prog_args_trusted(prog)) 6589 6589 info->reg_type |= PTR_TRUSTED; 6590 6590 6591 - if (btf_param_match_suffix(btf, &args[arg], "__nullable")) 6591 + /* Raw tracepoint arguments always get marked as maybe NULL */ 6592 + if (bpf_prog_is_raw_tp(prog)) 6593 + info->reg_type |= PTR_MAYBE_NULL; 6594 + else if (btf_param_match_suffix(btf, &args[arg], "__nullable")) 6592 6595 info->reg_type |= PTR_MAYBE_NULL; 6593 6596 6594 6597 if (tgt_prog) {
+72 -7
kernel/bpf/verifier.c
··· 418 418 return rec; 419 419 } 420 420 421 + static bool mask_raw_tp_reg_cond(const struct bpf_verifier_env *env, struct bpf_reg_state *reg) { 422 + return reg->type == (PTR_TO_BTF_ID | PTR_TRUSTED | PTR_MAYBE_NULL) && 423 + bpf_prog_is_raw_tp(env->prog) && !reg->ref_obj_id; 424 + } 425 + 426 + static bool mask_raw_tp_reg(const struct bpf_verifier_env *env, struct bpf_reg_state *reg) 427 + { 428 + if (!mask_raw_tp_reg_cond(env, reg)) 429 + return false; 430 + reg->type &= ~PTR_MAYBE_NULL; 431 + return true; 432 + } 433 + 434 + static void unmask_raw_tp_reg(struct bpf_reg_state *reg, bool result) 435 + { 436 + if (result) 437 + reg->type |= PTR_MAYBE_NULL; 438 + } 439 + 421 440 static bool subprog_is_global(const struct bpf_verifier_env *env, int subprog) 422 441 { 423 442 struct bpf_func_info_aux *aux = env->prog->aux->func_info_aux; ··· 6641 6622 const char *field_name = NULL; 6642 6623 enum bpf_type_flag flag = 0; 6643 6624 u32 btf_id = 0; 6625 + bool mask; 6644 6626 int ret; 6645 6627 6646 6628 if (!env->allow_ptr_leaks) { ··· 6713 6693 6714 6694 if (ret < 0) 6715 6695 return ret; 6716 - 6696 + /* For raw_tp progs, we allow dereference of PTR_MAYBE_NULL 6697 + * trusted PTR_TO_BTF_ID, these are the ones that are possibly 6698 + * arguments to the raw_tp. Since internal checks in for trusted 6699 + * reg in check_ptr_to_btf_access would consider PTR_MAYBE_NULL 6700 + * modifier as problematic, mask it out temporarily for the 6701 + * check. Don't apply this to pointers with ref_obj_id > 0, as 6702 + * those won't be raw_tp args. 6703 + * 6704 + * We may end up applying this relaxation to other trusted 6705 + * PTR_TO_BTF_ID with maybe null flag, since we cannot 6706 + * distinguish PTR_MAYBE_NULL tagged for arguments vs normal 6707 + * tagging, but that should expand allowed behavior, and not 6708 + * cause regression for existing behavior. 6709 + */ 6710 + mask = mask_raw_tp_reg(env, reg); 6717 6711 if (ret != PTR_TO_BTF_ID) { 6718 6712 /* just mark; */ 6719 6713 ··· 6788 6754 clear_trusted_flags(&flag); 6789 6755 } 6790 6756 6791 - if (atype == BPF_READ && value_regno >= 0) 6757 + if (atype == BPF_READ && value_regno >= 0) { 6792 6758 mark_btf_ld_reg(env, regs, value_regno, ret, reg->btf, btf_id, flag); 6759 + /* We've assigned a new type to regno, so don't undo masking. */ 6760 + if (regno == value_regno) 6761 + mask = false; 6762 + } 6763 + unmask_raw_tp_reg(reg, mask); 6793 6764 6794 6765 return 0; 6795 6766 } ··· 7179 7140 if (!err && t == BPF_READ && value_regno >= 0) 7180 7141 mark_reg_unknown(env, regs, value_regno); 7181 7142 } else if (base_type(reg->type) == PTR_TO_BTF_ID && 7182 - !type_may_be_null(reg->type)) { 7143 + (mask_raw_tp_reg_cond(env, reg) || !type_may_be_null(reg->type))) { 7183 7144 err = check_ptr_to_btf_access(env, regs, regno, off, size, t, 7184 7145 value_regno); 7185 7146 } else if (reg->type == CONST_PTR_TO_MAP) { ··· 8872 8833 enum bpf_reg_type type = reg->type; 8873 8834 u32 *arg_btf_id = NULL; 8874 8835 int err = 0; 8836 + bool mask; 8875 8837 8876 8838 if (arg_type == ARG_DONTCARE) 8877 8839 return 0; ··· 8913 8873 base_type(arg_type) == ARG_PTR_TO_SPIN_LOCK) 8914 8874 arg_btf_id = fn->arg_btf_id[arg]; 8915 8875 8876 + mask = mask_raw_tp_reg(env, reg); 8916 8877 err = check_reg_type(env, regno, arg_type, arg_btf_id, meta); 8917 - if (err) 8918 - return err; 8919 8878 8920 - err = check_func_arg_reg_off(env, reg, regno, arg_type); 8879 + err = err ?: check_func_arg_reg_off(env, reg, regno, arg_type); 8880 + unmask_raw_tp_reg(reg, mask); 8921 8881 if (err) 8922 8882 return err; 8923 8883 ··· 9712 9672 return ret; 9713 9673 } else if (base_type(arg->arg_type) == ARG_PTR_TO_BTF_ID) { 9714 9674 struct bpf_call_arg_meta meta; 9675 + bool mask; 9715 9676 int err; 9716 9677 9717 9678 if (register_is_null(reg) && type_may_be_null(arg->arg_type)) 9718 9679 continue; 9719 9680 9720 9681 memset(&meta, 0, sizeof(meta)); /* leave func_id as zero */ 9682 + mask = mask_raw_tp_reg(env, reg); 9721 9683 err = check_reg_type(env, regno, arg->arg_type, &arg->btf_id, &meta); 9722 9684 err = err ?: check_func_arg_reg_off(env, reg, regno, arg->arg_type); 9685 + unmask_raw_tp_reg(reg, mask); 9723 9686 if (err) 9724 9687 return err; 9725 9688 } else { ··· 12050 12007 enum bpf_arg_type arg_type = ARG_DONTCARE; 12051 12008 u32 regno = i + 1, ref_id, type_size; 12052 12009 bool is_ret_buf_sz = false; 12010 + bool mask = false; 12053 12011 int kf_arg_type; 12054 12012 12055 12013 t = btf_type_skip_modifiers(btf, args[i].type, NULL); ··· 12109 12065 return -EINVAL; 12110 12066 } 12111 12067 12068 + mask = mask_raw_tp_reg(env, reg); 12112 12069 if ((is_kfunc_trusted_args(meta) || is_kfunc_rcu(meta)) && 12113 12070 (register_is_null(reg) || type_may_be_null(reg->type)) && 12114 12071 !is_kfunc_arg_nullable(meta->btf, &args[i])) { 12115 12072 verbose(env, "Possibly NULL pointer passed to trusted arg%d\n", i); 12073 + unmask_raw_tp_reg(reg, mask); 12116 12074 return -EACCES; 12117 12075 } 12076 + unmask_raw_tp_reg(reg, mask); 12118 12077 12119 12078 if (reg->ref_obj_id) { 12120 12079 if (is_kfunc_release(meta) && meta->ref_obj_id) { ··· 12175 12128 if (!is_kfunc_trusted_args(meta) && !is_kfunc_rcu(meta)) 12176 12129 break; 12177 12130 12131 + /* Allow passing maybe NULL raw_tp arguments to 12132 + * kfuncs for compatibility. Don't apply this to 12133 + * arguments with ref_obj_id > 0. 12134 + */ 12135 + mask = mask_raw_tp_reg(env, reg); 12178 12136 if (!is_trusted_reg(reg)) { 12179 12137 if (!is_kfunc_rcu(meta)) { 12180 12138 verbose(env, "R%d must be referenced or trusted\n", regno); 12139 + unmask_raw_tp_reg(reg, mask); 12181 12140 return -EINVAL; 12182 12141 } 12183 12142 if (!is_rcu_reg(reg)) { 12184 12143 verbose(env, "R%d must be a rcu pointer\n", regno); 12144 + unmask_raw_tp_reg(reg, mask); 12185 12145 return -EINVAL; 12186 12146 } 12187 12147 } 12148 + unmask_raw_tp_reg(reg, mask); 12188 12149 fallthrough; 12189 12150 case KF_ARG_PTR_TO_CTX: 12190 12151 case KF_ARG_PTR_TO_DYNPTR: ··· 12215 12160 12216 12161 if (is_kfunc_release(meta) && reg->ref_obj_id) 12217 12162 arg_type |= OBJ_RELEASE; 12163 + mask = mask_raw_tp_reg(env, reg); 12218 12164 ret = check_func_arg_reg_off(env, reg, regno, arg_type); 12165 + unmask_raw_tp_reg(reg, mask); 12219 12166 if (ret < 0) 12220 12167 return ret; 12221 12168 ··· 12394 12337 ref_tname = btf_name_by_offset(btf, ref_t->name_off); 12395 12338 fallthrough; 12396 12339 case KF_ARG_PTR_TO_BTF_ID: 12340 + mask = mask_raw_tp_reg(env, reg); 12397 12341 /* Only base_type is checked, further checks are done here */ 12398 12342 if ((base_type(reg->type) != PTR_TO_BTF_ID || 12399 12343 (bpf_type_has_unsafe_modifiers(reg->type) && !is_rcu_reg(reg))) && ··· 12403 12345 verbose(env, "expected %s or socket\n", 12404 12346 reg_type_str(env, base_type(reg->type) | 12405 12347 (type_flag(reg->type) & BPF_REG_TRUSTED_MODIFIERS))); 12348 + unmask_raw_tp_reg(reg, mask); 12406 12349 return -EINVAL; 12407 12350 } 12408 12351 ret = process_kf_arg_ptr_to_btf_id(env, reg, ref_t, ref_tname, ref_id, meta, i); 12352 + unmask_raw_tp_reg(reg, mask); 12409 12353 if (ret < 0) 12410 12354 return ret; 12411 12355 break; ··· 13380 13320 */ 13381 13321 static int adjust_ptr_min_max_vals(struct bpf_verifier_env *env, 13382 13322 struct bpf_insn *insn, 13383 - const struct bpf_reg_state *ptr_reg, 13323 + struct bpf_reg_state *ptr_reg, 13384 13324 const struct bpf_reg_state *off_reg) 13385 13325 { 13386 13326 struct bpf_verifier_state *vstate = env->cur_state; ··· 13394 13334 struct bpf_sanitize_info info = {}; 13395 13335 u8 opcode = BPF_OP(insn->code); 13396 13336 u32 dst = insn->dst_reg; 13337 + bool mask; 13397 13338 int ret; 13398 13339 13399 13340 dst_reg = &regs[dst]; ··· 13421 13360 return -EACCES; 13422 13361 } 13423 13362 13363 + mask = mask_raw_tp_reg(env, ptr_reg); 13424 13364 if (ptr_reg->type & PTR_MAYBE_NULL) { 13425 13365 verbose(env, "R%d pointer arithmetic on %s prohibited, null-check it first\n", 13426 13366 dst, reg_type_str(env, ptr_reg->type)); 13367 + unmask_raw_tp_reg(ptr_reg, mask); 13427 13368 return -EACCES; 13428 13369 } 13370 + unmask_raw_tp_reg(ptr_reg, mask); 13429 13371 13430 13372 switch (base_type(ptr_reg->type)) { 13431 13373 case PTR_TO_CTX: ··· 19930 19866 * for this case. 19931 19867 */ 19932 19868 case PTR_TO_BTF_ID | MEM_ALLOC | PTR_UNTRUSTED: 19869 + case PTR_TO_BTF_ID | PTR_TRUSTED | PTR_MAYBE_NULL: 19933 19870 if (type == BPF_READ) { 19934 19871 if (BPF_MODE(insn->code) == BPF_MEM) 19935 19872 insn->code = BPF_LDX | BPF_PROBE_MEM |
+2 -1
tools/testing/selftests/bpf/benchs/bench_trigger.c
··· 4 4 #include <argp.h> 5 5 #include <unistd.h> 6 6 #include <stdint.h> 7 + #include "bpf_util.h" 7 8 #include "bench.h" 8 9 #include "trigger_bench.skel.h" 9 10 #include "trace_helpers.h" ··· 73 72 unsigned slot; 74 73 75 74 if (unlikely(tid == 0)) 76 - tid = syscall(SYS_gettid); 75 + tid = sys_gettid(); 77 76 78 77 /* multiplicative hashing, it's fast */ 79 78 slot = 2654435769U * tid;
+8
tools/testing/selftests/bpf/bpf_testmod/bpf_testmod-events.h
··· 40 40 TP_ARGS(ctx__nullable) 41 41 ); 42 42 43 + struct sk_buff; 44 + 45 + DECLARE_TRACE(bpf_testmod_test_raw_tp_null, 46 + TP_PROTO(struct sk_buff *skb), 47 + TP_ARGS(skb) 48 + ); 49 + 50 + 43 51 #undef BPF_TESTMOD_DECLARE_TRACE 44 52 #ifdef DECLARE_TRACE_WRITABLE 45 53 #define BPF_TESTMOD_DECLARE_TRACE(call, proto, args, size) \
+2
tools/testing/selftests/bpf/bpf_testmod/bpf_testmod.c
··· 380 380 381 381 (void)bpf_testmod_test_arg_ptr_to_struct(&struct_arg1_2); 382 382 383 + (void)trace_bpf_testmod_test_raw_tp_null(NULL); 384 + 383 385 struct_arg3 = kmalloc((sizeof(struct bpf_testmod_struct_arg_3) + 384 386 sizeof(int)), GFP_KERNEL); 385 387 if (struct_arg3 != NULL) {
+9
tools/testing/selftests/bpf/bpf_util.h
··· 6 6 #include <stdlib.h> 7 7 #include <string.h> 8 8 #include <errno.h> 9 + #include <syscall.h> 9 10 #include <bpf/libbpf.h> /* libbpf_num_possible_cpus */ 10 11 11 12 static inline unsigned int bpf_num_possible_cpus(void) ··· 59 58 #define offsetofend(TYPE, MEMBER) \ 60 59 (offsetof(TYPE, MEMBER) + sizeof_field(TYPE, MEMBER)) 61 60 #endif 61 + 62 + /* Availability of gettid across glibc versions is hit-and-miss, therefore 63 + * fallback to syscall in this macro and use it everywhere. 64 + */ 65 + #ifndef sys_gettid 66 + #define sys_gettid() syscall(SYS_gettid) 67 + #endif 68 + 62 69 63 70 #endif /* __BPF_UTIL__ */
+2 -1
tools/testing/selftests/bpf/map_tests/task_storage_map.c
··· 12 12 #include <bpf/bpf.h> 13 13 #include <bpf/libbpf.h> 14 14 15 + #include "bpf_util.h" 15 16 #include "test_maps.h" 16 17 #include "task_local_storage_helpers.h" 17 18 #include "read_bpf_task_storage_busy.skel.h" ··· 116 115 CHECK(err, "attach", "error %d\n", err); 117 116 118 117 /* Trigger program */ 119 - syscall(SYS_gettid); 118 + sys_gettid(); 120 119 skel->bss->pid = 0; 121 120 122 121 CHECK(skel->bss->busy != 0, "bad bpf_task_storage_busy", "got %d\n", skel->bss->busy);
+1 -1
tools/testing/selftests/bpf/prog_tests/bpf_cookie.c
··· 690 690 if (!ASSERT_OK_PTR(skel, "skel_open")) 691 691 return; 692 692 693 - skel->bss->my_tid = syscall(SYS_gettid); 693 + skel->bss->my_tid = sys_gettid(); 694 694 695 695 if (test__start_subtest("kprobe")) 696 696 kprobe_subtest(skel);
+3 -3
tools/testing/selftests/bpf/prog_tests/bpf_iter.c
··· 226 226 ASSERT_OK(pthread_create(&thread_id, NULL, &do_nothing_wait, NULL), 227 227 "pthread_create"); 228 228 229 - skel->bss->tid = syscall(SYS_gettid); 229 + skel->bss->tid = sys_gettid(); 230 230 231 231 do_dummy_read_opts(skel->progs.dump_task, opts); 232 232 ··· 255 255 union bpf_iter_link_info linfo; 256 256 int num_unknown_tid, num_known_tid; 257 257 258 - ASSERT_NEQ(getpid(), syscall(SYS_gettid), "check_new_thread_id"); 258 + ASSERT_NEQ(getpid(), sys_gettid(), "check_new_thread_id"); 259 259 260 260 memset(&linfo, 0, sizeof(linfo)); 261 - linfo.task.tid = syscall(SYS_gettid); 261 + linfo.task.tid = sys_gettid(); 262 262 opts.link_info = &linfo; 263 263 opts.link_info_len = sizeof(linfo); 264 264 test_task_common(&opts, 0, 1);
+5 -5
tools/testing/selftests/bpf/prog_tests/cgrp_local_storage.c
··· 63 63 if (!ASSERT_OK(err, "map_delete_elem")) 64 64 goto out; 65 65 66 - skel->bss->target_pid = syscall(SYS_gettid); 66 + skel->bss->target_pid = sys_gettid(); 67 67 68 68 err = cgrp_ls_tp_btf__attach(skel); 69 69 if (!ASSERT_OK(err, "skel_attach")) 70 70 goto out; 71 71 72 - syscall(SYS_gettid); 73 - syscall(SYS_gettid); 72 + sys_gettid(); 73 + sys_gettid(); 74 74 75 75 skel->bss->target_pid = 0; 76 76 ··· 154 154 goto out; 155 155 156 156 /* trigger sys_enter, make sure it does not cause deadlock */ 157 - syscall(SYS_gettid); 157 + sys_gettid(); 158 158 159 159 out: 160 160 cgrp_ls_recursion__destroy(skel); ··· 224 224 return; 225 225 226 226 CGROUP_MODE_SET(skel); 227 - skel->bss->target_pid = syscall(SYS_gettid); 227 + skel->bss->target_pid = sys_gettid(); 228 228 229 229 bpf_program__set_autoload(skel->progs.yes_rcu_lock, true); 230 230 err = cgrp_ls_sleepable__load(skel);
+1 -1
tools/testing/selftests/bpf/prog_tests/core_reloc.c
··· 1010 1010 struct data *data; 1011 1011 void *mmap_data = NULL; 1012 1012 1013 - my_pid_tgid = getpid() | ((uint64_t)syscall(SYS_gettid) << 32); 1013 + my_pid_tgid = getpid() | ((uint64_t)sys_gettid() << 32); 1014 1014 1015 1015 for (i = 0; i < ARRAY_SIZE(test_cases); i++) { 1016 1016 char btf_file[] = "/tmp/core_reloc.btf.XXXXXX";
+1 -1
tools/testing/selftests/bpf/prog_tests/linked_funcs.c
··· 20 20 bpf_program__set_autoload(skel->progs.handler1, true); 21 21 bpf_program__set_autoload(skel->progs.handler2, true); 22 22 23 - skel->rodata->my_tid = syscall(SYS_gettid); 23 + skel->rodata->my_tid = sys_gettid(); 24 24 skel->bss->syscall_id = SYS_getpgid; 25 25 26 26 err = linked_funcs__load(skel);
+1 -1
tools/testing/selftests/bpf/prog_tests/ns_current_pid_tgid.c
··· 23 23 struct stat st; 24 24 int err; 25 25 26 - *pid = syscall(SYS_gettid); 26 + *pid = sys_gettid(); 27 27 *tgid = getpid(); 28 28 29 29 err = stat("/proc/self/ns/pid", &st);
+25
tools/testing/selftests/bpf/prog_tests/raw_tp_null.c
··· 1 + // SPDX-License-Identifier: GPL-2.0 2 + /* Copyright (c) 2024 Meta Platforms, Inc. and affiliates. */ 3 + 4 + #include <test_progs.h> 5 + #include "raw_tp_null.skel.h" 6 + 7 + void test_raw_tp_null(void) 8 + { 9 + struct raw_tp_null *skel; 10 + 11 + skel = raw_tp_null__open_and_load(); 12 + if (!ASSERT_OK_PTR(skel, "raw_tp_null__open_and_load")) 13 + return; 14 + 15 + skel->bss->tid = sys_gettid(); 16 + 17 + if (!ASSERT_OK(raw_tp_null__attach(skel), "raw_tp_null__attach")) 18 + goto end; 19 + 20 + ASSERT_OK(trigger_module_test_read(2), "trigger testmod read"); 21 + ASSERT_EQ(skel->bss->i, 3, "invocations"); 22 + 23 + end: 24 + raw_tp_null__destroy(skel); 25 + }
+2 -2
tools/testing/selftests/bpf/prog_tests/rcu_read_lock.c
··· 21 21 if (!ASSERT_OK_PTR(skel, "skel_open")) 22 22 return; 23 23 24 - skel->bss->target_pid = syscall(SYS_gettid); 24 + skel->bss->target_pid = sys_gettid(); 25 25 26 26 bpf_program__set_autoload(skel->progs.get_cgroup_id, true); 27 27 bpf_program__set_autoload(skel->progs.task_succ, true); ··· 58 58 if (!ASSERT_OK_PTR(skel, "skel_open")) 59 59 return; 60 60 61 - skel->bss->target_pid = syscall(SYS_gettid); 61 + skel->bss->target_pid = sys_gettid(); 62 62 63 63 bpf_program__set_autoload(skel->progs.task_acquire, true); 64 64 err = rcu_read_lock__load(skel);
+5 -5
tools/testing/selftests/bpf/prog_tests/task_local_storage.c
··· 31 31 if (!ASSERT_OK_PTR(skel, "skel_open_and_load")) 32 32 return; 33 33 34 - skel->bss->target_pid = syscall(SYS_gettid); 34 + skel->bss->target_pid = sys_gettid(); 35 35 36 36 err = task_local_storage__attach(skel); 37 37 if (!ASSERT_OK(err, "skel_attach")) 38 38 goto out; 39 39 40 - syscall(SYS_gettid); 41 - syscall(SYS_gettid); 40 + sys_gettid(); 41 + sys_gettid(); 42 42 43 43 /* 3x syscalls: 1x attach and 2x gettid */ 44 44 ASSERT_EQ(skel->bss->enter_cnt, 3, "enter_cnt"); ··· 107 107 108 108 /* trigger sys_enter, make sure it does not cause deadlock */ 109 109 skel->bss->test_pid = getpid(); 110 - syscall(SYS_gettid); 110 + sys_gettid(); 111 111 skel->bss->test_pid = 0; 112 112 task_ls_recursion__detach(skel); 113 113 ··· 262 262 __u64 ev_dummy_data = 1; 263 263 int err; 264 264 265 - my_tid = syscall(SYS_gettid); 265 + my_tid = sys_gettid(); 266 266 parent_task_fd = sys_pidfd_open(my_tid, 0); 267 267 if (!ASSERT_OK_FD(parent_task_fd, "parent_task_fd")) 268 268 return;
+1 -1
tools/testing/selftests/bpf/prog_tests/uprobe_multi_test.c
··· 125 125 struct child *child = ctx; 126 126 int c = 0, err; 127 127 128 - child->tid = syscall(SYS_gettid); 128 + child->tid = sys_gettid(); 129 129 130 130 /* let parent know we are ready */ 131 131 err = write(child->c2p[1], &c, 1);
+32
tools/testing/selftests/bpf/progs/raw_tp_null.c
··· 1 + // SPDX-License-Identifier: GPL-2.0 2 + /* Copyright (c) 2024 Meta Platforms, Inc. and affiliates. */ 3 + 4 + #include <vmlinux.h> 5 + #include <bpf/bpf_tracing.h> 6 + 7 + char _license[] SEC("license") = "GPL"; 8 + 9 + int tid; 10 + int i; 11 + 12 + SEC("tp_btf/bpf_testmod_test_raw_tp_null") 13 + int BPF_PROG(test_raw_tp_null, struct sk_buff *skb) 14 + { 15 + struct task_struct *task = bpf_get_current_task_btf(); 16 + 17 + if (task->pid != tid) 18 + return 0; 19 + 20 + i = i + skb->mark + 1; 21 + /* The compiler may move the NULL check before this deref, which causes 22 + * the load to fail as deref of scalar. Prevent that by using a barrier. 23 + */ 24 + barrier(); 25 + /* If dead code elimination kicks in, the increment below will 26 + * be removed. For raw_tp programs, we mark input arguments as 27 + * PTR_MAYBE_NULL, so branch prediction should never kick in. 28 + */ 29 + if (!skb) 30 + i += 2; 31 + return 0; 32 + }
+5 -1
tools/testing/selftests/bpf/progs/test_tp_btf_nullable.c
··· 7 7 #include "bpf_misc.h" 8 8 9 9 SEC("tp_btf/bpf_testmod_test_nullable_bare") 10 - __failure __msg("R1 invalid mem access 'trusted_ptr_or_null_'") 10 + /* This used to be a failure test, but raw_tp nullable arguments can now 11 + * directly be dereferenced, whether they have nullable annotation or not, 12 + * and don't need to be explicitly checked. 13 + */ 14 + __success 11 15 int BPF_PROG(handle_tp_btf_nullable_bare1, struct bpf_testmod_test_read_ctx *nullable_ctx) 12 16 { 13 17 return nullable_ctx->len;