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
2974 2974
2975 ftrace_startup_enable(command);2975 ftrace_startup_enable(command);
2976 2976
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
2977 ops->flags &= ~FTRACE_OPS_FL_ADDING;2987 ops->flags &= ~FTRACE_OPS_FL_ADDING;
2978 2988
2979 return 0;2989 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
227 struct probe_arg *parg = &ep->tp.args[i];227 struct probe_arg *parg = &ep->tp.args[i];
228 struct ftrace_event_field *field;228 struct ftrace_event_field *field;
229 struct list_head *head;229 struct list_head *head;
230 int ret = -ENOENT;
230 231
231 head = trace_get_fields(ep->event);232 head = trace_get_fields(ep->event);
232 list_for_each_entry(field, head, link) {233 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
236 return 0;237 return 0;
237 }238 }
238 }239 }
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
239 kfree(parg->code->data);251 kfree(parg->code->data);
240 parg->code->data = NULL;252 parg->code->data = NULL;
241 return -ENOENT;253 return ret;
242}254}
243 255
244static int eprobe_event_define_fields(struct trace_event_call *event_call)256static 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
311 323
312 addr = rec + field->offset;324 addr = rec + field->offset;
313 325
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
314 switch (field->size) {347 switch (field->size) {
315 case 1:348 case 1:
316 if (field->is_signed)349 if (field->is_signed)
@@ -342,16 +375,38 @@ static unsigned long get_event_field(struct fetch_insn *code, void *rec) · 25 unmodified lines
342 375
343static int get_eprobe_size(struct trace_probe *tp, void *rec)376static int get_eprobe_size(struct trace_probe *tp, void *rec)
344{377{
378 struct fetch_insn *code;
345 struct probe_arg *arg;379 struct probe_arg *arg;
346 int i, len, ret = 0;380 int i, len, ret = 0;
347 381
348 for (i = 0; i < tp->nr_args; i++) {382 for (i = 0; i < tp->nr_args; i++) {
349 arg = tp->args + i;383 arg = tp->args + i;
350 if (unlikely(arg->dynamic)) {384 if (arg->dynamic) {
351 unsigned long val;385 unsigned long val;
352 386
353 val = get_event_field(arg->code, rec);387 code = arg->code;
354 len = process_fetch_insn_bottom(arg->code + 1, val, NULL, NULL);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);
355 if (len > 0)410 if (len > 0)
356 ret += len;411 ret += len;
357 }412 }
@@ -369,8 +424,28 @@ process_fetch_insn(struct fetch_insn *code, void *rec, void *dest, · 11 unmodified lines
369{424{
370 unsigned long val;425 unsigned long val;
371 426
372 val = get_event_field(code, rec);427 retry:
373 return process_fetch_insn_bottom(code + 1, val, dest, base);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);
374}449}
375NOKPROBE_SYMBOL(process_fetch_insn)450NOKPROBE_SYMBOL(process_fetch_insn)
376 451
@@ -845,6 +920,10 @@ static int trace_eprobe_tp_update_arg(struct trace_eprobe *ep, const char *argv[ · 468 unmodified lines
845 trace_probe_log_err(0, BAD_ATTACH_ARG);920 trace_probe_log_err(0, BAD_ATTACH_ARG);
846 }921 }
847 922
923 /* Handle symbols "@" */
924 if (!ret)
925 ret = traceprobe_update_arg(&ep->tp.args[i]);
926
848 return ret;927 return ret;
849}928}
850 929
@@ -883,7 +962,7 @@ static int __trace_eprobe_create(int argc, const char *argv[]) · 32 unmodified lines
883 trace_probe_log_set_index(1);962 trace_probe_log_set_index(1);
884 sys_event = argv[1];963 sys_event = argv[1];
885 ret = traceprobe_parse_event_name(&sys_event, &sys_name, buf2, 0);964 ret = traceprobe_parse_event_name(&sys_event, &sys_name, buf2, 0);
886 if (!sys_event || !sys_name) {965 if (ret || !sys_event || !sys_name) {
887 trace_probe_log_err(0, NO_EVENT_INFO);966 trace_probe_log_err(0, NO_EVENT_INFO);
888 goto parse_error;967 goto parse_error;
889 }968 }
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
157 int i;157 int i;
158 158
159 if (--tp_event->perf_refcount > 0)159 if (--tp_event->perf_refcount > 0)
160 goto out;160 return;
161 161
162 tp_event->class->reg(tp_event, TRACE_REG_PERF_UNREGISTER, NULL);162 tp_event->class->reg(tp_event, TRACE_REG_PERF_UNREGISTER, NULL);
163 163
@@ -176,8 +176,6 @@ static void perf_trace_event_unreg(struct perf_event *p_event) · 12 unmodified lines
176 perf_trace_buf[i] = NULL;176 perf_trace_buf[i] = NULL;
177 }177 }
178 }178 }
179out:
180 trace_event_put_ref(tp_event);
181}179}
182 180
183static int perf_trace_event_open(struct perf_event *p_event)181static 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
241 mutex_lock(&event_mutex);239 mutex_lock(&event_mutex);
242 perf_trace_event_close(p_event);240 perf_trace_event_close(p_event);
243 perf_trace_event_unreg(p_event);241 perf_trace_event_unreg(p_event);
242 trace_event_put_ref(p_event->tp_event);
244 mutex_unlock(&event_mutex);243 mutex_unlock(&event_mutex);
245}244}
246 245
@@ -292,6 +291,7 @@ void perf_kprobe_destroy(struct perf_event *p_event) · 45 unmodified lines
292 mutex_lock(&event_mutex);291 mutex_lock(&event_mutex);
293 perf_trace_event_close(p_event);292 perf_trace_event_close(p_event);
294 perf_trace_event_unreg(p_event);293 perf_trace_event_unreg(p_event);
294 trace_event_put_ref(p_event->tp_event);
295 mutex_unlock(&event_mutex);295 mutex_unlock(&event_mutex);
296 296
297 destroy_local_trace_kprobe(p_event->tp_event);297 destroy_local_trace_kprobe(p_event->tp_event);
@@ -347,6 +347,7 @@ void perf_uprobe_destroy(struct perf_event *p_event) · 49 unmodified lines
347 mutex_lock(&event_mutex);347 mutex_lock(&event_mutex);
348 perf_trace_event_close(p_event);348 perf_trace_event_close(p_event);
349 perf_trace_event_unreg(p_event);349 perf_trace_event_unreg(p_event);
350 trace_event_put_ref(p_event->tp_event);
350 mutex_unlock(&event_mutex);351 mutex_unlock(&event_mutex);
351 destroy_local_trace_uprobe(p_event->tp_event);352 destroy_local_trace_uprobe(p_event->tp_event);
352}353}
kernel/trace/trace_events.c+1−0
@@ -176,6 +176,7 @@ static int trace_define_generic_fields(void) · 175 unmodified lines
176 176
177 __generic_field(int, CPU, FILTER_CPU);177 __generic_field(int, CPU, FILTER_CPU);
178 __generic_field(int, cpu, FILTER_CPU);178 __generic_field(int, cpu, FILTER_CPU);
179 __generic_field(int, common_cpu, FILTER_CPU);
179 __generic_field(char *, COMM, FILTER_COMM);180 __generic_field(char *, COMM, FILTER_COMM);
180 __generic_field(char *, comm, FILTER_COMM);181 __generic_field(char *, comm, FILTER_COMM);
181 182
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
283 int ret = 0;283 int ret = 0;
284 int len;284 int len;
285 285
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) {
287 if (flags & TPARG_FL_RETURN) {294 if (flags & TPARG_FL_RETURN) {
288 code->op = FETCH_OP_RETVAL;295 code->op = FETCH_OP_RETVAL;
289 } else {296 } else {
@@ -307,7 +314,7 @@ static int parse_probe_vars(char *arg, const struct fetch_type *t, · 17 unmodified lines
307 }314 }
308 } else315 } else
309 goto inval_var;316 goto inval_var;
310 } else if (strcmp(arg, "comm") == 0) {317 } else if (strcmp(arg, "comm") == 0 || strcmp(arg, "COMM") == 0) {
311 code->op = FETCH_OP_COMM;318 code->op = FETCH_OP_COMM;
312#ifdef CONFIG_HAVE_FUNCTION_ARG_ACCESS_API319#ifdef CONFIG_HAVE_FUNCTION_ARG_ACCESS_API
313 } else if (((flags & TPARG_FL_MASK) ==320 } 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
323 code->op = FETCH_OP_ARG;330 code->op = FETCH_OP_ARG;
324 code->param = (unsigned int)param - 1;331 code->param = (unsigned int)param - 1;
325#endif332#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;
333 } else333 } else
334 goto inval_var;334 goto inval_var;
335 335
@@ -384,6 +384,11 @@ parse_probe_arg(char *arg, const struct fetch_type *type, · 48 unmodified lines
384 break;384 break;
385 385
386 case '%': /* named register */386 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 }
387 ret = regs_query_register_offset(arg + 1);392 ret = regs_query_register_offset(arg + 1);
388 if (ret >= 0) {393 if (ret >= 0) {
389 code->op = FETCH_OP_REG;394 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
617 622
618 /*623 /*
619 * Since $comm and immediate string can not be dereferenced,624 * 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.
621 */626 */
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)) {
623 /* The type of $comm must be "string", and not an array. */630 /* The type of $comm must be "string", and not an array. */
624 if (parg->count || (t && strcmp(t, "string")))631 if (parg->count || (t && strcmp(t, "string")))
625 goto out;632 goto out;