Skip to content

Commit a8e1a3d

Browse files
author
Alexei Starovoitov
committed
Merge branch 'explicit-raw_tp-null-arguments'
Kumar Kartikeya Dwivedi says: ==================== Explicit raw_tp NULL arguments This set reverts the raw_tp masking changes introduced in commit cb4158c ("bpf: Mark raw_tp arguments with PTR_MAYBE_NULL") and replaces it wwith an explicit list of tracepoints and their arguments which need to be annotated as PTR_MAYBE_NULL. More context on the fallout caused by the masking fix and subsequent discussions can be found in [0]. To remedy this, we implement a solution of explicitly defined tracepoint and define which args need to be marked NULL or scalar (for IS_ERR case). The commit logs describes the details of this approach in detail. We will follow up this solution an approach Eduard is working on to perform automated analysis of NULL-ness of tracepoint arguments. The current PoC is available here: - LLVM branch with the analysis: https://github.com/eddyz87/llvm-project/tree/nullness-for-tracepoint-params - Python script for merging of analysis results: https://gist.github.com/eddyz87/e47c164466a60e8d49e6911cff146f47 The idea is to infer a tri-state verdict for each tracepoint parameter: definitely not null, can be null, unknown (in which case no assumptions should be made). Using this information, the verifier in most cases will be able to precisely determine the state of the tracepoint parameter without any human effort. At that point, the table maintained manually in this set can be dropped and replace with this automated analysis tool's result. This will be kept up to date with each kernel release. [0]: https://lore.kernel.org/bpf/20241206161053.809580-1-memxor@gmail.com Changelog: ---------- v2 -> v3: v2: https://lore.kernel.org/bpf/20241213175127.2084759-1-memxor@gmail.com * Address Eduard's nits, add Reviewed-by v1 -> v2: v1: https://lore.kernel.org/bpf/20241211020156.18966-1-memxor@gmail.com * Address comments from Jiri * Mark module tracepoints args NULL by default * Add more sunrpc tracepoints * Unify scalar or null handling * Address comments from Alexei * Use bitmask approach suggested in review * Unify scalar or null handling * Drop most tests that rely on CONFIG options * Drop scripts to generate tests ==================== Link: https://patch.msgid.link/20241213221929.3495062-1-memxor@gmail.com Signed-off-by: Alexei Starovoitov <ast@kernel.org>
2 parents e4c80f6 + 0da1955 commit a8e1a3d

File tree

7 files changed

+183
-97
lines changed

7 files changed

+183
-97
lines changed

include/linux/bpf.h

Lines changed: 0 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -3514,10 +3514,4 @@ static inline bool bpf_is_subprog(const struct bpf_prog *prog)
35143514
return prog->aux->func_idx != 0;
35153515
}
35163516

3517-
static inline bool bpf_prog_is_raw_tp(const struct bpf_prog *prog)
3518-
{
3519-
return prog->type == BPF_PROG_TYPE_TRACING &&
3520-
prog->expected_attach_type == BPF_TRACE_RAW_TP;
3521-
}
3522-
35233517
#endif /* _LINUX_BPF_H */

kernel/bpf/btf.c

Lines changed: 139 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -6439,6 +6439,101 @@ int btf_ctx_arg_offset(const struct btf *btf, const struct btf_type *func_proto,
64396439
return off;
64406440
}
64416441

6442+
struct bpf_raw_tp_null_args {
6443+
const char *func;
6444+
u64 mask;
6445+
};
6446+
6447+
static const struct bpf_raw_tp_null_args raw_tp_null_args[] = {
6448+
/* sched */
6449+
{ "sched_pi_setprio", 0x10 },
6450+
/* ... from sched_numa_pair_template event class */
6451+
{ "sched_stick_numa", 0x100 },
6452+
{ "sched_swap_numa", 0x100 },
6453+
/* afs */
6454+
{ "afs_make_fs_call", 0x10 },
6455+
{ "afs_make_fs_calli", 0x10 },
6456+
{ "afs_make_fs_call1", 0x10 },
6457+
{ "afs_make_fs_call2", 0x10 },
6458+
{ "afs_protocol_error", 0x1 },
6459+
{ "afs_flock_ev", 0x10 },
6460+
/* cachefiles */
6461+
{ "cachefiles_lookup", 0x1 | 0x200 },
6462+
{ "cachefiles_unlink", 0x1 },
6463+
{ "cachefiles_rename", 0x1 },
6464+
{ "cachefiles_prep_read", 0x1 },
6465+
{ "cachefiles_mark_active", 0x1 },
6466+
{ "cachefiles_mark_failed", 0x1 },
6467+
{ "cachefiles_mark_inactive", 0x1 },
6468+
{ "cachefiles_vfs_error", 0x1 },
6469+
{ "cachefiles_io_error", 0x1 },
6470+
{ "cachefiles_ondemand_open", 0x1 },
6471+
{ "cachefiles_ondemand_copen", 0x1 },
6472+
{ "cachefiles_ondemand_close", 0x1 },
6473+
{ "cachefiles_ondemand_read", 0x1 },
6474+
{ "cachefiles_ondemand_cread", 0x1 },
6475+
{ "cachefiles_ondemand_fd_write", 0x1 },
6476+
{ "cachefiles_ondemand_fd_release", 0x1 },
6477+
/* ext4, from ext4__mballoc event class */
6478+
{ "ext4_mballoc_discard", 0x10 },
6479+
{ "ext4_mballoc_free", 0x10 },
6480+
/* fib */
6481+
{ "fib_table_lookup", 0x100 },
6482+
/* filelock */
6483+
/* ... from filelock_lock event class */
6484+
{ "posix_lock_inode", 0x10 },
6485+
{ "fcntl_setlk", 0x10 },
6486+
{ "locks_remove_posix", 0x10 },
6487+
{ "flock_lock_inode", 0x10 },
6488+
/* ... from filelock_lease event class */
6489+
{ "break_lease_noblock", 0x10 },
6490+
{ "break_lease_block", 0x10 },
6491+
{ "break_lease_unblock", 0x10 },
6492+
{ "generic_delete_lease", 0x10 },
6493+
{ "time_out_leases", 0x10 },
6494+
/* host1x */
6495+
{ "host1x_cdma_push_gather", 0x10000 },
6496+
/* huge_memory */
6497+
{ "mm_khugepaged_scan_pmd", 0x10 },
6498+
{ "mm_collapse_huge_page_isolate", 0x1 },
6499+
{ "mm_khugepaged_scan_file", 0x10 },
6500+
{ "mm_khugepaged_collapse_file", 0x10 },
6501+
/* kmem */
6502+
{ "mm_page_alloc", 0x1 },
6503+
{ "mm_page_pcpu_drain", 0x1 },
6504+
/* .. from mm_page event class */
6505+
{ "mm_page_alloc_zone_locked", 0x1 },
6506+
/* netfs */
6507+
{ "netfs_failure", 0x10 },
6508+
/* power */
6509+
{ "device_pm_callback_start", 0x10 },
6510+
/* qdisc */
6511+
{ "qdisc_dequeue", 0x1000 },
6512+
/* rxrpc */
6513+
{ "rxrpc_recvdata", 0x1 },
6514+
{ "rxrpc_resend", 0x10 },
6515+
/* sunrpc */
6516+
{ "xs_stream_read_data", 0x1 },
6517+
/* ... from xprt_cong_event event class */
6518+
{ "xprt_reserve_cong", 0x10 },
6519+
{ "xprt_release_cong", 0x10 },
6520+
{ "xprt_get_cong", 0x10 },
6521+
{ "xprt_put_cong", 0x10 },
6522+
/* tcp */
6523+
{ "tcp_send_reset", 0x11 },
6524+
/* tegra_apb_dma */
6525+
{ "tegra_dma_tx_status", 0x100 },
6526+
/* timer_migration */
6527+
{ "tmigr_update_events", 0x1 },
6528+
/* writeback, from writeback_folio_template event class */
6529+
{ "writeback_dirty_folio", 0x10 },
6530+
{ "folio_wait_writeback", 0x10 },
6531+
/* rdma */
6532+
{ "mr_integ_alloc", 0x2000 },
6533+
/* bpf_testmod */
6534+
{ "bpf_testmod_test_read", 0x0 },
6535+
};
6536+
64426537
bool btf_ctx_access(int off, int size, enum bpf_access_type type,
64436538
const struct bpf_prog *prog,
64446539
struct bpf_insn_access_aux *info)
@@ -6449,6 +6544,7 @@ bool btf_ctx_access(int off, int size, enum bpf_access_type type,
64496544
const char *tname = prog->aux->attach_func_name;
64506545
struct bpf_verifier_log *log = info->log;
64516546
const struct btf_param *args;
6547+
bool ptr_err_raw_tp = false;
64526548
const char *tag_value;
64536549
u32 nr_args, arg;
64546550
int i, ret;
@@ -6594,12 +6690,42 @@ bool btf_ctx_access(int off, int size, enum bpf_access_type type,
65946690
if (prog_args_trusted(prog))
65956691
info->reg_type |= PTR_TRUSTED;
65966692

6597-
/* Raw tracepoint arguments always get marked as maybe NULL */
6598-
if (bpf_prog_is_raw_tp(prog))
6599-
info->reg_type |= PTR_MAYBE_NULL;
6600-
else if (btf_param_match_suffix(btf, &args[arg], "__nullable"))
6693+
if (btf_param_match_suffix(btf, &args[arg], "__nullable"))
66016694
info->reg_type |= PTR_MAYBE_NULL;
66026695

6696+
if (prog->expected_attach_type == BPF_TRACE_RAW_TP) {
6697+
struct btf *btf = prog->aux->attach_btf;
6698+
const struct btf_type *t;
6699+
const char *tname;
6700+
6701+
/* BTF lookups cannot fail, return false on error */
6702+
t = btf_type_by_id(btf, prog->aux->attach_btf_id);
6703+
if (!t)
6704+
return false;
6705+
tname = btf_name_by_offset(btf, t->name_off);
6706+
if (!tname)
6707+
return false;
6708+
/* Checked by bpf_check_attach_target */
6709+
tname += sizeof("btf_trace_") - 1;
6710+
for (i = 0; i < ARRAY_SIZE(raw_tp_null_args); i++) {
6711+
/* Is this a func with potential NULL args? */
6712+
if (strcmp(tname, raw_tp_null_args[i].func))
6713+
continue;
6714+
if (raw_tp_null_args[i].mask & (0x1 << (arg * 4)))
6715+
info->reg_type |= PTR_MAYBE_NULL;
6716+
/* Is the current arg IS_ERR? */
6717+
if (raw_tp_null_args[i].mask & (0x2 << (arg * 4)))
6718+
ptr_err_raw_tp = true;
6719+
break;
6720+
}
6721+
/* If we don't know NULL-ness specification and the tracepoint
6722+
* is coming from a loadable module, be conservative and mark
6723+
* argument as PTR_MAYBE_NULL.
6724+
*/
6725+
if (i == ARRAY_SIZE(raw_tp_null_args) && btf_is_module(btf))
6726+
info->reg_type |= PTR_MAYBE_NULL;
6727+
}
6728+
66036729
if (tgt_prog) {
66046730
enum bpf_prog_type tgt_type;
66056731

@@ -6644,6 +6770,15 @@ bool btf_ctx_access(int off, int size, enum bpf_access_type type,
66446770
bpf_log(log, "func '%s' arg%d has btf_id %d type %s '%s'\n",
66456771
tname, arg, info->btf_id, btf_type_str(t),
66466772
__btf_name_by_offset(btf, t->name_off));
6773+
6774+
/* Perform all checks on the validity of type for this argument, but if
6775+
* we know it can be IS_ERR at runtime, scrub pointer type and mark as
6776+
* scalar.
6777+
*/
6778+
if (ptr_err_raw_tp) {
6779+
bpf_log(log, "marking pointer arg%d as scalar as it may encode error", arg);
6780+
info->reg_type = SCALAR_VALUE;
6781+
}
66476782
return true;
66486783
}
66496784
EXPORT_SYMBOL_GPL(btf_ctx_access);

0 commit comments

Comments
 (0)