Merge tag 'v3.14.25' into backport/v3.14.24-ltsi-rc1+v3.14.25/snapshot-merge.wip
[platform/adaptation/renesas_rcar/renesas_kernel.git] / drivers / staging / lttng / lttng-syscalls.c
1 /*
2  * lttng-syscalls.c
3  *
4  * LTTng syscall probes.
5  *
6  * Copyright (C) 2010-2012 Mathieu Desnoyers <mathieu.desnoyers@efficios.com>
7  *
8  * This library is free software; you can redistribute it and/or
9  * modify it under the terms of the GNU Lesser General Public
10  * License as published by the Free Software Foundation; only
11  * version 2.1 of the License.
12  *
13  * This library is distributed in the hope that it will be useful,
14  * but WITHOUT ANY WARRANTY; without even the implied warranty of
15  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
16  * Lesser General Public License for more details.
17  *
18  * You should have received a copy of the GNU Lesser General Public
19  * License along with this library; if not, write to the Free Software
20  * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
21  */
22
23 #include <linux/module.h>
24 #include <linux/slab.h>
25 #include <linux/compat.h>
26 #include <asm/ptrace.h>
27 #include <asm/syscall.h>
28
29 #include "wrapper/tracepoint.h"
30 #include "lttng-events.h"
31
32 #ifndef CONFIG_COMPAT
33 # ifndef is_compat_task
34 #  define is_compat_task()      (0)
35 # endif
36 #endif
37
38 static
39 void syscall_entry_probe(void *__data, struct pt_regs *regs, long id);
40
41 /*
42  * Forward declarations for old kernels.
43  */
44 struct mmsghdr;
45 struct rlimit64;
46 struct oldold_utsname;
47 struct old_utsname;
48 struct sel_arg_struct;
49 struct mmap_arg_struct;
50
51 /*
52  * Take care of NOARGS not supported by mainline.
53  */
54 #define DECLARE_EVENT_CLASS_NOARGS(name, tstruct, assign, print)
55 #define DEFINE_EVENT_NOARGS(template, name)
56 #define TRACE_EVENT_NOARGS(name, struct, assign, print)
57
58 /*
59  * Create LTTng tracepoint probes.
60  */
61 #define LTTNG_PACKAGE_BUILD
62 #define CREATE_TRACE_POINTS
63 #define TP_MODULE_NOINIT
64 #define TRACE_INCLUDE_PATH ../instrumentation/syscalls/headers
65
66 #define PARAMS(args...) args
67
68 /* Hijack probe callback for system calls */
69 #undef TP_PROBE_CB
70 #define TP_PROBE_CB(_template)          &syscall_entry_probe
71 #define SC_TRACE_EVENT(_name, _proto, _args, _struct, _assign, _printk) \
72         TRACE_EVENT(_name, PARAMS(_proto), PARAMS(_args),\
73                 PARAMS(_struct), PARAMS(_assign), PARAMS(_printk))
74 #define SC_DECLARE_EVENT_CLASS_NOARGS(_name, _struct, _assign, _printk) \
75         DECLARE_EVENT_CLASS_NOARGS(_name, PARAMS(_struct), PARAMS(_assign),\
76                 PARAMS(_printk))
77 #define SC_DEFINE_EVENT_NOARGS(_template, _name)                        \
78         DEFINE_EVENT_NOARGS(_template, _name)
79 #undef TRACE_SYSTEM
80 #define TRACE_SYSTEM syscalls_integers
81 #include "instrumentation/syscalls/headers/syscalls_integers.h"
82 #undef TRACE_SYSTEM
83 #define TRACE_SYSTEM syscalls_pointers
84 #include "instrumentation/syscalls/headers/syscalls_pointers.h"
85 #undef TRACE_SYSTEM
86 #undef SC_TRACE_EVENT
87 #undef SC_DECLARE_EVENT_CLASS_NOARGS
88 #undef SC_DEFINE_EVENT_NOARGS
89
90 #define TRACE_SYSTEM syscalls_unknown
91 #include "instrumentation/syscalls/headers/syscalls_unknown.h"
92 #undef TRACE_SYSTEM
93
94 /* For compat syscalls */
95 #undef _TRACE_SYSCALLS_integers_H
96 #undef _TRACE_SYSCALLS_pointers_H
97
98 /* Hijack probe callback for system calls */
99 #undef TP_PROBE_CB
100 #define TP_PROBE_CB(_template)          &syscall_entry_probe
101 #define SC_TRACE_EVENT(_name, _proto, _args, _struct, _assign, _printk) \
102         TRACE_EVENT(compat_##_name, PARAMS(_proto), PARAMS(_args),      \
103                 PARAMS(_struct), PARAMS(_assign),                       \
104                 PARAMS(_printk))
105 #define SC_DECLARE_EVENT_CLASS_NOARGS(_name, _struct, _assign, _printk) \
106         DECLARE_EVENT_CLASS_NOARGS(compat_##_name, PARAMS(_struct),     \
107                 PARAMS(_assign), PARAMS(_printk))
108 #define SC_DEFINE_EVENT_NOARGS(_template, _name)                        \
109         DEFINE_EVENT_NOARGS(compat_##_template, compat_##_name)
110 #define TRACE_SYSTEM compat_syscalls_integers
111 #include "instrumentation/syscalls/headers/compat_syscalls_integers.h"
112 #undef TRACE_SYSTEM
113 #define TRACE_SYSTEM compat_syscalls_pointers
114 #include "instrumentation/syscalls/headers/compat_syscalls_pointers.h"
115 #undef TRACE_SYSTEM
116 #undef SC_TRACE_EVENT
117 #undef SC_DECLARE_EVENT_CLASS_NOARGS
118 #undef SC_DEFINE_EVENT_NOARGS
119 #undef TP_PROBE_CB
120
121 #undef TP_MODULE_NOINIT
122 #undef LTTNG_PACKAGE_BUILD
123 #undef CREATE_TRACE_POINTS
124
125 struct trace_syscall_entry {
126         void *func;
127         const struct lttng_event_desc *desc;
128         const struct lttng_event_field *fields;
129         unsigned int nrargs;
130 };
131
132 #define CREATE_SYSCALL_TABLE
133
134 #undef TRACE_SYSCALL_TABLE
135 #define TRACE_SYSCALL_TABLE(_template, _name, _nr, _nrargs)     \
136         [ _nr ] = {                                             \
137                 .func = __event_probe__##_template,             \
138                 .nrargs = (_nrargs),                            \
139                 .fields = __event_fields___##_template,         \
140                 .desc = &__event_desc___##_name,                \
141         },
142
143 static const struct trace_syscall_entry sc_table[] = {
144 #include "instrumentation/syscalls/headers/syscalls_integers.h"
145 #include "instrumentation/syscalls/headers/syscalls_pointers.h"
146 };
147
148 #undef TRACE_SYSCALL_TABLE
149 #define TRACE_SYSCALL_TABLE(_template, _name, _nr, _nrargs)     \
150         [ _nr ] = {                                             \
151                 .func = __event_probe__##compat_##_template,    \
152                 .nrargs = (_nrargs),                            \
153                 .fields = __event_fields___##compat_##_template,\
154                 .desc = &__event_desc___##compat_##_name,       \
155         },
156
157 /* Create compatibility syscall table */
158 const struct trace_syscall_entry compat_sc_table[] = {
159 #include "instrumentation/syscalls/headers/compat_syscalls_integers.h"
160 #include "instrumentation/syscalls/headers/compat_syscalls_pointers.h"
161 };
162
163 #undef CREATE_SYSCALL_TABLE
164
165 static void syscall_entry_unknown(struct lttng_event *event,
166         struct pt_regs *regs, unsigned int id)
167 {
168         unsigned long args[UNKNOWN_SYSCALL_NRARGS];
169
170         syscall_get_arguments(current, regs, 0, UNKNOWN_SYSCALL_NRARGS, args);
171         if (unlikely(is_compat_task()))
172                 __event_probe__compat_sys_unknown(event, id, args);
173         else
174                 __event_probe__sys_unknown(event, id, args);
175 }
176
177 void syscall_entry_probe(void *__data, struct pt_regs *regs, long id)
178 {
179         struct lttng_channel *chan = __data;
180         struct lttng_event *event, *unknown_event;
181         const struct trace_syscall_entry *table, *entry;
182         size_t table_len;
183
184         if (unlikely(is_compat_task())) {
185                 table = compat_sc_table;
186                 table_len = ARRAY_SIZE(compat_sc_table);
187                 unknown_event = chan->sc_compat_unknown;
188         } else {
189                 table = sc_table;
190                 table_len = ARRAY_SIZE(sc_table);
191                 unknown_event = chan->sc_unknown;
192         }
193         if (unlikely(id >= table_len)) {
194                 syscall_entry_unknown(unknown_event, regs, id);
195                 return;
196         }
197         if (unlikely(is_compat_task()))
198                 event = chan->compat_sc_table[id];
199         else
200                 event = chan->sc_table[id];
201         if (unlikely(!event)) {
202                 syscall_entry_unknown(unknown_event, regs, id);
203                 return;
204         }
205         entry = &table[id];
206         WARN_ON_ONCE(!entry);
207
208         switch (entry->nrargs) {
209         case 0:
210         {
211                 void (*fptr)(void *__data) = entry->func;
212
213                 fptr(event);
214                 break;
215         }
216         case 1:
217         {
218                 void (*fptr)(void *__data, unsigned long arg0) = entry->func;
219                 unsigned long args[1];
220
221                 syscall_get_arguments(current, regs, 0, entry->nrargs, args);
222                 fptr(event, args[0]);
223                 break;
224         }
225         case 2:
226         {
227                 void (*fptr)(void *__data,
228                         unsigned long arg0,
229                         unsigned long arg1) = entry->func;
230                 unsigned long args[2];
231
232                 syscall_get_arguments(current, regs, 0, entry->nrargs, args);
233                 fptr(event, args[0], args[1]);
234                 break;
235         }
236         case 3:
237         {
238                 void (*fptr)(void *__data,
239                         unsigned long arg0,
240                         unsigned long arg1,
241                         unsigned long arg2) = entry->func;
242                 unsigned long args[3];
243
244                 syscall_get_arguments(current, regs, 0, entry->nrargs, args);
245                 fptr(event, args[0], args[1], args[2]);
246                 break;
247         }
248         case 4:
249         {
250                 void (*fptr)(void *__data,
251                         unsigned long arg0,
252                         unsigned long arg1,
253                         unsigned long arg2,
254                         unsigned long arg3) = entry->func;
255                 unsigned long args[4];
256
257                 syscall_get_arguments(current, regs, 0, entry->nrargs, args);
258                 fptr(event, args[0], args[1], args[2], args[3]);
259                 break;
260         }
261         case 5:
262         {
263                 void (*fptr)(void *__data,
264                         unsigned long arg0,
265                         unsigned long arg1,
266                         unsigned long arg2,
267                         unsigned long arg3,
268                         unsigned long arg4) = entry->func;
269                 unsigned long args[5];
270
271                 syscall_get_arguments(current, regs, 0, entry->nrargs, args);
272                 fptr(event, args[0], args[1], args[2], args[3], args[4]);
273                 break;
274         }
275         case 6:
276         {
277                 void (*fptr)(void *__data,
278                         unsigned long arg0,
279                         unsigned long arg1,
280                         unsigned long arg2,
281                         unsigned long arg3,
282                         unsigned long arg4,
283                         unsigned long arg5) = entry->func;
284                 unsigned long args[6];
285
286                 syscall_get_arguments(current, regs, 0, entry->nrargs, args);
287                 fptr(event, args[0], args[1], args[2],
288                         args[3], args[4], args[5]);
289                 break;
290         }
291         default:
292                 break;
293         }
294 }
295
296 /* noinline to diminish caller stack size */
297 static
298 int fill_table(const struct trace_syscall_entry *table, size_t table_len,
299         struct lttng_event **chan_table, struct lttng_channel *chan, void *filter)
300 {
301         const struct lttng_event_desc *desc;
302         unsigned int i;
303
304         /* Allocate events for each syscall, insert into table */
305         for (i = 0; i < table_len; i++) {
306                 struct lttng_kernel_event ev;
307                 desc = table[i].desc;
308
309                 if (!desc) {
310                         /* Unknown syscall */
311                         continue;
312                 }
313                 /*
314                  * Skip those already populated by previous failed
315                  * register for this channel.
316                  */
317                 if (chan_table[i])
318                         continue;
319                 memset(&ev, 0, sizeof(ev));
320                 strncpy(ev.name, desc->name, LTTNG_KERNEL_SYM_NAME_LEN);
321                 ev.name[LTTNG_KERNEL_SYM_NAME_LEN - 1] = '\0';
322                 ev.instrumentation = LTTNG_KERNEL_NOOP;
323                 chan_table[i] = lttng_event_create(chan, &ev, filter,
324                                                 desc);
325                 if (!chan_table[i]) {
326                         /*
327                          * If something goes wrong in event registration
328                          * after the first one, we have no choice but to
329                          * leave the previous events in there, until
330                          * deleted by session teardown.
331                          */
332                         return -EINVAL;
333                 }
334         }
335         return 0;
336 }
337
338 int lttng_syscalls_register(struct lttng_channel *chan, void *filter)
339 {
340         struct lttng_kernel_event ev;
341         int ret;
342
343         wrapper_vmalloc_sync_all();
344
345         if (!chan->sc_table) {
346                 /* create syscall table mapping syscall to events */
347                 chan->sc_table = kzalloc(sizeof(struct lttng_event *)
348                                         * ARRAY_SIZE(sc_table), GFP_KERNEL);
349                 if (!chan->sc_table)
350                         return -ENOMEM;
351         }
352
353 #ifdef CONFIG_COMPAT
354         if (!chan->compat_sc_table) {
355                 /* create syscall table mapping compat syscall to events */
356                 chan->compat_sc_table = kzalloc(sizeof(struct lttng_event *)
357                                         * ARRAY_SIZE(compat_sc_table), GFP_KERNEL);
358                 if (!chan->compat_sc_table)
359                         return -ENOMEM;
360         }
361 #endif
362         if (!chan->sc_unknown) {
363                 const struct lttng_event_desc *desc =
364                         &__event_desc___sys_unknown;
365
366                 memset(&ev, 0, sizeof(ev));
367                 strncpy(ev.name, desc->name, LTTNG_KERNEL_SYM_NAME_LEN);
368                 ev.name[LTTNG_KERNEL_SYM_NAME_LEN - 1] = '\0';
369                 ev.instrumentation = LTTNG_KERNEL_NOOP;
370                 chan->sc_unknown = lttng_event_create(chan, &ev, filter,
371                                                     desc);
372                 if (!chan->sc_unknown) {
373                         return -EINVAL;
374                 }
375         }
376
377         if (!chan->sc_compat_unknown) {
378                 const struct lttng_event_desc *desc =
379                         &__event_desc___compat_sys_unknown;
380
381                 memset(&ev, 0, sizeof(ev));
382                 strncpy(ev.name, desc->name, LTTNG_KERNEL_SYM_NAME_LEN);
383                 ev.name[LTTNG_KERNEL_SYM_NAME_LEN - 1] = '\0';
384                 ev.instrumentation = LTTNG_KERNEL_NOOP;
385                 chan->sc_compat_unknown = lttng_event_create(chan, &ev, filter,
386                                                            desc);
387                 if (!chan->sc_compat_unknown) {
388                         return -EINVAL;
389                 }
390         }
391
392         if (!chan->sc_exit) {
393                 const struct lttng_event_desc *desc =
394                         &__event_desc___exit_syscall;
395
396                 memset(&ev, 0, sizeof(ev));
397                 strncpy(ev.name, desc->name, LTTNG_KERNEL_SYM_NAME_LEN);
398                 ev.name[LTTNG_KERNEL_SYM_NAME_LEN - 1] = '\0';
399                 ev.instrumentation = LTTNG_KERNEL_NOOP;
400                 chan->sc_exit = lttng_event_create(chan, &ev, filter,
401                                                  desc);
402                 if (!chan->sc_exit) {
403                         return -EINVAL;
404                 }
405         }
406
407         ret = fill_table(sc_table, ARRAY_SIZE(sc_table),
408                         chan->sc_table, chan, filter);
409         if (ret)
410                 return ret;
411 #ifdef CONFIG_COMPAT
412         ret = fill_table(compat_sc_table, ARRAY_SIZE(compat_sc_table),
413                         chan->compat_sc_table, chan, filter);
414         if (ret)
415                 return ret;
416 #endif
417         ret = kabi_2635_tracepoint_probe_register("sys_enter",
418                         (void *) syscall_entry_probe, chan);
419         if (ret)
420                 return ret;
421         /*
422          * We change the name of sys_exit tracepoint due to namespace
423          * conflict with sys_exit syscall entry.
424          */
425         ret = kabi_2635_tracepoint_probe_register("sys_exit",
426                         (void *) __event_probe__exit_syscall,
427                         chan->sc_exit);
428         if (ret) {
429                 WARN_ON_ONCE(kabi_2635_tracepoint_probe_unregister("sys_enter",
430                         (void *) syscall_entry_probe, chan));
431         }
432         return ret;
433 }
434
435 /*
436  * Only called at session destruction.
437  */
438 int lttng_syscalls_unregister(struct lttng_channel *chan)
439 {
440         int ret;
441
442         if (!chan->sc_table)
443                 return 0;
444         ret = kabi_2635_tracepoint_probe_unregister("sys_exit",
445                         (void *) __event_probe__exit_syscall,
446                         chan->sc_exit);
447         if (ret)
448                 return ret;
449         ret = kabi_2635_tracepoint_probe_unregister("sys_enter",
450                         (void *) syscall_entry_probe, chan);
451         if (ret)
452                 return ret;
453         /* lttng_event destroy will be performed by lttng_session_destroy() */
454         kfree(chan->sc_table);
455 #ifdef CONFIG_COMPAT
456         kfree(chan->compat_sc_table);
457 #endif
458         return 0;
459 }