History

Merge tag 'trace-v6.0-rc1-2' of git://git.kernel.org/pub/scm/linux/kernel/git/rostedt/linux-trace

Pull tracing fixes from Steven Rostedt: "Various fixes for tracing: - Fix a return value of traceprobe_parse_event_name() - Fix NULL pointer dereference from failed ftrace enabling - Fix NULL pointer dereference when asking for registers from eprobes - Make eprobes consistent with kprobes/uprobes, filters and histograms" * tag 'trace-v6.0-rc1-2' of git://git.kernel.org/pub/scm/linux/kernel/git/rostedt/linux-trace: tracing: Have filter accept "common_cpu" to be consistent tracing/probes: Have kprobes and uprobes use $COMM too tracing/eprobes: Have event probes be consistent with kprobes and uprobes tracing/eprobes: Fix reading of string fields tracing/eprobes: Do not hardcode $comm as a string tracing/eprobes: Do not allow eprobes to use $stack, or % for regs ftrace: Fix NULL pointer dereference in is_ftrace_trampoline when ftrace is dead tracing/perf: Fix double put of trace event when init fails tracing: React to error return from traceprobe_parse_event_name()

Linus Torvalds committed 4 years ago

Commit 7fb312d2 parents e3f259d b2380575 files · +119 −21Browse files

Unified · Split

5 files
  1. kernel/trace/ftrace.c +10 −0
  2. kernel/trace/trace_eprobe.c +86 −7
  3. kernel/trace/trace_event_perf.c +4 −3
  4. kernel/trace/trace_events.c +1 −0
  5. kernel/trace/trace_probe.c +18 −11
kernel/trace/ftrace.c+10−0
@@ -2974,6 +2974,16 @@ int ftrace_startup(struct ftrace_ops *ops, int command) · 2973 unmodified lines
29742974
29752975 ftrace_startup_enable(command);
29762976
2977+ /*
2978+ * If ftrace is in an undefined state, we just remove ops from list
2979+ * to prevent the NULL pointer, instead of totally rolling it back and
2980+ * free trampoline, because those actions could cause further damage.
2981+ */
2982+ if (unlikely(ftrace_disabled)) {
2983+ __unregister_ftrace_function(ops);
2984+ return -ENODEV;
2985+ }
2986+
29772987 ops->flags &= ~FTRACE_OPS_FL_ADDING;
29782988
29792989 return 0;
kernel/trace/trace_eprobe.c+86−7
@@ -227,6 +227,7 @@ static int trace_eprobe_tp_arg_update(struct trace_eprobe *ep, int i) · 226 unmodified lines
227227 struct probe_arg *parg = &ep->tp.args[i];
228228 struct ftrace_event_field *field;
229229 struct list_head *head;
230+ int ret = -ENOENT;
230231
231232 head = trace_get_fields(ep->event);
232233 list_for_each_entry(field, head, link) {
@@ -236,9 +237,20 @@ static int trace_eprobe_tp_arg_update(struct trace_eprobe *ep, int i) · 3 unmodified lines
236237 return 0;
237238 }
238239 }
240+
241+ /*
242+ * Argument not found on event. But allow for comm and COMM
243+ * to be used to get the current->comm.
244+ */
245+ if (strcmp(parg->code->data, "COMM") == 0 ||
246+ strcmp(parg->code->data, "comm") == 0) {
247+ parg->code->op = FETCH_OP_COMM;
248+ ret = 0;
249+ }
250+
239251 kfree(parg->code->data);
240252 parg->code->data = NULL;
241− return -ENOENT;
253+ return ret;
242254 }
243255
244256 static int eprobe_event_define_fields(struct trace_event_call *event_call)
@@ -311,6 +323,27 @@ static unsigned long get_event_field(struct fetch_insn *code, void *rec) · 66 unmodified lines
311323
312324 addr = rec + field->offset;
313325
326+ if (is_string_field(field)) {
327+ switch (field->filter_type) {
328+ case FILTER_DYN_STRING:
329+ val = (unsigned long)(rec + (*(unsigned int *)addr & 0xffff));
330+ break;
331+ case FILTER_RDYN_STRING:
332+ val = (unsigned long)(addr + (*(unsigned int *)addr & 0xffff));
333+ break;
334+ case FILTER_STATIC_STRING:
335+ val = (unsigned long)addr;
336+ break;
337+ case FILTER_PTR_STRING:
338+ val = (unsigned long)(*(char *)addr);
339+ break;
340+ default:
341+ WARN_ON_ONCE(1);
342+ return 0;
343+ }
344+ return val;
345+ }
346+
314347 switch (field->size) {
315348 case 1:
316349 if (field->is_signed)
@@ -342,16 +375,38 @@ static unsigned long get_event_field(struct fetch_insn *code, void *rec) · 25 unmodified lines
342375
343376 static int get_eprobe_size(struct trace_probe *tp, void *rec)
344377 {
378+ struct fetch_insn *code;
345379 struct probe_arg *arg;
346380 int i, len, ret = 0;
347381
348382 for (i = 0; i < tp->nr_args; i++) {
349383 arg = tp->args + i;
350− if (unlikely(arg->dynamic)) {
384+ if (arg->dynamic) {
351385 unsigned long val;
352386
353− val = get_event_field(arg->code, rec);
354− len = process_fetch_insn_bottom(arg->code + 1, val, NULL, NULL);
387+ code = arg->code;
388+ retry:
389+ switch (code->op) {
390+ case FETCH_OP_TP_ARG:
391+ val = get_event_field(code, rec);
392+ break;
393+ case FETCH_OP_IMM:
394+ val = code->immediate;
395+ break;
396+ case FETCH_OP_COMM:
397+ val = (unsigned long)current->comm;
398+ break;
399+ case FETCH_OP_DATA:
400+ val = (unsigned long)code->data;
401+ break;
402+ case FETCH_NOP_SYMBOL: /* Ignore a place holder */
403+ code++;
404+ goto retry;
405+ default:
406+ continue;
407+ }
408+ code++;
409+ len = process_fetch_insn_bottom(code, val, NULL, NULL);
355410 if (len > 0)
356411 ret += len;
357412 }
@@ -369,8 +424,28 @@ process_fetch_insn(struct fetch_insn *code, void *rec, void *dest, · 11 unmodified lines
369424 {
370425 unsigned long val;
371426
372− val = get_event_field(code, rec);
373− return process_fetch_insn_bottom(code + 1, val, dest, base);
427+ retry:
428+ switch (code->op) {
429+ case FETCH_OP_TP_ARG:
430+ val = get_event_field(code, rec);
431+ break;
432+ case FETCH_OP_IMM:
433+ val = code->immediate;
434+ break;
435+ case FETCH_OP_COMM:
436+ val = (unsigned long)current->comm;
437+ break;
438+ case FETCH_OP_DATA:
439+ val = (unsigned long)code->data;
440+ break;
441+ case FETCH_NOP_SYMBOL: /* Ignore a place holder */
442+ code++;
443+ goto retry;
444+ default:
445+ return -EILSEQ;
446+ }
447+ code++;
448+ return process_fetch_insn_bottom(code, val, dest, base);
374449 }
375450 NOKPROBE_SYMBOL(process_fetch_insn)
376451
@@ -845,6 +920,10 @@ static int trace_eprobe_tp_update_arg(struct trace_eprobe *ep, const char *argv[ · 468 unmodified lines
845920 trace_probe_log_err(0, BAD_ATTACH_ARG);
846921 }
847922
923+ /* Handle symbols "@" */
924+ if (!ret)
925+ ret = traceprobe_update_arg(&ep->tp.args[i]);
926+
848927 return ret;
849928 }
850929
@@ -883,7 +962,7 @@ static int __trace_eprobe_create(int argc, const char *argv[]) · 32 unmodified lines
883962 trace_probe_log_set_index(1);
884963 sys_event = argv[1];
885964 ret = traceprobe_parse_event_name(&sys_event, &sys_name, buf2, 0);
886− if (!sys_event || !sys_name) {
965+ if (ret || !sys_event || !sys_name) {
887966 trace_probe_log_err(0, NO_EVENT_INFO);
888967 goto parse_error;
889968 }
kernel/trace/trace_event_perf.c+4−3
@@ -157,7 +157,7 @@ static void perf_trace_event_unreg(struct perf_event *p_event) · 156 unmodified lines
157157 int i;
158158
159159 if (--tp_event->perf_refcount > 0)
160− goto out;
160+ return;
161161
162162 tp_event->class->reg(tp_event, TRACE_REG_PERF_UNREGISTER, NULL);
163163
@@ -176,8 +176,6 @@ static void perf_trace_event_unreg(struct perf_event *p_event) · 12 unmodified lines
176176 perf_trace_buf[i] = NULL;
177177 }
178178 }
179−out:
180− trace_event_put_ref(tp_event);
181179 }
182180
183181 static int perf_trace_event_open(struct perf_event *p_event)
@@ -241,6 +239,7 @@ void perf_trace_destroy(struct perf_event *p_event) · 57 unmodified lines
241239 mutex_lock(&event_mutex);
242240 perf_trace_event_close(p_event);
243241 perf_trace_event_unreg(p_event);
242+ trace_event_put_ref(p_event->tp_event);
244243 mutex_unlock(&event_mutex);
245244 }
246245
@@ -292,6 +291,7 @@ void perf_kprobe_destroy(struct perf_event *p_event) · 45 unmodified lines
292291 mutex_lock(&event_mutex);
293292 perf_trace_event_close(p_event);
294293 perf_trace_event_unreg(p_event);
294+ trace_event_put_ref(p_event->tp_event);
295295 mutex_unlock(&event_mutex);
296296
297297 destroy_local_trace_kprobe(p_event->tp_event);
@@ -347,6 +347,7 @@ void perf_uprobe_destroy(struct perf_event *p_event) · 49 unmodified lines
347347 mutex_lock(&event_mutex);
348348 perf_trace_event_close(p_event);
349349 perf_trace_event_unreg(p_event);
350+ trace_event_put_ref(p_event->tp_event);
350351 mutex_unlock(&event_mutex);
351352 destroy_local_trace_uprobe(p_event->tp_event);
352353 }
kernel/trace/trace_events.c+1−0
@@ -176,6 +176,7 @@ static int trace_define_generic_fields(void) · 175 unmodified lines
176176
177177 __generic_field(int, CPU, FILTER_CPU);
178178 __generic_field(int, cpu, FILTER_CPU);
179+ __generic_field(int, common_cpu, FILTER_CPU);
179180 __generic_field(char *, COMM, FILTER_COMM);
180181 __generic_field(char *, comm, FILTER_COMM);
181182
kernel/trace/trace_probe.c+18−11
@@ -283,7 +283,14 @@ static int parse_probe_vars(char *arg, const struct fetch_type *t, · 282 unmodified lines
283283 int ret = 0;
284284 int len;
285285
286− if (strcmp(arg, "retval") == 0) {
286+ if (flags & TPARG_FL_TPOINT) {
287+ if (code->data)
288+ return -EFAULT;
289+ code->data = kstrdup(arg, GFP_KERNEL);
290+ if (!code->data)
291+ return -ENOMEM;
292+ code->op = FETCH_OP_TP_ARG;
293+ } else if (strcmp(arg, "retval") == 0) {
287294 if (flags & TPARG_FL_RETURN) {
288295 code->op = FETCH_OP_RETVAL;
289296 } else {
@@ -307,7 +314,7 @@ static int parse_probe_vars(char *arg, const struct fetch_type *t, · 17 unmodified lines
307314 }
308315 } else
309316 goto inval_var;
310− } else if (strcmp(arg, "comm") == 0) {
317+ } else if (strcmp(arg, "comm") == 0 || strcmp(arg, "COMM") == 0) {
311318 code->op = FETCH_OP_COMM;
312319 #ifdef CONFIG_HAVE_FUNCTION_ARG_ACCESS_API
313320 } else if (((flags & TPARG_FL_MASK) ==
@@ -323,13 +330,6 @@ static int parse_probe_vars(char *arg, const struct fetch_type *t, · 9 unmodified lines
323330 code->op = FETCH_OP_ARG;
324331 code->param = (unsigned int)param - 1;
325332 #endif
326− } else if (flags & TPARG_FL_TPOINT) {
327− if (code->data)
328− return -EFAULT;
329− code->data = kstrdup(arg, GFP_KERNEL);
330− if (!code->data)
331− return -ENOMEM;
332− code->op = FETCH_OP_TP_ARG;
333333 } else
334334 goto inval_var;
335335
@@ -384,6 +384,11 @@ parse_probe_arg(char *arg, const struct fetch_type *type, · 48 unmodified lines
384384 break;
385385
386386 case '%': /* named register */
387+ if (flags & TPARG_FL_TPOINT) {
388+ /* eprobes do not handle registers */
389+ trace_probe_log_err(offs, BAD_VAR);
390+ break;
391+ }
387392 ret = regs_query_register_offset(arg + 1);
388393 if (ret >= 0) {
389394 code->op = FETCH_OP_REG;
@@ -617,9 +622,11 @@ static int traceprobe_parse_probe_arg_body(const char *argv, ssize_t *size, · 227 unmodified lines
617622
618623 /*
619624 * Since $comm and immediate string can not be dereferenced,
620− * we can find those by strcmp.
625+ * we can find those by strcmp. But ignore for eprobes.
621626 */
622− if (strcmp(arg, "$comm") == 0 || strncmp(arg, "\\\"", 2) == 0) {
627+ if (!(flags & TPARG_FL_TPOINT) &&
628+ (strcmp(arg, "$comm") == 0 || strcmp(arg, "$COMM") == 0 ||
629+ strncmp(arg, "\\\"", 2) == 0)) {
623630 /* The type of $comm must be "string", and not an array. */
624631 if (parg->count || (t && strcmp(t, "string")))
625632 goto out;