X-Git-Url: http://git.lttng.org/?p=lttng-modules.git;a=blobdiff_plain;f=lttng-syscalls.c;h=a5b5f403fe359e6531650111fc05cb82a6c60aba;hp=a4a8ed44cd9c76dbc38d0ce8e319182b9f52392e;hb=cd4486798c2b046ea93b89439cd705e93c40b349;hpb=72a527538699ab5c72bfb0080a975f04209328b9 diff --git a/lttng-syscalls.c b/lttng-syscalls.c index a4a8ed44..a5b5f403 100644 --- a/lttng-syscalls.c +++ b/lttng-syscalls.c @@ -1,23 +1,10 @@ -/* +/* SPDX-License-Identifier: (GPL-2.0-only or LGPL-2.1-only) + * * lttng-syscalls.c * * LTTng syscall probes. * * Copyright (C) 2010-2012 Mathieu Desnoyers - * - * This library is free software; you can redistribute it and/or - * modify it under the terms of the GNU Lesser General Public - * License as published by the Free Software Foundation; only - * version 2.1 of the License. - * - * This library is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU - * Lesser General Public License for more details. - * - * You should have received a copy of the GNU Lesser General Public - * License along with this library; if not, write to the Free Software - * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA */ #include @@ -29,12 +16,18 @@ #include #include #include +#include +#include +#include #include #include -#include "lib/bitfield.h" -#include "wrapper/tracepoint.h" -#include "lttng-events.h" +#include +#include +#include +#include +#include +#include #ifndef CONFIG_COMPAT # ifndef is_compat_task @@ -42,6 +35,11 @@ # endif #endif +/* in_compat_syscall appears in kernel 4.6. */ +#ifndef in_compat_syscall + #define in_compat_syscall() is_compat_task() +#endif + enum sc_type { SC_TYPE_ENTRY, SC_TYPE_EXIT, @@ -73,6 +71,20 @@ struct oldold_utsname; struct old_utsname; struct sel_arg_struct; struct mmap_arg_struct; +struct file_handle; +struct user_msghdr; + +/* + * Forward declaration for kernels >= 5.6 + */ +struct timex; +struct timeval; +struct itimerval; +struct itimerspec; + +#if (LINUX_VERSION_CODE >= KERNEL_VERSION(5,6,0)) +typedef __kernel_old_time_t time_t; +#endif #ifdef IA32_NR_syscalls #define NR_compat_syscalls IA32_NR_syscalls @@ -86,14 +98,14 @@ struct mmap_arg_struct; #define LTTNG_PACKAGE_BUILD #define CREATE_TRACE_POINTS #define TP_MODULE_NOINIT -#define TRACE_INCLUDE_PATH ../instrumentation/syscalls/headers +#define TRACE_INCLUDE_PATH instrumentation/syscalls/headers #define PARAMS(args...) args /* Handle unknown syscalls */ #undef TRACE_SYSTEM #define TRACE_SYSTEM syscalls_unknown -#include "instrumentation/syscalls/headers/syscalls_unknown.h" +#include #undef TRACE_SYSTEM #define SC_ENTER @@ -110,29 +122,32 @@ struct mmap_arg_struct; /* Hijack probe callback for system call enter */ #undef TP_PROBE_CB #define TP_PROBE_CB(_template) &syscall_entry_probe -#define SC_LTTNG_TRACEPOINT_EVENT(_name, _proto, _args, _struct, _assign, _printk) \ +#define SC_LTTNG_TRACEPOINT_EVENT(_name, _proto, _args, _fields) \ LTTNG_TRACEPOINT_EVENT(syscall_entry_##_name, PARAMS(_proto), PARAMS(_args), \ - PARAMS(_struct), PARAMS(_assign), PARAMS(_printk)) -#define SC_LTTNG_TRACEPOINT_EVENT_CODE(_name, _proto, _args, _locvar, _code, _struct, _assign, _printk) \ + PARAMS(_fields)) +#define SC_LTTNG_TRACEPOINT_EVENT_CODE(_name, _proto, _args, _locvar, _code_pre, _fields, _code_post) \ LTTNG_TRACEPOINT_EVENT_CODE(syscall_entry_##_name, PARAMS(_proto), PARAMS(_args), \ - PARAMS(_locvar), PARAMS(_code), \ - PARAMS(_struct), PARAMS(_assign), PARAMS(_printk)) -#define SC_LTTNG_TRACEPOINT_EVENT_CLASS_NOARGS(_name, _struct, _assign, _printk) \ - LTTNG_TRACEPOINT_EVENT_CLASS_NOARGS(syscall_entry_##_name, PARAMS(_struct), PARAMS(_assign), \ - PARAMS(_printk)) + PARAMS(_locvar), PARAMS(_code_pre), \ + PARAMS(_fields), PARAMS(_code_post)) +#define SC_LTTNG_TRACEPOINT_EVENT_CLASS_NOARGS(_name, _fields) \ + LTTNG_TRACEPOINT_EVENT_CLASS_NOARGS(syscall_entry_##_name, PARAMS(_fields)) #define SC_LTTNG_TRACEPOINT_EVENT_INSTANCE_NOARGS(_template, _name) \ LTTNG_TRACEPOINT_EVENT_INSTANCE_NOARGS(syscall_entry_##_template, syscall_entry_##_name) +/* Enumerations only defined at first inclusion. */ +#define SC_LTTNG_TRACEPOINT_ENUM(_name, _values) \ + LTTNG_TRACEPOINT_ENUM(_name, PARAMS(_values)) #undef TRACE_SYSTEM #define TRACE_SYSTEM syscall_entry_integers #define TRACE_INCLUDE_FILE syscalls_integers -#include "instrumentation/syscalls/headers/syscalls_integers.h" +#include #undef TRACE_INCLUDE_FILE #undef TRACE_SYSTEM #define TRACE_SYSTEM syscall_entry_pointers #define TRACE_INCLUDE_FILE syscalls_pointers -#include "instrumentation/syscalls/headers/syscalls_pointers.h" +#include #undef TRACE_INCLUDE_FILE #undef TRACE_SYSTEM +#undef SC_LTTNG_TRACEPOINT_ENUM #undef SC_LTTNG_TRACEPOINT_EVENT_CODE #undef SC_LTTNG_TRACEPOINT_EVENT #undef SC_LTTNG_TRACEPOINT_EVENT_CLASS_NOARGS @@ -143,30 +158,31 @@ struct mmap_arg_struct; /* Hijack probe callback for compat system call enter */ #define TP_PROBE_CB(_template) &syscall_entry_probe -#define SC_LTTNG_TRACEPOINT_EVENT(_name, _proto, _args, _struct, _assign, _printk) \ +#define LTTNG_SC_COMPAT +#define SC_LTTNG_TRACEPOINT_EVENT(_name, _proto, _args, _fields) \ LTTNG_TRACEPOINT_EVENT(compat_syscall_entry_##_name, PARAMS(_proto), PARAMS(_args), \ - PARAMS(_struct), PARAMS(_assign), \ - PARAMS(_printk)) -#define SC_LTTNG_TRACEPOINT_EVENT_CODE(_name, _proto, _args, _locvar, _code, _struct, _assign, _printk) \ + PARAMS(_fields)) +#define SC_LTTNG_TRACEPOINT_EVENT_CODE(_name, _proto, _args, _locvar, _code_pre, _fields, _code_post) \ LTTNG_TRACEPOINT_EVENT_CODE(compat_syscall_entry_##_name, PARAMS(_proto), PARAMS(_args), \ - PARAMS(_locvar), PARAMS(_code), \ - PARAMS(_struct), PARAMS(_assign), PARAMS(_printk)) -#define SC_LTTNG_TRACEPOINT_EVENT_CLASS_NOARGS(_name, _struct, _assign, _printk) \ - LTTNG_TRACEPOINT_EVENT_CLASS_NOARGS(compat_syscall_entry_##_name, PARAMS(_struct), \ - PARAMS(_assign), PARAMS(_printk)) + PARAMS(_locvar), PARAMS(_code_pre), PARAMS(_fields), PARAMS(_code_post)) +#define SC_LTTNG_TRACEPOINT_EVENT_CLASS_NOARGS(_name, _fields) \ + LTTNG_TRACEPOINT_EVENT_CLASS_NOARGS(compat_syscall_entry_##_name, PARAMS(_fields)) #define SC_LTTNG_TRACEPOINT_EVENT_INSTANCE_NOARGS(_template, _name) \ LTTNG_TRACEPOINT_EVENT_INSTANCE_NOARGS(compat_syscall_entry_##_template, \ compat_syscall_entry_##_name) +/* Enumerations only defined at inital inclusion (not here). */ +#define SC_LTTNG_TRACEPOINT_ENUM(_name, _values) #define TRACE_SYSTEM compat_syscall_entry_integers #define TRACE_INCLUDE_FILE compat_syscalls_integers -#include "instrumentation/syscalls/headers/compat_syscalls_integers.h" +#include #undef TRACE_INCLUDE_FILE #undef TRACE_SYSTEM #define TRACE_SYSTEM compat_syscall_entry_pointers #define TRACE_INCLUDE_FILE compat_syscalls_pointers -#include "instrumentation/syscalls/headers/compat_syscalls_pointers.h" +#include #undef TRACE_INCLUDE_FILE #undef TRACE_SYSTEM +#undef SC_LTTNG_TRACEPOINT_ENUM #undef SC_LTTNG_TRACEPOINT_EVENT_CODE #undef SC_LTTNG_TRACEPOINT_EVENT #undef SC_LTTNG_TRACEPOINT_EVENT_CLASS_NOARGS @@ -174,6 +190,7 @@ struct mmap_arg_struct; #undef TP_PROBE_CB #undef _TRACE_SYSCALLS_INTEGERS_H #undef _TRACE_SYSCALLS_POINTERS_H +#undef LTTNG_SC_COMPAT #undef SC_ENTER @@ -190,29 +207,30 @@ struct mmap_arg_struct; /* Hijack probe callback for system call exit */ #define TP_PROBE_CB(_template) &syscall_exit_probe -#define SC_LTTNG_TRACEPOINT_EVENT(_name, _proto, _args, _struct, _assign, _printk) \ +#define SC_LTTNG_TRACEPOINT_EVENT(_name, _proto, _args, _fields) \ LTTNG_TRACEPOINT_EVENT(syscall_exit_##_name, PARAMS(_proto), PARAMS(_args), \ - PARAMS(_struct), PARAMS(_assign), PARAMS(_printk)) -#define SC_LTTNG_TRACEPOINT_EVENT_CODE(_name, _proto, _args, _locvar, _code, _struct, _assign, _printk) \ + PARAMS(_fields)) +#define SC_LTTNG_TRACEPOINT_EVENT_CODE(_name, _proto, _args, _locvar, _code_pre, _fields, _code_post) \ LTTNG_TRACEPOINT_EVENT_CODE(syscall_exit_##_name, PARAMS(_proto), PARAMS(_args), \ - PARAMS(_locvar), PARAMS(_code), \ - PARAMS(_struct), PARAMS(_assign), PARAMS(_printk)) -#define SC_LTTNG_TRACEPOINT_EVENT_CLASS_NOARGS(_name, _struct, _assign, _printk) \ - LTTNG_TRACEPOINT_EVENT_CLASS_NOARGS(syscall_exit_##_name, PARAMS(_struct), \ - PARAMS(_assign), PARAMS(_printk)) + PARAMS(_locvar), PARAMS(_code_pre), PARAMS(_fields), PARAMS(_code_post)) +#define SC_LTTNG_TRACEPOINT_EVENT_CLASS_NOARGS(_name, _fields) \ + LTTNG_TRACEPOINT_EVENT_CLASS_NOARGS(syscall_exit_##_name, PARAMS(_fields)) #define SC_LTTNG_TRACEPOINT_EVENT_INSTANCE_NOARGS(_template, _name) \ LTTNG_TRACEPOINT_EVENT_INSTANCE_NOARGS(syscall_exit_##_template, \ syscall_exit_##_name) +/* Enumerations only defined at inital inclusion (not here). */ +#define SC_LTTNG_TRACEPOINT_ENUM(_name, _values) #define TRACE_SYSTEM syscall_exit_integers #define TRACE_INCLUDE_FILE syscalls_integers -#include "instrumentation/syscalls/headers/syscalls_integers.h" +#include #undef TRACE_INCLUDE_FILE #undef TRACE_SYSTEM #define TRACE_SYSTEM syscall_exit_pointers #define TRACE_INCLUDE_FILE syscalls_pointers -#include "instrumentation/syscalls/headers/syscalls_pointers.h" +#include #undef TRACE_INCLUDE_FILE #undef TRACE_SYSTEM +#undef SC_LTTNG_TRACEPOINT_ENUM #undef SC_LTTNG_TRACEPOINT_EVENT_CODE #undef SC_LTTNG_TRACEPOINT_EVENT #undef SC_LTTNG_TRACEPOINT_EVENT_CLASS_NOARGS @@ -224,29 +242,31 @@ struct mmap_arg_struct; /* Hijack probe callback for compat system call exit */ #define TP_PROBE_CB(_template) &syscall_exit_probe -#define SC_LTTNG_TRACEPOINT_EVENT(_name, _proto, _args, _struct, _assign, _printk) \ +#define LTTNG_SC_COMPAT +#define SC_LTTNG_TRACEPOINT_EVENT(_name, _proto, _args, _fields) \ LTTNG_TRACEPOINT_EVENT(compat_syscall_exit_##_name, PARAMS(_proto), PARAMS(_args), \ - PARAMS(_struct), PARAMS(_assign), PARAMS(_printk)) -#define SC_LTTNG_TRACEPOINT_EVENT_CODE(_name, _proto, _args, _locvar, _code, _struct, _assign, _printk) \ + PARAMS(_fields)) +#define SC_LTTNG_TRACEPOINT_EVENT_CODE(_name, _proto, _args, _locvar, _code_pre, _fields, _code_post) \ LTTNG_TRACEPOINT_EVENT_CODE(compat_syscall_exit_##_name, PARAMS(_proto), PARAMS(_args), \ - PARAMS(_locvar), PARAMS(_code), \ - PARAMS(_struct), PARAMS(_assign), PARAMS(_printk)) -#define SC_LTTNG_TRACEPOINT_EVENT_CLASS_NOARGS(_name, _struct, _assign, _printk) \ - LTTNG_TRACEPOINT_EVENT_CLASS_NOARGS(compat_syscall_exit_##_name, PARAMS(_struct), \ - PARAMS(_assign), PARAMS(_printk)) + PARAMS(_locvar), PARAMS(_code_pre), PARAMS(_fields), PARAMS(_code_post)) +#define SC_LTTNG_TRACEPOINT_EVENT_CLASS_NOARGS(_name, _fields) \ + LTTNG_TRACEPOINT_EVENT_CLASS_NOARGS(compat_syscall_exit_##_name, PARAMS(_fields)) #define SC_LTTNG_TRACEPOINT_EVENT_INSTANCE_NOARGS(_template, _name) \ LTTNG_TRACEPOINT_EVENT_INSTANCE_NOARGS(compat_syscall_exit_##_template, \ compat_syscall_exit_##_name) +/* Enumerations only defined at inital inclusion (not here). */ +#define SC_LTTNG_TRACEPOINT_ENUM(_name, _values) #define TRACE_SYSTEM compat_syscall_exit_integers #define TRACE_INCLUDE_FILE compat_syscalls_integers -#include "instrumentation/syscalls/headers/compat_syscalls_integers.h" +#include #undef TRACE_INCLUDE_FILE #undef TRACE_SYSTEM #define TRACE_SYSTEM compat_syscall_exit_pointers #define TRACE_INCLUDE_FILE compat_syscalls_pointers -#include "instrumentation/syscalls/headers/compat_syscalls_pointers.h" +#include #undef TRACE_INCLUDE_FILE #undef TRACE_SYSTEM +#undef SC_LTTNG_TRACEPOINT_ENUM #undef SC_LTTNG_TRACEPOINT_EVENT_CODE #undef SC_LTTNG_TRACEPOINT_EVENT #undef SC_LTTNG_TRACEPOINT_EVENT_CLASS_NOARGS @@ -254,6 +274,7 @@ struct mmap_arg_struct; #undef TP_PROBE_CB #undef _TRACE_SYSCALLS_INTEGERS_H #undef _TRACE_SYSCALLS_POINTERS_H +#undef LTTNG_SC_COMPAT #undef SC_EXIT @@ -286,8 +307,8 @@ struct trace_syscall_entry { /* Syscall enter tracing table */ static const struct trace_syscall_entry sc_table[] = { -#include "instrumentation/syscalls/headers/syscalls_integers.h" -#include "instrumentation/syscalls/headers/syscalls_pointers.h" +#include +#include }; #undef TRACE_SYSCALL_TABLE @@ -301,8 +322,8 @@ static const struct trace_syscall_entry sc_table[] = { /* Compat syscall enter table */ const struct trace_syscall_entry compat_sc_table[] = { -#include "instrumentation/syscalls/headers/compat_syscalls_integers.h" -#include "instrumentation/syscalls/headers/compat_syscalls_pointers.h" +#include +#include }; #undef SC_ENTER @@ -323,8 +344,8 @@ const struct trace_syscall_entry compat_sc_table[] = { /* Syscall exit table */ static const struct trace_syscall_entry sc_exit_table[] = { -#include "instrumentation/syscalls/headers/syscalls_integers.h" -#include "instrumentation/syscalls/headers/syscalls_pointers.h" +#include +#include }; #undef TRACE_SYSCALL_TABLE @@ -338,8 +359,8 @@ static const struct trace_syscall_entry sc_exit_table[] = { /* Compat syscall exit table */ const struct trace_syscall_entry compat_sc_exit_table[] = { -#include "instrumentation/syscalls/headers/compat_syscalls_integers.h" -#include "instrumentation/syscalls/headers/compat_syscalls_pointers.h" +#include +#include }; #undef SC_EXIT @@ -354,10 +375,10 @@ struct lttng_syscall_filter { static void syscall_entry_unknown(struct lttng_event *event, struct pt_regs *regs, unsigned int id) { - unsigned long args[UNKNOWN_SYSCALL_NRARGS]; + unsigned long args[LTTNG_SYSCALL_NR_ARGS]; - syscall_get_arguments(current, regs, 0, UNKNOWN_SYSCALL_NRARGS, args); - if (unlikely(is_compat_task())) + lttng_syscall_get_arguments(current, regs, args); + if (unlikely(in_compat_syscall())) __event_probe__compat_syscall_entry_unknown(event, id, args); else __event_probe__syscall_entry_unknown(event, id, args); @@ -370,12 +391,12 @@ void syscall_entry_probe(void *__data, struct pt_regs *regs, long id) const struct trace_syscall_entry *table, *entry; size_t table_len; - if (unlikely(is_compat_task())) { + if (unlikely(in_compat_syscall())) { struct lttng_syscall_filter *filter; - filter = rcu_dereference(chan->sc_filter); + filter = lttng_rcu_dereference(chan->sc_filter); if (filter) { - if (id >= NR_compat_syscalls + if (id < 0 || id >= NR_compat_syscalls || !test_bit(id, filter->sc_compat)) { /* System call filtered out. */ return; @@ -387,9 +408,9 @@ void syscall_entry_probe(void *__data, struct pt_regs *regs, long id) } else { struct lttng_syscall_filter *filter; - filter = rcu_dereference(chan->sc_filter); + filter = lttng_rcu_dereference(chan->sc_filter); if (filter) { - if (id >= NR_syscalls + if (id < 0 || id >= NR_syscalls || !test_bit(id, filter->sc)) { /* System call filtered out. */ return; @@ -399,11 +420,11 @@ void syscall_entry_probe(void *__data, struct pt_regs *regs, long id) table_len = ARRAY_SIZE(sc_table); unknown_event = chan->sc_unknown; } - if (unlikely(id >= table_len)) { + if (unlikely(id < 0 || id >= table_len)) { syscall_entry_unknown(unknown_event, regs, id); return; } - if (unlikely(is_compat_task())) + if (unlikely(in_compat_syscall())) event = chan->compat_sc_table[id]; else event = chan->sc_table[id]; @@ -425,9 +446,9 @@ void syscall_entry_probe(void *__data, struct pt_regs *regs, long id) case 1: { void (*fptr)(void *__data, unsigned long arg0) = entry->func; - unsigned long args[1]; + unsigned long args[LTTNG_SYSCALL_NR_ARGS]; - syscall_get_arguments(current, regs, 0, entry->nrargs, args); + lttng_syscall_get_arguments(current, regs, args); fptr(event, args[0]); break; } @@ -436,9 +457,9 @@ void syscall_entry_probe(void *__data, struct pt_regs *regs, long id) void (*fptr)(void *__data, unsigned long arg0, unsigned long arg1) = entry->func; - unsigned long args[2]; + unsigned long args[LTTNG_SYSCALL_NR_ARGS]; - syscall_get_arguments(current, regs, 0, entry->nrargs, args); + lttng_syscall_get_arguments(current, regs, args); fptr(event, args[0], args[1]); break; } @@ -448,9 +469,9 @@ void syscall_entry_probe(void *__data, struct pt_regs *regs, long id) unsigned long arg0, unsigned long arg1, unsigned long arg2) = entry->func; - unsigned long args[3]; + unsigned long args[LTTNG_SYSCALL_NR_ARGS]; - syscall_get_arguments(current, regs, 0, entry->nrargs, args); + lttng_syscall_get_arguments(current, regs, args); fptr(event, args[0], args[1], args[2]); break; } @@ -461,9 +482,9 @@ void syscall_entry_probe(void *__data, struct pt_regs *regs, long id) unsigned long arg1, unsigned long arg2, unsigned long arg3) = entry->func; - unsigned long args[4]; + unsigned long args[LTTNG_SYSCALL_NR_ARGS]; - syscall_get_arguments(current, regs, 0, entry->nrargs, args); + lttng_syscall_get_arguments(current, regs, args); fptr(event, args[0], args[1], args[2], args[3]); break; } @@ -475,9 +496,9 @@ void syscall_entry_probe(void *__data, struct pt_regs *regs, long id) unsigned long arg2, unsigned long arg3, unsigned long arg4) = entry->func; - unsigned long args[5]; + unsigned long args[LTTNG_SYSCALL_NR_ARGS]; - syscall_get_arguments(current, regs, 0, entry->nrargs, args); + lttng_syscall_get_arguments(current, regs, args); fptr(event, args[0], args[1], args[2], args[3], args[4]); break; } @@ -490,9 +511,9 @@ void syscall_entry_probe(void *__data, struct pt_regs *regs, long id) unsigned long arg3, unsigned long arg4, unsigned long arg5) = entry->func; - unsigned long args[6]; + unsigned long args[LTTNG_SYSCALL_NR_ARGS]; - syscall_get_arguments(current, regs, 0, entry->nrargs, args); + lttng_syscall_get_arguments(current, regs, args); fptr(event, args[0], args[1], args[2], args[3], args[4], args[5]); break; @@ -503,12 +524,12 @@ void syscall_entry_probe(void *__data, struct pt_regs *regs, long id) } static void syscall_exit_unknown(struct lttng_event *event, - struct pt_regs *regs, unsigned int id, long ret) + struct pt_regs *regs, int id, long ret) { - unsigned long args[UNKNOWN_SYSCALL_NRARGS]; + unsigned long args[LTTNG_SYSCALL_NR_ARGS]; - syscall_get_arguments(current, regs, 0, UNKNOWN_SYSCALL_NRARGS, args); - if (unlikely(is_compat_task())) + lttng_syscall_get_arguments(current, regs, args); + if (unlikely(in_compat_syscall())) __event_probe__compat_syscall_exit_unknown(event, id, ret, args); else @@ -524,12 +545,12 @@ void syscall_exit_probe(void *__data, struct pt_regs *regs, long ret) long id; id = syscall_get_nr(current, regs); - if (unlikely(is_compat_task())) { + if (unlikely(in_compat_syscall())) { struct lttng_syscall_filter *filter; - filter = rcu_dereference(chan->sc_filter); + filter = lttng_rcu_dereference(chan->sc_filter); if (filter) { - if (id >= NR_compat_syscalls + if (id < 0 || id >= NR_compat_syscalls || !test_bit(id, filter->sc_compat)) { /* System call filtered out. */ return; @@ -541,9 +562,9 @@ void syscall_exit_probe(void *__data, struct pt_regs *regs, long ret) } else { struct lttng_syscall_filter *filter; - filter = rcu_dereference(chan->sc_filter); + filter = lttng_rcu_dereference(chan->sc_filter); if (filter) { - if (id >= NR_syscalls + if (id < 0 || id >= NR_syscalls || !test_bit(id, filter->sc)) { /* System call filtered out. */ return; @@ -553,11 +574,11 @@ void syscall_exit_probe(void *__data, struct pt_regs *regs, long ret) table_len = ARRAY_SIZE(sc_exit_table); unknown_event = chan->sc_exit_unknown; } - if (unlikely(id >= table_len)) { + if (unlikely(id < 0 || id >= table_len)) { syscall_exit_unknown(unknown_event, regs, id, ret); return; } - if (unlikely(is_compat_task())) + if (unlikely(in_compat_syscall())) event = chan->compat_sc_exit_table[id]; else event = chan->sc_exit_table[id]; @@ -581,9 +602,9 @@ void syscall_exit_probe(void *__data, struct pt_regs *regs, long ret) void (*fptr)(void *__data, long ret, unsigned long arg0) = entry->func; - unsigned long args[1]; + unsigned long args[LTTNG_SYSCALL_NR_ARGS]; - syscall_get_arguments(current, regs, 0, entry->nrargs, args); + lttng_syscall_get_arguments(current, regs, args); fptr(event, ret, args[0]); break; } @@ -593,9 +614,9 @@ void syscall_exit_probe(void *__data, struct pt_regs *regs, long ret) long ret, unsigned long arg0, unsigned long arg1) = entry->func; - unsigned long args[2]; + unsigned long args[LTTNG_SYSCALL_NR_ARGS]; - syscall_get_arguments(current, regs, 0, entry->nrargs, args); + lttng_syscall_get_arguments(current, regs, args); fptr(event, ret, args[0], args[1]); break; } @@ -606,9 +627,9 @@ void syscall_exit_probe(void *__data, struct pt_regs *regs, long ret) unsigned long arg0, unsigned long arg1, unsigned long arg2) = entry->func; - unsigned long args[3]; + unsigned long args[LTTNG_SYSCALL_NR_ARGS]; - syscall_get_arguments(current, regs, 0, entry->nrargs, args); + lttng_syscall_get_arguments(current, regs, args); fptr(event, ret, args[0], args[1], args[2]); break; } @@ -620,9 +641,9 @@ void syscall_exit_probe(void *__data, struct pt_regs *regs, long ret) unsigned long arg1, unsigned long arg2, unsigned long arg3) = entry->func; - unsigned long args[4]; + unsigned long args[LTTNG_SYSCALL_NR_ARGS]; - syscall_get_arguments(current, regs, 0, entry->nrargs, args); + lttng_syscall_get_arguments(current, regs, args); fptr(event, ret, args[0], args[1], args[2], args[3]); break; } @@ -635,9 +656,9 @@ void syscall_exit_probe(void *__data, struct pt_regs *regs, long ret) unsigned long arg2, unsigned long arg3, unsigned long arg4) = entry->func; - unsigned long args[5]; + unsigned long args[LTTNG_SYSCALL_NR_ARGS]; - syscall_get_arguments(current, regs, 0, entry->nrargs, args); + lttng_syscall_get_arguments(current, regs, args); fptr(event, ret, args[0], args[1], args[2], args[3], args[4]); break; } @@ -651,9 +672,9 @@ void syscall_exit_probe(void *__data, struct pt_regs *regs, long ret) unsigned long arg3, unsigned long arg4, unsigned long arg5) = entry->func; - unsigned long args[6]; + unsigned long args[LTTNG_SYSCALL_NR_ARGS]; - syscall_get_arguments(current, regs, 0, entry->nrargs, args); + lttng_syscall_get_arguments(current, regs, args); fptr(event, ret, args[0], args[1], args[2], args[3], args[4], args[5]); break; @@ -663,7 +684,10 @@ void syscall_exit_probe(void *__data, struct pt_regs *regs, long ret) } } -/* noinline to diminish caller stack size */ +/* + * noinline to diminish caller stack size. + * Should be called with sessions lock held. + */ static int fill_table(const struct trace_syscall_entry *table, size_t table_len, struct lttng_event **chan_table, struct lttng_channel *chan, @@ -712,9 +736,9 @@ int fill_table(const struct trace_syscall_entry *table, size_t table_len, strncat(ev.name, desc->name, LTTNG_KERNEL_SYM_NAME_LEN - strlen(ev.name) - 1); ev.name[LTTNG_KERNEL_SYM_NAME_LEN - 1] = '\0'; - ev.instrumentation = LTTNG_KERNEL_NOOP; - chan_table[i] = lttng_event_create(chan, &ev, filter, - desc); + ev.instrumentation = LTTNG_KERNEL_SYSCALL; + chan_table[i] = _lttng_event_create(chan, &ev, filter, + desc, ev.instrumentation); WARN_ON_ONCE(!chan_table[i]); if (IS_ERR(chan_table[i])) { /* @@ -729,12 +753,15 @@ int fill_table(const struct trace_syscall_entry *table, size_t table_len, return 0; } +/* + * Should be called with sessions lock held. + */ int lttng_syscalls_register(struct lttng_channel *chan, void *filter) { struct lttng_kernel_event ev; int ret; - wrapper_vmalloc_sync_all(); + wrapper_vmalloc_sync_mappings(); if (!chan->sc_table) { /* create syscall table mapping syscall to events */ @@ -776,9 +803,10 @@ int lttng_syscalls_register(struct lttng_channel *chan, void *filter) memset(&ev, 0, sizeof(ev)); strncpy(ev.name, desc->name, LTTNG_KERNEL_SYM_NAME_LEN); ev.name[LTTNG_KERNEL_SYM_NAME_LEN - 1] = '\0'; - ev.instrumentation = LTTNG_KERNEL_NOOP; - chan->sc_unknown = lttng_event_create(chan, &ev, filter, - desc); + ev.instrumentation = LTTNG_KERNEL_SYSCALL; + chan->sc_unknown = _lttng_event_create(chan, &ev, filter, + desc, + ev.instrumentation); WARN_ON_ONCE(!chan->sc_unknown); if (IS_ERR(chan->sc_unknown)) { return PTR_ERR(chan->sc_unknown); @@ -792,9 +820,10 @@ int lttng_syscalls_register(struct lttng_channel *chan, void *filter) memset(&ev, 0, sizeof(ev)); strncpy(ev.name, desc->name, LTTNG_KERNEL_SYM_NAME_LEN); ev.name[LTTNG_KERNEL_SYM_NAME_LEN - 1] = '\0'; - ev.instrumentation = LTTNG_KERNEL_NOOP; - chan->sc_compat_unknown = lttng_event_create(chan, &ev, filter, - desc); + ev.instrumentation = LTTNG_KERNEL_SYSCALL; + chan->sc_compat_unknown = _lttng_event_create(chan, &ev, filter, + desc, + ev.instrumentation); WARN_ON_ONCE(!chan->sc_unknown); if (IS_ERR(chan->sc_compat_unknown)) { return PTR_ERR(chan->sc_compat_unknown); @@ -808,9 +837,10 @@ int lttng_syscalls_register(struct lttng_channel *chan, void *filter) memset(&ev, 0, sizeof(ev)); strncpy(ev.name, desc->name, LTTNG_KERNEL_SYM_NAME_LEN); ev.name[LTTNG_KERNEL_SYM_NAME_LEN - 1] = '\0'; - ev.instrumentation = LTTNG_KERNEL_NOOP; - chan->compat_sc_exit_unknown = lttng_event_create(chan, &ev, - filter, desc); + ev.instrumentation = LTTNG_KERNEL_SYSCALL; + chan->compat_sc_exit_unknown = _lttng_event_create(chan, &ev, + filter, desc, + ev.instrumentation); WARN_ON_ONCE(!chan->compat_sc_exit_unknown); if (IS_ERR(chan->compat_sc_exit_unknown)) { return PTR_ERR(chan->compat_sc_exit_unknown); @@ -824,9 +854,9 @@ int lttng_syscalls_register(struct lttng_channel *chan, void *filter) memset(&ev, 0, sizeof(ev)); strncpy(ev.name, desc->name, LTTNG_KERNEL_SYM_NAME_LEN); ev.name[LTTNG_KERNEL_SYM_NAME_LEN - 1] = '\0'; - ev.instrumentation = LTTNG_KERNEL_NOOP; - chan->sc_exit_unknown = lttng_event_create(chan, &ev, filter, - desc); + ev.instrumentation = LTTNG_KERNEL_SYSCALL; + chan->sc_exit_unknown = _lttng_event_create(chan, &ev, filter, + desc, ev.instrumentation); WARN_ON_ONCE(!chan->sc_exit_unknown); if (IS_ERR(chan->sc_exit_unknown)) { return PTR_ERR(chan->sc_exit_unknown); @@ -888,15 +918,15 @@ int lttng_syscalls_unregister(struct lttng_channel *chan) if (!chan->sc_table) return 0; if (chan->sys_enter_registered) { - ret = lttng_wrapper_tracepoint_probe_unregister("sys_exit", - (void *) syscall_exit_probe, chan); + ret = lttng_wrapper_tracepoint_probe_unregister("sys_enter", + (void *) syscall_entry_probe, chan); if (ret) return ret; chan->sys_enter_registered = 0; } if (chan->sys_exit_registered) { - ret = lttng_wrapper_tracepoint_probe_unregister("sys_enter", - (void *) syscall_entry_probe, chan); + ret = lttng_wrapper_tracepoint_probe_unregister("sys_exit", + (void *) syscall_exit_probe, chan); if (ret) return ret; chan->sys_exit_registered = 0; @@ -1230,16 +1260,66 @@ long lttng_channel_syscall_mask(struct lttng_channel *channel, filter = channel->sc_filter; for (bit = 0; bit < ARRAY_SIZE(sc_table); bit++) { - bt_bitfield_write_be(tmp_mask, char, bit, 1, - filter ? test_bit(bit, filter->sc) : 1); + char state; + + if (channel->sc_table) { + if (filter) + state = test_bit(bit, filter->sc); + else + state = 1; + } else { + state = 0; + } + bt_bitfield_write_be(tmp_mask, char, bit, 1, state); } for (; bit < sc_tables_len; bit++) { - bt_bitfield_write_be(tmp_mask, char, bit, 1, - filter ? test_bit(bit - ARRAY_SIZE(sc_table), - filter->sc_compat) : 1); + char state; + + if (channel->compat_sc_table) { + if (filter) + state = test_bit(bit - ARRAY_SIZE(sc_table), + filter->sc_compat); + else + state = 1; + } else { + state = 0; + } + bt_bitfield_write_be(tmp_mask, char, bit, 1, state); } if (copy_to_user(usyscall_mask->mask, tmp_mask, bitmask_len)) ret = -EFAULT; kfree(tmp_mask); return ret; } + +int lttng_abi_syscall_list(void) +{ + struct file *syscall_list_file; + int file_fd, ret; + + file_fd = lttng_get_unused_fd(); + if (file_fd < 0) { + ret = file_fd; + goto fd_error; + } + + syscall_list_file = anon_inode_getfile("[lttng_syscall_list]", + <tng_syscall_list_fops, + NULL, O_RDWR); + if (IS_ERR(syscall_list_file)) { + ret = PTR_ERR(syscall_list_file); + goto file_error; + } + ret = lttng_syscall_list_fops.open(NULL, syscall_list_file); + if (ret < 0) + goto open_error; + fd_install(file_fd, syscall_list_file); + return file_fd; + +open_error: + fput(syscall_list_file); +file_error: + put_unused_fd(file_fd); +fd_error: + return ret; +}