aboutsummaryrefslogtreecommitdiffstats
path: root/kernel/trace/trace_syscalls.c
diff options
context:
space:
mode:
Diffstat (limited to 'kernel/trace/trace_syscalls.c')
-rw-r--r--kernel/trace/trace_syscalls.c122
1 files changed, 76 insertions, 46 deletions
diff --git a/kernel/trace/trace_syscalls.c b/kernel/trace/trace_syscalls.c
index 2485a7d09b11..7a809e321058 100644
--- a/kernel/trace/trace_syscalls.c
+++ b/kernel/trace/trace_syscalls.c
@@ -1,5 +1,6 @@
1#include <trace/syscall.h> 1#include <trace/syscall.h>
2#include <trace/events/syscalls.h> 2#include <trace/events/syscalls.h>
3#include <linux/syscalls.h>
3#include <linux/slab.h> 4#include <linux/slab.h>
4#include <linux/kernel.h> 5#include <linux/kernel.h>
5#include <linux/module.h> /* for MODULE_NAME_LEN via KSYM_SYMBOL_LEN */ 6#include <linux/module.h> /* for MODULE_NAME_LEN via KSYM_SYMBOL_LEN */
@@ -21,9 +22,6 @@ static int syscall_enter_register(struct ftrace_event_call *event,
21static int syscall_exit_register(struct ftrace_event_call *event, 22static int syscall_exit_register(struct ftrace_event_call *event,
22 enum trace_reg type, void *data); 23 enum trace_reg type, void *data);
23 24
24static int syscall_enter_define_fields(struct ftrace_event_call *call);
25static int syscall_exit_define_fields(struct ftrace_event_call *call);
26
27static struct list_head * 25static struct list_head *
28syscall_get_enter_fields(struct ftrace_event_call *call) 26syscall_get_enter_fields(struct ftrace_event_call *call)
29{ 27{
@@ -32,30 +30,6 @@ syscall_get_enter_fields(struct ftrace_event_call *call)
32 return &entry->enter_fields; 30 return &entry->enter_fields;
33} 31}
34 32
35struct trace_event_functions enter_syscall_print_funcs = {
36 .trace = print_syscall_enter,
37};
38
39struct trace_event_functions exit_syscall_print_funcs = {
40 .trace = print_syscall_exit,
41};
42
43struct ftrace_event_class event_class_syscall_enter = {
44 .system = "syscalls",
45 .reg = syscall_enter_register,
46 .define_fields = syscall_enter_define_fields,
47 .get_fields = syscall_get_enter_fields,
48 .raw_init = init_syscall_trace,
49};
50
51struct ftrace_event_class event_class_syscall_exit = {
52 .system = "syscalls",
53 .reg = syscall_exit_register,
54 .define_fields = syscall_exit_define_fields,
55 .fields = LIST_HEAD_INIT(event_class_syscall_exit.fields),
56 .raw_init = init_syscall_trace,
57};
58
59extern struct syscall_metadata *__start_syscalls_metadata[]; 33extern struct syscall_metadata *__start_syscalls_metadata[];
60extern struct syscall_metadata *__stop_syscalls_metadata[]; 34extern struct syscall_metadata *__stop_syscalls_metadata[];
61 35
@@ -74,6 +48,38 @@ static inline bool arch_syscall_match_sym_name(const char *sym, const char *name
74} 48}
75#endif 49#endif
76 50
51#ifdef ARCH_TRACE_IGNORE_COMPAT_SYSCALLS
52/*
53 * Some architectures that allow for 32bit applications
54 * to run on a 64bit kernel, do not map the syscalls for
55 * the 32bit tasks the same as they do for 64bit tasks.
56 *
57 * *cough*x86*cough*
58 *
59 * In such a case, instead of reporting the wrong syscalls,
60 * simply ignore them.
61 *
62 * For an arch to ignore the compat syscalls it needs to
63 * define ARCH_TRACE_IGNORE_COMPAT_SYSCALLS as well as
64 * define the function arch_trace_is_compat_syscall() to let
65 * the tracing system know that it should ignore it.
66 */
67static int
68trace_get_syscall_nr(struct task_struct *task, struct pt_regs *regs)
69{
70 if (unlikely(arch_trace_is_compat_syscall(regs)))
71 return -1;
72
73 return syscall_get_nr(task, regs);
74}
75#else
76static inline int
77trace_get_syscall_nr(struct task_struct *task, struct pt_regs *regs)
78{
79 return syscall_get_nr(task, regs);
80}
81#endif /* ARCH_TRACE_IGNORE_COMPAT_SYSCALLS */
82
77static __init struct syscall_metadata * 83static __init struct syscall_metadata *
78find_syscall_meta(unsigned long syscall) 84find_syscall_meta(unsigned long syscall)
79{ 85{
@@ -104,7 +110,7 @@ static struct syscall_metadata *syscall_nr_to_meta(int nr)
104 return syscalls_metadata[nr]; 110 return syscalls_metadata[nr];
105} 111}
106 112
107enum print_line_t 113static enum print_line_t
108print_syscall_enter(struct trace_iterator *iter, int flags, 114print_syscall_enter(struct trace_iterator *iter, int flags,
109 struct trace_event *event) 115 struct trace_event *event)
110{ 116{
@@ -157,7 +163,7 @@ end:
157 return TRACE_TYPE_HANDLED; 163 return TRACE_TYPE_HANDLED;
158} 164}
159 165
160enum print_line_t 166static enum print_line_t
161print_syscall_exit(struct trace_iterator *iter, int flags, 167print_syscall_exit(struct trace_iterator *iter, int flags,
162 struct trace_event *event) 168 struct trace_event *event)
163{ 169{
@@ -297,16 +303,16 @@ static int syscall_exit_define_fields(struct ftrace_event_call *call)
297 return ret; 303 return ret;
298} 304}
299 305
300void ftrace_syscall_enter(void *ignore, struct pt_regs *regs, long id) 306static void ftrace_syscall_enter(void *ignore, struct pt_regs *regs, long id)
301{ 307{
302 struct syscall_trace_enter *entry; 308 struct syscall_trace_enter *entry;
303 struct syscall_metadata *sys_data; 309 struct syscall_metadata *sys_data;
304 struct ring_buffer_event *event; 310 struct ring_buffer_event *event;
305 struct ring_buffer *buffer; 311 struct ring_buffer *buffer;
306 int size;
307 int syscall_nr; 312 int syscall_nr;
313 int size;
308 314
309 syscall_nr = syscall_get_nr(current, regs); 315 syscall_nr = trace_get_syscall_nr(current, regs);
310 if (syscall_nr < 0) 316 if (syscall_nr < 0)
311 return; 317 return;
312 if (!test_bit(syscall_nr, enabled_enter_syscalls)) 318 if (!test_bit(syscall_nr, enabled_enter_syscalls))
@@ -332,7 +338,7 @@ void ftrace_syscall_enter(void *ignore, struct pt_regs *regs, long id)
332 trace_current_buffer_unlock_commit(buffer, event, 0, 0); 338 trace_current_buffer_unlock_commit(buffer, event, 0, 0);
333} 339}
334 340
335void ftrace_syscall_exit(void *ignore, struct pt_regs *regs, long ret) 341static void ftrace_syscall_exit(void *ignore, struct pt_regs *regs, long ret)
336{ 342{
337 struct syscall_trace_exit *entry; 343 struct syscall_trace_exit *entry;
338 struct syscall_metadata *sys_data; 344 struct syscall_metadata *sys_data;
@@ -340,7 +346,7 @@ void ftrace_syscall_exit(void *ignore, struct pt_regs *regs, long ret)
340 struct ring_buffer *buffer; 346 struct ring_buffer *buffer;
341 int syscall_nr; 347 int syscall_nr;
342 348
343 syscall_nr = syscall_get_nr(current, regs); 349 syscall_nr = trace_get_syscall_nr(current, regs);
344 if (syscall_nr < 0) 350 if (syscall_nr < 0)
345 return; 351 return;
346 if (!test_bit(syscall_nr, enabled_exit_syscalls)) 352 if (!test_bit(syscall_nr, enabled_exit_syscalls))
@@ -364,7 +370,7 @@ void ftrace_syscall_exit(void *ignore, struct pt_regs *regs, long ret)
364 trace_current_buffer_unlock_commit(buffer, event, 0, 0); 370 trace_current_buffer_unlock_commit(buffer, event, 0, 0);
365} 371}
366 372
367int reg_event_syscall_enter(struct ftrace_event_call *call) 373static int reg_event_syscall_enter(struct ftrace_event_call *call)
368{ 374{
369 int ret = 0; 375 int ret = 0;
370 int num; 376 int num;
@@ -383,7 +389,7 @@ int reg_event_syscall_enter(struct ftrace_event_call *call)
383 return ret; 389 return ret;
384} 390}
385 391
386void unreg_event_syscall_enter(struct ftrace_event_call *call) 392static void unreg_event_syscall_enter(struct ftrace_event_call *call)
387{ 393{
388 int num; 394 int num;
389 395
@@ -398,7 +404,7 @@ void unreg_event_syscall_enter(struct ftrace_event_call *call)
398 mutex_unlock(&syscall_trace_lock); 404 mutex_unlock(&syscall_trace_lock);
399} 405}
400 406
401int reg_event_syscall_exit(struct ftrace_event_call *call) 407static int reg_event_syscall_exit(struct ftrace_event_call *call)
402{ 408{
403 int ret = 0; 409 int ret = 0;
404 int num; 410 int num;
@@ -417,7 +423,7 @@ int reg_event_syscall_exit(struct ftrace_event_call *call)
417 return ret; 423 return ret;
418} 424}
419 425
420void unreg_event_syscall_exit(struct ftrace_event_call *call) 426static void unreg_event_syscall_exit(struct ftrace_event_call *call)
421{ 427{
422 int num; 428 int num;
423 429
@@ -432,7 +438,7 @@ void unreg_event_syscall_exit(struct ftrace_event_call *call)
432 mutex_unlock(&syscall_trace_lock); 438 mutex_unlock(&syscall_trace_lock);
433} 439}
434 440
435int init_syscall_trace(struct ftrace_event_call *call) 441static int init_syscall_trace(struct ftrace_event_call *call)
436{ 442{
437 int id; 443 int id;
438 int num; 444 int num;
@@ -457,12 +463,36 @@ int init_syscall_trace(struct ftrace_event_call *call)
457 return id; 463 return id;
458} 464}
459 465
466struct trace_event_functions enter_syscall_print_funcs = {
467 .trace = print_syscall_enter,
468};
469
470struct trace_event_functions exit_syscall_print_funcs = {
471 .trace = print_syscall_exit,
472};
473
474struct ftrace_event_class event_class_syscall_enter = {
475 .system = "syscalls",
476 .reg = syscall_enter_register,
477 .define_fields = syscall_enter_define_fields,
478 .get_fields = syscall_get_enter_fields,
479 .raw_init = init_syscall_trace,
480};
481
482struct ftrace_event_class event_class_syscall_exit = {
483 .system = "syscalls",
484 .reg = syscall_exit_register,
485 .define_fields = syscall_exit_define_fields,
486 .fields = LIST_HEAD_INIT(event_class_syscall_exit.fields),
487 .raw_init = init_syscall_trace,
488};
489
460unsigned long __init __weak arch_syscall_addr(int nr) 490unsigned long __init __weak arch_syscall_addr(int nr)
461{ 491{
462 return (unsigned long)sys_call_table[nr]; 492 return (unsigned long)sys_call_table[nr];
463} 493}
464 494
465int __init init_ftrace_syscalls(void) 495static int __init init_ftrace_syscalls(void)
466{ 496{
467 struct syscall_metadata *meta; 497 struct syscall_metadata *meta;
468 unsigned long addr; 498 unsigned long addr;
@@ -505,7 +535,7 @@ static void perf_syscall_enter(void *ignore, struct pt_regs *regs, long id)
505 int rctx; 535 int rctx;
506 int size; 536 int size;
507 537
508 syscall_nr = syscall_get_nr(current, regs); 538 syscall_nr = trace_get_syscall_nr(current, regs);
509 if (syscall_nr < 0) 539 if (syscall_nr < 0)
510 return; 540 return;
511 if (!test_bit(syscall_nr, enabled_perf_enter_syscalls)) 541 if (!test_bit(syscall_nr, enabled_perf_enter_syscalls))
@@ -537,7 +567,7 @@ static void perf_syscall_enter(void *ignore, struct pt_regs *regs, long id)
537 perf_trace_buf_submit(rec, size, rctx, 0, 1, regs, head, NULL); 567 perf_trace_buf_submit(rec, size, rctx, 0, 1, regs, head, NULL);
538} 568}
539 569
540int perf_sysenter_enable(struct ftrace_event_call *call) 570static int perf_sysenter_enable(struct ftrace_event_call *call)
541{ 571{
542 int ret = 0; 572 int ret = 0;
543 int num; 573 int num;
@@ -558,7 +588,7 @@ int perf_sysenter_enable(struct ftrace_event_call *call)
558 return ret; 588 return ret;
559} 589}
560 590
561void perf_sysenter_disable(struct ftrace_event_call *call) 591static void perf_sysenter_disable(struct ftrace_event_call *call)
562{ 592{
563 int num; 593 int num;
564 594
@@ -581,7 +611,7 @@ static void perf_syscall_exit(void *ignore, struct pt_regs *regs, long ret)
581 int rctx; 611 int rctx;
582 int size; 612 int size;
583 613
584 syscall_nr = syscall_get_nr(current, regs); 614 syscall_nr = trace_get_syscall_nr(current, regs);
585 if (syscall_nr < 0) 615 if (syscall_nr < 0)
586 return; 616 return;
587 if (!test_bit(syscall_nr, enabled_perf_exit_syscalls)) 617 if (!test_bit(syscall_nr, enabled_perf_exit_syscalls))
@@ -615,7 +645,7 @@ static void perf_syscall_exit(void *ignore, struct pt_regs *regs, long ret)
615 perf_trace_buf_submit(rec, size, rctx, 0, 1, regs, head, NULL); 645 perf_trace_buf_submit(rec, size, rctx, 0, 1, regs, head, NULL);
616} 646}
617 647
618int perf_sysexit_enable(struct ftrace_event_call *call) 648static int perf_sysexit_enable(struct ftrace_event_call *call)
619{ 649{
620 int ret = 0; 650 int ret = 0;
621 int num; 651 int num;
@@ -636,7 +666,7 @@ int perf_sysexit_enable(struct ftrace_event_call *call)
636 return ret; 666 return ret;
637} 667}
638 668
639void perf_sysexit_disable(struct ftrace_event_call *call) 669static void perf_sysexit_disable(struct ftrace_event_call *call)
640{ 670{
641 int num; 671 int num;
642 672