Introduce lazy system call event creation
[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>
8a8ac9a8 32#include <lttng/utils.h>
259b6cb3 33
6333ace3 34#ifndef CONFIG_COMPAT
bfa949bf
MD
35# ifndef is_compat_task
36# define is_compat_task() (0)
37# endif
6333ace3
MD
38#endif
39
1aa3298b
MD
40/* in_compat_syscall appears in kernel 4.6. */
41#ifndef in_compat_syscall
42 #define in_compat_syscall() is_compat_task()
43#endif
44
5b7ac358
MD
45enum sc_type {
46 SC_TYPE_ENTRY,
47 SC_TYPE_EXIT,
48 SC_TYPE_COMPAT_ENTRY,
49 SC_TYPE_COMPAT_EXIT,
50};
51
d4291869
MD
52#define SYSCALL_ENTRY_TOK syscall_entry_
53#define COMPAT_SYSCALL_ENTRY_TOK compat_syscall_entry_
54#define SYSCALL_EXIT_TOK syscall_exit_
55#define COMPAT_SYSCALL_EXIT_TOK compat_syscall_exit_
56
57#define SYSCALL_ENTRY_STR __stringify(SYSCALL_ENTRY_TOK)
58#define COMPAT_SYSCALL_ENTRY_STR __stringify(COMPAT_SYSCALL_ENTRY_TOK)
59#define SYSCALL_EXIT_STR __stringify(SYSCALL_EXIT_TOK)
60#define COMPAT_SYSCALL_EXIT_STR __stringify(COMPAT_SYSCALL_EXIT_TOK)
5b7ac358 61
a93244f8 62static
2d6d88c6 63void syscall_entry_event_probe(void *__data, struct pt_regs *regs, long id);
5b7ac358 64static
2d6d88c6 65void syscall_exit_event_probe(void *__data, struct pt_regs *regs, long ret);
259b6cb3 66
8a8ac9a8
FD
67static
68void syscall_entry_event_notifier_probe(void *__data, struct pt_regs *regs,
69 long id);
70static
71void syscall_exit_event_notifier_probe(void *__data, struct pt_regs *regs,
72 long ret);
73
3a523f5b
MD
74/*
75 * Forward declarations for old kernels.
76 */
77struct mmsghdr;
78struct rlimit64;
79struct oldold_utsname;
80struct old_utsname;
81struct sel_arg_struct;
82struct mmap_arg_struct;
c0b71117 83struct file_handle;
a292e6f1 84struct user_msghdr;
3a523f5b 85
9eb15e8b
MJ
86/*
87 * Forward declaration for kernels >= 5.6
88 */
89struct timex;
edfdcb68
MJ
90struct timeval;
91struct itimerval;
92struct itimerspec;
93
94#if (LINUX_VERSION_CODE >= KERNEL_VERSION(5,6,0))
95typedef __kernel_old_time_t time_t;
96#endif
9eb15e8b 97
80f87dd2
MD
98#ifdef IA32_NR_syscalls
99#define NR_compat_syscalls IA32_NR_syscalls
100#else
101#define NR_compat_syscalls NR_syscalls
102#endif
103
259b6cb3
MD
104/*
105 * Create LTTng tracepoint probes.
106 */
107#define LTTNG_PACKAGE_BUILD
108#define CREATE_TRACE_POINTS
2655f9ad 109#define TP_MODULE_NOINIT
c075712b 110#define TRACE_INCLUDE_PATH instrumentation/syscalls/headers
259b6cb3 111
a93244f8
MD
112#define PARAMS(args...) args
113
5b7ac358 114/* Handle unknown syscalls */
72a52753 115#undef TRACE_SYSTEM
5b7ac358 116#define TRACE_SYSTEM syscalls_unknown
241ae9a8 117#include <instrumentation/syscalls/headers/syscalls_unknown.h>
5b7ac358
MD
118#undef TRACE_SYSTEM
119
fc4f7161
MD
120#define SC_ENTER
121
fc4f7161
MD
122#undef sc_exit
123#define sc_exit(...)
b75d00c4
MD
124#undef sc_in
125#define sc_in(...) __VA_ARGS__
126#undef sc_out
127#define sc_out(...)
128#undef sc_inout
129#define sc_inout(...) __VA_ARGS__
5b7ac358
MD
130
131/* Hijack probe callback for system call enter */
a93244f8 132#undef TP_PROBE_CB
2d6d88c6 133#define TP_PROBE_CB(_template) &syscall_entry_event_probe
57ede728 134#define SC_LTTNG_TRACEPOINT_EVENT(_name, _proto, _args, _fields) \
d4291869 135 LTTNG_TRACEPOINT_EVENT(syscall_entry_##_name, PARAMS(_proto), PARAMS(_args), \
57ede728 136 PARAMS(_fields))
265822ae 137#define SC_LTTNG_TRACEPOINT_EVENT_CODE(_name, _proto, _args, _locvar, _code_pre, _fields, _code_post) \
d4291869 138 LTTNG_TRACEPOINT_EVENT_CODE(syscall_entry_##_name, PARAMS(_proto), PARAMS(_args), \
265822ae
MD
139 PARAMS(_locvar), PARAMS(_code_pre), \
140 PARAMS(_fields), PARAMS(_code_post))
57ede728
MD
141#define SC_LTTNG_TRACEPOINT_EVENT_CLASS_NOARGS(_name, _fields) \
142 LTTNG_TRACEPOINT_EVENT_CLASS_NOARGS(syscall_entry_##_name, PARAMS(_fields))
cb3ef14c 143#define SC_LTTNG_TRACEPOINT_EVENT_INSTANCE_NOARGS(_template, _name) \
d4291869 144 LTTNG_TRACEPOINT_EVENT_INSTANCE_NOARGS(syscall_entry_##_template, syscall_entry_##_name)
141ddf28
MD
145/* Enumerations only defined at first inclusion. */
146#define SC_LTTNG_TRACEPOINT_ENUM(_name, _values) \
147 LTTNG_TRACEPOINT_ENUM(_name, PARAMS(_values))
a93244f8 148#undef TRACE_SYSTEM
d4291869 149#define TRACE_SYSTEM syscall_entry_integers
5b7ac358 150#define TRACE_INCLUDE_FILE syscalls_integers
241ae9a8 151#include <instrumentation/syscalls/headers/syscalls_integers.h>
5b7ac358 152#undef TRACE_INCLUDE_FILE
a93244f8 153#undef TRACE_SYSTEM
d4291869 154#define TRACE_SYSTEM syscall_entry_pointers
5b7ac358 155#define TRACE_INCLUDE_FILE syscalls_pointers
241ae9a8 156#include <instrumentation/syscalls/headers/syscalls_pointers.h>
5b7ac358 157#undef TRACE_INCLUDE_FILE
a93244f8 158#undef TRACE_SYSTEM
141ddf28 159#undef SC_LTTNG_TRACEPOINT_ENUM
cb3ef14c
MD
160#undef SC_LTTNG_TRACEPOINT_EVENT_CODE
161#undef SC_LTTNG_TRACEPOINT_EVENT
162#undef SC_LTTNG_TRACEPOINT_EVENT_CLASS_NOARGS
163#undef SC_LTTNG_TRACEPOINT_EVENT_INSTANCE_NOARGS
5b7ac358 164#undef TP_PROBE_CB
3bc29f0a
MD
165#undef _TRACE_SYSCALLS_INTEGERS_H
166#undef _TRACE_SYSCALLS_POINTERS_H
5b7ac358
MD
167
168/* Hijack probe callback for compat system call enter */
2d6d88c6 169#define TP_PROBE_CB(_template) &syscall_entry_event_probe
771af27e 170#define LTTNG_SC_COMPAT
57ede728 171#define SC_LTTNG_TRACEPOINT_EVENT(_name, _proto, _args, _fields) \
d4291869 172 LTTNG_TRACEPOINT_EVENT(compat_syscall_entry_##_name, PARAMS(_proto), PARAMS(_args), \
57ede728 173 PARAMS(_fields))
265822ae 174#define SC_LTTNG_TRACEPOINT_EVENT_CODE(_name, _proto, _args, _locvar, _code_pre, _fields, _code_post) \
d4291869 175 LTTNG_TRACEPOINT_EVENT_CODE(compat_syscall_entry_##_name, PARAMS(_proto), PARAMS(_args), \
265822ae 176 PARAMS(_locvar), PARAMS(_code_pre), PARAMS(_fields), PARAMS(_code_post))
57ede728
MD
177#define SC_LTTNG_TRACEPOINT_EVENT_CLASS_NOARGS(_name, _fields) \
178 LTTNG_TRACEPOINT_EVENT_CLASS_NOARGS(compat_syscall_entry_##_name, PARAMS(_fields))
cb3ef14c 179#define SC_LTTNG_TRACEPOINT_EVENT_INSTANCE_NOARGS(_template, _name) \
d4291869
MD
180 LTTNG_TRACEPOINT_EVENT_INSTANCE_NOARGS(compat_syscall_entry_##_template, \
181 compat_syscall_entry_##_name)
141ddf28
MD
182/* Enumerations only defined at inital inclusion (not here). */
183#define SC_LTTNG_TRACEPOINT_ENUM(_name, _values)
d4291869 184#define TRACE_SYSTEM compat_syscall_entry_integers
5b7ac358 185#define TRACE_INCLUDE_FILE compat_syscalls_integers
241ae9a8 186#include <instrumentation/syscalls/headers/compat_syscalls_integers.h>
5b7ac358
MD
187#undef TRACE_INCLUDE_FILE
188#undef TRACE_SYSTEM
d4291869 189#define TRACE_SYSTEM compat_syscall_entry_pointers
5b7ac358 190#define TRACE_INCLUDE_FILE compat_syscalls_pointers
241ae9a8 191#include <instrumentation/syscalls/headers/compat_syscalls_pointers.h>
5b7ac358
MD
192#undef TRACE_INCLUDE_FILE
193#undef TRACE_SYSTEM
141ddf28 194#undef SC_LTTNG_TRACEPOINT_ENUM
cb3ef14c
MD
195#undef SC_LTTNG_TRACEPOINT_EVENT_CODE
196#undef SC_LTTNG_TRACEPOINT_EVENT
197#undef SC_LTTNG_TRACEPOINT_EVENT_CLASS_NOARGS
198#undef SC_LTTNG_TRACEPOINT_EVENT_INSTANCE_NOARGS
5b7ac358 199#undef TP_PROBE_CB
3bc29f0a
MD
200#undef _TRACE_SYSCALLS_INTEGERS_H
201#undef _TRACE_SYSCALLS_POINTERS_H
771af27e 202#undef LTTNG_SC_COMPAT
5b7ac358 203
fc4f7161
MD
204#undef SC_ENTER
205
206#define SC_EXIT
207
fc4f7161
MD
208#undef sc_exit
209#define sc_exit(...) __VA_ARGS__
b75d00c4
MD
210#undef sc_in
211#define sc_in(...)
212#undef sc_out
213#define sc_out(...) __VA_ARGS__
214#undef sc_inout
215#define sc_inout(...) __VA_ARGS__
5b7ac358
MD
216
217/* Hijack probe callback for system call exit */
2d6d88c6 218#define TP_PROBE_CB(_template) &syscall_exit_event_probe
57ede728 219#define SC_LTTNG_TRACEPOINT_EVENT(_name, _proto, _args, _fields) \
3bc29f0a 220 LTTNG_TRACEPOINT_EVENT(syscall_exit_##_name, PARAMS(_proto), PARAMS(_args), \
57ede728 221 PARAMS(_fields))
265822ae 222#define SC_LTTNG_TRACEPOINT_EVENT_CODE(_name, _proto, _args, _locvar, _code_pre, _fields, _code_post) \
3bc29f0a 223 LTTNG_TRACEPOINT_EVENT_CODE(syscall_exit_##_name, PARAMS(_proto), PARAMS(_args), \
265822ae 224 PARAMS(_locvar), PARAMS(_code_pre), PARAMS(_fields), PARAMS(_code_post))
57ede728
MD
225#define SC_LTTNG_TRACEPOINT_EVENT_CLASS_NOARGS(_name, _fields) \
226 LTTNG_TRACEPOINT_EVENT_CLASS_NOARGS(syscall_exit_##_name, PARAMS(_fields))
cb3ef14c
MD
227#define SC_LTTNG_TRACEPOINT_EVENT_INSTANCE_NOARGS(_template, _name) \
228 LTTNG_TRACEPOINT_EVENT_INSTANCE_NOARGS(syscall_exit_##_template, \
5b7ac358 229 syscall_exit_##_name)
141ddf28
MD
230/* Enumerations only defined at inital inclusion (not here). */
231#define SC_LTTNG_TRACEPOINT_ENUM(_name, _values)
5b7ac358
MD
232#define TRACE_SYSTEM syscall_exit_integers
233#define TRACE_INCLUDE_FILE syscalls_integers
241ae9a8 234#include <instrumentation/syscalls/headers/syscalls_integers.h>
5b7ac358
MD
235#undef TRACE_INCLUDE_FILE
236#undef TRACE_SYSTEM
237#define TRACE_SYSTEM syscall_exit_pointers
238#define TRACE_INCLUDE_FILE syscalls_pointers
241ae9a8 239#include <instrumentation/syscalls/headers/syscalls_pointers.h>
5b7ac358
MD
240#undef TRACE_INCLUDE_FILE
241#undef TRACE_SYSTEM
141ddf28 242#undef SC_LTTNG_TRACEPOINT_ENUM
cb3ef14c
MD
243#undef SC_LTTNG_TRACEPOINT_EVENT_CODE
244#undef SC_LTTNG_TRACEPOINT_EVENT
245#undef SC_LTTNG_TRACEPOINT_EVENT_CLASS_NOARGS
246#undef SC_LTTNG_TRACEPOINT_EVENT_INSTANCE_NOARGS
5b7ac358 247#undef TP_PROBE_CB
3bc29f0a
MD
248#undef _TRACE_SYSCALLS_INTEGERS_H
249#undef _TRACE_SYSCALLS_POINTERS_H
5b7ac358
MD
250
251
252/* Hijack probe callback for compat system call exit */
2d6d88c6 253#define TP_PROBE_CB(_template) &syscall_exit_event_probe
771af27e 254#define LTTNG_SC_COMPAT
57ede728 255#define SC_LTTNG_TRACEPOINT_EVENT(_name, _proto, _args, _fields) \
3bc29f0a 256 LTTNG_TRACEPOINT_EVENT(compat_syscall_exit_##_name, PARAMS(_proto), PARAMS(_args), \
57ede728 257 PARAMS(_fields))
265822ae 258#define SC_LTTNG_TRACEPOINT_EVENT_CODE(_name, _proto, _args, _locvar, _code_pre, _fields, _code_post) \
3bc29f0a 259 LTTNG_TRACEPOINT_EVENT_CODE(compat_syscall_exit_##_name, PARAMS(_proto), PARAMS(_args), \
265822ae 260 PARAMS(_locvar), PARAMS(_code_pre), PARAMS(_fields), PARAMS(_code_post))
57ede728
MD
261#define SC_LTTNG_TRACEPOINT_EVENT_CLASS_NOARGS(_name, _fields) \
262 LTTNG_TRACEPOINT_EVENT_CLASS_NOARGS(compat_syscall_exit_##_name, PARAMS(_fields))
cb3ef14c 263#define SC_LTTNG_TRACEPOINT_EVENT_INSTANCE_NOARGS(_template, _name) \
3bc29f0a 264 LTTNG_TRACEPOINT_EVENT_INSTANCE_NOARGS(compat_syscall_exit_##_template, \
5b7ac358 265 compat_syscall_exit_##_name)
141ddf28
MD
266/* Enumerations only defined at inital inclusion (not here). */
267#define SC_LTTNG_TRACEPOINT_ENUM(_name, _values)
5b7ac358
MD
268#define TRACE_SYSTEM compat_syscall_exit_integers
269#define TRACE_INCLUDE_FILE compat_syscalls_integers
241ae9a8 270#include <instrumentation/syscalls/headers/compat_syscalls_integers.h>
5b7ac358 271#undef TRACE_INCLUDE_FILE
a93244f8 272#undef TRACE_SYSTEM
5b7ac358
MD
273#define TRACE_SYSTEM compat_syscall_exit_pointers
274#define TRACE_INCLUDE_FILE compat_syscalls_pointers
241ae9a8 275#include <instrumentation/syscalls/headers/compat_syscalls_pointers.h>
5b7ac358 276#undef TRACE_INCLUDE_FILE
a93244f8 277#undef TRACE_SYSTEM
141ddf28 278#undef SC_LTTNG_TRACEPOINT_ENUM
cb3ef14c
MD
279#undef SC_LTTNG_TRACEPOINT_EVENT_CODE
280#undef SC_LTTNG_TRACEPOINT_EVENT
281#undef SC_LTTNG_TRACEPOINT_EVENT_CLASS_NOARGS
282#undef SC_LTTNG_TRACEPOINT_EVENT_INSTANCE_NOARGS
a93244f8 283#undef TP_PROBE_CB
3bc29f0a
MD
284#undef _TRACE_SYSCALLS_INTEGERS_H
285#undef _TRACE_SYSCALLS_POINTERS_H
771af27e 286#undef LTTNG_SC_COMPAT
5b7ac358 287
fc4f7161 288#undef SC_EXIT
259b6cb3 289
2655f9ad 290#undef TP_MODULE_NOINIT
259b6cb3
MD
291#undef LTTNG_PACKAGE_BUILD
292#undef CREATE_TRACE_POINTS
293
a93244f8 294struct trace_syscall_entry {
2d6d88c6 295 void *event_func;
8a8ac9a8 296 void *event_notifier_func;
a93244f8
MD
297 const struct lttng_event_desc *desc;
298 const struct lttng_event_field *fields;
299 unsigned int nrargs;
300};
301
302#define CREATE_SYSCALL_TABLE
303
fc4f7161
MD
304#define SC_ENTER
305
306#undef sc_exit
307#define sc_exit(...)
308
259b6cb3 309#undef TRACE_SYSCALL_TABLE
f7bdf4db 310#define TRACE_SYSCALL_TABLE(_template, _name, _nr, _nrargs) \
259b6cb3 311 [ _nr ] = { \
2d6d88c6 312 .event_func = __event_probe__syscall_entry_##_template, \
8a8ac9a8 313 .event_notifier_func = __event_notifier_probe__syscall_entry_##_template, \
259b6cb3 314 .nrargs = (_nrargs), \
d4291869
MD
315 .fields = __event_fields___syscall_entry_##_template, \
316 .desc = &__event_desc___syscall_entry_##_name, \
259b6cb3
MD
317 },
318
2d6d88c6 319/* Event syscall enter tracing table */
49c50022 320static const struct trace_syscall_entry sc_table[] = {
241ae9a8
MD
321#include <instrumentation/syscalls/headers/syscalls_integers.h>
322#include <instrumentation/syscalls/headers/syscalls_pointers.h>
259b6cb3
MD
323};
324
a93244f8
MD
325#undef TRACE_SYSCALL_TABLE
326#define TRACE_SYSCALL_TABLE(_template, _name, _nr, _nrargs) \
327 [ _nr ] = { \
2d6d88c6 328 .event_func = __event_probe__compat_syscall_entry_##_template, \
8a8ac9a8 329 .event_notifier_func = __event_notifier_probe__compat_syscall_entry_##_template, \
a93244f8 330 .nrargs = (_nrargs), \
d4291869
MD
331 .fields = __event_fields___compat_syscall_entry_##_template, \
332 .desc = &__event_desc___compat_syscall_entry_##_name, \
a93244f8
MD
333 },
334
2d6d88c6 335/* Event compat syscall enter table */
a93244f8 336const struct trace_syscall_entry compat_sc_table[] = {
241ae9a8
MD
337#include <instrumentation/syscalls/headers/compat_syscalls_integers.h>
338#include <instrumentation/syscalls/headers/compat_syscalls_pointers.h>
a93244f8 339};
259b6cb3 340
fc4f7161
MD
341#undef SC_ENTER
342
343#define SC_EXIT
344
345#undef sc_exit
346#define sc_exit(...) __VA_ARGS__
347
5b7ac358
MD
348#undef TRACE_SYSCALL_TABLE
349#define TRACE_SYSCALL_TABLE(_template, _name, _nr, _nrargs) \
350 [ _nr ] = { \
2d6d88c6 351 .event_func = __event_probe__syscall_exit_##_template, \
8a8ac9a8 352 .event_notifier_func = __event_notifier_probe__syscall_exit_##_template, \
5b7ac358
MD
353 .nrargs = (_nrargs), \
354 .fields = __event_fields___syscall_exit_##_template, \
355 .desc = &__event_desc___syscall_exit_##_name, \
356 },
357
2d6d88c6 358/* Event syscall exit table */
5b7ac358 359static const struct trace_syscall_entry sc_exit_table[] = {
241ae9a8
MD
360#include <instrumentation/syscalls/headers/syscalls_integers.h>
361#include <instrumentation/syscalls/headers/syscalls_pointers.h>
5b7ac358
MD
362};
363
364#undef TRACE_SYSCALL_TABLE
365#define TRACE_SYSCALL_TABLE(_template, _name, _nr, _nrargs) \
366 [ _nr ] = { \
2d6d88c6 367 .event_func = __event_probe__compat_syscall_exit_##_template, \
8a8ac9a8 368 .event_notifier_func = __event_notifier_probe__compat_syscall_exit_##_template, \
5b7ac358
MD
369 .nrargs = (_nrargs), \
370 .fields = __event_fields___compat_syscall_exit_##_template, \
371 .desc = &__event_desc___compat_syscall_exit_##_name, \
372 },
373
2d6d88c6 374/* Event compat syscall exit table */
5b7ac358 375const struct trace_syscall_entry compat_sc_exit_table[] = {
241ae9a8
MD
376#include <instrumentation/syscalls/headers/compat_syscalls_integers.h>
377#include <instrumentation/syscalls/headers/compat_syscalls_pointers.h>
5b7ac358
MD
378};
379
fc4f7161
MD
380#undef SC_EXIT
381
a93244f8 382#undef CREATE_SYSCALL_TABLE
2faf7d1b 383
80f87dd2 384struct lttng_syscall_filter {
badfe9f5
MD
385 DECLARE_BITMAP(sc_entry, NR_syscalls);
386 DECLARE_BITMAP(sc_exit, NR_syscalls);
387 DECLARE_BITMAP(sc_compat_entry, NR_compat_syscalls);
388 DECLARE_BITMAP(sc_compat_exit, NR_compat_syscalls);
80f87dd2
MD
389};
390
3b82c4e1 391static void syscall_entry_event_unknown(struct hlist_head *unknown_action_list_head,
8a8ac9a8 392 struct pt_regs *regs, long id)
f405cfce 393{
1b7b9c65 394 unsigned long args[LTTNG_SYSCALL_NR_ARGS];
3b82c4e1 395 struct lttng_event *event;
f405cfce 396
1b7b9c65 397 lttng_syscall_get_arguments(current, regs, args);
3b82c4e1
MD
398 hlist_for_each_entry_rcu(event, unknown_action_list_head, u.syscall.node) {
399 if (unlikely(in_compat_syscall()))
400 __event_probe__compat_syscall_entry_unknown(event, id, args);
401 else
402 __event_probe__syscall_entry_unknown(event, id, args);
403 }
f405cfce
MD
404}
405
8a8ac9a8
FD
406static void syscall_entry_event_notifier_unknown(
407 struct hlist_head *unknown_dispatch_list_head,
408 struct pt_regs *regs, long id)
409{
410 unsigned long args[LTTNG_SYSCALL_NR_ARGS];
411 struct lttng_event_notifier *notifier;
412
413 lttng_syscall_get_arguments(current, regs, args);
414 lttng_hlist_for_each_entry_rcu(notifier, unknown_dispatch_list_head, u.syscall.node) {
415 if (unlikely(in_compat_syscall()))
416 __event_notifier_probe__compat_syscall_entry_unknown(notifier, id, args);
417 else
418 __event_notifier_probe__syscall_entry_unknown(notifier, id, args);
419 }
420}
421
422static void syscall_exit_event_notifier_unknown(
423 struct hlist_head *unknown_dispatch_list_head,
424 struct pt_regs *regs, long id, long ret)
425{
426 unsigned long args[LTTNG_SYSCALL_NR_ARGS];
427 struct lttng_event_notifier *notifier;
428
429 lttng_syscall_get_arguments(current, regs, args);
430 lttng_hlist_for_each_entry_rcu(notifier, unknown_dispatch_list_head, u.syscall.node) {
431 if (unlikely(in_compat_syscall()))
432 __event_notifier_probe__compat_syscall_exit_unknown(notifier, id, ret, args);
433 else
434 __event_notifier_probe__syscall_exit_unknown(notifier, id, ret, args);
435 }
436}
437
63aa9160 438static __always_inline
3b82c4e1
MD
439void syscall_entry_call_func(struct hlist_head *action_list,
440 void *func, unsigned int nrargs,
63aa9160 441 struct pt_regs *regs)
259b6cb3 442{
3b82c4e1
MD
443 struct lttng_event *event;
444
63aa9160 445 switch (nrargs) {
259b6cb3
MD
446 case 0:
447 {
63aa9160 448 void (*fptr)(void *__data) = func;
259b6cb3 449
3b82c4e1
MD
450 hlist_for_each_entry_rcu(event, action_list, u.syscall.node)
451 fptr(event);
259b6cb3
MD
452 break;
453 }
454 case 1:
455 {
63aa9160 456 void (*fptr)(void *__data, unsigned long arg0) = func;
1b7b9c65 457 unsigned long args[LTTNG_SYSCALL_NR_ARGS];
259b6cb3 458
1b7b9c65 459 lttng_syscall_get_arguments(current, regs, args);
3b82c4e1
MD
460 hlist_for_each_entry_rcu(event, action_list, u.syscall.node)
461 fptr(event, args[0]);
259b6cb3
MD
462 break;
463 }
464 case 2:
465 {
466 void (*fptr)(void *__data,
467 unsigned long arg0,
63aa9160 468 unsigned long arg1) = func;
1b7b9c65 469 unsigned long args[LTTNG_SYSCALL_NR_ARGS];
259b6cb3 470
1b7b9c65 471 lttng_syscall_get_arguments(current, regs, args);
3b82c4e1
MD
472 hlist_for_each_entry_rcu(event, action_list, u.syscall.node)
473 fptr(event, args[0], args[1]);
259b6cb3
MD
474 break;
475 }
476 case 3:
477 {
478 void (*fptr)(void *__data,
479 unsigned long arg0,
480 unsigned long arg1,
63aa9160 481 unsigned long arg2) = func;
1b7b9c65 482 unsigned long args[LTTNG_SYSCALL_NR_ARGS];
259b6cb3 483
1b7b9c65 484 lttng_syscall_get_arguments(current, regs, args);
3b82c4e1
MD
485 hlist_for_each_entry_rcu(event, action_list, u.syscall.node)
486 fptr(event, args[0], args[1], args[2]);
259b6cb3
MD
487 break;
488 }
489 case 4:
490 {
491 void (*fptr)(void *__data,
492 unsigned long arg0,
493 unsigned long arg1,
494 unsigned long arg2,
63aa9160 495 unsigned long arg3) = func;
1b7b9c65 496 unsigned long args[LTTNG_SYSCALL_NR_ARGS];
259b6cb3 497
1b7b9c65 498 lttng_syscall_get_arguments(current, regs, args);
3b82c4e1
MD
499 hlist_for_each_entry_rcu(event, action_list, u.syscall.node)
500 fptr(event, args[0], args[1], args[2], args[3]);
259b6cb3
MD
501 break;
502 }
503 case 5:
504 {
505 void (*fptr)(void *__data,
506 unsigned long arg0,
507 unsigned long arg1,
508 unsigned long arg2,
509 unsigned long arg3,
63aa9160 510 unsigned long arg4) = func;
1b7b9c65 511 unsigned long args[LTTNG_SYSCALL_NR_ARGS];
259b6cb3 512
1b7b9c65 513 lttng_syscall_get_arguments(current, regs, args);
3b82c4e1
MD
514 hlist_for_each_entry_rcu(event, action_list, u.syscall.node)
515 fptr(event, args[0], args[1], args[2], args[3], args[4]);
259b6cb3
MD
516 break;
517 }
518 case 6:
519 {
520 void (*fptr)(void *__data,
521 unsigned long arg0,
522 unsigned long arg1,
523 unsigned long arg2,
524 unsigned long arg3,
525 unsigned long arg4,
63aa9160 526 unsigned long arg5) = func;
1b7b9c65 527 unsigned long args[LTTNG_SYSCALL_NR_ARGS];
259b6cb3 528
1b7b9c65 529 lttng_syscall_get_arguments(current, regs, args);
3b82c4e1
MD
530 hlist_for_each_entry_rcu(event, action_list, u.syscall.node)
531 fptr(event, args[0], args[1], args[2],
532 args[3], args[4], args[5]);
259b6cb3
MD
533 break;
534 }
535 default:
536 break;
537 }
538}
539
8a8ac9a8
FD
540static __always_inline
541void syscall_entry_event_notifier_call_func(struct hlist_head *dispatch_list,
542 void *func, unsigned int nrargs, struct pt_regs *regs)
543{
544 struct lttng_event_notifier *notifier;
545
546 switch (nrargs) {
547 case 0:
548 {
549 void (*fptr)(void *__data) = func;
550
551 lttng_hlist_for_each_entry_rcu(notifier, dispatch_list, u.syscall.node)
552 fptr(notifier);
553 break;
554 }
555 case 1:
556 {
557 void (*fptr)(void *__data, unsigned long arg0) = func;
558 unsigned long args[LTTNG_SYSCALL_NR_ARGS];
559
560 lttng_syscall_get_arguments(current, regs, args);
561 lttng_hlist_for_each_entry_rcu(notifier, dispatch_list, u.syscall.node)
562 fptr(notifier, args[0]);
563 break;
564 }
565 case 2:
566 {
567 void (*fptr)(void *__data,
568 unsigned long arg0,
569 unsigned long arg1) = func;
570 unsigned long args[LTTNG_SYSCALL_NR_ARGS];
571
572 lttng_syscall_get_arguments(current, regs, args);
573 lttng_hlist_for_each_entry_rcu(notifier, dispatch_list, u.syscall.node)
574 fptr(notifier, args[0], args[1]);
575 break;
576 }
577 case 3:
578 {
579 void (*fptr)(void *__data,
580 unsigned long arg0,
581 unsigned long arg1,
582 unsigned long arg2) = func;
583 unsigned long args[LTTNG_SYSCALL_NR_ARGS];
584
585 lttng_syscall_get_arguments(current, regs, args);
586 lttng_hlist_for_each_entry_rcu(notifier, dispatch_list, u.syscall.node)
587 fptr(notifier, args[0], args[1], args[2]);
588 break;
589 }
590 case 4:
591 {
592 void (*fptr)(void *__data,
593 unsigned long arg0,
594 unsigned long arg1,
595 unsigned long arg2,
596 unsigned long arg3) = func;
597 unsigned long args[LTTNG_SYSCALL_NR_ARGS];
598
599 lttng_syscall_get_arguments(current, regs, args);
600 lttng_hlist_for_each_entry_rcu(notifier, dispatch_list, u.syscall.node)
601 fptr(notifier, args[0], args[1], args[2], args[3]);
602 break;
603 }
604 case 5:
605 {
606 void (*fptr)(void *__data,
607 unsigned long arg0,
608 unsigned long arg1,
609 unsigned long arg2,
610 unsigned long arg3,
611 unsigned long arg4) = func;
612 unsigned long args[LTTNG_SYSCALL_NR_ARGS];
613
614 lttng_syscall_get_arguments(current, regs, args);
615 lttng_hlist_for_each_entry_rcu(notifier, dispatch_list, u.syscall.node)
616 fptr(notifier, args[0], args[1], args[2], args[3], args[4]);
617 break;
618 }
619 case 6:
620 {
621 void (*fptr)(void *__data,
622 unsigned long arg0,
623 unsigned long arg1,
624 unsigned long arg2,
625 unsigned long arg3,
626 unsigned long arg4,
627 unsigned long arg5) = func;
628 unsigned long args[LTTNG_SYSCALL_NR_ARGS];
629
630 lttng_syscall_get_arguments(current, regs, args);
631 lttng_hlist_for_each_entry_rcu(notifier, dispatch_list, u.syscall.node)
632 fptr(notifier, args[0], args[1], args[2], args[3], args[4], args[5]);
633 break;
634 }
635 default:
636 break;
637 }
638}
639
63aa9160
FD
640void syscall_entry_event_probe(void *__data, struct pt_regs *regs, long id)
641{
642 struct lttng_channel *chan = __data;
3b82c4e1 643 struct hlist_head *action_list, *unknown_action_list;
63aa9160
FD
644 const struct trace_syscall_entry *table, *entry;
645 size_t table_len;
646
647 if (unlikely(in_compat_syscall())) {
648 struct lttng_syscall_filter *filter = chan->sc_filter;
649
650 if (id < 0 || id >= NR_compat_syscalls
3b82c4e1 651 || (!READ_ONCE(chan->syscall_all_entry) && !test_bit(id, filter->sc_compat_entry))) {
63aa9160
FD
652 /* System call filtered out. */
653 return;
654 }
655 table = compat_sc_table;
656 table_len = ARRAY_SIZE(compat_sc_table);
3b82c4e1 657 unknown_action_list = &chan->sc_compat_unknown;
63aa9160
FD
658 } else {
659 struct lttng_syscall_filter *filter = chan->sc_filter;
660
661 if (id < 0 || id >= NR_syscalls
3b82c4e1 662 || (!READ_ONCE(chan->syscall_all_entry) && !test_bit(id, filter->sc_entry))) {
63aa9160
FD
663 /* System call filtered out. */
664 return;
665 }
666 table = sc_table;
667 table_len = ARRAY_SIZE(sc_table);
3b82c4e1 668 unknown_action_list = &chan->sc_unknown;
63aa9160
FD
669 }
670 if (unlikely(id < 0 || id >= table_len)) {
3b82c4e1 671 syscall_entry_event_unknown(unknown_action_list, regs, id);
63aa9160
FD
672 return;
673 }
3b82c4e1
MD
674
675 entry = &table[id];
676 if (!entry->event_func) {
677 syscall_entry_event_unknown(unknown_action_list, regs, id);
63aa9160
FD
678 return;
679 }
3b82c4e1
MD
680
681 if (unlikely(in_compat_syscall())) {
682 action_list = &chan->compat_sc_table[id];
683 } else {
684 action_list = &chan->sc_table[id];
685 }
686 if (unlikely(hlist_empty(action_list)))
687 return;
688
689 syscall_entry_call_func(action_list, entry->event_func, entry->nrargs, regs);
63aa9160
FD
690}
691
8a8ac9a8
FD
692void syscall_entry_event_notifier_probe(void *__data, struct pt_regs *regs,
693 long id)
694{
695 struct lttng_event_notifier_group *group = __data;
696 const struct trace_syscall_entry *table, *entry;
697 struct hlist_head *dispatch_list, *unknown_dispatch_list;
698 size_t table_len;
699
700 if (unlikely(in_compat_syscall())) {
701 struct lttng_syscall_filter *filter = group->sc_filter;
702
703 if (id < 0 || id >= NR_compat_syscalls
704 || (!READ_ONCE(group->syscall_all_entry) &&
705 !test_bit(id, filter->sc_compat_entry))) {
706 /* System call filtered out. */
707 return;
708 }
709 table = compat_sc_table;
710 table_len = ARRAY_SIZE(compat_sc_table);
711 unknown_dispatch_list = &group->event_notifier_compat_unknown_syscall_dispatch;
712 } else {
713 struct lttng_syscall_filter *filter = group->sc_filter;
714
715 if (id < 0 || id >= NR_syscalls
716 || (!READ_ONCE(group->syscall_all_entry) &&
717 !test_bit(id, filter->sc_entry))) {
718 /* System call filtered out. */
719 return;
720 }
721 table = sc_table;
722 table_len = ARRAY_SIZE(sc_table);
723 unknown_dispatch_list = &group->event_notifier_unknown_syscall_dispatch;
724 }
725 /* Check if the syscall id is out of bound. */
726 if (unlikely(id < 0 || id >= table_len)) {
727 syscall_entry_event_notifier_unknown(unknown_dispatch_list,
728 regs, id);
729 return;
730 }
731
732 entry = &table[id];
733 if (!entry->event_notifier_func) {
734 syscall_entry_event_notifier_unknown(unknown_dispatch_list,
735 regs, id);
736 return;
737 }
738
739 if (unlikely(in_compat_syscall())) {
740 dispatch_list = &group->event_notifier_compat_syscall_dispatch[id];
741 } else {
742 dispatch_list = &group->event_notifier_syscall_dispatch[id];
743 }
744 if (unlikely(hlist_empty(dispatch_list)))
745 return;
746
747 syscall_entry_event_notifier_call_func(dispatch_list,
748 entry->event_notifier_func, entry->nrargs, regs);
749}
750
3b82c4e1 751static void syscall_exit_event_unknown(struct hlist_head *unknown_action_list_head,
8a8ac9a8 752 struct pt_regs *regs, long id, long ret)
5b7ac358 753{
1b7b9c65 754 unsigned long args[LTTNG_SYSCALL_NR_ARGS];
3b82c4e1 755 struct lttng_event *event;
5b7ac358 756
1b7b9c65 757 lttng_syscall_get_arguments(current, regs, args);
3b82c4e1
MD
758 hlist_for_each_entry_rcu(event, unknown_action_list_head, u.syscall.node) {
759 if (unlikely(in_compat_syscall()))
760 __event_probe__compat_syscall_exit_unknown(event, id, ret,
761 args);
762 else
763 __event_probe__syscall_exit_unknown(event, id, ret, args);
764 }
5b7ac358
MD
765}
766
3b82c4e1
MD
767static __always_inline
768void syscall_exit_call_func(struct hlist_head *action_list,
769 void *func, unsigned int nrargs,
770 struct pt_regs *regs, long ret)
5b7ac358 771{
3b82c4e1 772 struct lttng_event *event;
badfe9f5 773
3b82c4e1 774 switch (nrargs) {
5b7ac358
MD
775 case 0:
776 {
3b82c4e1 777 void (*fptr)(void *__data, long ret) = func;
5b7ac358 778
3b82c4e1
MD
779 hlist_for_each_entry_rcu(event, action_list, u.syscall.node)
780 fptr(event, ret);
5b7ac358
MD
781 break;
782 }
783 case 1:
784 {
785 void (*fptr)(void *__data,
fc4f7161 786 long ret,
3b82c4e1 787 unsigned long arg0) = func;
1b7b9c65 788 unsigned long args[LTTNG_SYSCALL_NR_ARGS];
5b7ac358 789
1b7b9c65 790 lttng_syscall_get_arguments(current, regs, args);
3b82c4e1
MD
791 hlist_for_each_entry_rcu(event, action_list, u.syscall.node)
792 fptr(event, ret, args[0]);
5b7ac358
MD
793 break;
794 }
795 case 2:
796 {
797 void (*fptr)(void *__data,
fc4f7161 798 long ret,
5b7ac358 799 unsigned long arg0,
3b82c4e1 800 unsigned long arg1) = func;
1b7b9c65 801 unsigned long args[LTTNG_SYSCALL_NR_ARGS];
5b7ac358 802
1b7b9c65 803 lttng_syscall_get_arguments(current, regs, args);
3b82c4e1
MD
804 hlist_for_each_entry_rcu(event, action_list, u.syscall.node)
805 fptr(event, ret, args[0], args[1]);
5b7ac358
MD
806 break;
807 }
808 case 3:
809 {
810 void (*fptr)(void *__data,
fc4f7161 811 long ret,
5b7ac358
MD
812 unsigned long arg0,
813 unsigned long arg1,
3b82c4e1 814 unsigned long arg2) = func;
1b7b9c65 815 unsigned long args[LTTNG_SYSCALL_NR_ARGS];
5b7ac358 816
1b7b9c65 817 lttng_syscall_get_arguments(current, regs, args);
3b82c4e1
MD
818 hlist_for_each_entry_rcu(event, action_list, u.syscall.node)
819 fptr(event, ret, args[0], args[1], args[2]);
5b7ac358
MD
820 break;
821 }
822 case 4:
823 {
824 void (*fptr)(void *__data,
fc4f7161 825 long ret,
5b7ac358
MD
826 unsigned long arg0,
827 unsigned long arg1,
828 unsigned long arg2,
3b82c4e1 829 unsigned long arg3) = func;
1b7b9c65 830 unsigned long args[LTTNG_SYSCALL_NR_ARGS];
5b7ac358 831
1b7b9c65 832 lttng_syscall_get_arguments(current, regs, args);
3b82c4e1
MD
833 hlist_for_each_entry_rcu(event, action_list, u.syscall.node)
834 fptr(event, ret, args[0], args[1], args[2], args[3]);
5b7ac358
MD
835 break;
836 }
837 case 5:
838 {
839 void (*fptr)(void *__data,
fc4f7161 840 long ret,
5b7ac358
MD
841 unsigned long arg0,
842 unsigned long arg1,
843 unsigned long arg2,
844 unsigned long arg3,
3b82c4e1 845 unsigned long arg4) = func;
1b7b9c65 846 unsigned long args[LTTNG_SYSCALL_NR_ARGS];
5b7ac358 847
1b7b9c65 848 lttng_syscall_get_arguments(current, regs, args);
3b82c4e1
MD
849 hlist_for_each_entry_rcu(event, action_list, u.syscall.node)
850 fptr(event, ret, args[0], args[1], args[2], args[3], args[4]);
5b7ac358
MD
851 break;
852 }
853 case 6:
854 {
855 void (*fptr)(void *__data,
fc4f7161 856 long ret,
5b7ac358
MD
857 unsigned long arg0,
858 unsigned long arg1,
859 unsigned long arg2,
860 unsigned long arg3,
861 unsigned long arg4,
3b82c4e1 862 unsigned long arg5) = func;
1b7b9c65 863 unsigned long args[LTTNG_SYSCALL_NR_ARGS];
5b7ac358 864
1b7b9c65 865 lttng_syscall_get_arguments(current, regs, args);
3b82c4e1
MD
866 hlist_for_each_entry_rcu(event, action_list, u.syscall.node)
867 fptr(event, ret, args[0], args[1], args[2],
868 args[3], args[4], args[5]);
5b7ac358
MD
869 break;
870 }
871 default:
872 break;
873 }
874}
875
3b82c4e1
MD
876void syscall_exit_event_probe(void *__data, struct pt_regs *regs, long ret)
877{
878 struct lttng_channel *chan = __data;
879 struct hlist_head *action_list, *unknown_action_list;
880 const struct trace_syscall_entry *table, *entry;
881 size_t table_len;
882 long id;
883
884 id = syscall_get_nr(current, regs);
885
886 if (unlikely(in_compat_syscall())) {
887 struct lttng_syscall_filter *filter = chan->sc_filter;
888
889 if (id < 0 || id >= NR_compat_syscalls
890 || (!READ_ONCE(chan->syscall_all_exit) && !test_bit(id, filter->sc_compat_exit))) {
891 /* System call filtered out. */
892 return;
893 }
894 table = compat_sc_exit_table;
895 table_len = ARRAY_SIZE(compat_sc_exit_table);
896 unknown_action_list = &chan->compat_sc_exit_unknown;
897 } else {
898 struct lttng_syscall_filter *filter = chan->sc_filter;
899
900 if (id < 0 || id >= NR_syscalls
901 || (!READ_ONCE(chan->syscall_all_exit) && !test_bit(id, filter->sc_exit))) {
902 /* System call filtered out. */
903 return;
904 }
905 table = sc_exit_table;
906 table_len = ARRAY_SIZE(sc_exit_table);
907 unknown_action_list = &chan->sc_exit_unknown;
908 }
909 if (unlikely(id < 0 || id >= table_len)) {
910 syscall_exit_event_unknown(unknown_action_list, regs, id, ret);
911 return;
912 }
913
914 entry = &table[id];
915 if (!entry->event_func) {
916 syscall_exit_event_unknown(unknown_action_list, regs, id, ret);
917 return;
918 }
919
920 if (unlikely(in_compat_syscall())) {
921 action_list = &chan->compat_sc_exit_table[id];
922 } else {
923 action_list = &chan->sc_exit_table[id];
924 }
925 if (unlikely(hlist_empty(action_list)))
926 return;
927
928 syscall_exit_call_func(action_list, entry->event_func, entry->nrargs,
929 regs, ret);
930}
931
8a8ac9a8
FD
932static __always_inline
933void syscall_exit_event_notifier_call_func(struct hlist_head *dispatch_list,
934 void *func, unsigned int nrargs, struct pt_regs *regs, long ret)
935{
936 struct lttng_event_notifier *notifier;
937
938 switch (nrargs) {
939 case 0:
940 {
941 void (*fptr)(void *__data, long ret) = func;
942
943 lttng_hlist_for_each_entry_rcu(notifier, dispatch_list, u.syscall.node)
944 fptr(notifier, ret);
945 break;
946 }
947 case 1:
948 {
949 void (*fptr)(void *__data, long ret, unsigned long arg0) = func;
950 unsigned long args[LTTNG_SYSCALL_NR_ARGS];
951
952 lttng_syscall_get_arguments(current, regs, args);
953 lttng_hlist_for_each_entry_rcu(notifier, dispatch_list, u.syscall.node)
954 fptr(notifier, ret, args[0]);
955 break;
956 }
957 case 2:
958 {
959 void (*fptr)(void *__data,
960 long ret,
961 unsigned long arg0,
962 unsigned long arg1) = func;
963 unsigned long args[LTTNG_SYSCALL_NR_ARGS];
964
965 lttng_syscall_get_arguments(current, regs, args);
966 lttng_hlist_for_each_entry_rcu(notifier, dispatch_list, u.syscall.node)
967 fptr(notifier, ret, args[0], args[1]);
968 break;
969 }
970 case 3:
971 {
972 void (*fptr)(void *__data,
973 long ret,
974 unsigned long arg0,
975 unsigned long arg1,
976 unsigned long arg2) = func;
977 unsigned long args[LTTNG_SYSCALL_NR_ARGS];
978
979 lttng_syscall_get_arguments(current, regs, args);
980 lttng_hlist_for_each_entry_rcu(notifier, dispatch_list, u.syscall.node)
981 fptr(notifier, ret, args[0], args[1], args[2]);
982 break;
983 }
984 case 4:
985 {
986 void (*fptr)(void *__data,
987 long ret,
988 unsigned long arg0,
989 unsigned long arg1,
990 unsigned long arg2,
991 unsigned long arg3) = func;
992 unsigned long args[LTTNG_SYSCALL_NR_ARGS];
993
994 lttng_syscall_get_arguments(current, regs, args);
995 lttng_hlist_for_each_entry_rcu(notifier, dispatch_list, u.syscall.node)
996 fptr(notifier, ret, args[0], args[1], args[2], args[3]);
997 break;
998 }
999 case 5:
1000 {
1001 void (*fptr)(void *__data,
1002 long ret,
1003 unsigned long arg0,
1004 unsigned long arg1,
1005 unsigned long arg2,
1006 unsigned long arg3,
1007 unsigned long arg4) = func;
1008 unsigned long args[LTTNG_SYSCALL_NR_ARGS];
1009
1010 lttng_syscall_get_arguments(current, regs, args);
1011 lttng_hlist_for_each_entry_rcu(notifier, dispatch_list, u.syscall.node)
1012 fptr(notifier, ret, args[0], args[1], args[2], args[3], args[4]);
1013 break;
1014 }
1015 case 6:
1016 {
1017 void (*fptr)(void *__data,
1018 long ret,
1019 unsigned long arg0,
1020 unsigned long arg1,
1021 unsigned long arg2,
1022 unsigned long arg3,
1023 unsigned long arg4,
1024 unsigned long arg5) = func;
1025 unsigned long args[LTTNG_SYSCALL_NR_ARGS];
1026
1027 lttng_syscall_get_arguments(current, regs, args);
1028 lttng_hlist_for_each_entry_rcu(notifier, dispatch_list, u.syscall.node)
1029 fptr(notifier, ret, args[0], args[1], args[2], args[3], args[4], args[5]);
1030 break;
1031 }
1032 default:
1033 break;
1034 }
1035}
1036
1037static
1038void syscall_exit_event_notifier_probe(void *__data, struct pt_regs *regs,
1039 long ret)
1040{
1041 struct lttng_event_notifier_group *group = __data;
1042 const struct trace_syscall_entry *table, *entry;
1043 struct hlist_head *dispatch_list, *unknown_dispatch_list;
1044 size_t table_len;
1045 long id;
1046
1047 id = syscall_get_nr(current, regs);
1048
1049 if (unlikely(in_compat_syscall())) {
1050 struct lttng_syscall_filter *filter = group->sc_filter;
1051
1052 if (id < 0 || id >= NR_compat_syscalls
1053 || (!READ_ONCE(group->syscall_all_exit) &&
1054 !test_bit(id, filter->sc_compat_exit))) {
1055 /* System call filtered out. */
1056 return;
1057 }
1058 table = compat_sc_exit_table;
1059 table_len = ARRAY_SIZE(compat_sc_exit_table);
1060 unknown_dispatch_list = &group->event_notifier_exit_compat_unknown_syscall_dispatch;
1061 } else {
1062 struct lttng_syscall_filter *filter = group->sc_filter;
1063
1064 if (id < 0 || id >= NR_syscalls
1065 || (!READ_ONCE(group->syscall_all_exit) &&
1066 !test_bit(id, filter->sc_exit))) {
1067 /* System call filtered out. */
1068 return;
1069 }
1070 table = sc_exit_table;
1071 table_len = ARRAY_SIZE(sc_exit_table);
1072 unknown_dispatch_list = &group->event_notifier_exit_unknown_syscall_dispatch;
1073 }
1074 /* Check if the syscall id is out of bound. */
1075 if (unlikely(id < 0 || id >= table_len)) {
1076 syscall_exit_event_notifier_unknown(unknown_dispatch_list,
1077 regs, id, ret);
1078 return;
1079 }
1080
1081 entry = &table[id];
1082 if (!entry->event_notifier_func) {
1083 syscall_entry_event_notifier_unknown(unknown_dispatch_list,
1084 regs, id);
1085 return;
1086 }
1087
1088 if (unlikely(in_compat_syscall())) {
1089 dispatch_list = &group->event_notifier_exit_compat_syscall_dispatch[id];
1090 } else {
1091 dispatch_list = &group->event_notifier_exit_syscall_dispatch[id];
1092 }
1093 if (unlikely(hlist_empty(dispatch_list)))
1094 return;
1095
1096 syscall_exit_event_notifier_call_func(dispatch_list,
1097 entry->event_notifier_func, entry->nrargs, regs, ret);
1098}
33a39a3c
MD
1099/*
1100 * noinline to diminish caller stack size.
1101 * Should be called with sessions lock held.
1102 */
49c50022 1103static
3b82c4e1
MD
1104int lttng_create_syscall_event_if_missing(const struct trace_syscall_entry *table, size_t table_len,
1105 struct hlist_head *chan_table, struct lttng_event_enabler *event_enabler,
5b7ac358 1106 void *filter, enum sc_type type)
259b6cb3 1107{
3b82c4e1
MD
1108 struct lttng_channel *chan = event_enabler->chan;
1109 struct lttng_session *session = chan->session;
259b6cb3 1110 unsigned int i;
49c50022 1111
3b82c4e1 1112 /* Allocate events for each syscall matching enabler, insert into table */
49c50022 1113 for (i = 0; i < table_len; i++) {
3b82c4e1 1114 const struct lttng_event_desc *desc = table[i].desc;
49c50022 1115 struct lttng_kernel_event ev;
3b82c4e1
MD
1116 struct lttng_event *event;
1117 struct hlist_head *head;
1118 bool found = false;
49c50022
MD
1119
1120 if (!desc) {
1121 /* Unknown syscall */
1122 continue;
1123 }
3b82c4e1
MD
1124 if (lttng_desc_match_enabler(desc,
1125 lttng_event_enabler_as_enabler(event_enabler)) <= 0)
1126 continue;
49c50022 1127 /*
3b82c4e1 1128 * Check if already created.
49c50022 1129 */
3b82c4e1
MD
1130 head = utils_borrow_hash_table_bucket(
1131 session->events_ht.table, LTTNG_EVENT_HT_SIZE,
1132 desc->name);
1133 lttng_hlist_for_each_entry(event, head, hlist) {
1134 if (event->desc == desc
1135 && event->chan == event_enabler->chan)
1136 found = true;
1137 }
1138 if (found)
49c50022 1139 continue;
3b82c4e1
MD
1140
1141 /* We need to create an event for this syscall/enabler. */
49c50022 1142 memset(&ev, 0, sizeof(ev));
5b7ac358
MD
1143 switch (type) {
1144 case SC_TYPE_ENTRY:
badfe9f5
MD
1145 ev.u.syscall.entryexit = LTTNG_KERNEL_SYSCALL_ENTRY;
1146 ev.u.syscall.abi = LTTNG_KERNEL_SYSCALL_ABI_NATIVE;
5b7ac358
MD
1147 break;
1148 case SC_TYPE_EXIT:
badfe9f5
MD
1149 ev.u.syscall.entryexit = LTTNG_KERNEL_SYSCALL_EXIT;
1150 ev.u.syscall.abi = LTTNG_KERNEL_SYSCALL_ABI_NATIVE;
5b7ac358
MD
1151 break;
1152 case SC_TYPE_COMPAT_ENTRY:
badfe9f5
MD
1153 ev.u.syscall.entryexit = LTTNG_KERNEL_SYSCALL_ENTRY;
1154 ev.u.syscall.abi = LTTNG_KERNEL_SYSCALL_ABI_COMPAT;
5b7ac358
MD
1155 break;
1156 case SC_TYPE_COMPAT_EXIT:
badfe9f5
MD
1157 ev.u.syscall.entryexit = LTTNG_KERNEL_SYSCALL_EXIT;
1158 ev.u.syscall.abi = LTTNG_KERNEL_SYSCALL_ABI_COMPAT;
5b7ac358
MD
1159 break;
1160 }
092ffe97 1161 strncpy(ev.name, desc->name, LTTNG_KERNEL_SYM_NAME_LEN - 1);
f8695253 1162 ev.name[LTTNG_KERNEL_SYM_NAME_LEN - 1] = '\0';
33a39a3c 1163 ev.instrumentation = LTTNG_KERNEL_SYSCALL;
3b82c4e1
MD
1164 event = _lttng_event_create(chan, &ev, filter,
1165 desc, ev.instrumentation);
1166 WARN_ON_ONCE(!event);
1167 if (IS_ERR(event)) {
49c50022
MD
1168 /*
1169 * If something goes wrong in event registration
1170 * after the first one, we have no choice but to
1171 * leave the previous events in there, until
1172 * deleted by session teardown.
1173 */
3b82c4e1 1174 return PTR_ERR(event);
49c50022 1175 }
3b82c4e1 1176 hlist_add_head(&event->u.syscall.node, &chan_table[i]);
49c50022
MD
1177 }
1178 return 0;
1179}
1180
33a39a3c
MD
1181/*
1182 * Should be called with sessions lock held.
1183 */
3b82c4e1 1184int lttng_syscalls_register_event(struct lttng_event_enabler *event_enabler, void *filter)
49c50022 1185{
3b82c4e1 1186 struct lttng_channel *chan = event_enabler->chan;
2a0c4816 1187 struct lttng_kernel_event ev;
259b6cb3
MD
1188 int ret;
1189
263b6c88 1190 wrapper_vmalloc_sync_mappings();
259b6cb3
MD
1191
1192 if (!chan->sc_table) {
1193 /* create syscall table mapping syscall to events */
a90917c3 1194 chan->sc_table = kzalloc(sizeof(struct lttng_event *)
259b6cb3
MD
1195 * ARRAY_SIZE(sc_table), GFP_KERNEL);
1196 if (!chan->sc_table)
1197 return -ENOMEM;
1198 }
5b7ac358
MD
1199 if (!chan->sc_exit_table) {
1200 /* create syscall table mapping syscall to events */
1201 chan->sc_exit_table = kzalloc(sizeof(struct lttng_event *)
1202 * ARRAY_SIZE(sc_exit_table), GFP_KERNEL);
1203 if (!chan->sc_exit_table)
1204 return -ENOMEM;
1205 }
1206
259b6cb3 1207
49c50022
MD
1208#ifdef CONFIG_COMPAT
1209 if (!chan->compat_sc_table) {
1210 /* create syscall table mapping compat syscall to events */
a90917c3 1211 chan->compat_sc_table = kzalloc(sizeof(struct lttng_event *)
a93244f8 1212 * ARRAY_SIZE(compat_sc_table), GFP_KERNEL);
49c50022
MD
1213 if (!chan->compat_sc_table)
1214 return -ENOMEM;
1215 }
5b7ac358
MD
1216
1217 if (!chan->compat_sc_exit_table) {
1218 /* create syscall table mapping compat syscall to events */
1219 chan->compat_sc_exit_table = kzalloc(sizeof(struct lttng_event *)
1220 * ARRAY_SIZE(compat_sc_exit_table), GFP_KERNEL);
1221 if (!chan->compat_sc_exit_table)
1222 return -ENOMEM;
1223 }
49c50022 1224#endif
3b82c4e1 1225 if (hlist_empty(&chan->sc_unknown)) {
f405cfce 1226 const struct lttng_event_desc *desc =
d4291869 1227 &__event_desc___syscall_entry_unknown;
3b82c4e1 1228 struct lttng_event *event;
2f804c0a 1229
f405cfce 1230 memset(&ev, 0, sizeof(ev));
f8695253
MD
1231 strncpy(ev.name, desc->name, LTTNG_KERNEL_SYM_NAME_LEN);
1232 ev.name[LTTNG_KERNEL_SYM_NAME_LEN - 1] = '\0';
33a39a3c 1233 ev.instrumentation = LTTNG_KERNEL_SYSCALL;
badfe9f5
MD
1234 ev.u.syscall.entryexit = LTTNG_KERNEL_SYSCALL_ENTRY;
1235 ev.u.syscall.abi = LTTNG_KERNEL_SYSCALL_ABI_NATIVE;
3b82c4e1
MD
1236 event = _lttng_event_create(chan, &ev, filter, desc,
1237 ev.instrumentation);
1238 WARN_ON_ONCE(!event);
1239 if (IS_ERR(event)) {
1240 return PTR_ERR(event);
f405cfce 1241 }
3b82c4e1 1242 hlist_add_head(&event->u.syscall.node, &chan->sc_unknown);
f405cfce
MD
1243 }
1244
3b82c4e1 1245 if (hlist_empty(&chan->sc_compat_unknown)) {
b76dc1a0 1246 const struct lttng_event_desc *desc =
d4291869 1247 &__event_desc___compat_syscall_entry_unknown;
3b82c4e1 1248 struct lttng_event *event;
b76dc1a0
MD
1249
1250 memset(&ev, 0, sizeof(ev));
f8695253
MD
1251 strncpy(ev.name, desc->name, LTTNG_KERNEL_SYM_NAME_LEN);
1252 ev.name[LTTNG_KERNEL_SYM_NAME_LEN - 1] = '\0';
33a39a3c 1253 ev.instrumentation = LTTNG_KERNEL_SYSCALL;
badfe9f5
MD
1254 ev.u.syscall.entryexit = LTTNG_KERNEL_SYSCALL_ENTRY;
1255 ev.u.syscall.abi = LTTNG_KERNEL_SYSCALL_ABI_COMPAT;
3b82c4e1
MD
1256 event = _lttng_event_create(chan, &ev, filter, desc,
1257 ev.instrumentation);
1258 WARN_ON_ONCE(!event);
1259 if (IS_ERR(event)) {
1260 return PTR_ERR(event);
b76dc1a0 1261 }
3b82c4e1 1262 hlist_add_head(&event->u.syscall.node, &chan->sc_compat_unknown);
b76dc1a0
MD
1263 }
1264
3b82c4e1 1265 if (hlist_empty(&chan->compat_sc_exit_unknown)) {
2f804c0a 1266 const struct lttng_event_desc *desc =
5b7ac358 1267 &__event_desc___compat_syscall_exit_unknown;
3b82c4e1 1268 struct lttng_event *event;
2f804c0a
MD
1269
1270 memset(&ev, 0, sizeof(ev));
f8695253
MD
1271 strncpy(ev.name, desc->name, LTTNG_KERNEL_SYM_NAME_LEN);
1272 ev.name[LTTNG_KERNEL_SYM_NAME_LEN - 1] = '\0';
33a39a3c 1273 ev.instrumentation = LTTNG_KERNEL_SYSCALL;
badfe9f5
MD
1274 ev.u.syscall.entryexit = LTTNG_KERNEL_SYSCALL_EXIT;
1275 ev.u.syscall.abi = LTTNG_KERNEL_SYSCALL_ABI_COMPAT;
3b82c4e1
MD
1276 event = _lttng_event_create(chan, &ev, filter, desc,
1277 ev.instrumentation);
1278 WARN_ON_ONCE(!event);
1279 if (IS_ERR(event)) {
1280 return PTR_ERR(event);
5b7ac358 1281 }
3b82c4e1 1282 hlist_add_head(&event->u.syscall.node, &chan->compat_sc_exit_unknown);
5b7ac358
MD
1283 }
1284
3b82c4e1 1285 if (hlist_empty(&chan->sc_exit_unknown)) {
5b7ac358
MD
1286 const struct lttng_event_desc *desc =
1287 &__event_desc___syscall_exit_unknown;
3b82c4e1 1288 struct lttng_event *event;
5b7ac358
MD
1289
1290 memset(&ev, 0, sizeof(ev));
1291 strncpy(ev.name, desc->name, LTTNG_KERNEL_SYM_NAME_LEN);
1292 ev.name[LTTNG_KERNEL_SYM_NAME_LEN - 1] = '\0';
33a39a3c 1293 ev.instrumentation = LTTNG_KERNEL_SYSCALL;
badfe9f5
MD
1294 ev.u.syscall.entryexit = LTTNG_KERNEL_SYSCALL_EXIT;
1295 ev.u.syscall.abi = LTTNG_KERNEL_SYSCALL_ABI_NATIVE;
3b82c4e1
MD
1296 event = _lttng_event_create(chan, &ev, filter, desc,
1297 ev.instrumentation);
1298 WARN_ON_ONCE(!event);
1299 if (IS_ERR(event)) {
1300 return PTR_ERR(event);
2f804c0a 1301 }
3b82c4e1 1302 hlist_add_head(&event->u.syscall.node, &chan->sc_exit_unknown);
2f804c0a
MD
1303 }
1304
3b82c4e1
MD
1305 ret = lttng_create_syscall_event_if_missing(sc_table, ARRAY_SIZE(sc_table),
1306 chan->sc_table, event_enabler, filter, SC_TYPE_ENTRY);
5b7ac358
MD
1307 if (ret)
1308 return ret;
3b82c4e1
MD
1309 ret = lttng_create_syscall_event_if_missing(sc_exit_table, ARRAY_SIZE(sc_exit_table),
1310 chan->sc_exit_table, event_enabler, filter, SC_TYPE_EXIT);
49c50022
MD
1311 if (ret)
1312 return ret;
5b7ac358 1313
49c50022 1314#ifdef CONFIG_COMPAT
3b82c4e1
MD
1315 ret = lttng_create_syscall_event_if_missing(compat_sc_table, ARRAY_SIZE(compat_sc_table),
1316 chan->compat_sc_table, event_enabler, filter,
5b7ac358
MD
1317 SC_TYPE_COMPAT_ENTRY);
1318 if (ret)
1319 return ret;
3b82c4e1
MD
1320 ret = lttng_create_syscall_event_if_missing(compat_sc_exit_table, ARRAY_SIZE(compat_sc_exit_table),
1321 chan->compat_sc_exit_table, event_enabler, filter,
5b7ac358 1322 SC_TYPE_COMPAT_EXIT);
49c50022
MD
1323 if (ret)
1324 return ret;
1325#endif
badfe9f5
MD
1326
1327 if (!chan->sc_filter) {
1328 chan->sc_filter = kzalloc(sizeof(struct lttng_syscall_filter),
1329 GFP_KERNEL);
1330 if (!chan->sc_filter)
1331 return -ENOMEM;
1332 }
1333
80f87dd2
MD
1334 if (!chan->sys_enter_registered) {
1335 ret = lttng_wrapper_tracepoint_probe_register("sys_enter",
2d6d88c6 1336 (void *) syscall_entry_event_probe, chan);
80f87dd2
MD
1337 if (ret)
1338 return ret;
1339 chan->sys_enter_registered = 1;
1340 }
63728b02
MD
1341 /*
1342 * We change the name of sys_exit tracepoint due to namespace
1343 * conflict with sys_exit syscall entry.
1344 */
80f87dd2
MD
1345 if (!chan->sys_exit_registered) {
1346 ret = lttng_wrapper_tracepoint_probe_register("sys_exit",
2d6d88c6 1347 (void *) syscall_exit_event_probe, chan);
80f87dd2
MD
1348 if (ret) {
1349 WARN_ON_ONCE(lttng_wrapper_tracepoint_probe_unregister("sys_enter",
2d6d88c6 1350 (void *) syscall_entry_event_probe, chan));
80f87dd2
MD
1351 return ret;
1352 }
1353 chan->sys_exit_registered = 1;
63728b02 1354 }
259b6cb3
MD
1355 return ret;
1356}
1357
1358/*
8a8ac9a8
FD
1359 * Should be called with sessions lock held.
1360 */
1361int lttng_syscalls_register_event_notifier(
1362 struct lttng_event_notifier_enabler *event_notifier_enabler,
1363 void *filter)
1364{
1365 struct lttng_event_notifier_group *group = event_notifier_enabler->group;
1366 unsigned int i;
1367 int ret = 0;
1368
1369 wrapper_vmalloc_sync_mappings();
1370
1371 if (!group->event_notifier_syscall_dispatch) {
1372 group->event_notifier_syscall_dispatch =
1373 kzalloc(sizeof(struct hlist_head) * ARRAY_SIZE(sc_table),
1374 GFP_KERNEL);
1375 if (!group->event_notifier_syscall_dispatch)
1376 return -ENOMEM;
1377
1378 /* Initialize all list_head */
1379 for (i = 0; i < ARRAY_SIZE(sc_table); i++)
1380 INIT_HLIST_HEAD(&group->event_notifier_syscall_dispatch[i]);
1381
1382 /* Init the unknown syscall notifier list. */
1383 INIT_HLIST_HEAD(&group->event_notifier_unknown_syscall_dispatch);
1384 }
1385
1386 if (!group->event_notifier_exit_syscall_dispatch) {
1387 group->event_notifier_exit_syscall_dispatch =
1388 kzalloc(sizeof(struct hlist_head) * ARRAY_SIZE(sc_table),
1389 GFP_KERNEL);
1390 if (!group->event_notifier_exit_syscall_dispatch)
1391 return -ENOMEM;
1392
1393 /* Initialize all list_head */
1394 for (i = 0; i < ARRAY_SIZE(sc_table); i++)
1395 INIT_HLIST_HEAD(&group->event_notifier_exit_syscall_dispatch[i]);
1396
1397 /* Init the unknown exit syscall notifier list. */
1398 INIT_HLIST_HEAD(&group->event_notifier_exit_unknown_syscall_dispatch);
1399 }
1400
1401#ifdef CONFIG_COMPAT
1402 if (!group->event_notifier_compat_syscall_dispatch) {
1403 group->event_notifier_compat_syscall_dispatch =
1404 kzalloc(sizeof(struct hlist_head) * ARRAY_SIZE(compat_sc_table),
1405 GFP_KERNEL);
1406 if (!group->event_notifier_syscall_dispatch)
1407 return -ENOMEM;
1408
1409 /* Initialize all list_head */
1410 for (i = 0; i < ARRAY_SIZE(compat_sc_table); i++)
1411 INIT_HLIST_HEAD(&group->event_notifier_compat_syscall_dispatch[i]);
1412
1413 /* Init the unknown syscall notifier list. */
1414 INIT_HLIST_HEAD(&group->event_notifier_compat_unknown_syscall_dispatch);
1415 }
1416
1417 if (!group->event_notifier_exit_compat_syscall_dispatch) {
1418 group->event_notifier_exit_compat_syscall_dispatch =
1419 kzalloc(sizeof(struct hlist_head) * ARRAY_SIZE(compat_sc_exit_table),
1420 GFP_KERNEL);
1421 if (!group->event_notifier_exit_syscall_dispatch)
1422 return -ENOMEM;
1423
1424 /* Initialize all list_head */
1425 for (i = 0; i < ARRAY_SIZE(compat_sc_exit_table); i++)
1426 INIT_HLIST_HEAD(&group->event_notifier_exit_compat_syscall_dispatch[i]);
1427
1428 /* Init the unknown exit syscall notifier list. */
1429 INIT_HLIST_HEAD(&group->event_notifier_exit_compat_unknown_syscall_dispatch);
1430 }
1431#endif
1432
1433 if (!group->sc_filter) {
1434 group->sc_filter = kzalloc(sizeof(struct lttng_syscall_filter),
1435 GFP_KERNEL);
1436 if (!group->sc_filter)
1437 return -ENOMEM;
1438 }
1439
1440 if (!group->sys_enter_registered) {
1441 ret = lttng_wrapper_tracepoint_probe_register("sys_enter",
1442 (void *) syscall_entry_event_notifier_probe, group);
1443 if (ret)
1444 return ret;
1445 group->sys_enter_registered = 1;
1446 }
1447
1448 if (!group->sys_exit_registered) {
1449 ret = lttng_wrapper_tracepoint_probe_register("sys_exit",
1450 (void *) syscall_exit_event_notifier_probe, group);
1451 if (ret) {
1452 WARN_ON_ONCE(lttng_wrapper_tracepoint_probe_unregister("sys_enter",
1453 (void *) syscall_entry_event_notifier_probe, group));
1454 return ret;
1455 }
1456 group->sys_exit_registered = 1;
1457 }
1458
1459 return ret;
1460}
1461
1462static
1463int create_unknown_event_notifier(
1464 struct lttng_event_notifier_enabler *event_notifier_enabler,
1465 enum sc_type type)
1466{
1467 struct lttng_event_notifier *notifier;
1468 const struct lttng_event_desc *desc;
1469 struct lttng_event_notifier_group *group = event_notifier_enabler->group;
1470 struct lttng_kernel_event_notifier event_notifier_param;
1471 uint64_t user_token = event_notifier_enabler->base.user_token;
99f52fcc 1472 uint64_t error_counter_index = event_notifier_enabler->error_counter_index;
8a8ac9a8
FD
1473 struct lttng_enabler *base_enabler = lttng_event_notifier_enabler_as_enabler(
1474 event_notifier_enabler);
1475 struct hlist_head *unknown_dispatch_list;
1476 int ret = 0;
1477 bool found = false;
1478 enum lttng_kernel_syscall_abi abi;
1479 enum lttng_kernel_syscall_entryexit entryexit;
1480 struct hlist_head *head;
1481
1482 switch (type) {
1483 case SC_TYPE_ENTRY:
1484 desc = &__event_desc___syscall_entry_unknown;
1485 unknown_dispatch_list = &group->event_notifier_unknown_syscall_dispatch;
1486 entryexit = LTTNG_KERNEL_SYSCALL_ENTRY;
1487 abi = LTTNG_KERNEL_SYSCALL_ABI_NATIVE;
1488 break;
1489 case SC_TYPE_EXIT:
1490 desc = &__event_desc___syscall_exit_unknown;
1491 unknown_dispatch_list = &group->event_notifier_exit_unknown_syscall_dispatch;
1492 entryexit = LTTNG_KERNEL_SYSCALL_EXIT;
1493 abi = LTTNG_KERNEL_SYSCALL_ABI_NATIVE;
1494 break;
1495 case SC_TYPE_COMPAT_ENTRY:
1496 desc = &__event_desc___compat_syscall_entry_unknown;
1497 unknown_dispatch_list = &group->event_notifier_compat_unknown_syscall_dispatch;
1498 entryexit = LTTNG_KERNEL_SYSCALL_ENTRY;
1499 abi = LTTNG_KERNEL_SYSCALL_ABI_COMPAT;
1500 break;
1501 case SC_TYPE_COMPAT_EXIT:
1502 desc = &__event_desc___compat_syscall_exit_unknown;
1503 unknown_dispatch_list = &group->event_notifier_exit_compat_unknown_syscall_dispatch;
1504 entryexit = LTTNG_KERNEL_SYSCALL_EXIT;
1505 abi = LTTNG_KERNEL_SYSCALL_ABI_COMPAT;
1506 break;
1507 default:
1508 BUG_ON(1);
1509 }
1510
1511 /*
1512 * Check if already created.
1513 */
1514 head = utils_borrow_hash_table_bucket(group->event_notifiers_ht.table,
1515 LTTNG_EVENT_NOTIFIER_HT_SIZE, desc->name);
1516 lttng_hlist_for_each_entry(notifier, head, hlist) {
1517 if (notifier->desc == desc &&
1518 notifier->user_token == base_enabler->user_token)
1519 found = true;
1520 }
1521 if (found)
1522 goto end;
1523
1524 memset(&event_notifier_param, 0, sizeof(event_notifier_param));
1525 strncat(event_notifier_param.event.name, desc->name,
1526 LTTNG_KERNEL_SYM_NAME_LEN - strlen(event_notifier_param.event.name) - 1);
1527
1528 event_notifier_param.event.name[LTTNG_KERNEL_SYM_NAME_LEN - 1] = '\0';
1529
1530 event_notifier_param.event.instrumentation = LTTNG_KERNEL_SYSCALL;
1531 event_notifier_param.event.u.syscall.abi = abi;
1532 event_notifier_param.event.u.syscall.entryexit = entryexit;
1533
1534 notifier = _lttng_event_notifier_create(desc, user_token,
99f52fcc 1535 error_counter_index, group, &event_notifier_param, NULL,
8a8ac9a8
FD
1536 event_notifier_param.event.instrumentation);
1537 if (IS_ERR(notifier)) {
1538 printk(KERN_INFO "Unable to create unknown notifier %s\n",
1539 desc->name);
1540 ret = -ENOMEM;
1541 goto end;
1542 }
1543
1544 hlist_add_head_rcu(&notifier->u.syscall.node, unknown_dispatch_list);
1545
1546end:
1547 return ret;
1548}
1549
1550static int create_matching_event_notifiers(
1551 struct lttng_event_notifier_enabler *event_notifier_enabler,
1552 void *filter, const struct trace_syscall_entry *table,
1553 size_t table_len, enum sc_type type)
1554{
1555 struct lttng_event_notifier_group *group = event_notifier_enabler->group;
1556 const struct lttng_event_desc *desc;
1557 uint64_t user_token = event_notifier_enabler->base.user_token;
99f52fcc 1558 uint64_t error_counter_index = event_notifier_enabler->error_counter_index;
8a8ac9a8
FD
1559 unsigned int i;
1560 int ret = 0;
1561
1562 /* iterate over all syscall and create event_notifier that match */
1563 for (i = 0; i < table_len; i++) {
1564 struct lttng_event_notifier *event_notifier;
1565 struct lttng_kernel_event_notifier event_notifier_param;
1566 struct hlist_head *head;
1567 int found = 0;
1568
1569 desc = table[i].desc;
1570 if (!desc) {
1571 /* Unknown syscall */
1572 continue;
1573 }
1574
1575 if (!lttng_desc_match_enabler(desc,
1576 lttng_event_notifier_enabler_as_enabler(event_notifier_enabler)))
1577 continue;
1578
1579 /*
1580 * Check if already created.
1581 */
1582 head = utils_borrow_hash_table_bucket(group->event_notifiers_ht.table,
1583 LTTNG_EVENT_NOTIFIER_HT_SIZE, desc->name);
1584 lttng_hlist_for_each_entry(event_notifier, head, hlist) {
1585 if (event_notifier->desc == desc
1586 && event_notifier->user_token == event_notifier_enabler->base.user_token)
1587 found = 1;
1588 }
1589 if (found)
1590 continue;
1591
1592 memset(&event_notifier_param, 0, sizeof(event_notifier_param));
1593 switch (type) {
1594 case SC_TYPE_ENTRY:
1595 event_notifier_param.event.u.syscall.entryexit = LTTNG_KERNEL_SYSCALL_ENTRY;
1596 event_notifier_param.event.u.syscall.abi = LTTNG_KERNEL_SYSCALL_ABI_NATIVE;
1597 break;
1598 case SC_TYPE_EXIT:
1599 event_notifier_param.event.u.syscall.entryexit = LTTNG_KERNEL_SYSCALL_EXIT;
1600 event_notifier_param.event.u.syscall.abi = LTTNG_KERNEL_SYSCALL_ABI_NATIVE;
1601 break;
1602 case SC_TYPE_COMPAT_ENTRY:
1603 event_notifier_param.event.u.syscall.entryexit = LTTNG_KERNEL_SYSCALL_ENTRY;
1604 event_notifier_param.event.u.syscall.abi = LTTNG_KERNEL_SYSCALL_ABI_COMPAT;
1605 break;
1606 case SC_TYPE_COMPAT_EXIT:
1607 event_notifier_param.event.u.syscall.entryexit = LTTNG_KERNEL_SYSCALL_EXIT;
1608 event_notifier_param.event.u.syscall.abi = LTTNG_KERNEL_SYSCALL_ABI_COMPAT;
1609 break;
1610 }
1611 strncat(event_notifier_param.event.name, desc->name,
1612 LTTNG_KERNEL_SYM_NAME_LEN - strlen(event_notifier_param.event.name) - 1);
1613 event_notifier_param.event.name[LTTNG_KERNEL_SYM_NAME_LEN - 1] = '\0';
1614 event_notifier_param.event.instrumentation = LTTNG_KERNEL_SYSCALL;
1615
99f52fcc
FD
1616 event_notifier = _lttng_event_notifier_create(desc, user_token,
1617 error_counter_index, group, &event_notifier_param,
1618 filter, event_notifier_param.event.instrumentation);
8a8ac9a8
FD
1619 if (IS_ERR(event_notifier)) {
1620 printk(KERN_INFO "Unable to create event_notifier %s\n",
1621 desc->name);
1622 ret = -ENOMEM;
1623 goto end;
1624 }
1625
1626 event_notifier->u.syscall.syscall_id = i;
1627 }
1628
1629end:
1630 return ret;
1631
1632}
1633
1634int lttng_syscals_create_matching_event_notifiers(
1635 struct lttng_event_notifier_enabler *event_notifier_enabler,
1636 void *filter)
1637{
1638 int ret;
1639 struct lttng_enabler *base_enabler =
1640 lttng_event_notifier_enabler_as_enabler(event_notifier_enabler);
1641 enum lttng_kernel_syscall_entryexit entryexit =
1642 base_enabler->event_param.u.syscall.entryexit;
1643
1644 if (entryexit == LTTNG_KERNEL_SYSCALL_ENTRY || entryexit == LTTNG_KERNEL_SYSCALL_ENTRYEXIT) {
1645 ret = create_matching_event_notifiers(event_notifier_enabler,
1646 filter, sc_table, ARRAY_SIZE(sc_table), SC_TYPE_ENTRY);
1647 if (ret)
1648 goto end;
1649
1650 ret = create_matching_event_notifiers(event_notifier_enabler,
1651 filter, compat_sc_table, ARRAY_SIZE(compat_sc_table),
1652 SC_TYPE_COMPAT_ENTRY);
1653 if (ret)
1654 goto end;
1655
1656 ret = create_unknown_event_notifier(event_notifier_enabler,
1657 SC_TYPE_ENTRY);
1658 if (ret)
1659 goto end;
1660
1661 ret = create_unknown_event_notifier(event_notifier_enabler,
1662 SC_TYPE_COMPAT_ENTRY);
1663 if (ret)
1664 goto end;
1665 }
1666
1667 if (entryexit == LTTNG_KERNEL_SYSCALL_EXIT || entryexit == LTTNG_KERNEL_SYSCALL_ENTRYEXIT) {
1668 ret = create_matching_event_notifiers(event_notifier_enabler,
1669 filter, sc_exit_table, ARRAY_SIZE(sc_exit_table),
1670 SC_TYPE_EXIT);
1671 if (ret)
1672 goto end;
1673
1674 ret = create_unknown_event_notifier(event_notifier_enabler,
1675 SC_TYPE_EXIT);
1676 if (ret)
1677 goto end;
1678
1679 ret = create_matching_event_notifiers(event_notifier_enabler,
1680 filter, compat_sc_exit_table, ARRAY_SIZE(compat_sc_exit_table),
1681 SC_TYPE_COMPAT_EXIT);
1682 if (ret)
1683 goto end;
1684
1685 ret = create_unknown_event_notifier(event_notifier_enabler,
1686 SC_TYPE_COMPAT_EXIT);
1687 if (ret)
1688 goto end;
1689 }
1690
1691end:
1692 return ret;
1693}
1694
1695/*
1696 * Unregister the syscall event_notifier probes from the callsites.
259b6cb3 1697 */
3b82c4e1 1698int lttng_syscalls_unregister_event_notifier_group(
8a8ac9a8
FD
1699 struct lttng_event_notifier_group *event_notifier_group)
1700{
1701 int ret;
1702
1703 /*
1704 * Only register the event_notifier probe on the `sys_enter` callsite for now.
1705 * At the moment, we don't think it's desirable to have one fired
1706 * event_notifier for the entry and one for the exit of a syscall.
1707 */
1708 if (event_notifier_group->sys_enter_registered) {
1709 ret = lttng_wrapper_tracepoint_probe_unregister("sys_enter",
1710 (void *) syscall_entry_event_notifier_probe, event_notifier_group);
1711 if (ret)
1712 return ret;
1713 event_notifier_group->sys_enter_registered = 0;
1714 }
1715 if (event_notifier_group->sys_exit_registered) {
1716 ret = lttng_wrapper_tracepoint_probe_unregister("sys_exit",
1717 (void *) syscall_exit_event_notifier_probe, event_notifier_group);
1718 if (ret)
1719 return ret;
1720 event_notifier_group->sys_enter_registered = 0;
1721 }
1722
1723 kfree(event_notifier_group->event_notifier_syscall_dispatch);
1724 kfree(event_notifier_group->event_notifier_exit_syscall_dispatch);
1725#ifdef CONFIG_COMPAT
1726 kfree(event_notifier_group->event_notifier_compat_syscall_dispatch);
1727 kfree(event_notifier_group->event_notifier_exit_compat_syscall_dispatch);
1728#endif
1729 return 0;
1730}
1731
3b82c4e1 1732int lttng_syscalls_unregister_channel(struct lttng_channel *chan)
259b6cb3
MD
1733{
1734 int ret;
1735
1736 if (!chan->sc_table)
1737 return 0;
80f87dd2 1738 if (chan->sys_enter_registered) {
2d9cd7f3 1739 ret = lttng_wrapper_tracepoint_probe_unregister("sys_enter",
2d6d88c6 1740 (void *) syscall_entry_event_probe, chan);
80f87dd2
MD
1741 if (ret)
1742 return ret;
1743 chan->sys_enter_registered = 0;
1744 }
1745 if (chan->sys_exit_registered) {
2d9cd7f3 1746 ret = lttng_wrapper_tracepoint_probe_unregister("sys_exit",
2d6d88c6 1747 (void *) syscall_exit_event_probe, chan);
80f87dd2
MD
1748 if (ret)
1749 return ret;
1750 chan->sys_exit_registered = 0;
1751 }
badfe9f5
MD
1752 return 0;
1753}
1754
2d6d88c6 1755int lttng_syscalls_destroy_event(struct lttng_channel *chan)
badfe9f5 1756{
259b6cb3 1757 kfree(chan->sc_table);
5b7ac358 1758 kfree(chan->sc_exit_table);
49c50022
MD
1759#ifdef CONFIG_COMPAT
1760 kfree(chan->compat_sc_table);
5b7ac358 1761 kfree(chan->compat_sc_exit_table);
49c50022 1762#endif
80f87dd2
MD
1763 kfree(chan->sc_filter);
1764 return 0;
1765}
1766
1767static
1768int get_syscall_nr(const char *syscall_name)
1769{
1770 int syscall_nr = -1;
1771 int i;
1772
1773 for (i = 0; i < ARRAY_SIZE(sc_table); i++) {
1774 const struct trace_syscall_entry *entry;
5b7ac358 1775 const char *it_name;
80f87dd2
MD
1776
1777 entry = &sc_table[i];
1778 if (!entry->desc)
1779 continue;
5b7ac358
MD
1780 it_name = entry->desc->name;
1781 it_name += strlen(SYSCALL_ENTRY_STR);
1782 if (!strcmp(syscall_name, it_name)) {
80f87dd2
MD
1783 syscall_nr = i;
1784 break;
1785 }
1786 }
1787 return syscall_nr;
1788}
1789
1790static
1791int get_compat_syscall_nr(const char *syscall_name)
1792{
1793 int syscall_nr = -1;
1794 int i;
1795
1796 for (i = 0; i < ARRAY_SIZE(compat_sc_table); i++) {
1797 const struct trace_syscall_entry *entry;
5b7ac358 1798 const char *it_name;
80f87dd2
MD
1799
1800 entry = &compat_sc_table[i];
1801 if (!entry->desc)
1802 continue;
5b7ac358
MD
1803 it_name = entry->desc->name;
1804 it_name += strlen(COMPAT_SYSCALL_ENTRY_STR);
1805 if (!strcmp(syscall_name, it_name)) {
80f87dd2
MD
1806 syscall_nr = i;
1807 break;
1808 }
1809 }
1810 return syscall_nr;
1811}
1812
12e579db
MD
1813static
1814uint32_t get_sc_tables_len(void)
1815{
1816 return ARRAY_SIZE(sc_table) + ARRAY_SIZE(compat_sc_table);
1817}
1818
badfe9f5 1819static
ade8a729
FD
1820const char *get_syscall_name(const char *desc_name,
1821 enum lttng_syscall_abi abi,
1822 enum lttng_syscall_entryexit entryexit)
80f87dd2 1823{
badfe9f5 1824 size_t prefix_len = 0;
80f87dd2 1825
80f87dd2 1826
ade8a729 1827 switch (entryexit) {
badfe9f5 1828 case LTTNG_SYSCALL_ENTRY:
ade8a729 1829 switch (abi) {
badfe9f5
MD
1830 case LTTNG_SYSCALL_ABI_NATIVE:
1831 prefix_len = strlen(SYSCALL_ENTRY_STR);
1832 break;
1833 case LTTNG_SYSCALL_ABI_COMPAT:
1834 prefix_len = strlen(COMPAT_SYSCALL_ENTRY_STR);
1835 break;
80f87dd2 1836 }
badfe9f5
MD
1837 break;
1838 case LTTNG_SYSCALL_EXIT:
ade8a729 1839 switch (abi) {
badfe9f5
MD
1840 case LTTNG_SYSCALL_ABI_NATIVE:
1841 prefix_len = strlen(SYSCALL_EXIT_STR);
1842 break;
1843 case LTTNG_SYSCALL_ABI_COMPAT:
1844 prefix_len = strlen(COMPAT_SYSCALL_EXIT_STR);
1845 break;
80f87dd2 1846 }
badfe9f5 1847 break;
80f87dd2 1848 }
badfe9f5 1849 WARN_ON_ONCE(prefix_len == 0);
ade8a729 1850 return desc_name + prefix_len;
badfe9f5
MD
1851}
1852
ade8a729
FD
1853static
1854int lttng_syscall_filter_enable(
1855 struct lttng_syscall_filter *filter,
1856 const char *desc_name, enum lttng_syscall_abi abi,
1857 enum lttng_syscall_entryexit entryexit)
badfe9f5 1858{
badfe9f5
MD
1859 const char *syscall_name;
1860 unsigned long *bitmap;
1861 int syscall_nr;
1862
ade8a729 1863 syscall_name = get_syscall_name(desc_name, abi, entryexit);
badfe9f5 1864
ade8a729 1865 switch (abi) {
badfe9f5
MD
1866 case LTTNG_SYSCALL_ABI_NATIVE:
1867 syscall_nr = get_syscall_nr(syscall_name);
1868 break;
1869 case LTTNG_SYSCALL_ABI_COMPAT:
1870 syscall_nr = get_compat_syscall_nr(syscall_name);
1871 break;
1872 default:
1873 return -EINVAL;
80f87dd2 1874 }
badfe9f5
MD
1875 if (syscall_nr < 0)
1876 return -ENOENT;
1877
ade8a729 1878 switch (entryexit) {
badfe9f5 1879 case LTTNG_SYSCALL_ENTRY:
ade8a729 1880 switch (abi) {
badfe9f5
MD
1881 case LTTNG_SYSCALL_ABI_NATIVE:
1882 bitmap = filter->sc_entry;
1883 break;
1884 case LTTNG_SYSCALL_ABI_COMPAT:
1885 bitmap = filter->sc_compat_entry;
1886 break;
6d9694d8
MD
1887 default:
1888 return -EINVAL;
80f87dd2 1889 }
badfe9f5
MD
1890 break;
1891 case LTTNG_SYSCALL_EXIT:
ade8a729 1892 switch (abi) {
badfe9f5
MD
1893 case LTTNG_SYSCALL_ABI_NATIVE:
1894 bitmap = filter->sc_exit;
1895 break;
1896 case LTTNG_SYSCALL_ABI_COMPAT:
1897 bitmap = filter->sc_compat_exit;
1898 break;
6d9694d8
MD
1899 default:
1900 return -EINVAL;
80f87dd2 1901 }
badfe9f5
MD
1902 break;
1903 default:
1904 return -EINVAL;
80f87dd2 1905 }
badfe9f5
MD
1906 if (test_bit(syscall_nr, bitmap))
1907 return -EEXIST;
1908 bitmap_set(bitmap, syscall_nr, 1);
80f87dd2 1909 return 0;
80f87dd2
MD
1910}
1911
8a8ac9a8
FD
1912int lttng_syscall_filter_enable_event_notifier(
1913 struct lttng_event_notifier *notifier)
1914{
1915 struct lttng_event_notifier_group *group = notifier->group;
1916 unsigned int syscall_id = notifier->u.syscall.syscall_id;
1917 struct hlist_head *dispatch_list;
1918 int ret = 0;
1919
1920 WARN_ON_ONCE(notifier->instrumentation != LTTNG_KERNEL_SYSCALL);
1921
1922 ret = lttng_syscall_filter_enable(group->sc_filter,
1923 notifier->desc->name, notifier->u.syscall.abi,
1924 notifier->u.syscall.entryexit);
1925 if (ret) {
1926 goto end;
1927 }
1928
1929 switch (notifier->u.syscall.entryexit) {
1930 case LTTNG_SYSCALL_ENTRY:
1931 switch (notifier->u.syscall.abi) {
1932 case LTTNG_SYSCALL_ABI_NATIVE:
1933 dispatch_list = &group->event_notifier_syscall_dispatch[syscall_id];
1934 break;
1935 case LTTNG_SYSCALL_ABI_COMPAT:
1936 dispatch_list = &group->event_notifier_compat_syscall_dispatch[syscall_id];
1937 break;
1938 }
1939 break;
1940 case LTTNG_SYSCALL_EXIT:
1941 switch (notifier->u.syscall.abi) {
1942 case LTTNG_SYSCALL_ABI_NATIVE:
1943 dispatch_list = &group->event_notifier_exit_syscall_dispatch[syscall_id];
1944 break;
1945 case LTTNG_SYSCALL_ABI_COMPAT:
1946 dispatch_list = &group->event_notifier_exit_compat_syscall_dispatch[syscall_id];
1947 break;
1948 }
1949 break;
1950 }
1951
1952 hlist_add_head_rcu(&notifier->u.syscall.node, dispatch_list);
1953
1954end:
1955 return ret ;
1956}
1957
ade8a729
FD
1958int lttng_syscall_filter_enable_event(
1959 struct lttng_channel *channel,
badfe9f5 1960 struct lttng_event *event)
80f87dd2 1961{
ade8a729
FD
1962 WARN_ON_ONCE(event->instrumentation != LTTNG_KERNEL_SYSCALL);
1963
1964 return lttng_syscall_filter_enable(channel->sc_filter,
1965 event->desc->name, event->u.syscall.abi,
1966 event->u.syscall.entryexit);
1967}
1968
1969static
1970int lttng_syscall_filter_disable(
1971 struct lttng_syscall_filter *filter,
1972 const char *desc_name, enum lttng_syscall_abi abi,
1973 enum lttng_syscall_entryexit entryexit)
1974{
badfe9f5
MD
1975 const char *syscall_name;
1976 unsigned long *bitmap;
1977 int syscall_nr;
80f87dd2 1978
ade8a729 1979 syscall_name = get_syscall_name(desc_name, abi, entryexit);
80f87dd2 1980
ade8a729 1981 switch (abi) {
badfe9f5
MD
1982 case LTTNG_SYSCALL_ABI_NATIVE:
1983 syscall_nr = get_syscall_nr(syscall_name);
1984 break;
1985 case LTTNG_SYSCALL_ABI_COMPAT:
1986 syscall_nr = get_compat_syscall_nr(syscall_name);
1987 break;
1988 default:
1989 return -EINVAL;
80f87dd2 1990 }
badfe9f5
MD
1991 if (syscall_nr < 0)
1992 return -ENOENT;
80f87dd2 1993
ade8a729 1994 switch (entryexit) {
badfe9f5 1995 case LTTNG_SYSCALL_ENTRY:
ade8a729 1996 switch (abi) {
badfe9f5
MD
1997 case LTTNG_SYSCALL_ABI_NATIVE:
1998 bitmap = filter->sc_entry;
1999 break;
2000 case LTTNG_SYSCALL_ABI_COMPAT:
2001 bitmap = filter->sc_compat_entry;
2002 break;
6d9694d8
MD
2003 default:
2004 return -EINVAL;
80f87dd2 2005 }
badfe9f5
MD
2006 break;
2007 case LTTNG_SYSCALL_EXIT:
ade8a729 2008 switch (abi) {
badfe9f5
MD
2009 case LTTNG_SYSCALL_ABI_NATIVE:
2010 bitmap = filter->sc_exit;
2011 break;
2012 case LTTNG_SYSCALL_ABI_COMPAT:
2013 bitmap = filter->sc_compat_exit;
2014 break;
6d9694d8
MD
2015 default:
2016 return -EINVAL;
80f87dd2 2017 }
badfe9f5
MD
2018 break;
2019 default:
2020 return -EINVAL;
80f87dd2 2021 }
badfe9f5
MD
2022 if (!test_bit(syscall_nr, bitmap))
2023 return -EEXIST;
2024 bitmap_clear(bitmap, syscall_nr, 1);
80f87dd2 2025
badfe9f5 2026 return 0;
259b6cb3 2027}
2d2464bd 2028
8a8ac9a8
FD
2029int lttng_syscall_filter_disable_event_notifier(
2030 struct lttng_event_notifier *notifier)
2031{
2032 struct lttng_event_notifier_group *group = notifier->group;
2033 int ret;
2034
2035 WARN_ON_ONCE(notifier->instrumentation != LTTNG_KERNEL_SYSCALL);
2036
2037 ret = lttng_syscall_filter_disable(group->sc_filter,
2038 notifier->desc->name, notifier->u.syscall.abi,
2039 notifier->u.syscall.entryexit);
2040 WARN_ON_ONCE(ret != 0);
2041
2042 hlist_del_rcu(&notifier->u.syscall.node);
2043 return 0;
2044}
2045
ade8a729
FD
2046int lttng_syscall_filter_disable_event(
2047 struct lttng_channel *channel,
2048 struct lttng_event *event)
2049{
2050 return lttng_syscall_filter_disable(channel->sc_filter,
2051 event->desc->name, event->u.syscall.abi,
2052 event->u.syscall.entryexit);
2053}
2054
2d2464bd
MD
2055static
2056const struct trace_syscall_entry *syscall_list_get_entry(loff_t *pos)
2057{
2058 const struct trace_syscall_entry *entry;
2059 int iter = 0;
2060
2061 for (entry = sc_table;
2062 entry < sc_table + ARRAY_SIZE(sc_table);
2063 entry++) {
2064 if (iter++ >= *pos)
2065 return entry;
2066 }
2067 for (entry = compat_sc_table;
2068 entry < compat_sc_table + ARRAY_SIZE(compat_sc_table);
2069 entry++) {
2070 if (iter++ >= *pos)
2071 return entry;
2072 }
2073 /* End of list */
2074 return NULL;
2075}
2076
2077static
2078void *syscall_list_start(struct seq_file *m, loff_t *pos)
2079{
2080 return (void *) syscall_list_get_entry(pos);
2081}
2082
2083static
2084void *syscall_list_next(struct seq_file *m, void *p, loff_t *ppos)
2085{
2086 (*ppos)++;
2087 return (void *) syscall_list_get_entry(ppos);
2088}
2089
2090static
2091void syscall_list_stop(struct seq_file *m, void *p)
2092{
2093}
2094
12e579db
MD
2095static
2096int get_sc_table(const struct trace_syscall_entry *entry,
2097 const struct trace_syscall_entry **table,
2098 unsigned int *bitness)
2099{
2100 if (entry >= sc_table && entry < sc_table + ARRAY_SIZE(sc_table)) {
2101 if (bitness)
2102 *bitness = BITS_PER_LONG;
2103 if (table)
2104 *table = sc_table;
2105 return 0;
2106 }
2107 if (!(entry >= compat_sc_table
2108 && entry < compat_sc_table + ARRAY_SIZE(compat_sc_table))) {
2109 return -EINVAL;
2110 }
2111 if (bitness)
2112 *bitness = 32;
2113 if (table)
2114 *table = compat_sc_table;
2115 return 0;
2116}
2117
2d2464bd
MD
2118static
2119int syscall_list_show(struct seq_file *m, void *p)
2120{
2121 const struct trace_syscall_entry *table, *entry = p;
2122 unsigned int bitness;
d4291869 2123 unsigned long index;
12e579db 2124 int ret;
d4291869 2125 const char *name;
2d2464bd 2126
12e579db
MD
2127 ret = get_sc_table(entry, &table, &bitness);
2128 if (ret)
2129 return ret;
f4855b46
MD
2130 if (!entry->desc)
2131 return 0;
d4291869
MD
2132 if (table == sc_table) {
2133 index = entry - table;
2134 name = &entry->desc->name[strlen(SYSCALL_ENTRY_STR)];
2135 } else {
2136 index = (entry - table) + ARRAY_SIZE(sc_table);
2137 name = &entry->desc->name[strlen(COMPAT_SYSCALL_ENTRY_STR)];
2138 }
12e579db 2139 seq_printf(m, "syscall { index = %lu; name = %s; bitness = %u; };\n",
d4291869 2140 index, name, bitness);
2d2464bd
MD
2141 return 0;
2142}
2143
2144static
2145const struct seq_operations lttng_syscall_list_seq_ops = {
2146 .start = syscall_list_start,
2147 .next = syscall_list_next,
2148 .stop = syscall_list_stop,
2149 .show = syscall_list_show,
2150};
2151
2152static
2153int lttng_syscall_list_open(struct inode *inode, struct file *file)
2154{
2155 return seq_open(file, &lttng_syscall_list_seq_ops);
2156}
2157
2158const struct file_operations lttng_syscall_list_fops = {
2159 .owner = THIS_MODULE,
2160 .open = lttng_syscall_list_open,
2161 .read = seq_read,
2162 .llseek = seq_lseek,
2163 .release = seq_release,
2164};
12e579db 2165
badfe9f5
MD
2166/*
2167 * A syscall is enabled if it is traced for either entry or exit.
2168 */
12e579db
MD
2169long lttng_channel_syscall_mask(struct lttng_channel *channel,
2170 struct lttng_kernel_syscall_mask __user *usyscall_mask)
2171{
2172 uint32_t len, sc_tables_len, bitmask_len;
2173 int ret = 0, bit;
2174 char *tmp_mask;
2175 struct lttng_syscall_filter *filter;
2176
2177 ret = get_user(len, &usyscall_mask->len);
2178 if (ret)
2179 return ret;
2180 sc_tables_len = get_sc_tables_len();
2181 bitmask_len = ALIGN(sc_tables_len, 8) >> 3;
2182 if (len < sc_tables_len) {
2183 return put_user(sc_tables_len, &usyscall_mask->len);
2184 }
2185 /* Array is large enough, we can copy array to user-space. */
2186 tmp_mask = kzalloc(bitmask_len, GFP_KERNEL);
2187 if (!tmp_mask)
2188 return -ENOMEM;
2189 filter = channel->sc_filter;
2190
2191 for (bit = 0; bit < ARRAY_SIZE(sc_table); bit++) {
e2129868 2192 char state;
2f25059d
MD
2193
2194 if (channel->sc_table) {
3b82c4e1
MD
2195 if (!(READ_ONCE(channel->syscall_all_entry)
2196 || READ_ONCE(channel->syscall_all_exit)) && filter)
badfe9f5
MD
2197 state = test_bit(bit, filter->sc_entry)
2198 || test_bit(bit, filter->sc_exit);
2f25059d
MD
2199 else
2200 state = 1;
2201 } else {
2202 state = 0;
2203 }
2204 bt_bitfield_write_be(tmp_mask, char, bit, 1, state);
12e579db
MD
2205 }
2206 for (; bit < sc_tables_len; bit++) {
e2129868 2207 char state;
2f25059d
MD
2208
2209 if (channel->compat_sc_table) {
3b82c4e1
MD
2210 if (!(READ_ONCE(channel->syscall_all_entry)
2211 || READ_ONCE(channel->syscall_all_exit)) && filter)
2f25059d 2212 state = test_bit(bit - ARRAY_SIZE(sc_table),
badfe9f5
MD
2213 filter->sc_compat_entry)
2214 || test_bit(bit - ARRAY_SIZE(sc_table),
2215 filter->sc_compat_exit);
2f25059d
MD
2216 else
2217 state = 1;
2218 } else {
2219 state = 0;
2220 }
2221 bt_bitfield_write_be(tmp_mask, char, bit, 1, state);
12e579db
MD
2222 }
2223 if (copy_to_user(usyscall_mask->mask, tmp_mask, bitmask_len))
2224 ret = -EFAULT;
2225 kfree(tmp_mask);
2226 return ret;
2227}
082d4946
MD
2228
2229int lttng_abi_syscall_list(void)
2230{
2231 struct file *syscall_list_file;
2232 int file_fd, ret;
2233
4ac10b76 2234 file_fd = lttng_get_unused_fd();
082d4946
MD
2235 if (file_fd < 0) {
2236 ret = file_fd;
2237 goto fd_error;
2238 }
2239
2240 syscall_list_file = anon_inode_getfile("[lttng_syscall_list]",
2241 &lttng_syscall_list_fops,
2242 NULL, O_RDWR);
2243 if (IS_ERR(syscall_list_file)) {
2244 ret = PTR_ERR(syscall_list_file);
2245 goto file_error;
2246 }
2247 ret = lttng_syscall_list_fops.open(NULL, syscall_list_file);
2248 if (ret < 0)
2249 goto open_error;
2250 fd_install(file_fd, syscall_list_file);
082d4946
MD
2251 return file_fd;
2252
2253open_error:
2254 fput(syscall_list_file);
2255file_error:
2256 put_unused_fd(file_fd);
2257fd_error:
2258 return ret;
2259}
This page took 0.149775 seconds and 4 git commands to generate.