Pull probes fixes from Masami Hiramatsu: "fprobe fixes and spelling typos: - Fix NULL pointer dereference in fprobe_fgraph_entry(). Prevent general protection faults by checking shadow-stack reservation bounds. Skip mid-flight registered fprobes that were not counted during sizing. eprobe: fix string pointer extraction - Correct the casting of string pointers read from the ringbuffer to prevent truncation of base event pointer variables when dereferencing FILTER_PTR_STRING fields. tracing/probes: clean up argument parsing and BTF helper logic - Make the $ prefix mandatory for comm access: Require the $ prefix for special fetcharg variables like $comm and $COMM, preventing naming conflicts with regular BTF-based event fields. - Fix double addition of offset for @+FOFFSET: Clear the temporary offset variable after setting the FETCH_OP_FOFFS instruction to avoid applying the offset multiple times. - Remove WARN_ON_ONCE from parse_btf_arg: Prevent triggering a kernel warning via user-space input when creating a kprobe event on a raw address. - Fix typo in a log message: Correct a spelling error ("$-valiable") in trace probe log messages. samples/trace_events: improve error checking - Validate the thread pointer returned from kthread_run() in the trace events sample code to properly handle thread creation failures" * tag 'probes-fixes-v7.2-rc1' of git://git.kernel.org/pub/scm/linux/kernel/git/trace/linux-trace: tracing/probes: Make the $ prefix mandatory for comm access tracing/fprobe: Fix NULL pointer dereference in fprobe_fgraph_entry() tracing/probes: Fix double addition of offset for @+FOFFSET tracing: eprobe: read the complete FILTER_PTR_STRING pointer tracing/events: Fix to check the simple_tsk_fn creation tracing/probes: Remove WARN_ON_ONCE from parse_btf_arg tracing: probes: fix typo in a log message
Unified · Split
| @@ -613,6 +613,16 @@ static int fprobe_fgraph_entry(struct ftrace_graph_ent *trace, struct fgraph_ops · 612 unmodified lines | |||
| 613 | continue; | 613 | continue; |
| 614 | 614 | ||
| 615 | data_size = fp->entry_data_size; | 615 | data_size = fp->entry_data_size; |
| 616 | /* | ||
| 617 | * The list may have grown since it was sized, so this node | ||
| 618 | * may not fit. Skip it as missed rather than overrun the | ||
| 619 | * reservation. | ||
| 620 | */ | ||
| 621 | if (fp->exit_handler && | ||
| 622 | used + FPROBE_HEADER_SIZE_IN_LONG + SIZE_IN_LONG(data_size) > reserved_words) { | ||
| 623 | fp->nmissed++; | ||
| 624 | continue; | ||
| 625 | } | ||
| 616 | if (data_size && fp->exit_handler) | 626 | if (data_size && fp->exit_handler) |
| 617 | data = fgraph_data + used + FPROBE_HEADER_SIZE_IN_LONG; | 627 | data = fgraph_data + used + FPROBE_HEADER_SIZE_IN_LONG; |
| 618 | else | 628 | else |
| @@ -315,7 +315,7 @@ get_event_field(struct fetch_insn *code, void *rec) · 314 unmodified lines | |||
| 315 | val = (unsigned long)addr; | 315 | val = (unsigned long)addr; |
| 316 | break; | 316 | break; |
| 317 | case FILTER_PTR_STRING: | 317 | case FILTER_PTR_STRING: |
| 318 | val = (unsigned long)(*(char *)addr); | 318 | val = *(unsigned long *)addr; |
| 319 | break; | 319 | break; |
| 320 | default: | 320 | default: |
| 321 | WARN_ON_ONCE(1); | 321 | WARN_ON_ONCE(1); |
| @@ -342,10 +342,6 @@ static int parse_trace_event(char *arg, struct fetch_insn *code, · 341 unmodified lines | |||
| 342 | ret = parse_trace_event_arg(arg, code, ctx); | 342 | ret = parse_trace_event_arg(arg, code, ctx); |
| 343 | if (!ret) | 343 | if (!ret) |
| 344 | return 0; | 344 | return 0; |
| 345 | if (strcmp(arg, "comm") == 0 || strcmp(arg, "COMM") == 0) { | ||
| 346 | code->op = FETCH_OP_COMM; | ||
| 347 | return 0; | ||
| 348 | } | ||
| 349 | return -EINVAL; | 345 | return -EINVAL; |
| 350 | } | 346 | } |
| 351 | 347 | ||
| @@ -678,7 +674,7 @@ static int parse_btf_arg(char *varname, · 326 unmodified lines | |||
| 678 | int i, is_ptr, ret; | 674 | int i, is_ptr, ret; |
| 679 | u32 tid; | 675 | u32 tid; |
| 680 | 676 | ||
| 681 | if (WARN_ON_ONCE(!ctx->funcname && !(ctx->flags & TPARG_FL_TEVENT))) | 677 | if (!ctx->funcname && !(ctx->flags & TPARG_FL_TEVENT)) |
| 682 | return -EINVAL; | 678 | return -EINVAL; |
| 683 | 679 | ||
| 684 | is_ptr = split_next_field(varname, &field, ctx); | 680 | is_ptr = split_next_field(varname, &field, ctx); |
| @@ -1068,8 +1064,14 @@ static int parse_probe_vars(char *orig_arg, const struct fetch_type *t, · 383 unmodified lines | |||
| 1068 | int len; | 1064 | int len; |
| 1069 | 1065 | ||
| 1070 | if (ctx->flags & TPARG_FL_TEVENT) { | 1066 | if (ctx->flags & TPARG_FL_TEVENT) { |
| 1071 | if (parse_trace_event(arg, code, ctx) < 0) | 1067 | if (parse_trace_event(arg, code, ctx) < 0) { |
| 1068 | /* 'comm' should be checked after field parsing. */ | ||
| 1069 | if (strcmp(arg, "comm") == 0 || strcmp(arg, "COMM") == 0) { | ||
| 1070 | code->op = FETCH_OP_COMM; | ||
| 1071 | return 0; | ||
| 1072 | } | ||
| 1072 | goto inval; | 1073 | goto inval; |
| 1074 | } | ||
| 1073 | return 0; | 1075 | return 0; |
| 1074 | } | 1076 | } |
| 1075 | 1077 | ||
| @@ -1241,6 +1243,7 @@ parse_probe_arg(char *arg, const struct fetch_type *type, · 165 unmodified lines | |||
| 1241 | 1243 | ||
| 1242 | code->op = FETCH_OP_FOFFS; | 1244 | code->op = FETCH_OP_FOFFS; |
| 1243 | code->immediate = (unsigned long)offset; // imm64? | 1245 | code->immediate = (unsigned long)offset; // imm64? |
| 1246 | offset = 0; | ||
| 1244 | } else { | 1247 | } else { |
| 1245 | /* uprobes don't support symbols */ | 1248 | /* uprobes don't support symbols */ |
| 1246 | if (!(ctx->flags & TPARG_FL_KERNEL)) { | 1249 | if (!(ctx->flags & TPARG_FL_KERNEL)) { |
| @@ -511,7 +511,7 @@ extern int traceprobe_define_arg_fields(struct trace_event_call *event_call, · 510 unmodified lines | |||
| 511 | C(NO_RETVAL, "This function returns 'void' type"), \ | 511 | C(NO_RETVAL, "This function returns 'void' type"), \ |
| 512 | C(BAD_STACK_NUM, "Invalid stack number"), \ | 512 | C(BAD_STACK_NUM, "Invalid stack number"), \ |
| 513 | C(BAD_ARG_NUM, "Invalid argument number"), \ | 513 | C(BAD_ARG_NUM, "Invalid argument number"), \ |
| 514 | C(BAD_VAR, "Invalid $-valiable specified"), \ | 514 | C(BAD_VAR, "Invalid $-variable specified"), \ |
| 515 | C(BAD_REG_NAME, "Invalid register name"), \ | 515 | C(BAD_REG_NAME, "Invalid register name"), \ |
| 516 | C(BAD_MEM_ADDR, "Invalid memory address"), \ | 516 | C(BAD_MEM_ADDR, "Invalid memory address"), \ |
| 517 | C(BAD_IMM, "Invalid immediate value"), \ | 517 | C(BAD_IMM, "Invalid immediate value"), \ |
| @@ -107,6 +107,10 @@ int foo_bar_reg(void) · 106 unmodified lines | |||
| 107 | * for consistency sake, we still take the thread_mutex. | 107 | * for consistency sake, we still take the thread_mutex. |
| 108 | */ | 108 | */ |
| 109 | simple_tsk_fn = kthread_run(simple_thread_fn, NULL, "event-sample-fn"); | 109 | simple_tsk_fn = kthread_run(simple_thread_fn, NULL, "event-sample-fn"); |
| 110 | if (IS_ERR_OR_NULL(simple_tsk_fn)) { | ||
| 111 | pr_err("Failed to create simple_thread_fn\n"); | ||
| 112 | simple_tsk_fn = NULL; | ||
| 113 | } | ||
| 110 | out: | 114 | out: |
| 111 | mutex_unlock(&thread_mutex); | 115 | mutex_unlock(&thread_mutex); |
| 112 | return 0; | 116 | return 0; |