diff options
Diffstat (limited to 'kernel/trace/trace_syscalls.c')
| -rw-r--r-- | kernel/trace/trace_syscalls.c | 122 |
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, | |||
| 21 | static int syscall_exit_register(struct ftrace_event_call *event, | 22 | static 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 | ||
| 24 | static int syscall_enter_define_fields(struct ftrace_event_call *call); | ||
| 25 | static int syscall_exit_define_fields(struct ftrace_event_call *call); | ||
| 26 | |||
| 27 | static struct list_head * | 25 | static struct list_head * |
| 28 | syscall_get_enter_fields(struct ftrace_event_call *call) | 26 | syscall_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 | ||
| 35 | struct trace_event_functions enter_syscall_print_funcs = { | ||
| 36 | .trace = print_syscall_enter, | ||
| 37 | }; | ||
| 38 | |||
| 39 | struct trace_event_functions exit_syscall_print_funcs = { | ||
| 40 | .trace = print_syscall_exit, | ||
| 41 | }; | ||
| 42 | |||
| 43 | struct 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 | |||
| 51 | struct 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 | |||
| 59 | extern struct syscall_metadata *__start_syscalls_metadata[]; | 33 | extern struct syscall_metadata *__start_syscalls_metadata[]; |
| 60 | extern struct syscall_metadata *__stop_syscalls_metadata[]; | 34 | extern 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 | */ | ||
| 67 | static int | ||
| 68 | trace_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 | ||
| 76 | static inline int | ||
| 77 | trace_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 | |||
| 77 | static __init struct syscall_metadata * | 83 | static __init struct syscall_metadata * |
| 78 | find_syscall_meta(unsigned long syscall) | 84 | find_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 | ||
| 107 | enum print_line_t | 113 | static enum print_line_t |
| 108 | print_syscall_enter(struct trace_iterator *iter, int flags, | 114 | print_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 | ||
| 160 | enum print_line_t | 166 | static enum print_line_t |
| 161 | print_syscall_exit(struct trace_iterator *iter, int flags, | 167 | print_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 | ||
| 300 | void ftrace_syscall_enter(void *ignore, struct pt_regs *regs, long id) | 306 | static 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 | ||
| 335 | void ftrace_syscall_exit(void *ignore, struct pt_regs *regs, long ret) | 341 | static 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 | ||
| 367 | int reg_event_syscall_enter(struct ftrace_event_call *call) | 373 | static 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 | ||
| 386 | void unreg_event_syscall_enter(struct ftrace_event_call *call) | 392 | static 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 | ||
| 401 | int reg_event_syscall_exit(struct ftrace_event_call *call) | 407 | static 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 | ||
| 420 | void unreg_event_syscall_exit(struct ftrace_event_call *call) | 426 | static 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 | ||
| 435 | int init_syscall_trace(struct ftrace_event_call *call) | 441 | static 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 | ||
| 466 | struct trace_event_functions enter_syscall_print_funcs = { | ||
| 467 | .trace = print_syscall_enter, | ||
| 468 | }; | ||
| 469 | |||
| 470 | struct trace_event_functions exit_syscall_print_funcs = { | ||
| 471 | .trace = print_syscall_exit, | ||
| 472 | }; | ||
| 473 | |||
| 474 | struct 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 | |||
| 482 | struct 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 | |||
| 460 | unsigned long __init __weak arch_syscall_addr(int nr) | 490 | unsigned 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 | ||
| 465 | int __init init_ftrace_syscalls(void) | 495 | static 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 | ||
| 540 | int perf_sysenter_enable(struct ftrace_event_call *call) | 570 | static 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 | ||
| 561 | void perf_sysenter_disable(struct ftrace_event_call *call) | 591 | static 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 | ||
| 618 | int perf_sysexit_enable(struct ftrace_event_call *call) | 648 | static 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 | ||
| 639 | void perf_sysexit_disable(struct ftrace_event_call *call) | 669 | static void perf_sysexit_disable(struct ftrace_event_call *call) |
| 640 | { | 670 | { |
| 641 | int num; | 671 | int num; |
| 642 | 672 | ||
