Revert "Implement event notifiers for syscalls"
[lttng-modules.git] / src / lttng-syscalls.c
CommitLineData
b7cdc182 1/* SPDX-License-Identifier: (GPL-2.0-only or LGPL-2.1-only)
9f36eaed 2 *
259b6cb3
MD
3 * lttng-syscalls.c
4 *
2faf7d1b 5 * LTTng syscall probes.
259b6cb3 6 *
886d51a3 7 * Copyright (C) 2010-2012 Mathieu Desnoyers <mathieu.desnoyers@efficios.com>
259b6cb3
MD
8 */
9
10#include <linux/module.h>
11#include <linux/slab.h>
6333ace3 12#include <linux/compat.h>
abc0446a 13#include <linux/err.h>
80f87dd2 14#include <linux/bitmap.h>
7ca580f8
MD
15#include <linux/in.h>
16#include <linux/in6.h>
2d2464bd 17#include <linux/seq_file.h>
d4291869 18#include <linux/stringify.h>
082d4946
MD
19#include <linux/file.h>
20#include <linux/anon_inodes.h>
c8dfb724 21#include <linux/fcntl.h>
3cf55950 22#include <linux/mman.h>
259b6cb3
MD
23#include <asm/ptrace.h>
24#include <asm/syscall.h>
25
a071f25d 26#include <lttng/bitfield.h>
241ae9a8
MD
27#include <wrapper/tracepoint.h>
28#include <wrapper/file.h>
29#include <wrapper/rcu.h>
1b7b9c65 30#include <wrapper/syscall.h>
2df37e95 31#include <lttng/events.h>
259b6cb3 32
6333ace3 33#ifndef CONFIG_COMPAT
bfa949bf
MD
34# ifndef is_compat_task
35# define is_compat_task() (0)
36# endif
6333ace3
MD
37#endif
38
1aa3298b
MD
39/* in_compat_syscall appears in kernel 4.6. */
40#ifndef in_compat_syscall
41 #define in_compat_syscall() is_compat_task()
42#endif
43
5b7ac358
MD
44enum sc_type {
45 SC_TYPE_ENTRY,
46 SC_TYPE_EXIT,
47 SC_TYPE_COMPAT_ENTRY,
48 SC_TYPE_COMPAT_EXIT,
49};
50
d4291869
MD
51#define SYSCALL_ENTRY_TOK syscall_entry_
52#define COMPAT_SYSCALL_ENTRY_TOK compat_syscall_entry_
53#define SYSCALL_EXIT_TOK syscall_exit_
54#define COMPAT_SYSCALL_EXIT_TOK compat_syscall_exit_
55
56#define SYSCALL_ENTRY_STR __stringify(SYSCALL_ENTRY_TOK)
57#define COMPAT_SYSCALL_ENTRY_STR __stringify(COMPAT_SYSCALL_ENTRY_TOK)
58#define SYSCALL_EXIT_STR __stringify(SYSCALL_EXIT_TOK)
59#define COMPAT_SYSCALL_EXIT_STR __stringify(COMPAT_SYSCALL_EXIT_TOK)
5b7ac358 60
a93244f8 61static
2d6d88c6 62void syscall_entry_event_probe(void *__data, struct pt_regs *regs, long id);
5b7ac358 63static
2d6d88c6 64void syscall_exit_event_probe(void *__data, struct pt_regs *regs, long ret);
259b6cb3 65
3a523f5b
MD
66/*
67 * Forward declarations for old kernels.
68 */
69struct mmsghdr;
70struct rlimit64;
71struct oldold_utsname;
72struct old_utsname;
73struct sel_arg_struct;
74struct mmap_arg_struct;
c0b71117 75struct file_handle;
a292e6f1 76struct user_msghdr;
3a523f5b 77
9eb15e8b
MJ
78/*
79 * Forward declaration for kernels >= 5.6
80 */
81struct timex;
edfdcb68
MJ
82struct timeval;
83struct itimerval;
84struct itimerspec;
85
86#if (LINUX_VERSION_CODE >= KERNEL_VERSION(5,6,0))
87typedef __kernel_old_time_t time_t;
88#endif
9eb15e8b 89
80f87dd2
MD
90#ifdef IA32_NR_syscalls
91#define NR_compat_syscalls IA32_NR_syscalls
92#else
93#define NR_compat_syscalls NR_syscalls
94#endif
95
259b6cb3
MD
96/*
97 * Create LTTng tracepoint probes.
98 */
99#define LTTNG_PACKAGE_BUILD
100#define CREATE_TRACE_POINTS
2655f9ad 101#define TP_MODULE_NOINIT
c075712b 102#define TRACE_INCLUDE_PATH instrumentation/syscalls/headers
259b6cb3 103
a93244f8
MD
104#define PARAMS(args...) args
105
5b7ac358 106/* Handle unknown syscalls */
72a52753 107#undef TRACE_SYSTEM
5b7ac358 108#define TRACE_SYSTEM syscalls_unknown
241ae9a8 109#include <instrumentation/syscalls/headers/syscalls_unknown.h>
5b7ac358
MD
110#undef TRACE_SYSTEM
111
fc4f7161
MD
112#define SC_ENTER
113
fc4f7161
MD
114#undef sc_exit
115#define sc_exit(...)
b75d00c4
MD
116#undef sc_in
117#define sc_in(...) __VA_ARGS__
118#undef sc_out
119#define sc_out(...)
120#undef sc_inout
121#define sc_inout(...) __VA_ARGS__
5b7ac358
MD
122
123/* Hijack probe callback for system call enter */
a93244f8 124#undef TP_PROBE_CB
2d6d88c6 125#define TP_PROBE_CB(_template) &syscall_entry_event_probe
57ede728 126#define SC_LTTNG_TRACEPOINT_EVENT(_name, _proto, _args, _fields) \
d4291869 127 LTTNG_TRACEPOINT_EVENT(syscall_entry_##_name, PARAMS(_proto), PARAMS(_args), \
57ede728 128 PARAMS(_fields))
265822ae 129#define SC_LTTNG_TRACEPOINT_EVENT_CODE(_name, _proto, _args, _locvar, _code_pre, _fields, _code_post) \
d4291869 130 LTTNG_TRACEPOINT_EVENT_CODE(syscall_entry_##_name, PARAMS(_proto), PARAMS(_args), \
265822ae
MD
131 PARAMS(_locvar), PARAMS(_code_pre), \
132 PARAMS(_fields), PARAMS(_code_post))
57ede728
MD
133#define SC_LTTNG_TRACEPOINT_EVENT_CLASS_NOARGS(_name, _fields) \
134 LTTNG_TRACEPOINT_EVENT_CLASS_NOARGS(syscall_entry_##_name, PARAMS(_fields))
cb3ef14c 135#define SC_LTTNG_TRACEPOINT_EVENT_INSTANCE_NOARGS(_template, _name) \
d4291869 136 LTTNG_TRACEPOINT_EVENT_INSTANCE_NOARGS(syscall_entry_##_template, syscall_entry_##_name)
141ddf28
MD
137/* Enumerations only defined at first inclusion. */
138#define SC_LTTNG_TRACEPOINT_ENUM(_name, _values) \
139 LTTNG_TRACEPOINT_ENUM(_name, PARAMS(_values))
a93244f8 140#undef TRACE_SYSTEM
d4291869 141#define TRACE_SYSTEM syscall_entry_integers
5b7ac358 142#define TRACE_INCLUDE_FILE syscalls_integers
241ae9a8 143#include <instrumentation/syscalls/headers/syscalls_integers.h>
5b7ac358 144#undef TRACE_INCLUDE_FILE
a93244f8 145#undef TRACE_SYSTEM
d4291869 146#define TRACE_SYSTEM syscall_entry_pointers
5b7ac358 147#define TRACE_INCLUDE_FILE syscalls_pointers
241ae9a8 148#include <instrumentation/syscalls/headers/syscalls_pointers.h>
5b7ac358 149#undef TRACE_INCLUDE_FILE
a93244f8 150#undef TRACE_SYSTEM
141ddf28 151#undef SC_LTTNG_TRACEPOINT_ENUM
cb3ef14c
MD
152#undef SC_LTTNG_TRACEPOINT_EVENT_CODE
153#undef SC_LTTNG_TRACEPOINT_EVENT
154#undef SC_LTTNG_TRACEPOINT_EVENT_CLASS_NOARGS
155#undef SC_LTTNG_TRACEPOINT_EVENT_INSTANCE_NOARGS
5b7ac358 156#undef TP_PROBE_CB
3bc29f0a
MD
157#undef _TRACE_SYSCALLS_INTEGERS_H
158#undef _TRACE_SYSCALLS_POINTERS_H
5b7ac358
MD
159
160/* Hijack probe callback for compat system call enter */
2d6d88c6 161#define TP_PROBE_CB(_template) &syscall_entry_event_probe
771af27e 162#define LTTNG_SC_COMPAT
57ede728 163#define SC_LTTNG_TRACEPOINT_EVENT(_name, _proto, _args, _fields) \
d4291869 164 LTTNG_TRACEPOINT_EVENT(compat_syscall_entry_##_name, PARAMS(_proto), PARAMS(_args), \
57ede728 165 PARAMS(_fields))
265822ae 166#define SC_LTTNG_TRACEPOINT_EVENT_CODE(_name, _proto, _args, _locvar, _code_pre, _fields, _code_post) \
d4291869 167 LTTNG_TRACEPOINT_EVENT_CODE(compat_syscall_entry_##_name, PARAMS(_proto), PARAMS(_args), \
265822ae 168 PARAMS(_locvar), PARAMS(_code_pre), PARAMS(_fields), PARAMS(_code_post))
57ede728
MD
169#define SC_LTTNG_TRACEPOINT_EVENT_CLASS_NOARGS(_name, _fields) \
170 LTTNG_TRACEPOINT_EVENT_CLASS_NOARGS(compat_syscall_entry_##_name, PARAMS(_fields))
cb3ef14c 171#define SC_LTTNG_TRACEPOINT_EVENT_INSTANCE_NOARGS(_template, _name) \
d4291869
MD
172 LTTNG_TRACEPOINT_EVENT_INSTANCE_NOARGS(compat_syscall_entry_##_template, \
173 compat_syscall_entry_##_name)
141ddf28
MD
174/* Enumerations only defined at inital inclusion (not here). */
175#define SC_LTTNG_TRACEPOINT_ENUM(_name, _values)
d4291869 176#define TRACE_SYSTEM compat_syscall_entry_integers
5b7ac358 177#define TRACE_INCLUDE_FILE compat_syscalls_integers
241ae9a8 178#include <instrumentation/syscalls/headers/compat_syscalls_integers.h>
5b7ac358
MD
179#undef TRACE_INCLUDE_FILE
180#undef TRACE_SYSTEM
d4291869 181#define TRACE_SYSTEM compat_syscall_entry_pointers
5b7ac358 182#define TRACE_INCLUDE_FILE compat_syscalls_pointers
241ae9a8 183#include <instrumentation/syscalls/headers/compat_syscalls_pointers.h>
5b7ac358
MD
184#undef TRACE_INCLUDE_FILE
185#undef TRACE_SYSTEM
141ddf28 186#undef SC_LTTNG_TRACEPOINT_ENUM
cb3ef14c
MD
187#undef SC_LTTNG_TRACEPOINT_EVENT_CODE
188#undef SC_LTTNG_TRACEPOINT_EVENT
189#undef SC_LTTNG_TRACEPOINT_EVENT_CLASS_NOARGS
190#undef SC_LTTNG_TRACEPOINT_EVENT_INSTANCE_NOARGS
5b7ac358 191#undef TP_PROBE_CB
3bc29f0a
MD
192#undef _TRACE_SYSCALLS_INTEGERS_H
193#undef _TRACE_SYSCALLS_POINTERS_H
771af27e 194#undef LTTNG_SC_COMPAT
5b7ac358 195
fc4f7161
MD
196#undef SC_ENTER
197
198#define SC_EXIT
199
fc4f7161
MD
200#undef sc_exit
201#define sc_exit(...) __VA_ARGS__
b75d00c4
MD
202#undef sc_in
203#define sc_in(...)
204#undef sc_out
205#define sc_out(...) __VA_ARGS__
206#undef sc_inout
207#define sc_inout(...) __VA_ARGS__
5b7ac358
MD
208
209/* Hijack probe callback for system call exit */
2d6d88c6 210#define TP_PROBE_CB(_template) &syscall_exit_event_probe
57ede728 211#define SC_LTTNG_TRACEPOINT_EVENT(_name, _proto, _args, _fields) \
3bc29f0a 212 LTTNG_TRACEPOINT_EVENT(syscall_exit_##_name, PARAMS(_proto), PARAMS(_args), \
57ede728 213 PARAMS(_fields))
265822ae 214#define SC_LTTNG_TRACEPOINT_EVENT_CODE(_name, _proto, _args, _locvar, _code_pre, _fields, _code_post) \
3bc29f0a 215 LTTNG_TRACEPOINT_EVENT_CODE(syscall_exit_##_name, PARAMS(_proto), PARAMS(_args), \
265822ae 216 PARAMS(_locvar), PARAMS(_code_pre), PARAMS(_fields), PARAMS(_code_post))
57ede728
MD
217#define SC_LTTNG_TRACEPOINT_EVENT_CLASS_NOARGS(_name, _fields) \
218 LTTNG_TRACEPOINT_EVENT_CLASS_NOARGS(syscall_exit_##_name, PARAMS(_fields))
cb3ef14c
MD
219#define SC_LTTNG_TRACEPOINT_EVENT_INSTANCE_NOARGS(_template, _name) \
220 LTTNG_TRACEPOINT_EVENT_INSTANCE_NOARGS(syscall_exit_##_template, \
5b7ac358 221 syscall_exit_##_name)
141ddf28
MD
222/* Enumerations only defined at inital inclusion (not here). */
223#define SC_LTTNG_TRACEPOINT_ENUM(_name, _values)
5b7ac358
MD
224#define TRACE_SYSTEM syscall_exit_integers
225#define TRACE_INCLUDE_FILE syscalls_integers
241ae9a8 226#include <instrumentation/syscalls/headers/syscalls_integers.h>
5b7ac358
MD
227#undef TRACE_INCLUDE_FILE
228#undef TRACE_SYSTEM
229#define TRACE_SYSTEM syscall_exit_pointers
230#define TRACE_INCLUDE_FILE syscalls_pointers
241ae9a8 231#include <instrumentation/syscalls/headers/syscalls_pointers.h>
5b7ac358
MD
232#undef TRACE_INCLUDE_FILE
233#undef TRACE_SYSTEM
141ddf28 234#undef SC_LTTNG_TRACEPOINT_ENUM
cb3ef14c
MD
235#undef SC_LTTNG_TRACEPOINT_EVENT_CODE
236#undef SC_LTTNG_TRACEPOINT_EVENT
237#undef SC_LTTNG_TRACEPOINT_EVENT_CLASS_NOARGS
238#undef SC_LTTNG_TRACEPOINT_EVENT_INSTANCE_NOARGS
5b7ac358 239#undef TP_PROBE_CB
3bc29f0a
MD
240#undef _TRACE_SYSCALLS_INTEGERS_H
241#undef _TRACE_SYSCALLS_POINTERS_H
5b7ac358
MD
242
243
244/* Hijack probe callback for compat system call exit */
2d6d88c6 245#define TP_PROBE_CB(_template) &syscall_exit_event_probe
771af27e 246#define LTTNG_SC_COMPAT
57ede728 247#define SC_LTTNG_TRACEPOINT_EVENT(_name, _proto, _args, _fields) \
3bc29f0a 248 LTTNG_TRACEPOINT_EVENT(compat_syscall_exit_##_name, PARAMS(_proto), PARAMS(_args), \
57ede728 249 PARAMS(_fields))
265822ae 250#define SC_LTTNG_TRACEPOINT_EVENT_CODE(_name, _proto, _args, _locvar, _code_pre, _fields, _code_post) \
3bc29f0a 251 LTTNG_TRACEPOINT_EVENT_CODE(compat_syscall_exit_##_name, PARAMS(_proto), PARAMS(_args), \
265822ae 252 PARAMS(_locvar), PARAMS(_code_pre), PARAMS(_fields), PARAMS(_code_post))
57ede728
MD
253#define SC_LTTNG_TRACEPOINT_EVENT_CLASS_NOARGS(_name, _fields) \
254 LTTNG_TRACEPOINT_EVENT_CLASS_NOARGS(compat_syscall_exit_##_name, PARAMS(_fields))
cb3ef14c 255#define SC_LTTNG_TRACEPOINT_EVENT_INSTANCE_NOARGS(_template, _name) \
3bc29f0a 256 LTTNG_TRACEPOINT_EVENT_INSTANCE_NOARGS(compat_syscall_exit_##_template, \
5b7ac358 257 compat_syscall_exit_##_name)
141ddf28
MD
258/* Enumerations only defined at inital inclusion (not here). */
259#define SC_LTTNG_TRACEPOINT_ENUM(_name, _values)
5b7ac358
MD
260#define TRACE_SYSTEM compat_syscall_exit_integers
261#define TRACE_INCLUDE_FILE compat_syscalls_integers
241ae9a8 262#include <instrumentation/syscalls/headers/compat_syscalls_integers.h>
5b7ac358 263#undef TRACE_INCLUDE_FILE
a93244f8 264#undef TRACE_SYSTEM
5b7ac358
MD
265#define TRACE_SYSTEM compat_syscall_exit_pointers
266#define TRACE_INCLUDE_FILE compat_syscalls_pointers
241ae9a8 267#include <instrumentation/syscalls/headers/compat_syscalls_pointers.h>
5b7ac358 268#undef TRACE_INCLUDE_FILE
a93244f8 269#undef TRACE_SYSTEM
141ddf28 270#undef SC_LTTNG_TRACEPOINT_ENUM
cb3ef14c
MD
271#undef SC_LTTNG_TRACEPOINT_EVENT_CODE
272#undef SC_LTTNG_TRACEPOINT_EVENT
273#undef SC_LTTNG_TRACEPOINT_EVENT_CLASS_NOARGS
274#undef SC_LTTNG_TRACEPOINT_EVENT_INSTANCE_NOARGS
a93244f8 275#undef TP_PROBE_CB
3bc29f0a
MD
276#undef _TRACE_SYSCALLS_INTEGERS_H
277#undef _TRACE_SYSCALLS_POINTERS_H
771af27e 278#undef LTTNG_SC_COMPAT
5b7ac358 279
fc4f7161 280#undef SC_EXIT
259b6cb3 281
2655f9ad 282#undef TP_MODULE_NOINIT
259b6cb3
MD
283#undef LTTNG_PACKAGE_BUILD
284#undef CREATE_TRACE_POINTS
285
a93244f8 286struct trace_syscall_entry {
2d6d88c6 287 void *event_func;
a93244f8
MD
288 const struct lttng_event_desc *desc;
289 const struct lttng_event_field *fields;
290 unsigned int nrargs;
291};
292
293#define CREATE_SYSCALL_TABLE
294
fc4f7161
MD
295#define SC_ENTER
296
297#undef sc_exit
298#define sc_exit(...)
299
259b6cb3 300#undef TRACE_SYSCALL_TABLE
f7bdf4db 301#define TRACE_SYSCALL_TABLE(_template, _name, _nr, _nrargs) \
259b6cb3 302 [ _nr ] = { \
2d6d88c6 303 .event_func = __event_probe__syscall_entry_##_template, \
259b6cb3 304 .nrargs = (_nrargs), \
d4291869
MD
305 .fields = __event_fields___syscall_entry_##_template, \
306 .desc = &__event_desc___syscall_entry_##_name, \
259b6cb3
MD
307 },
308
2d6d88c6 309/* Event syscall enter tracing table */
49c50022 310static const struct trace_syscall_entry sc_table[] = {
241ae9a8
MD
311#include <instrumentation/syscalls/headers/syscalls_integers.h>
312#include <instrumentation/syscalls/headers/syscalls_pointers.h>
259b6cb3
MD
313};
314
a93244f8
MD
315#undef TRACE_SYSCALL_TABLE
316#define TRACE_SYSCALL_TABLE(_template, _name, _nr, _nrargs) \
317 [ _nr ] = { \
2d6d88c6 318 .event_func = __event_probe__compat_syscall_entry_##_template, \
a93244f8 319 .nrargs = (_nrargs), \
d4291869
MD
320 .fields = __event_fields___compat_syscall_entry_##_template, \
321 .desc = &__event_desc___compat_syscall_entry_##_name, \
a93244f8
MD
322 },
323
2d6d88c6 324/* Event compat syscall enter table */
a93244f8 325const struct trace_syscall_entry compat_sc_table[] = {
241ae9a8
MD
326#include <instrumentation/syscalls/headers/compat_syscalls_integers.h>
327#include <instrumentation/syscalls/headers/compat_syscalls_pointers.h>
a93244f8 328};
259b6cb3 329
fc4f7161
MD
330#undef SC_ENTER
331
332#define SC_EXIT
333
334#undef sc_exit
335#define sc_exit(...) __VA_ARGS__
336
5b7ac358
MD
337#undef TRACE_SYSCALL_TABLE
338#define TRACE_SYSCALL_TABLE(_template, _name, _nr, _nrargs) \
339 [ _nr ] = { \
2d6d88c6 340 .event_func = __event_probe__syscall_exit_##_template, \
5b7ac358
MD
341 .nrargs = (_nrargs), \
342 .fields = __event_fields___syscall_exit_##_template, \
343 .desc = &__event_desc___syscall_exit_##_name, \
344 },
345
2d6d88c6 346/* Event syscall exit table */
5b7ac358 347static const struct trace_syscall_entry sc_exit_table[] = {
241ae9a8
MD
348#include <instrumentation/syscalls/headers/syscalls_integers.h>
349#include <instrumentation/syscalls/headers/syscalls_pointers.h>
5b7ac358
MD
350};
351
352#undef TRACE_SYSCALL_TABLE
353#define TRACE_SYSCALL_TABLE(_template, _name, _nr, _nrargs) \
354 [ _nr ] = { \
2d6d88c6 355 .event_func = __event_probe__compat_syscall_exit_##_template, \
5b7ac358
MD
356 .nrargs = (_nrargs), \
357 .fields = __event_fields___compat_syscall_exit_##_template, \
358 .desc = &__event_desc___compat_syscall_exit_##_name, \
359 },
360
2d6d88c6 361/* Event compat syscall exit table */
5b7ac358 362const struct trace_syscall_entry compat_sc_exit_table[] = {
241ae9a8
MD
363#include <instrumentation/syscalls/headers/compat_syscalls_integers.h>
364#include <instrumentation/syscalls/headers/compat_syscalls_pointers.h>
5b7ac358
MD
365};
366
fc4f7161
MD
367#undef SC_EXIT
368
a93244f8 369#undef CREATE_SYSCALL_TABLE
2faf7d1b 370
80f87dd2 371struct lttng_syscall_filter {
badfe9f5
MD
372 DECLARE_BITMAP(sc_entry, NR_syscalls);
373 DECLARE_BITMAP(sc_exit, NR_syscalls);
374 DECLARE_BITMAP(sc_compat_entry, NR_compat_syscalls);
375 DECLARE_BITMAP(sc_compat_exit, NR_compat_syscalls);
80f87dd2
MD
376};
377
2d6d88c6 378static void syscall_entry_event_unknown(struct lttng_event *event,
f405cfce
MD
379 struct pt_regs *regs, unsigned int id)
380{
1b7b9c65 381 unsigned long args[LTTNG_SYSCALL_NR_ARGS];
f405cfce 382
1b7b9c65 383 lttng_syscall_get_arguments(current, regs, args);
1aa3298b 384 if (unlikely(in_compat_syscall()))
d4291869 385 __event_probe__compat_syscall_entry_unknown(event, id, args);
a93244f8 386 else
d4291869 387 __event_probe__syscall_entry_unknown(event, id, args);
f405cfce
MD
388}
389
63aa9160
FD
390static __always_inline
391void syscall_entry_call_func(void *func, unsigned int nrargs, void *data,
392 struct pt_regs *regs)
259b6cb3 393{
63aa9160 394 switch (nrargs) {
259b6cb3
MD
395 case 0:
396 {
63aa9160 397 void (*fptr)(void *__data) = func;
259b6cb3 398
63aa9160 399 fptr(data);
259b6cb3
MD
400 break;
401 }
402 case 1:
403 {
63aa9160 404 void (*fptr)(void *__data, unsigned long arg0) = func;
1b7b9c65 405 unsigned long args[LTTNG_SYSCALL_NR_ARGS];
259b6cb3 406
1b7b9c65 407 lttng_syscall_get_arguments(current, regs, args);
63aa9160 408 fptr(data, args[0]);
259b6cb3
MD
409 break;
410 }
411 case 2:
412 {
413 void (*fptr)(void *__data,
414 unsigned long arg0,
63aa9160 415 unsigned long arg1) = func;
1b7b9c65 416 unsigned long args[LTTNG_SYSCALL_NR_ARGS];
259b6cb3 417
1b7b9c65 418 lttng_syscall_get_arguments(current, regs, args);
63aa9160 419 fptr(data, args[0], args[1]);
259b6cb3
MD
420 break;
421 }
422 case 3:
423 {
424 void (*fptr)(void *__data,
425 unsigned long arg0,
426 unsigned long arg1,
63aa9160 427 unsigned long arg2) = func;
1b7b9c65 428 unsigned long args[LTTNG_SYSCALL_NR_ARGS];
259b6cb3 429
1b7b9c65 430 lttng_syscall_get_arguments(current, regs, args);
63aa9160 431 fptr(data, args[0], args[1], args[2]);
259b6cb3
MD
432 break;
433 }
434 case 4:
435 {
436 void (*fptr)(void *__data,
437 unsigned long arg0,
438 unsigned long arg1,
439 unsigned long arg2,
63aa9160 440 unsigned long arg3) = func;
1b7b9c65 441 unsigned long args[LTTNG_SYSCALL_NR_ARGS];
259b6cb3 442
1b7b9c65 443 lttng_syscall_get_arguments(current, regs, args);
63aa9160 444 fptr(data, args[0], args[1], args[2], args[3]);
259b6cb3
MD
445 break;
446 }
447 case 5:
448 {
449 void (*fptr)(void *__data,
450 unsigned long arg0,
451 unsigned long arg1,
452 unsigned long arg2,
453 unsigned long arg3,
63aa9160 454 unsigned long arg4) = func;
1b7b9c65 455 unsigned long args[LTTNG_SYSCALL_NR_ARGS];
259b6cb3 456
1b7b9c65 457 lttng_syscall_get_arguments(current, regs, args);
63aa9160 458 fptr(data, args[0], args[1], args[2], args[3], args[4]);
259b6cb3
MD
459 break;
460 }
461 case 6:
462 {
463 void (*fptr)(void *__data,
464 unsigned long arg0,
465 unsigned long arg1,
466 unsigned long arg2,
467 unsigned long arg3,
468 unsigned long arg4,
63aa9160 469 unsigned long arg5) = func;
1b7b9c65 470 unsigned long args[LTTNG_SYSCALL_NR_ARGS];
259b6cb3 471
1b7b9c65 472 lttng_syscall_get_arguments(current, regs, args);
63aa9160 473 fptr(data, args[0], args[1], args[2],
259b6cb3
MD
474 args[3], args[4], args[5]);
475 break;
476 }
477 default:
478 break;
479 }
480}
481
63aa9160
FD
482void syscall_entry_event_probe(void *__data, struct pt_regs *regs, long id)
483{
484 struct lttng_channel *chan = __data;
485 struct lttng_event *event, *unknown_event;
486 const struct trace_syscall_entry *table, *entry;
487 size_t table_len;
488
489 if (unlikely(in_compat_syscall())) {
490 struct lttng_syscall_filter *filter = chan->sc_filter;
491
492 if (id < 0 || id >= NR_compat_syscalls
493 || (!READ_ONCE(chan->syscall_all) && !test_bit(id, filter->sc_compat_entry))) {
494 /* System call filtered out. */
495 return;
496 }
497 table = compat_sc_table;
498 table_len = ARRAY_SIZE(compat_sc_table);
499 unknown_event = chan->sc_compat_unknown;
500 } else {
501 struct lttng_syscall_filter *filter = chan->sc_filter;
502
503 if (id < 0 || id >= NR_syscalls
504 || (!READ_ONCE(chan->syscall_all) && !test_bit(id, filter->sc_entry))) {
505 /* System call filtered out. */
506 return;
507 }
508 table = sc_table;
509 table_len = ARRAY_SIZE(sc_table);
510 unknown_event = chan->sc_unknown;
511 }
512 if (unlikely(id < 0 || id >= table_len)) {
513 syscall_entry_event_unknown(unknown_event, regs, id);
514 return;
515 }
516 if (unlikely(in_compat_syscall()))
517 event = chan->compat_sc_table[id];
518 else
519 event = chan->sc_table[id];
520 if (unlikely(!event)) {
521 syscall_entry_event_unknown(unknown_event, regs, id);
522 return;
523 }
524 entry = &table[id];
525 WARN_ON_ONCE(!entry);
526 syscall_entry_call_func(entry->event_func, entry->nrargs, event, regs);
527}
528
2d6d88c6 529static void syscall_exit_event_unknown(struct lttng_event *event,
74f7b56a 530 struct pt_regs *regs, int id, long ret)
5b7ac358 531{
1b7b9c65 532 unsigned long args[LTTNG_SYSCALL_NR_ARGS];
5b7ac358 533
1b7b9c65 534 lttng_syscall_get_arguments(current, regs, args);
1aa3298b 535 if (unlikely(in_compat_syscall()))
5b7ac358
MD
536 __event_probe__compat_syscall_exit_unknown(event, id, ret,
537 args);
538 else
539 __event_probe__syscall_exit_unknown(event, id, ret, args);
540}
541
2d6d88c6 542void syscall_exit_event_probe(void *__data, struct pt_regs *regs, long ret)
5b7ac358
MD
543{
544 struct lttng_channel *chan = __data;
545 struct lttng_event *event, *unknown_event;
546 const struct trace_syscall_entry *table, *entry;
547 size_t table_len;
548 long id;
549
550 id = syscall_get_nr(current, regs);
1aa3298b 551 if (unlikely(in_compat_syscall())) {
badfe9f5
MD
552 struct lttng_syscall_filter *filter = chan->sc_filter;
553
554 if (id < 0 || id >= NR_compat_syscalls
555 || (!READ_ONCE(chan->syscall_all) && !test_bit(id, filter->sc_compat_exit))) {
556 /* System call filtered out. */
557 return;
5b7ac358
MD
558 }
559 table = compat_sc_exit_table;
560 table_len = ARRAY_SIZE(compat_sc_exit_table);
561 unknown_event = chan->compat_sc_exit_unknown;
562 } else {
badfe9f5
MD
563 struct lttng_syscall_filter *filter = chan->sc_filter;
564
565 if (id < 0 || id >= NR_syscalls
566 || (!READ_ONCE(chan->syscall_all) && !test_bit(id, filter->sc_exit))) {
567 /* System call filtered out. */
568 return;
5b7ac358
MD
569 }
570 table = sc_exit_table;
571 table_len = ARRAY_SIZE(sc_exit_table);
572 unknown_event = chan->sc_exit_unknown;
573 }
74f7b56a 574 if (unlikely(id < 0 || id >= table_len)) {
2d6d88c6 575 syscall_exit_event_unknown(unknown_event, regs, id, ret);
5b7ac358
MD
576 return;
577 }
1aa3298b 578 if (unlikely(in_compat_syscall()))
5b7ac358
MD
579 event = chan->compat_sc_exit_table[id];
580 else
581 event = chan->sc_exit_table[id];
582 if (unlikely(!event)) {
2d6d88c6 583 syscall_exit_event_unknown(unknown_event, regs, id, ret);
5b7ac358
MD
584 return;
585 }
586 entry = &table[id];
587 WARN_ON_ONCE(!entry);
588
589 switch (entry->nrargs) {
590 case 0:
591 {
2d6d88c6 592 void (*fptr)(void *__data, long ret) = entry->event_func;
5b7ac358 593
fc4f7161 594 fptr(event, ret);
5b7ac358
MD
595 break;
596 }
597 case 1:
598 {
599 void (*fptr)(void *__data,
fc4f7161 600 long ret,
2d6d88c6 601 unsigned long arg0) = entry->event_func;
1b7b9c65 602 unsigned long args[LTTNG_SYSCALL_NR_ARGS];
5b7ac358 603
1b7b9c65 604 lttng_syscall_get_arguments(current, regs, args);
fc4f7161 605 fptr(event, ret, args[0]);
5b7ac358
MD
606 break;
607 }
608 case 2:
609 {
610 void (*fptr)(void *__data,
fc4f7161 611 long ret,
5b7ac358 612 unsigned long arg0,
2d6d88c6 613 unsigned long arg1) = entry->event_func;
1b7b9c65 614 unsigned long args[LTTNG_SYSCALL_NR_ARGS];
5b7ac358 615
1b7b9c65 616 lttng_syscall_get_arguments(current, regs, args);
fc4f7161 617 fptr(event, ret, args[0], args[1]);
5b7ac358
MD
618 break;
619 }
620 case 3:
621 {
622 void (*fptr)(void *__data,
fc4f7161 623 long ret,
5b7ac358
MD
624 unsigned long arg0,
625 unsigned long arg1,
2d6d88c6 626 unsigned long arg2) = entry->event_func;
1b7b9c65 627 unsigned long args[LTTNG_SYSCALL_NR_ARGS];
5b7ac358 628
1b7b9c65 629 lttng_syscall_get_arguments(current, regs, args);
fc4f7161 630 fptr(event, ret, args[0], args[1], args[2]);
5b7ac358
MD
631 break;
632 }
633 case 4:
634 {
635 void (*fptr)(void *__data,
fc4f7161 636 long ret,
5b7ac358
MD
637 unsigned long arg0,
638 unsigned long arg1,
639 unsigned long arg2,
2d6d88c6 640 unsigned long arg3) = entry->event_func;
1b7b9c65 641 unsigned long args[LTTNG_SYSCALL_NR_ARGS];
5b7ac358 642
1b7b9c65 643 lttng_syscall_get_arguments(current, regs, args);
fc4f7161 644 fptr(event, ret, args[0], args[1], args[2], args[3]);
5b7ac358
MD
645 break;
646 }
647 case 5:
648 {
649 void (*fptr)(void *__data,
fc4f7161 650 long ret,
5b7ac358
MD
651 unsigned long arg0,
652 unsigned long arg1,
653 unsigned long arg2,
654 unsigned long arg3,
2d6d88c6 655 unsigned long arg4) = entry->event_func;
1b7b9c65 656 unsigned long args[LTTNG_SYSCALL_NR_ARGS];
5b7ac358 657
1b7b9c65 658 lttng_syscall_get_arguments(current, regs, args);
fc4f7161 659 fptr(event, ret, args[0], args[1], args[2], args[3], args[4]);
5b7ac358
MD
660 break;
661 }
662 case 6:
663 {
664 void (*fptr)(void *__data,
fc4f7161 665 long ret,
5b7ac358
MD
666 unsigned long arg0,
667 unsigned long arg1,
668 unsigned long arg2,
669 unsigned long arg3,
670 unsigned long arg4,
2d6d88c6 671 unsigned long arg5) = entry->event_func;
1b7b9c65 672 unsigned long args[LTTNG_SYSCALL_NR_ARGS];
5b7ac358 673
1b7b9c65 674 lttng_syscall_get_arguments(current, regs, args);
fc4f7161 675 fptr(event, ret, args[0], args[1], args[2],
5b7ac358
MD
676 args[3], args[4], args[5]);
677 break;
678 }
679 default:
680 break;
681 }
682}
683
33a39a3c
MD
684/*
685 * noinline to diminish caller stack size.
686 * Should be called with sessions lock held.
687 */
49c50022 688static
2d6d88c6 689int fill_event_table(const struct trace_syscall_entry *table, size_t table_len,
5b7ac358
MD
690 struct lttng_event **chan_table, struct lttng_channel *chan,
691 void *filter, enum sc_type type)
259b6cb3 692{
2a0c4816 693 const struct lttng_event_desc *desc;
259b6cb3 694 unsigned int i;
49c50022
MD
695
696 /* Allocate events for each syscall, insert into table */
697 for (i = 0; i < table_len; i++) {
698 struct lttng_kernel_event ev;
2a0c4816 699 desc = table[i].desc;
49c50022
MD
700
701 if (!desc) {
702 /* Unknown syscall */
703 continue;
704 }
705 /*
706 * Skip those already populated by previous failed
707 * register for this channel.
708 */
709 if (chan_table[i])
710 continue;
711 memset(&ev, 0, sizeof(ev));
5b7ac358
MD
712 switch (type) {
713 case SC_TYPE_ENTRY:
badfe9f5
MD
714 ev.u.syscall.entryexit = LTTNG_KERNEL_SYSCALL_ENTRY;
715 ev.u.syscall.abi = LTTNG_KERNEL_SYSCALL_ABI_NATIVE;
5b7ac358
MD
716 break;
717 case SC_TYPE_EXIT:
badfe9f5
MD
718 ev.u.syscall.entryexit = LTTNG_KERNEL_SYSCALL_EXIT;
719 ev.u.syscall.abi = LTTNG_KERNEL_SYSCALL_ABI_NATIVE;
5b7ac358
MD
720 break;
721 case SC_TYPE_COMPAT_ENTRY:
badfe9f5
MD
722 ev.u.syscall.entryexit = LTTNG_KERNEL_SYSCALL_ENTRY;
723 ev.u.syscall.abi = LTTNG_KERNEL_SYSCALL_ABI_COMPAT;
5b7ac358
MD
724 break;
725 case SC_TYPE_COMPAT_EXIT:
badfe9f5
MD
726 ev.u.syscall.entryexit = LTTNG_KERNEL_SYSCALL_EXIT;
727 ev.u.syscall.abi = LTTNG_KERNEL_SYSCALL_ABI_COMPAT;
5b7ac358
MD
728 break;
729 }
092ffe97 730 strncpy(ev.name, desc->name, LTTNG_KERNEL_SYM_NAME_LEN - 1);
f8695253 731 ev.name[LTTNG_KERNEL_SYM_NAME_LEN - 1] = '\0';
33a39a3c
MD
732 ev.instrumentation = LTTNG_KERNEL_SYSCALL;
733 chan_table[i] = _lttng_event_create(chan, &ev, filter,
3c997079 734 desc, ev.instrumentation);
abc0446a
MD
735 WARN_ON_ONCE(!chan_table[i]);
736 if (IS_ERR(chan_table[i])) {
49c50022
MD
737 /*
738 * If something goes wrong in event registration
739 * after the first one, we have no choice but to
740 * leave the previous events in there, until
741 * deleted by session teardown.
742 */
abc0446a 743 return PTR_ERR(chan_table[i]);
49c50022
MD
744 }
745 }
746 return 0;
747}
748
33a39a3c
MD
749/*
750 * Should be called with sessions lock held.
751 */
2d6d88c6 752int lttng_syscalls_register_event(struct lttng_channel *chan, void *filter)
49c50022 753{
2a0c4816 754 struct lttng_kernel_event ev;
259b6cb3
MD
755 int ret;
756
263b6c88 757 wrapper_vmalloc_sync_mappings();
259b6cb3
MD
758
759 if (!chan->sc_table) {
760 /* create syscall table mapping syscall to events */
a90917c3 761 chan->sc_table = kzalloc(sizeof(struct lttng_event *)
259b6cb3
MD
762 * ARRAY_SIZE(sc_table), GFP_KERNEL);
763 if (!chan->sc_table)
764 return -ENOMEM;
765 }
5b7ac358
MD
766 if (!chan->sc_exit_table) {
767 /* create syscall table mapping syscall to events */
768 chan->sc_exit_table = kzalloc(sizeof(struct lttng_event *)
769 * ARRAY_SIZE(sc_exit_table), GFP_KERNEL);
770 if (!chan->sc_exit_table)
771 return -ENOMEM;
772 }
773
259b6cb3 774
49c50022
MD
775#ifdef CONFIG_COMPAT
776 if (!chan->compat_sc_table) {
777 /* create syscall table mapping compat syscall to events */
a90917c3 778 chan->compat_sc_table = kzalloc(sizeof(struct lttng_event *)
a93244f8 779 * ARRAY_SIZE(compat_sc_table), GFP_KERNEL);
49c50022
MD
780 if (!chan->compat_sc_table)
781 return -ENOMEM;
782 }
5b7ac358
MD
783
784 if (!chan->compat_sc_exit_table) {
785 /* create syscall table mapping compat syscall to events */
786 chan->compat_sc_exit_table = kzalloc(sizeof(struct lttng_event *)
787 * ARRAY_SIZE(compat_sc_exit_table), GFP_KERNEL);
788 if (!chan->compat_sc_exit_table)
789 return -ENOMEM;
790 }
49c50022 791#endif
f405cfce 792 if (!chan->sc_unknown) {
f405cfce 793 const struct lttng_event_desc *desc =
d4291869 794 &__event_desc___syscall_entry_unknown;
2f804c0a 795
f405cfce 796 memset(&ev, 0, sizeof(ev));
f8695253
MD
797 strncpy(ev.name, desc->name, LTTNG_KERNEL_SYM_NAME_LEN);
798 ev.name[LTTNG_KERNEL_SYM_NAME_LEN - 1] = '\0';
33a39a3c 799 ev.instrumentation = LTTNG_KERNEL_SYSCALL;
badfe9f5
MD
800 ev.u.syscall.entryexit = LTTNG_KERNEL_SYSCALL_ENTRY;
801 ev.u.syscall.abi = LTTNG_KERNEL_SYSCALL_ABI_NATIVE;
33a39a3c 802 chan->sc_unknown = _lttng_event_create(chan, &ev, filter,
3c997079
MD
803 desc,
804 ev.instrumentation);
abc0446a
MD
805 WARN_ON_ONCE(!chan->sc_unknown);
806 if (IS_ERR(chan->sc_unknown)) {
807 return PTR_ERR(chan->sc_unknown);
f405cfce
MD
808 }
809 }
810
b76dc1a0 811 if (!chan->sc_compat_unknown) {
b76dc1a0 812 const struct lttng_event_desc *desc =
d4291869 813 &__event_desc___compat_syscall_entry_unknown;
b76dc1a0
MD
814
815 memset(&ev, 0, sizeof(ev));
f8695253
MD
816 strncpy(ev.name, desc->name, LTTNG_KERNEL_SYM_NAME_LEN);
817 ev.name[LTTNG_KERNEL_SYM_NAME_LEN - 1] = '\0';
33a39a3c 818 ev.instrumentation = LTTNG_KERNEL_SYSCALL;
badfe9f5
MD
819 ev.u.syscall.entryexit = LTTNG_KERNEL_SYSCALL_ENTRY;
820 ev.u.syscall.abi = LTTNG_KERNEL_SYSCALL_ABI_COMPAT;
33a39a3c 821 chan->sc_compat_unknown = _lttng_event_create(chan, &ev, filter,
3c997079
MD
822 desc,
823 ev.instrumentation);
abc0446a
MD
824 WARN_ON_ONCE(!chan->sc_unknown);
825 if (IS_ERR(chan->sc_compat_unknown)) {
826 return PTR_ERR(chan->sc_compat_unknown);
b76dc1a0
MD
827 }
828 }
829
5b7ac358 830 if (!chan->compat_sc_exit_unknown) {
2f804c0a 831 const struct lttng_event_desc *desc =
5b7ac358 832 &__event_desc___compat_syscall_exit_unknown;
2f804c0a
MD
833
834 memset(&ev, 0, sizeof(ev));
f8695253
MD
835 strncpy(ev.name, desc->name, LTTNG_KERNEL_SYM_NAME_LEN);
836 ev.name[LTTNG_KERNEL_SYM_NAME_LEN - 1] = '\0';
33a39a3c 837 ev.instrumentation = LTTNG_KERNEL_SYSCALL;
badfe9f5
MD
838 ev.u.syscall.entryexit = LTTNG_KERNEL_SYSCALL_EXIT;
839 ev.u.syscall.abi = LTTNG_KERNEL_SYSCALL_ABI_COMPAT;
33a39a3c 840 chan->compat_sc_exit_unknown = _lttng_event_create(chan, &ev,
3c997079
MD
841 filter, desc,
842 ev.instrumentation);
5b7ac358
MD
843 WARN_ON_ONCE(!chan->compat_sc_exit_unknown);
844 if (IS_ERR(chan->compat_sc_exit_unknown)) {
845 return PTR_ERR(chan->compat_sc_exit_unknown);
846 }
847 }
848
849 if (!chan->sc_exit_unknown) {
850 const struct lttng_event_desc *desc =
851 &__event_desc___syscall_exit_unknown;
852
853 memset(&ev, 0, sizeof(ev));
854 strncpy(ev.name, desc->name, LTTNG_KERNEL_SYM_NAME_LEN);
855 ev.name[LTTNG_KERNEL_SYM_NAME_LEN - 1] = '\0';
33a39a3c 856 ev.instrumentation = LTTNG_KERNEL_SYSCALL;
badfe9f5
MD
857 ev.u.syscall.entryexit = LTTNG_KERNEL_SYSCALL_EXIT;
858 ev.u.syscall.abi = LTTNG_KERNEL_SYSCALL_ABI_NATIVE;
33a39a3c 859 chan->sc_exit_unknown = _lttng_event_create(chan, &ev, filter,
3c997079 860 desc, ev.instrumentation);
5b7ac358
MD
861 WARN_ON_ONCE(!chan->sc_exit_unknown);
862 if (IS_ERR(chan->sc_exit_unknown)) {
863 return PTR_ERR(chan->sc_exit_unknown);
2f804c0a
MD
864 }
865 }
866
2d6d88c6 867 ret = fill_event_table(sc_table, ARRAY_SIZE(sc_table),
5b7ac358
MD
868 chan->sc_table, chan, filter, SC_TYPE_ENTRY);
869 if (ret)
870 return ret;
2d6d88c6 871 ret = fill_event_table(sc_exit_table, ARRAY_SIZE(sc_exit_table),
5b7ac358 872 chan->sc_exit_table, chan, filter, SC_TYPE_EXIT);
49c50022
MD
873 if (ret)
874 return ret;
5b7ac358 875
49c50022 876#ifdef CONFIG_COMPAT
2d6d88c6 877 ret = fill_event_table(compat_sc_table, ARRAY_SIZE(compat_sc_table),
5b7ac358
MD
878 chan->compat_sc_table, chan, filter,
879 SC_TYPE_COMPAT_ENTRY);
880 if (ret)
881 return ret;
2d6d88c6 882 ret = fill_event_table(compat_sc_exit_table, ARRAY_SIZE(compat_sc_exit_table),
5b7ac358
MD
883 chan->compat_sc_exit_table, chan, filter,
884 SC_TYPE_COMPAT_EXIT);
49c50022
MD
885 if (ret)
886 return ret;
887#endif
badfe9f5
MD
888
889 if (!chan->sc_filter) {
890 chan->sc_filter = kzalloc(sizeof(struct lttng_syscall_filter),
891 GFP_KERNEL);
892 if (!chan->sc_filter)
893 return -ENOMEM;
894 }
895
80f87dd2
MD
896 if (!chan->sys_enter_registered) {
897 ret = lttng_wrapper_tracepoint_probe_register("sys_enter",
2d6d88c6 898 (void *) syscall_entry_event_probe, chan);
80f87dd2
MD
899 if (ret)
900 return ret;
901 chan->sys_enter_registered = 1;
902 }
63728b02
MD
903 /*
904 * We change the name of sys_exit tracepoint due to namespace
905 * conflict with sys_exit syscall entry.
906 */
80f87dd2
MD
907 if (!chan->sys_exit_registered) {
908 ret = lttng_wrapper_tracepoint_probe_register("sys_exit",
2d6d88c6 909 (void *) syscall_exit_event_probe, chan);
80f87dd2
MD
910 if (ret) {
911 WARN_ON_ONCE(lttng_wrapper_tracepoint_probe_unregister("sys_enter",
2d6d88c6 912 (void *) syscall_entry_event_probe, chan));
80f87dd2
MD
913 return ret;
914 }
915 chan->sys_exit_registered = 1;
63728b02 916 }
259b6cb3
MD
917 return ret;
918}
919
920/*
3b783111 921 * Only called at session destruction.
259b6cb3 922 */
2d6d88c6 923int lttng_syscalls_unregister_event(struct lttng_channel *chan)
259b6cb3
MD
924{
925 int ret;
926
927 if (!chan->sc_table)
928 return 0;
80f87dd2 929 if (chan->sys_enter_registered) {
2d9cd7f3 930 ret = lttng_wrapper_tracepoint_probe_unregister("sys_enter",
2d6d88c6 931 (void *) syscall_entry_event_probe, chan);
80f87dd2
MD
932 if (ret)
933 return ret;
934 chan->sys_enter_registered = 0;
935 }
936 if (chan->sys_exit_registered) {
2d9cd7f3 937 ret = lttng_wrapper_tracepoint_probe_unregister("sys_exit",
2d6d88c6 938 (void *) syscall_exit_event_probe, chan);
80f87dd2
MD
939 if (ret)
940 return ret;
941 chan->sys_exit_registered = 0;
942 }
badfe9f5
MD
943 return 0;
944}
945
2d6d88c6 946int lttng_syscalls_destroy_event(struct lttng_channel *chan)
badfe9f5 947{
259b6cb3 948 kfree(chan->sc_table);
5b7ac358 949 kfree(chan->sc_exit_table);
49c50022
MD
950#ifdef CONFIG_COMPAT
951 kfree(chan->compat_sc_table);
5b7ac358 952 kfree(chan->compat_sc_exit_table);
49c50022 953#endif
80f87dd2
MD
954 kfree(chan->sc_filter);
955 return 0;
956}
957
958static
959int get_syscall_nr(const char *syscall_name)
960{
961 int syscall_nr = -1;
962 int i;
963
964 for (i = 0; i < ARRAY_SIZE(sc_table); i++) {
965 const struct trace_syscall_entry *entry;
5b7ac358 966 const char *it_name;
80f87dd2
MD
967
968 entry = &sc_table[i];
969 if (!entry->desc)
970 continue;
5b7ac358
MD
971 it_name = entry->desc->name;
972 it_name += strlen(SYSCALL_ENTRY_STR);
973 if (!strcmp(syscall_name, it_name)) {
80f87dd2
MD
974 syscall_nr = i;
975 break;
976 }
977 }
978 return syscall_nr;
979}
980
981static
982int get_compat_syscall_nr(const char *syscall_name)
983{
984 int syscall_nr = -1;
985 int i;
986
987 for (i = 0; i < ARRAY_SIZE(compat_sc_table); i++) {
988 const struct trace_syscall_entry *entry;
5b7ac358 989 const char *it_name;
80f87dd2
MD
990
991 entry = &compat_sc_table[i];
992 if (!entry->desc)
993 continue;
5b7ac358
MD
994 it_name = entry->desc->name;
995 it_name += strlen(COMPAT_SYSCALL_ENTRY_STR);
996 if (!strcmp(syscall_name, it_name)) {
80f87dd2
MD
997 syscall_nr = i;
998 break;
999 }
1000 }
1001 return syscall_nr;
1002}
1003
12e579db
MD
1004static
1005uint32_t get_sc_tables_len(void)
1006{
1007 return ARRAY_SIZE(sc_table) + ARRAY_SIZE(compat_sc_table);
1008}
1009
badfe9f5
MD
1010static
1011const char *get_syscall_name(struct lttng_event *event)
80f87dd2 1012{
badfe9f5 1013 size_t prefix_len = 0;
80f87dd2 1014
badfe9f5 1015 WARN_ON_ONCE(event->instrumentation != LTTNG_KERNEL_SYSCALL);
80f87dd2 1016
badfe9f5
MD
1017 switch (event->u.syscall.entryexit) {
1018 case LTTNG_SYSCALL_ENTRY:
1019 switch (event->u.syscall.abi) {
1020 case LTTNG_SYSCALL_ABI_NATIVE:
1021 prefix_len = strlen(SYSCALL_ENTRY_STR);
1022 break;
1023 case LTTNG_SYSCALL_ABI_COMPAT:
1024 prefix_len = strlen(COMPAT_SYSCALL_ENTRY_STR);
1025 break;
80f87dd2 1026 }
badfe9f5
MD
1027 break;
1028 case LTTNG_SYSCALL_EXIT:
1029 switch (event->u.syscall.abi) {
1030 case LTTNG_SYSCALL_ABI_NATIVE:
1031 prefix_len = strlen(SYSCALL_EXIT_STR);
1032 break;
1033 case LTTNG_SYSCALL_ABI_COMPAT:
1034 prefix_len = strlen(COMPAT_SYSCALL_EXIT_STR);
1035 break;
80f87dd2 1036 }
badfe9f5 1037 break;
80f87dd2 1038 }
badfe9f5
MD
1039 WARN_ON_ONCE(prefix_len == 0);
1040 return event->desc->name + prefix_len;
1041}
1042
2d6d88c6 1043int lttng_syscall_filter_enable_event(struct lttng_channel *chan,
badfe9f5
MD
1044 struct lttng_event *event)
1045{
1046 struct lttng_syscall_filter *filter = chan->sc_filter;
1047 const char *syscall_name;
1048 unsigned long *bitmap;
1049 int syscall_nr;
1050
1051 WARN_ON_ONCE(!chan->sc_table);
1052
1053 syscall_name = get_syscall_name(event);
1054
1055 switch (event->u.syscall.abi) {
1056 case LTTNG_SYSCALL_ABI_NATIVE:
1057 syscall_nr = get_syscall_nr(syscall_name);
1058 break;
1059 case LTTNG_SYSCALL_ABI_COMPAT:
1060 syscall_nr = get_compat_syscall_nr(syscall_name);
1061 break;
1062 default:
1063 return -EINVAL;
80f87dd2 1064 }
badfe9f5
MD
1065 if (syscall_nr < 0)
1066 return -ENOENT;
1067
badfe9f5
MD
1068 switch (event->u.syscall.entryexit) {
1069 case LTTNG_SYSCALL_ENTRY:
1070 switch (event->u.syscall.abi) {
1071 case LTTNG_SYSCALL_ABI_NATIVE:
1072 bitmap = filter->sc_entry;
1073 break;
1074 case LTTNG_SYSCALL_ABI_COMPAT:
1075 bitmap = filter->sc_compat_entry;
1076 break;
6d9694d8
MD
1077 default:
1078 return -EINVAL;
80f87dd2 1079 }
badfe9f5
MD
1080 break;
1081 case LTTNG_SYSCALL_EXIT:
1082 switch (event->u.syscall.abi) {
1083 case LTTNG_SYSCALL_ABI_NATIVE:
1084 bitmap = filter->sc_exit;
1085 break;
1086 case LTTNG_SYSCALL_ABI_COMPAT:
1087 bitmap = filter->sc_compat_exit;
1088 break;
6d9694d8
MD
1089 default:
1090 return -EINVAL;
80f87dd2 1091 }
badfe9f5
MD
1092 break;
1093 default:
1094 return -EINVAL;
80f87dd2 1095 }
badfe9f5
MD
1096 if (test_bit(syscall_nr, bitmap))
1097 return -EEXIST;
1098 bitmap_set(bitmap, syscall_nr, 1);
80f87dd2 1099 return 0;
80f87dd2
MD
1100}
1101
2d6d88c6 1102int lttng_syscall_filter_disable_event(struct lttng_channel *chan,
badfe9f5 1103 struct lttng_event *event)
80f87dd2 1104{
badfe9f5
MD
1105 struct lttng_syscall_filter *filter = chan->sc_filter;
1106 const char *syscall_name;
1107 unsigned long *bitmap;
1108 int syscall_nr;
80f87dd2
MD
1109
1110 WARN_ON_ONCE(!chan->sc_table);
1111
badfe9f5
MD
1112 syscall_name = get_syscall_name(event);
1113
1114 switch (event->u.syscall.abi) {
1115 case LTTNG_SYSCALL_ABI_NATIVE:
1116 syscall_nr = get_syscall_nr(syscall_name);
1117 break;
1118 case LTTNG_SYSCALL_ABI_COMPAT:
1119 syscall_nr = get_compat_syscall_nr(syscall_name);
1120 break;
1121 default:
1122 return -EINVAL;
80f87dd2 1123 }
badfe9f5
MD
1124 if (syscall_nr < 0)
1125 return -ENOENT;
80f87dd2 1126
badfe9f5
MD
1127 switch (event->u.syscall.entryexit) {
1128 case LTTNG_SYSCALL_ENTRY:
1129 switch (event->u.syscall.abi) {
1130 case LTTNG_SYSCALL_ABI_NATIVE:
1131 bitmap = filter->sc_entry;
1132 break;
1133 case LTTNG_SYSCALL_ABI_COMPAT:
1134 bitmap = filter->sc_compat_entry;
1135 break;
6d9694d8
MD
1136 default:
1137 return -EINVAL;
80f87dd2 1138 }
badfe9f5
MD
1139 break;
1140 case LTTNG_SYSCALL_EXIT:
1141 switch (event->u.syscall.abi) {
1142 case LTTNG_SYSCALL_ABI_NATIVE:
1143 bitmap = filter->sc_exit;
1144 break;
1145 case LTTNG_SYSCALL_ABI_COMPAT:
1146 bitmap = filter->sc_compat_exit;
1147 break;
6d9694d8
MD
1148 default:
1149 return -EINVAL;
80f87dd2 1150 }
badfe9f5
MD
1151 break;
1152 default:
1153 return -EINVAL;
80f87dd2 1154 }
badfe9f5
MD
1155 if (!test_bit(syscall_nr, bitmap))
1156 return -EEXIST;
1157 bitmap_clear(bitmap, syscall_nr, 1);
80f87dd2 1158
badfe9f5 1159 return 0;
259b6cb3 1160}
2d2464bd
MD
1161
1162static
1163const struct trace_syscall_entry *syscall_list_get_entry(loff_t *pos)
1164{
1165 const struct trace_syscall_entry *entry;
1166 int iter = 0;
1167
1168 for (entry = sc_table;
1169 entry < sc_table + ARRAY_SIZE(sc_table);
1170 entry++) {
1171 if (iter++ >= *pos)
1172 return entry;
1173 }
1174 for (entry = compat_sc_table;
1175 entry < compat_sc_table + ARRAY_SIZE(compat_sc_table);
1176 entry++) {
1177 if (iter++ >= *pos)
1178 return entry;
1179 }
1180 /* End of list */
1181 return NULL;
1182}
1183
1184static
1185void *syscall_list_start(struct seq_file *m, loff_t *pos)
1186{
1187 return (void *) syscall_list_get_entry(pos);
1188}
1189
1190static
1191void *syscall_list_next(struct seq_file *m, void *p, loff_t *ppos)
1192{
1193 (*ppos)++;
1194 return (void *) syscall_list_get_entry(ppos);
1195}
1196
1197static
1198void syscall_list_stop(struct seq_file *m, void *p)
1199{
1200}
1201
12e579db
MD
1202static
1203int get_sc_table(const struct trace_syscall_entry *entry,
1204 const struct trace_syscall_entry **table,
1205 unsigned int *bitness)
1206{
1207 if (entry >= sc_table && entry < sc_table + ARRAY_SIZE(sc_table)) {
1208 if (bitness)
1209 *bitness = BITS_PER_LONG;
1210 if (table)
1211 *table = sc_table;
1212 return 0;
1213 }
1214 if (!(entry >= compat_sc_table
1215 && entry < compat_sc_table + ARRAY_SIZE(compat_sc_table))) {
1216 return -EINVAL;
1217 }
1218 if (bitness)
1219 *bitness = 32;
1220 if (table)
1221 *table = compat_sc_table;
1222 return 0;
1223}
1224
2d2464bd
MD
1225static
1226int syscall_list_show(struct seq_file *m, void *p)
1227{
1228 const struct trace_syscall_entry *table, *entry = p;
1229 unsigned int bitness;
d4291869 1230 unsigned long index;
12e579db 1231 int ret;
d4291869 1232 const char *name;
2d2464bd 1233
12e579db
MD
1234 ret = get_sc_table(entry, &table, &bitness);
1235 if (ret)
1236 return ret;
f4855b46
MD
1237 if (!entry->desc)
1238 return 0;
d4291869
MD
1239 if (table == sc_table) {
1240 index = entry - table;
1241 name = &entry->desc->name[strlen(SYSCALL_ENTRY_STR)];
1242 } else {
1243 index = (entry - table) + ARRAY_SIZE(sc_table);
1244 name = &entry->desc->name[strlen(COMPAT_SYSCALL_ENTRY_STR)];
1245 }
12e579db 1246 seq_printf(m, "syscall { index = %lu; name = %s; bitness = %u; };\n",
d4291869 1247 index, name, bitness);
2d2464bd
MD
1248 return 0;
1249}
1250
1251static
1252const struct seq_operations lttng_syscall_list_seq_ops = {
1253 .start = syscall_list_start,
1254 .next = syscall_list_next,
1255 .stop = syscall_list_stop,
1256 .show = syscall_list_show,
1257};
1258
1259static
1260int lttng_syscall_list_open(struct inode *inode, struct file *file)
1261{
1262 return seq_open(file, &lttng_syscall_list_seq_ops);
1263}
1264
1265const struct file_operations lttng_syscall_list_fops = {
1266 .owner = THIS_MODULE,
1267 .open = lttng_syscall_list_open,
1268 .read = seq_read,
1269 .llseek = seq_lseek,
1270 .release = seq_release,
1271};
12e579db 1272
badfe9f5
MD
1273/*
1274 * A syscall is enabled if it is traced for either entry or exit.
1275 */
12e579db
MD
1276long lttng_channel_syscall_mask(struct lttng_channel *channel,
1277 struct lttng_kernel_syscall_mask __user *usyscall_mask)
1278{
1279 uint32_t len, sc_tables_len, bitmask_len;
1280 int ret = 0, bit;
1281 char *tmp_mask;
1282 struct lttng_syscall_filter *filter;
1283
1284 ret = get_user(len, &usyscall_mask->len);
1285 if (ret)
1286 return ret;
1287 sc_tables_len = get_sc_tables_len();
1288 bitmask_len = ALIGN(sc_tables_len, 8) >> 3;
1289 if (len < sc_tables_len) {
1290 return put_user(sc_tables_len, &usyscall_mask->len);
1291 }
1292 /* Array is large enough, we can copy array to user-space. */
1293 tmp_mask = kzalloc(bitmask_len, GFP_KERNEL);
1294 if (!tmp_mask)
1295 return -ENOMEM;
1296 filter = channel->sc_filter;
1297
1298 for (bit = 0; bit < ARRAY_SIZE(sc_table); bit++) {
e2129868 1299 char state;
2f25059d
MD
1300
1301 if (channel->sc_table) {
badfe9f5
MD
1302 if (!READ_ONCE(channel->syscall_all) && filter)
1303 state = test_bit(bit, filter->sc_entry)
1304 || test_bit(bit, filter->sc_exit);
2f25059d
MD
1305 else
1306 state = 1;
1307 } else {
1308 state = 0;
1309 }
1310 bt_bitfield_write_be(tmp_mask, char, bit, 1, state);
12e579db
MD
1311 }
1312 for (; bit < sc_tables_len; bit++) {
e2129868 1313 char state;
2f25059d
MD
1314
1315 if (channel->compat_sc_table) {
badfe9f5 1316 if (!READ_ONCE(channel->syscall_all) && filter)
2f25059d 1317 state = test_bit(bit - ARRAY_SIZE(sc_table),
badfe9f5
MD
1318 filter->sc_compat_entry)
1319 || test_bit(bit - ARRAY_SIZE(sc_table),
1320 filter->sc_compat_exit);
2f25059d
MD
1321 else
1322 state = 1;
1323 } else {
1324 state = 0;
1325 }
1326 bt_bitfield_write_be(tmp_mask, char, bit, 1, state);
12e579db
MD
1327 }
1328 if (copy_to_user(usyscall_mask->mask, tmp_mask, bitmask_len))
1329 ret = -EFAULT;
1330 kfree(tmp_mask);
1331 return ret;
1332}
082d4946
MD
1333
1334int lttng_abi_syscall_list(void)
1335{
1336 struct file *syscall_list_file;
1337 int file_fd, ret;
1338
4ac10b76 1339 file_fd = lttng_get_unused_fd();
082d4946
MD
1340 if (file_fd < 0) {
1341 ret = file_fd;
1342 goto fd_error;
1343 }
1344
1345 syscall_list_file = anon_inode_getfile("[lttng_syscall_list]",
1346 &lttng_syscall_list_fops,
1347 NULL, O_RDWR);
1348 if (IS_ERR(syscall_list_file)) {
1349 ret = PTR_ERR(syscall_list_file);
1350 goto file_error;
1351 }
1352 ret = lttng_syscall_list_fops.open(NULL, syscall_list_file);
1353 if (ret < 0)
1354 goto open_error;
1355 fd_install(file_fd, syscall_list_file);
082d4946
MD
1356 return file_fd;
1357
1358open_error:
1359 fput(syscall_list_file);
1360file_error:
1361 put_unused_fd(file_fd);
1362fd_error:
1363 return ret;
1364}
This page took 0.110571 seconds and 4 git commands to generate.