Skip to content

Commit 6a832ec

Browse files
committed
tracing/eprobes: Have event probes be consistent with kprobes and uprobes
Currently, if a symbol "@" is attempted to be used with an event probe (eprobes), it will cause a NULL pointer dereference crash. Both kprobes and uprobes can reference data other than the main registers. Such as immediate address, symbols and the current task name. Have eprobes do the same thing. For "comm", if "comm" is used and the event being attached to does not have the "comm" field, then make it the "$comm" that kprobes has. This is consistent to the way histograms and filters work. Link: https://lkml.kernel.org/r/[email protected] Cc: [email protected] Cc: Ingo Molnar <[email protected]> Cc: Andrew Morton <[email protected]> Cc: Masami Hiramatsu <[email protected]> Cc: Tzvetomir Stoyanov <[email protected]> Cc: Tom Zanussi <[email protected]> Fixes: 7491e2c ("tracing: Add a probe that attaches to trace events") Signed-off-by: Steven Rostedt (Google) <[email protected]>
1 parent f04dec9 commit 6a832ec

File tree

1 file changed

+64
-6
lines changed

1 file changed

+64
-6
lines changed

kernel/trace/trace_eprobe.c

Lines changed: 64 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -227,6 +227,7 @@ static int trace_eprobe_tp_arg_update(struct trace_eprobe *ep, int i)
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)
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)
@@ -363,16 +375,38 @@ static unsigned long get_event_field(struct fetch_insn *code, void *rec)
363375

364376
static int get_eprobe_size(struct trace_probe *tp, void *rec)
365377
{
378+
struct fetch_insn *code;
366379
struct probe_arg *arg;
367380
int i, len, ret = 0;
368381

369382
for (i = 0; i < tp->nr_args; i++) {
370383
arg = tp->args + i;
371-
if (unlikely(arg->dynamic)) {
384+
if (arg->dynamic) {
372385
unsigned long val;
373386

374-
val = get_event_field(arg->code, rec);
375-
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);
376410
if (len > 0)
377411
ret += len;
378412
}
@@ -390,8 +424,28 @@ process_fetch_insn(struct fetch_insn *code, void *rec, void *dest,
390424
{
391425
unsigned long val;
392426

393-
val = get_event_field(code, rec);
394-
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);
395449
}
396450
NOKPROBE_SYMBOL(process_fetch_insn)
397451

@@ -866,6 +920,10 @@ static int trace_eprobe_tp_update_arg(struct trace_eprobe *ep, const char *argv[
866920
trace_probe_log_err(0, BAD_ATTACH_ARG);
867921
}
868922

923+
/* Handle symbols "@" */
924+
if (!ret)
925+
ret = traceprobe_update_arg(&ep->tp.args[i]);
926+
869927
return ret;
870928
}
871929

0 commit comments

Comments
 (0)