Implement event notifier error counter
[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
2d6d88c6 391static void syscall_entry_event_unknown(struct lttng_event *event,
8a8ac9a8 392 struct pt_regs *regs, long id)
f405cfce 393{
1b7b9c65 394 unsigned long args[LTTNG_SYSCALL_NR_ARGS];
f405cfce 395
1b7b9c65 396 lttng_syscall_get_arguments(current, regs, args);
1aa3298b 397 if (unlikely(in_compat_syscall()))
d4291869 398 __event_probe__compat_syscall_entry_unknown(event, id, args);
a93244f8 399 else
d4291869 400 __event_probe__syscall_entry_unknown(event, id, args);
f405cfce
MD
401}
402
8a8ac9a8
FD
403static void syscall_entry_event_notifier_unknown(
404 struct hlist_head *unknown_dispatch_list_head,
405 struct pt_regs *regs, long id)
406{
407 unsigned long args[LTTNG_SYSCALL_NR_ARGS];
408 struct lttng_event_notifier *notifier;
409
410 lttng_syscall_get_arguments(current, regs, args);
411 lttng_hlist_for_each_entry_rcu(notifier, unknown_dispatch_list_head, u.syscall.node) {
412 if (unlikely(in_compat_syscall()))
413 __event_notifier_probe__compat_syscall_entry_unknown(notifier, id, args);
414 else
415 __event_notifier_probe__syscall_entry_unknown(notifier, id, args);
416 }
417}
418
419static void syscall_exit_event_notifier_unknown(
420 struct hlist_head *unknown_dispatch_list_head,
421 struct pt_regs *regs, long id, long ret)
422{
423 unsigned long args[LTTNG_SYSCALL_NR_ARGS];
424 struct lttng_event_notifier *notifier;
425
426 lttng_syscall_get_arguments(current, regs, args);
427 lttng_hlist_for_each_entry_rcu(notifier, unknown_dispatch_list_head, u.syscall.node) {
428 if (unlikely(in_compat_syscall()))
429 __event_notifier_probe__compat_syscall_exit_unknown(notifier, id, ret, args);
430 else
431 __event_notifier_probe__syscall_exit_unknown(notifier, id, ret, args);
432 }
433}
434
63aa9160
FD
435static __always_inline
436void syscall_entry_call_func(void *func, unsigned int nrargs, void *data,
437 struct pt_regs *regs)
259b6cb3 438{
63aa9160 439 switch (nrargs) {
259b6cb3
MD
440 case 0:
441 {
63aa9160 442 void (*fptr)(void *__data) = func;
259b6cb3 443
63aa9160 444 fptr(data);
259b6cb3
MD
445 break;
446 }
447 case 1:
448 {
63aa9160 449 void (*fptr)(void *__data, unsigned long arg0) = func;
1b7b9c65 450 unsigned long args[LTTNG_SYSCALL_NR_ARGS];
259b6cb3 451
1b7b9c65 452 lttng_syscall_get_arguments(current, regs, args);
63aa9160 453 fptr(data, args[0]);
259b6cb3
MD
454 break;
455 }
456 case 2:
457 {
458 void (*fptr)(void *__data,
459 unsigned long arg0,
63aa9160 460 unsigned long arg1) = func;
1b7b9c65 461 unsigned long args[LTTNG_SYSCALL_NR_ARGS];
259b6cb3 462
1b7b9c65 463 lttng_syscall_get_arguments(current, regs, args);
63aa9160 464 fptr(data, args[0], args[1]);
259b6cb3
MD
465 break;
466 }
467 case 3:
468 {
469 void (*fptr)(void *__data,
470 unsigned long arg0,
471 unsigned long arg1,
63aa9160 472 unsigned long arg2) = func;
1b7b9c65 473 unsigned long args[LTTNG_SYSCALL_NR_ARGS];
259b6cb3 474
1b7b9c65 475 lttng_syscall_get_arguments(current, regs, args);
63aa9160 476 fptr(data, args[0], args[1], args[2]);
259b6cb3
MD
477 break;
478 }
479 case 4:
480 {
481 void (*fptr)(void *__data,
482 unsigned long arg0,
483 unsigned long arg1,
484 unsigned long arg2,
63aa9160 485 unsigned long arg3) = func;
1b7b9c65 486 unsigned long args[LTTNG_SYSCALL_NR_ARGS];
259b6cb3 487
1b7b9c65 488 lttng_syscall_get_arguments(current, regs, args);
63aa9160 489 fptr(data, args[0], args[1], args[2], args[3]);
259b6cb3
MD
490 break;
491 }
492 case 5:
493 {
494 void (*fptr)(void *__data,
495 unsigned long arg0,
496 unsigned long arg1,
497 unsigned long arg2,
498 unsigned long arg3,
63aa9160 499 unsigned long arg4) = func;
1b7b9c65 500 unsigned long args[LTTNG_SYSCALL_NR_ARGS];
259b6cb3 501
1b7b9c65 502 lttng_syscall_get_arguments(current, regs, args);
63aa9160 503 fptr(data, args[0], args[1], args[2], args[3], args[4]);
259b6cb3
MD
504 break;
505 }
506 case 6:
507 {
508 void (*fptr)(void *__data,
509 unsigned long arg0,
510 unsigned long arg1,
511 unsigned long arg2,
512 unsigned long arg3,
513 unsigned long arg4,
63aa9160 514 unsigned long arg5) = func;
1b7b9c65 515 unsigned long args[LTTNG_SYSCALL_NR_ARGS];
259b6cb3 516
1b7b9c65 517 lttng_syscall_get_arguments(current, regs, args);
63aa9160 518 fptr(data, args[0], args[1], args[2],
259b6cb3
MD
519 args[3], args[4], args[5]);
520 break;
521 }
522 default:
523 break;
524 }
525}
526
8a8ac9a8
FD
527static __always_inline
528void syscall_entry_event_notifier_call_func(struct hlist_head *dispatch_list,
529 void *func, unsigned int nrargs, struct pt_regs *regs)
530{
531 struct lttng_event_notifier *notifier;
532
533 switch (nrargs) {
534 case 0:
535 {
536 void (*fptr)(void *__data) = func;
537
538 lttng_hlist_for_each_entry_rcu(notifier, dispatch_list, u.syscall.node)
539 fptr(notifier);
540 break;
541 }
542 case 1:
543 {
544 void (*fptr)(void *__data, unsigned long arg0) = func;
545 unsigned long args[LTTNG_SYSCALL_NR_ARGS];
546
547 lttng_syscall_get_arguments(current, regs, args);
548 lttng_hlist_for_each_entry_rcu(notifier, dispatch_list, u.syscall.node)
549 fptr(notifier, args[0]);
550 break;
551 }
552 case 2:
553 {
554 void (*fptr)(void *__data,
555 unsigned long arg0,
556 unsigned long arg1) = func;
557 unsigned long args[LTTNG_SYSCALL_NR_ARGS];
558
559 lttng_syscall_get_arguments(current, regs, args);
560 lttng_hlist_for_each_entry_rcu(notifier, dispatch_list, u.syscall.node)
561 fptr(notifier, args[0], args[1]);
562 break;
563 }
564 case 3:
565 {
566 void (*fptr)(void *__data,
567 unsigned long arg0,
568 unsigned long arg1,
569 unsigned long arg2) = 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], args[2]);
575 break;
576 }
577 case 4:
578 {
579 void (*fptr)(void *__data,
580 unsigned long arg0,
581 unsigned long arg1,
582 unsigned long arg2,
583 unsigned long arg3) = func;
584 unsigned long args[LTTNG_SYSCALL_NR_ARGS];
585
586 lttng_syscall_get_arguments(current, regs, args);
587 lttng_hlist_for_each_entry_rcu(notifier, dispatch_list, u.syscall.node)
588 fptr(notifier, args[0], args[1], args[2], args[3]);
589 break;
590 }
591 case 5:
592 {
593 void (*fptr)(void *__data,
594 unsigned long arg0,
595 unsigned long arg1,
596 unsigned long arg2,
597 unsigned long arg3,
598 unsigned long arg4) = func;
599 unsigned long args[LTTNG_SYSCALL_NR_ARGS];
600
601 lttng_syscall_get_arguments(current, regs, args);
602 lttng_hlist_for_each_entry_rcu(notifier, dispatch_list, u.syscall.node)
603 fptr(notifier, args[0], args[1], args[2], args[3], args[4]);
604 break;
605 }
606 case 6:
607 {
608 void (*fptr)(void *__data,
609 unsigned long arg0,
610 unsigned long arg1,
611 unsigned long arg2,
612 unsigned long arg3,
613 unsigned long arg4,
614 unsigned long arg5) = func;
615 unsigned long args[LTTNG_SYSCALL_NR_ARGS];
616
617 lttng_syscall_get_arguments(current, regs, args);
618 lttng_hlist_for_each_entry_rcu(notifier, dispatch_list, u.syscall.node)
619 fptr(notifier, args[0], args[1], args[2], args[3], args[4], args[5]);
620 break;
621 }
622 default:
623 break;
624 }
625}
626
63aa9160
FD
627void syscall_entry_event_probe(void *__data, struct pt_regs *regs, long id)
628{
629 struct lttng_channel *chan = __data;
630 struct lttng_event *event, *unknown_event;
631 const struct trace_syscall_entry *table, *entry;
632 size_t table_len;
633
634 if (unlikely(in_compat_syscall())) {
635 struct lttng_syscall_filter *filter = chan->sc_filter;
636
637 if (id < 0 || id >= NR_compat_syscalls
638 || (!READ_ONCE(chan->syscall_all) && !test_bit(id, filter->sc_compat_entry))) {
639 /* System call filtered out. */
640 return;
641 }
642 table = compat_sc_table;
643 table_len = ARRAY_SIZE(compat_sc_table);
644 unknown_event = chan->sc_compat_unknown;
645 } else {
646 struct lttng_syscall_filter *filter = chan->sc_filter;
647
648 if (id < 0 || id >= NR_syscalls
649 || (!READ_ONCE(chan->syscall_all) && !test_bit(id, filter->sc_entry))) {
650 /* System call filtered out. */
651 return;
652 }
653 table = sc_table;
654 table_len = ARRAY_SIZE(sc_table);
655 unknown_event = chan->sc_unknown;
656 }
657 if (unlikely(id < 0 || id >= table_len)) {
658 syscall_entry_event_unknown(unknown_event, regs, id);
659 return;
660 }
661 if (unlikely(in_compat_syscall()))
662 event = chan->compat_sc_table[id];
663 else
664 event = chan->sc_table[id];
665 if (unlikely(!event)) {
666 syscall_entry_event_unknown(unknown_event, regs, id);
667 return;
668 }
669 entry = &table[id];
d053f3ee 670 WARN_ON_ONCE(!entry->event_func);
63aa9160
FD
671 syscall_entry_call_func(entry->event_func, entry->nrargs, event, regs);
672}
673
8a8ac9a8
FD
674void syscall_entry_event_notifier_probe(void *__data, struct pt_regs *regs,
675 long id)
676{
677 struct lttng_event_notifier_group *group = __data;
678 const struct trace_syscall_entry *table, *entry;
679 struct hlist_head *dispatch_list, *unknown_dispatch_list;
680 size_t table_len;
681
682 if (unlikely(in_compat_syscall())) {
683 struct lttng_syscall_filter *filter = group->sc_filter;
684
685 if (id < 0 || id >= NR_compat_syscalls
686 || (!READ_ONCE(group->syscall_all_entry) &&
687 !test_bit(id, filter->sc_compat_entry))) {
688 /* System call filtered out. */
689 return;
690 }
691 table = compat_sc_table;
692 table_len = ARRAY_SIZE(compat_sc_table);
693 unknown_dispatch_list = &group->event_notifier_compat_unknown_syscall_dispatch;
694 } else {
695 struct lttng_syscall_filter *filter = group->sc_filter;
696
697 if (id < 0 || id >= NR_syscalls
698 || (!READ_ONCE(group->syscall_all_entry) &&
699 !test_bit(id, filter->sc_entry))) {
700 /* System call filtered out. */
701 return;
702 }
703 table = sc_table;
704 table_len = ARRAY_SIZE(sc_table);
705 unknown_dispatch_list = &group->event_notifier_unknown_syscall_dispatch;
706 }
707 /* Check if the syscall id is out of bound. */
708 if (unlikely(id < 0 || id >= table_len)) {
709 syscall_entry_event_notifier_unknown(unknown_dispatch_list,
710 regs, id);
711 return;
712 }
713
714 entry = &table[id];
715 if (!entry->event_notifier_func) {
716 syscall_entry_event_notifier_unknown(unknown_dispatch_list,
717 regs, id);
718 return;
719 }
720
721 if (unlikely(in_compat_syscall())) {
722 dispatch_list = &group->event_notifier_compat_syscall_dispatch[id];
723 } else {
724 dispatch_list = &group->event_notifier_syscall_dispatch[id];
725 }
726 if (unlikely(hlist_empty(dispatch_list)))
727 return;
728
729 syscall_entry_event_notifier_call_func(dispatch_list,
730 entry->event_notifier_func, entry->nrargs, regs);
731}
732
2d6d88c6 733static void syscall_exit_event_unknown(struct lttng_event *event,
8a8ac9a8 734 struct pt_regs *regs, long id, long ret)
5b7ac358 735{
1b7b9c65 736 unsigned long args[LTTNG_SYSCALL_NR_ARGS];
5b7ac358 737
1b7b9c65 738 lttng_syscall_get_arguments(current, regs, args);
1aa3298b 739 if (unlikely(in_compat_syscall()))
5b7ac358
MD
740 __event_probe__compat_syscall_exit_unknown(event, id, ret,
741 args);
742 else
743 __event_probe__syscall_exit_unknown(event, id, ret, args);
744}
745
2d6d88c6 746void syscall_exit_event_probe(void *__data, struct pt_regs *regs, long ret)
5b7ac358
MD
747{
748 struct lttng_channel *chan = __data;
749 struct lttng_event *event, *unknown_event;
750 const struct trace_syscall_entry *table, *entry;
751 size_t table_len;
752 long id;
753
754 id = syscall_get_nr(current, regs);
1aa3298b 755 if (unlikely(in_compat_syscall())) {
badfe9f5
MD
756 struct lttng_syscall_filter *filter = chan->sc_filter;
757
758 if (id < 0 || id >= NR_compat_syscalls
759 || (!READ_ONCE(chan->syscall_all) && !test_bit(id, filter->sc_compat_exit))) {
760 /* System call filtered out. */
761 return;
5b7ac358
MD
762 }
763 table = compat_sc_exit_table;
764 table_len = ARRAY_SIZE(compat_sc_exit_table);
765 unknown_event = chan->compat_sc_exit_unknown;
766 } else {
badfe9f5
MD
767 struct lttng_syscall_filter *filter = chan->sc_filter;
768
769 if (id < 0 || id >= NR_syscalls
770 || (!READ_ONCE(chan->syscall_all) && !test_bit(id, filter->sc_exit))) {
771 /* System call filtered out. */
772 return;
5b7ac358
MD
773 }
774 table = sc_exit_table;
775 table_len = ARRAY_SIZE(sc_exit_table);
776 unknown_event = chan->sc_exit_unknown;
777 }
74f7b56a 778 if (unlikely(id < 0 || id >= table_len)) {
2d6d88c6 779 syscall_exit_event_unknown(unknown_event, regs, id, ret);
5b7ac358
MD
780 return;
781 }
1aa3298b 782 if (unlikely(in_compat_syscall()))
5b7ac358
MD
783 event = chan->compat_sc_exit_table[id];
784 else
785 event = chan->sc_exit_table[id];
786 if (unlikely(!event)) {
2d6d88c6 787 syscall_exit_event_unknown(unknown_event, regs, id, ret);
5b7ac358
MD
788 return;
789 }
790 entry = &table[id];
d053f3ee 791 WARN_ON_ONCE(!entry->event_func);
5b7ac358
MD
792
793 switch (entry->nrargs) {
794 case 0:
795 {
2d6d88c6 796 void (*fptr)(void *__data, long ret) = entry->event_func;
5b7ac358 797
fc4f7161 798 fptr(event, ret);
5b7ac358
MD
799 break;
800 }
801 case 1:
802 {
803 void (*fptr)(void *__data,
fc4f7161 804 long ret,
2d6d88c6 805 unsigned long arg0) = entry->event_func;
1b7b9c65 806 unsigned long args[LTTNG_SYSCALL_NR_ARGS];
5b7ac358 807
1b7b9c65 808 lttng_syscall_get_arguments(current, regs, args);
fc4f7161 809 fptr(event, ret, args[0]);
5b7ac358
MD
810 break;
811 }
812 case 2:
813 {
814 void (*fptr)(void *__data,
fc4f7161 815 long ret,
5b7ac358 816 unsigned long arg0,
2d6d88c6 817 unsigned long arg1) = entry->event_func;
1b7b9c65 818 unsigned long args[LTTNG_SYSCALL_NR_ARGS];
5b7ac358 819
1b7b9c65 820 lttng_syscall_get_arguments(current, regs, args);
fc4f7161 821 fptr(event, ret, args[0], args[1]);
5b7ac358
MD
822 break;
823 }
824 case 3:
825 {
826 void (*fptr)(void *__data,
fc4f7161 827 long ret,
5b7ac358
MD
828 unsigned long arg0,
829 unsigned long arg1,
2d6d88c6 830 unsigned long arg2) = entry->event_func;
1b7b9c65 831 unsigned long args[LTTNG_SYSCALL_NR_ARGS];
5b7ac358 832
1b7b9c65 833 lttng_syscall_get_arguments(current, regs, args);
fc4f7161 834 fptr(event, ret, args[0], args[1], args[2]);
5b7ac358
MD
835 break;
836 }
837 case 4:
838 {
839 void (*fptr)(void *__data,
fc4f7161 840 long ret,
5b7ac358
MD
841 unsigned long arg0,
842 unsigned long arg1,
843 unsigned long arg2,
2d6d88c6 844 unsigned long arg3) = entry->event_func;
1b7b9c65 845 unsigned long args[LTTNG_SYSCALL_NR_ARGS];
5b7ac358 846
1b7b9c65 847 lttng_syscall_get_arguments(current, regs, args);
fc4f7161 848 fptr(event, ret, args[0], args[1], args[2], args[3]);
5b7ac358
MD
849 break;
850 }
851 case 5:
852 {
853 void (*fptr)(void *__data,
fc4f7161 854 long ret,
5b7ac358
MD
855 unsigned long arg0,
856 unsigned long arg1,
857 unsigned long arg2,
858 unsigned long arg3,
2d6d88c6 859 unsigned long arg4) = entry->event_func;
1b7b9c65 860 unsigned long args[LTTNG_SYSCALL_NR_ARGS];
5b7ac358 861
1b7b9c65 862 lttng_syscall_get_arguments(current, regs, args);
fc4f7161 863 fptr(event, ret, args[0], args[1], args[2], args[3], args[4]);
5b7ac358
MD
864 break;
865 }
866 case 6:
867 {
868 void (*fptr)(void *__data,
fc4f7161 869 long ret,
5b7ac358
MD
870 unsigned long arg0,
871 unsigned long arg1,
872 unsigned long arg2,
873 unsigned long arg3,
874 unsigned long arg4,
2d6d88c6 875 unsigned long arg5) = entry->event_func;
1b7b9c65 876 unsigned long args[LTTNG_SYSCALL_NR_ARGS];
5b7ac358 877
1b7b9c65 878 lttng_syscall_get_arguments(current, regs, args);
fc4f7161 879 fptr(event, ret, args[0], args[1], args[2],
5b7ac358
MD
880 args[3], args[4], args[5]);
881 break;
882 }
883 default:
884 break;
885 }
886}
887
8a8ac9a8
FD
888static __always_inline
889void syscall_exit_event_notifier_call_func(struct hlist_head *dispatch_list,
890 void *func, unsigned int nrargs, struct pt_regs *regs, long ret)
891{
892 struct lttng_event_notifier *notifier;
893
894 switch (nrargs) {
895 case 0:
896 {
897 void (*fptr)(void *__data, long ret) = func;
898
899 lttng_hlist_for_each_entry_rcu(notifier, dispatch_list, u.syscall.node)
900 fptr(notifier, ret);
901 break;
902 }
903 case 1:
904 {
905 void (*fptr)(void *__data, long ret, unsigned long arg0) = func;
906 unsigned long args[LTTNG_SYSCALL_NR_ARGS];
907
908 lttng_syscall_get_arguments(current, regs, args);
909 lttng_hlist_for_each_entry_rcu(notifier, dispatch_list, u.syscall.node)
910 fptr(notifier, ret, args[0]);
911 break;
912 }
913 case 2:
914 {
915 void (*fptr)(void *__data,
916 long ret,
917 unsigned long arg0,
918 unsigned long arg1) = func;
919 unsigned long args[LTTNG_SYSCALL_NR_ARGS];
920
921 lttng_syscall_get_arguments(current, regs, args);
922 lttng_hlist_for_each_entry_rcu(notifier, dispatch_list, u.syscall.node)
923 fptr(notifier, ret, args[0], args[1]);
924 break;
925 }
926 case 3:
927 {
928 void (*fptr)(void *__data,
929 long ret,
930 unsigned long arg0,
931 unsigned long arg1,
932 unsigned long arg2) = func;
933 unsigned long args[LTTNG_SYSCALL_NR_ARGS];
934
935 lttng_syscall_get_arguments(current, regs, args);
936 lttng_hlist_for_each_entry_rcu(notifier, dispatch_list, u.syscall.node)
937 fptr(notifier, ret, args[0], args[1], args[2]);
938 break;
939 }
940 case 4:
941 {
942 void (*fptr)(void *__data,
943 long ret,
944 unsigned long arg0,
945 unsigned long arg1,
946 unsigned long arg2,
947 unsigned long arg3) = func;
948 unsigned long args[LTTNG_SYSCALL_NR_ARGS];
949
950 lttng_syscall_get_arguments(current, regs, args);
951 lttng_hlist_for_each_entry_rcu(notifier, dispatch_list, u.syscall.node)
952 fptr(notifier, ret, args[0], args[1], args[2], args[3]);
953 break;
954 }
955 case 5:
956 {
957 void (*fptr)(void *__data,
958 long ret,
959 unsigned long arg0,
960 unsigned long arg1,
961 unsigned long arg2,
962 unsigned long arg3,
963 unsigned long arg4) = func;
964 unsigned long args[LTTNG_SYSCALL_NR_ARGS];
965
966 lttng_syscall_get_arguments(current, regs, args);
967 lttng_hlist_for_each_entry_rcu(notifier, dispatch_list, u.syscall.node)
968 fptr(notifier, ret, args[0], args[1], args[2], args[3], args[4]);
969 break;
970 }
971 case 6:
972 {
973 void (*fptr)(void *__data,
974 long ret,
975 unsigned long arg0,
976 unsigned long arg1,
977 unsigned long arg2,
978 unsigned long arg3,
979 unsigned long arg4,
980 unsigned long arg5) = func;
981 unsigned long args[LTTNG_SYSCALL_NR_ARGS];
982
983 lttng_syscall_get_arguments(current, regs, args);
984 lttng_hlist_for_each_entry_rcu(notifier, dispatch_list, u.syscall.node)
985 fptr(notifier, ret, args[0], args[1], args[2], args[3], args[4], args[5]);
986 break;
987 }
988 default:
989 break;
990 }
991}
992
993static
994void syscall_exit_event_notifier_probe(void *__data, struct pt_regs *regs,
995 long ret)
996{
997 struct lttng_event_notifier_group *group = __data;
998 const struct trace_syscall_entry *table, *entry;
999 struct hlist_head *dispatch_list, *unknown_dispatch_list;
1000 size_t table_len;
1001 long id;
1002
1003 id = syscall_get_nr(current, regs);
1004
1005 if (unlikely(in_compat_syscall())) {
1006 struct lttng_syscall_filter *filter = group->sc_filter;
1007
1008 if (id < 0 || id >= NR_compat_syscalls
1009 || (!READ_ONCE(group->syscall_all_exit) &&
1010 !test_bit(id, filter->sc_compat_exit))) {
1011 /* System call filtered out. */
1012 return;
1013 }
1014 table = compat_sc_exit_table;
1015 table_len = ARRAY_SIZE(compat_sc_exit_table);
1016 unknown_dispatch_list = &group->event_notifier_exit_compat_unknown_syscall_dispatch;
1017 } else {
1018 struct lttng_syscall_filter *filter = group->sc_filter;
1019
1020 if (id < 0 || id >= NR_syscalls
1021 || (!READ_ONCE(group->syscall_all_exit) &&
1022 !test_bit(id, filter->sc_exit))) {
1023 /* System call filtered out. */
1024 return;
1025 }
1026 table = sc_exit_table;
1027 table_len = ARRAY_SIZE(sc_exit_table);
1028 unknown_dispatch_list = &group->event_notifier_exit_unknown_syscall_dispatch;
1029 }
1030 /* Check if the syscall id is out of bound. */
1031 if (unlikely(id < 0 || id >= table_len)) {
1032 syscall_exit_event_notifier_unknown(unknown_dispatch_list,
1033 regs, id, ret);
1034 return;
1035 }
1036
1037 entry = &table[id];
1038 if (!entry->event_notifier_func) {
1039 syscall_entry_event_notifier_unknown(unknown_dispatch_list,
1040 regs, id);
1041 return;
1042 }
1043
1044 if (unlikely(in_compat_syscall())) {
1045 dispatch_list = &group->event_notifier_exit_compat_syscall_dispatch[id];
1046 } else {
1047 dispatch_list = &group->event_notifier_exit_syscall_dispatch[id];
1048 }
1049 if (unlikely(hlist_empty(dispatch_list)))
1050 return;
1051
1052 syscall_exit_event_notifier_call_func(dispatch_list,
1053 entry->event_notifier_func, entry->nrargs, regs, ret);
1054}
33a39a3c
MD
1055/*
1056 * noinline to diminish caller stack size.
1057 * Should be called with sessions lock held.
1058 */
49c50022 1059static
2d6d88c6 1060int fill_event_table(const struct trace_syscall_entry *table, size_t table_len,
5b7ac358
MD
1061 struct lttng_event **chan_table, struct lttng_channel *chan,
1062 void *filter, enum sc_type type)
259b6cb3 1063{
2a0c4816 1064 const struct lttng_event_desc *desc;
259b6cb3 1065 unsigned int i;
49c50022
MD
1066
1067 /* Allocate events for each syscall, insert into table */
1068 for (i = 0; i < table_len; i++) {
1069 struct lttng_kernel_event ev;
2a0c4816 1070 desc = table[i].desc;
49c50022
MD
1071
1072 if (!desc) {
1073 /* Unknown syscall */
1074 continue;
1075 }
1076 /*
1077 * Skip those already populated by previous failed
1078 * register for this channel.
1079 */
1080 if (chan_table[i])
1081 continue;
1082 memset(&ev, 0, sizeof(ev));
5b7ac358
MD
1083 switch (type) {
1084 case SC_TYPE_ENTRY:
badfe9f5
MD
1085 ev.u.syscall.entryexit = LTTNG_KERNEL_SYSCALL_ENTRY;
1086 ev.u.syscall.abi = LTTNG_KERNEL_SYSCALL_ABI_NATIVE;
5b7ac358
MD
1087 break;
1088 case SC_TYPE_EXIT:
badfe9f5
MD
1089 ev.u.syscall.entryexit = LTTNG_KERNEL_SYSCALL_EXIT;
1090 ev.u.syscall.abi = LTTNG_KERNEL_SYSCALL_ABI_NATIVE;
5b7ac358
MD
1091 break;
1092 case SC_TYPE_COMPAT_ENTRY:
badfe9f5
MD
1093 ev.u.syscall.entryexit = LTTNG_KERNEL_SYSCALL_ENTRY;
1094 ev.u.syscall.abi = LTTNG_KERNEL_SYSCALL_ABI_COMPAT;
5b7ac358
MD
1095 break;
1096 case SC_TYPE_COMPAT_EXIT:
badfe9f5
MD
1097 ev.u.syscall.entryexit = LTTNG_KERNEL_SYSCALL_EXIT;
1098 ev.u.syscall.abi = LTTNG_KERNEL_SYSCALL_ABI_COMPAT;
5b7ac358
MD
1099 break;
1100 }
092ffe97 1101 strncpy(ev.name, desc->name, LTTNG_KERNEL_SYM_NAME_LEN - 1);
f8695253 1102 ev.name[LTTNG_KERNEL_SYM_NAME_LEN - 1] = '\0';
33a39a3c
MD
1103 ev.instrumentation = LTTNG_KERNEL_SYSCALL;
1104 chan_table[i] = _lttng_event_create(chan, &ev, filter,
3c997079 1105 desc, ev.instrumentation);
abc0446a
MD
1106 WARN_ON_ONCE(!chan_table[i]);
1107 if (IS_ERR(chan_table[i])) {
49c50022
MD
1108 /*
1109 * If something goes wrong in event registration
1110 * after the first one, we have no choice but to
1111 * leave the previous events in there, until
1112 * deleted by session teardown.
1113 */
abc0446a 1114 return PTR_ERR(chan_table[i]);
49c50022
MD
1115 }
1116 }
1117 return 0;
1118}
1119
33a39a3c
MD
1120/*
1121 * Should be called with sessions lock held.
1122 */
2d6d88c6 1123int lttng_syscalls_register_event(struct lttng_channel *chan, void *filter)
49c50022 1124{
2a0c4816 1125 struct lttng_kernel_event ev;
259b6cb3
MD
1126 int ret;
1127
263b6c88 1128 wrapper_vmalloc_sync_mappings();
259b6cb3
MD
1129
1130 if (!chan->sc_table) {
1131 /* create syscall table mapping syscall to events */
a90917c3 1132 chan->sc_table = kzalloc(sizeof(struct lttng_event *)
259b6cb3
MD
1133 * ARRAY_SIZE(sc_table), GFP_KERNEL);
1134 if (!chan->sc_table)
1135 return -ENOMEM;
1136 }
5b7ac358
MD
1137 if (!chan->sc_exit_table) {
1138 /* create syscall table mapping syscall to events */
1139 chan->sc_exit_table = kzalloc(sizeof(struct lttng_event *)
1140 * ARRAY_SIZE(sc_exit_table), GFP_KERNEL);
1141 if (!chan->sc_exit_table)
1142 return -ENOMEM;
1143 }
1144
259b6cb3 1145
49c50022
MD
1146#ifdef CONFIG_COMPAT
1147 if (!chan->compat_sc_table) {
1148 /* create syscall table mapping compat syscall to events */
a90917c3 1149 chan->compat_sc_table = kzalloc(sizeof(struct lttng_event *)
a93244f8 1150 * ARRAY_SIZE(compat_sc_table), GFP_KERNEL);
49c50022
MD
1151 if (!chan->compat_sc_table)
1152 return -ENOMEM;
1153 }
5b7ac358
MD
1154
1155 if (!chan->compat_sc_exit_table) {
1156 /* create syscall table mapping compat syscall to events */
1157 chan->compat_sc_exit_table = kzalloc(sizeof(struct lttng_event *)
1158 * ARRAY_SIZE(compat_sc_exit_table), GFP_KERNEL);
1159 if (!chan->compat_sc_exit_table)
1160 return -ENOMEM;
1161 }
49c50022 1162#endif
f405cfce 1163 if (!chan->sc_unknown) {
f405cfce 1164 const struct lttng_event_desc *desc =
d4291869 1165 &__event_desc___syscall_entry_unknown;
2f804c0a 1166
f405cfce 1167 memset(&ev, 0, sizeof(ev));
f8695253
MD
1168 strncpy(ev.name, desc->name, LTTNG_KERNEL_SYM_NAME_LEN);
1169 ev.name[LTTNG_KERNEL_SYM_NAME_LEN - 1] = '\0';
33a39a3c 1170 ev.instrumentation = LTTNG_KERNEL_SYSCALL;
badfe9f5
MD
1171 ev.u.syscall.entryexit = LTTNG_KERNEL_SYSCALL_ENTRY;
1172 ev.u.syscall.abi = LTTNG_KERNEL_SYSCALL_ABI_NATIVE;
33a39a3c 1173 chan->sc_unknown = _lttng_event_create(chan, &ev, filter,
3c997079
MD
1174 desc,
1175 ev.instrumentation);
abc0446a
MD
1176 WARN_ON_ONCE(!chan->sc_unknown);
1177 if (IS_ERR(chan->sc_unknown)) {
1178 return PTR_ERR(chan->sc_unknown);
f405cfce
MD
1179 }
1180 }
1181
b76dc1a0 1182 if (!chan->sc_compat_unknown) {
b76dc1a0 1183 const struct lttng_event_desc *desc =
d4291869 1184 &__event_desc___compat_syscall_entry_unknown;
b76dc1a0
MD
1185
1186 memset(&ev, 0, sizeof(ev));
f8695253
MD
1187 strncpy(ev.name, desc->name, LTTNG_KERNEL_SYM_NAME_LEN);
1188 ev.name[LTTNG_KERNEL_SYM_NAME_LEN - 1] = '\0';
33a39a3c 1189 ev.instrumentation = LTTNG_KERNEL_SYSCALL;
badfe9f5
MD
1190 ev.u.syscall.entryexit = LTTNG_KERNEL_SYSCALL_ENTRY;
1191 ev.u.syscall.abi = LTTNG_KERNEL_SYSCALL_ABI_COMPAT;
33a39a3c 1192 chan->sc_compat_unknown = _lttng_event_create(chan, &ev, filter,
3c997079
MD
1193 desc,
1194 ev.instrumentation);
abc0446a
MD
1195 WARN_ON_ONCE(!chan->sc_unknown);
1196 if (IS_ERR(chan->sc_compat_unknown)) {
1197 return PTR_ERR(chan->sc_compat_unknown);
b76dc1a0
MD
1198 }
1199 }
1200
5b7ac358 1201 if (!chan->compat_sc_exit_unknown) {
2f804c0a 1202 const struct lttng_event_desc *desc =
5b7ac358 1203 &__event_desc___compat_syscall_exit_unknown;
2f804c0a
MD
1204
1205 memset(&ev, 0, sizeof(ev));
f8695253
MD
1206 strncpy(ev.name, desc->name, LTTNG_KERNEL_SYM_NAME_LEN);
1207 ev.name[LTTNG_KERNEL_SYM_NAME_LEN - 1] = '\0';
33a39a3c 1208 ev.instrumentation = LTTNG_KERNEL_SYSCALL;
badfe9f5
MD
1209 ev.u.syscall.entryexit = LTTNG_KERNEL_SYSCALL_EXIT;
1210 ev.u.syscall.abi = LTTNG_KERNEL_SYSCALL_ABI_COMPAT;
33a39a3c 1211 chan->compat_sc_exit_unknown = _lttng_event_create(chan, &ev,
3c997079
MD
1212 filter, desc,
1213 ev.instrumentation);
5b7ac358
MD
1214 WARN_ON_ONCE(!chan->compat_sc_exit_unknown);
1215 if (IS_ERR(chan->compat_sc_exit_unknown)) {
1216 return PTR_ERR(chan->compat_sc_exit_unknown);
1217 }
1218 }
1219
1220 if (!chan->sc_exit_unknown) {
1221 const struct lttng_event_desc *desc =
1222 &__event_desc___syscall_exit_unknown;
1223
1224 memset(&ev, 0, sizeof(ev));
1225 strncpy(ev.name, desc->name, LTTNG_KERNEL_SYM_NAME_LEN);
1226 ev.name[LTTNG_KERNEL_SYM_NAME_LEN - 1] = '\0';
33a39a3c 1227 ev.instrumentation = LTTNG_KERNEL_SYSCALL;
badfe9f5
MD
1228 ev.u.syscall.entryexit = LTTNG_KERNEL_SYSCALL_EXIT;
1229 ev.u.syscall.abi = LTTNG_KERNEL_SYSCALL_ABI_NATIVE;
33a39a3c 1230 chan->sc_exit_unknown = _lttng_event_create(chan, &ev, filter,
3c997079 1231 desc, ev.instrumentation);
5b7ac358
MD
1232 WARN_ON_ONCE(!chan->sc_exit_unknown);
1233 if (IS_ERR(chan->sc_exit_unknown)) {
1234 return PTR_ERR(chan->sc_exit_unknown);
2f804c0a
MD
1235 }
1236 }
1237
2d6d88c6 1238 ret = fill_event_table(sc_table, ARRAY_SIZE(sc_table),
5b7ac358
MD
1239 chan->sc_table, chan, filter, SC_TYPE_ENTRY);
1240 if (ret)
1241 return ret;
2d6d88c6 1242 ret = fill_event_table(sc_exit_table, ARRAY_SIZE(sc_exit_table),
5b7ac358 1243 chan->sc_exit_table, chan, filter, SC_TYPE_EXIT);
49c50022
MD
1244 if (ret)
1245 return ret;
5b7ac358 1246
49c50022 1247#ifdef CONFIG_COMPAT
2d6d88c6 1248 ret = fill_event_table(compat_sc_table, ARRAY_SIZE(compat_sc_table),
5b7ac358
MD
1249 chan->compat_sc_table, chan, filter,
1250 SC_TYPE_COMPAT_ENTRY);
1251 if (ret)
1252 return ret;
2d6d88c6 1253 ret = fill_event_table(compat_sc_exit_table, ARRAY_SIZE(compat_sc_exit_table),
5b7ac358
MD
1254 chan->compat_sc_exit_table, chan, filter,
1255 SC_TYPE_COMPAT_EXIT);
49c50022
MD
1256 if (ret)
1257 return ret;
1258#endif
badfe9f5
MD
1259
1260 if (!chan->sc_filter) {
1261 chan->sc_filter = kzalloc(sizeof(struct lttng_syscall_filter),
1262 GFP_KERNEL);
1263 if (!chan->sc_filter)
1264 return -ENOMEM;
1265 }
1266
80f87dd2
MD
1267 if (!chan->sys_enter_registered) {
1268 ret = lttng_wrapper_tracepoint_probe_register("sys_enter",
2d6d88c6 1269 (void *) syscall_entry_event_probe, chan);
80f87dd2
MD
1270 if (ret)
1271 return ret;
1272 chan->sys_enter_registered = 1;
1273 }
63728b02
MD
1274 /*
1275 * We change the name of sys_exit tracepoint due to namespace
1276 * conflict with sys_exit syscall entry.
1277 */
80f87dd2
MD
1278 if (!chan->sys_exit_registered) {
1279 ret = lttng_wrapper_tracepoint_probe_register("sys_exit",
2d6d88c6 1280 (void *) syscall_exit_event_probe, chan);
80f87dd2
MD
1281 if (ret) {
1282 WARN_ON_ONCE(lttng_wrapper_tracepoint_probe_unregister("sys_enter",
2d6d88c6 1283 (void *) syscall_entry_event_probe, chan));
80f87dd2
MD
1284 return ret;
1285 }
1286 chan->sys_exit_registered = 1;
63728b02 1287 }
259b6cb3
MD
1288 return ret;
1289}
1290
1291/*
8a8ac9a8
FD
1292 * Should be called with sessions lock held.
1293 */
1294int lttng_syscalls_register_event_notifier(
1295 struct lttng_event_notifier_enabler *event_notifier_enabler,
1296 void *filter)
1297{
1298 struct lttng_event_notifier_group *group = event_notifier_enabler->group;
1299 unsigned int i;
1300 int ret = 0;
1301
1302 wrapper_vmalloc_sync_mappings();
1303
1304 if (!group->event_notifier_syscall_dispatch) {
1305 group->event_notifier_syscall_dispatch =
1306 kzalloc(sizeof(struct hlist_head) * ARRAY_SIZE(sc_table),
1307 GFP_KERNEL);
1308 if (!group->event_notifier_syscall_dispatch)
1309 return -ENOMEM;
1310
1311 /* Initialize all list_head */
1312 for (i = 0; i < ARRAY_SIZE(sc_table); i++)
1313 INIT_HLIST_HEAD(&group->event_notifier_syscall_dispatch[i]);
1314
1315 /* Init the unknown syscall notifier list. */
1316 INIT_HLIST_HEAD(&group->event_notifier_unknown_syscall_dispatch);
1317 }
1318
1319 if (!group->event_notifier_exit_syscall_dispatch) {
1320 group->event_notifier_exit_syscall_dispatch =
1321 kzalloc(sizeof(struct hlist_head) * ARRAY_SIZE(sc_table),
1322 GFP_KERNEL);
1323 if (!group->event_notifier_exit_syscall_dispatch)
1324 return -ENOMEM;
1325
1326 /* Initialize all list_head */
1327 for (i = 0; i < ARRAY_SIZE(sc_table); i++)
1328 INIT_HLIST_HEAD(&group->event_notifier_exit_syscall_dispatch[i]);
1329
1330 /* Init the unknown exit syscall notifier list. */
1331 INIT_HLIST_HEAD(&group->event_notifier_exit_unknown_syscall_dispatch);
1332 }
1333
1334#ifdef CONFIG_COMPAT
1335 if (!group->event_notifier_compat_syscall_dispatch) {
1336 group->event_notifier_compat_syscall_dispatch =
1337 kzalloc(sizeof(struct hlist_head) * ARRAY_SIZE(compat_sc_table),
1338 GFP_KERNEL);
1339 if (!group->event_notifier_syscall_dispatch)
1340 return -ENOMEM;
1341
1342 /* Initialize all list_head */
1343 for (i = 0; i < ARRAY_SIZE(compat_sc_table); i++)
1344 INIT_HLIST_HEAD(&group->event_notifier_compat_syscall_dispatch[i]);
1345
1346 /* Init the unknown syscall notifier list. */
1347 INIT_HLIST_HEAD(&group->event_notifier_compat_unknown_syscall_dispatch);
1348 }
1349
1350 if (!group->event_notifier_exit_compat_syscall_dispatch) {
1351 group->event_notifier_exit_compat_syscall_dispatch =
1352 kzalloc(sizeof(struct hlist_head) * ARRAY_SIZE(compat_sc_exit_table),
1353 GFP_KERNEL);
1354 if (!group->event_notifier_exit_syscall_dispatch)
1355 return -ENOMEM;
1356
1357 /* Initialize all list_head */
1358 for (i = 0; i < ARRAY_SIZE(compat_sc_exit_table); i++)
1359 INIT_HLIST_HEAD(&group->event_notifier_exit_compat_syscall_dispatch[i]);
1360
1361 /* Init the unknown exit syscall notifier list. */
1362 INIT_HLIST_HEAD(&group->event_notifier_exit_compat_unknown_syscall_dispatch);
1363 }
1364#endif
1365
1366 if (!group->sc_filter) {
1367 group->sc_filter = kzalloc(sizeof(struct lttng_syscall_filter),
1368 GFP_KERNEL);
1369 if (!group->sc_filter)
1370 return -ENOMEM;
1371 }
1372
1373 if (!group->sys_enter_registered) {
1374 ret = lttng_wrapper_tracepoint_probe_register("sys_enter",
1375 (void *) syscall_entry_event_notifier_probe, group);
1376 if (ret)
1377 return ret;
1378 group->sys_enter_registered = 1;
1379 }
1380
1381 if (!group->sys_exit_registered) {
1382 ret = lttng_wrapper_tracepoint_probe_register("sys_exit",
1383 (void *) syscall_exit_event_notifier_probe, group);
1384 if (ret) {
1385 WARN_ON_ONCE(lttng_wrapper_tracepoint_probe_unregister("sys_enter",
1386 (void *) syscall_entry_event_notifier_probe, group));
1387 return ret;
1388 }
1389 group->sys_exit_registered = 1;
1390 }
1391
1392 return ret;
1393}
1394
1395static
1396int create_unknown_event_notifier(
1397 struct lttng_event_notifier_enabler *event_notifier_enabler,
1398 enum sc_type type)
1399{
1400 struct lttng_event_notifier *notifier;
1401 const struct lttng_event_desc *desc;
1402 struct lttng_event_notifier_group *group = event_notifier_enabler->group;
1403 struct lttng_kernel_event_notifier event_notifier_param;
1404 uint64_t user_token = event_notifier_enabler->base.user_token;
99f52fcc 1405 uint64_t error_counter_index = event_notifier_enabler->error_counter_index;
8a8ac9a8
FD
1406 struct lttng_enabler *base_enabler = lttng_event_notifier_enabler_as_enabler(
1407 event_notifier_enabler);
1408 struct hlist_head *unknown_dispatch_list;
1409 int ret = 0;
1410 bool found = false;
1411 enum lttng_kernel_syscall_abi abi;
1412 enum lttng_kernel_syscall_entryexit entryexit;
1413 struct hlist_head *head;
1414
1415 switch (type) {
1416 case SC_TYPE_ENTRY:
1417 desc = &__event_desc___syscall_entry_unknown;
1418 unknown_dispatch_list = &group->event_notifier_unknown_syscall_dispatch;
1419 entryexit = LTTNG_KERNEL_SYSCALL_ENTRY;
1420 abi = LTTNG_KERNEL_SYSCALL_ABI_NATIVE;
1421 break;
1422 case SC_TYPE_EXIT:
1423 desc = &__event_desc___syscall_exit_unknown;
1424 unknown_dispatch_list = &group->event_notifier_exit_unknown_syscall_dispatch;
1425 entryexit = LTTNG_KERNEL_SYSCALL_EXIT;
1426 abi = LTTNG_KERNEL_SYSCALL_ABI_NATIVE;
1427 break;
1428 case SC_TYPE_COMPAT_ENTRY:
1429 desc = &__event_desc___compat_syscall_entry_unknown;
1430 unknown_dispatch_list = &group->event_notifier_compat_unknown_syscall_dispatch;
1431 entryexit = LTTNG_KERNEL_SYSCALL_ENTRY;
1432 abi = LTTNG_KERNEL_SYSCALL_ABI_COMPAT;
1433 break;
1434 case SC_TYPE_COMPAT_EXIT:
1435 desc = &__event_desc___compat_syscall_exit_unknown;
1436 unknown_dispatch_list = &group->event_notifier_exit_compat_unknown_syscall_dispatch;
1437 entryexit = LTTNG_KERNEL_SYSCALL_EXIT;
1438 abi = LTTNG_KERNEL_SYSCALL_ABI_COMPAT;
1439 break;
1440 default:
1441 BUG_ON(1);
1442 }
1443
1444 /*
1445 * Check if already created.
1446 */
1447 head = utils_borrow_hash_table_bucket(group->event_notifiers_ht.table,
1448 LTTNG_EVENT_NOTIFIER_HT_SIZE, desc->name);
1449 lttng_hlist_for_each_entry(notifier, head, hlist) {
1450 if (notifier->desc == desc &&
1451 notifier->user_token == base_enabler->user_token)
1452 found = true;
1453 }
1454 if (found)
1455 goto end;
1456
1457 memset(&event_notifier_param, 0, sizeof(event_notifier_param));
1458 strncat(event_notifier_param.event.name, desc->name,
1459 LTTNG_KERNEL_SYM_NAME_LEN - strlen(event_notifier_param.event.name) - 1);
1460
1461 event_notifier_param.event.name[LTTNG_KERNEL_SYM_NAME_LEN - 1] = '\0';
1462
1463 event_notifier_param.event.instrumentation = LTTNG_KERNEL_SYSCALL;
1464 event_notifier_param.event.u.syscall.abi = abi;
1465 event_notifier_param.event.u.syscall.entryexit = entryexit;
1466
1467 notifier = _lttng_event_notifier_create(desc, user_token,
99f52fcc 1468 error_counter_index, group, &event_notifier_param, NULL,
8a8ac9a8
FD
1469 event_notifier_param.event.instrumentation);
1470 if (IS_ERR(notifier)) {
1471 printk(KERN_INFO "Unable to create unknown notifier %s\n",
1472 desc->name);
1473 ret = -ENOMEM;
1474 goto end;
1475 }
1476
1477 hlist_add_head_rcu(&notifier->u.syscall.node, unknown_dispatch_list);
1478
1479end:
1480 return ret;
1481}
1482
1483static int create_matching_event_notifiers(
1484 struct lttng_event_notifier_enabler *event_notifier_enabler,
1485 void *filter, const struct trace_syscall_entry *table,
1486 size_t table_len, enum sc_type type)
1487{
1488 struct lttng_event_notifier_group *group = event_notifier_enabler->group;
1489 const struct lttng_event_desc *desc;
1490 uint64_t user_token = event_notifier_enabler->base.user_token;
99f52fcc 1491 uint64_t error_counter_index = event_notifier_enabler->error_counter_index;
8a8ac9a8
FD
1492 unsigned int i;
1493 int ret = 0;
1494
1495 /* iterate over all syscall and create event_notifier that match */
1496 for (i = 0; i < table_len; i++) {
1497 struct lttng_event_notifier *event_notifier;
1498 struct lttng_kernel_event_notifier event_notifier_param;
1499 struct hlist_head *head;
1500 int found = 0;
1501
1502 desc = table[i].desc;
1503 if (!desc) {
1504 /* Unknown syscall */
1505 continue;
1506 }
1507
1508 if (!lttng_desc_match_enabler(desc,
1509 lttng_event_notifier_enabler_as_enabler(event_notifier_enabler)))
1510 continue;
1511
1512 /*
1513 * Check if already created.
1514 */
1515 head = utils_borrow_hash_table_bucket(group->event_notifiers_ht.table,
1516 LTTNG_EVENT_NOTIFIER_HT_SIZE, desc->name);
1517 lttng_hlist_for_each_entry(event_notifier, head, hlist) {
1518 if (event_notifier->desc == desc
1519 && event_notifier->user_token == event_notifier_enabler->base.user_token)
1520 found = 1;
1521 }
1522 if (found)
1523 continue;
1524
1525 memset(&event_notifier_param, 0, sizeof(event_notifier_param));
1526 switch (type) {
1527 case SC_TYPE_ENTRY:
1528 event_notifier_param.event.u.syscall.entryexit = LTTNG_KERNEL_SYSCALL_ENTRY;
1529 event_notifier_param.event.u.syscall.abi = LTTNG_KERNEL_SYSCALL_ABI_NATIVE;
1530 break;
1531 case SC_TYPE_EXIT:
1532 event_notifier_param.event.u.syscall.entryexit = LTTNG_KERNEL_SYSCALL_EXIT;
1533 event_notifier_param.event.u.syscall.abi = LTTNG_KERNEL_SYSCALL_ABI_NATIVE;
1534 break;
1535 case SC_TYPE_COMPAT_ENTRY:
1536 event_notifier_param.event.u.syscall.entryexit = LTTNG_KERNEL_SYSCALL_ENTRY;
1537 event_notifier_param.event.u.syscall.abi = LTTNG_KERNEL_SYSCALL_ABI_COMPAT;
1538 break;
1539 case SC_TYPE_COMPAT_EXIT:
1540 event_notifier_param.event.u.syscall.entryexit = LTTNG_KERNEL_SYSCALL_EXIT;
1541 event_notifier_param.event.u.syscall.abi = LTTNG_KERNEL_SYSCALL_ABI_COMPAT;
1542 break;
1543 }
1544 strncat(event_notifier_param.event.name, desc->name,
1545 LTTNG_KERNEL_SYM_NAME_LEN - strlen(event_notifier_param.event.name) - 1);
1546 event_notifier_param.event.name[LTTNG_KERNEL_SYM_NAME_LEN - 1] = '\0';
1547 event_notifier_param.event.instrumentation = LTTNG_KERNEL_SYSCALL;
1548
99f52fcc
FD
1549 event_notifier = _lttng_event_notifier_create(desc, user_token,
1550 error_counter_index, group, &event_notifier_param,
1551 filter, event_notifier_param.event.instrumentation);
8a8ac9a8
FD
1552 if (IS_ERR(event_notifier)) {
1553 printk(KERN_INFO "Unable to create event_notifier %s\n",
1554 desc->name);
1555 ret = -ENOMEM;
1556 goto end;
1557 }
1558
1559 event_notifier->u.syscall.syscall_id = i;
1560 }
1561
1562end:
1563 return ret;
1564
1565}
1566
1567int lttng_syscals_create_matching_event_notifiers(
1568 struct lttng_event_notifier_enabler *event_notifier_enabler,
1569 void *filter)
1570{
1571 int ret;
1572 struct lttng_enabler *base_enabler =
1573 lttng_event_notifier_enabler_as_enabler(event_notifier_enabler);
1574 enum lttng_kernel_syscall_entryexit entryexit =
1575 base_enabler->event_param.u.syscall.entryexit;
1576
1577 if (entryexit == LTTNG_KERNEL_SYSCALL_ENTRY || entryexit == LTTNG_KERNEL_SYSCALL_ENTRYEXIT) {
1578 ret = create_matching_event_notifiers(event_notifier_enabler,
1579 filter, sc_table, ARRAY_SIZE(sc_table), SC_TYPE_ENTRY);
1580 if (ret)
1581 goto end;
1582
1583 ret = create_matching_event_notifiers(event_notifier_enabler,
1584 filter, compat_sc_table, ARRAY_SIZE(compat_sc_table),
1585 SC_TYPE_COMPAT_ENTRY);
1586 if (ret)
1587 goto end;
1588
1589 ret = create_unknown_event_notifier(event_notifier_enabler,
1590 SC_TYPE_ENTRY);
1591 if (ret)
1592 goto end;
1593
1594 ret = create_unknown_event_notifier(event_notifier_enabler,
1595 SC_TYPE_COMPAT_ENTRY);
1596 if (ret)
1597 goto end;
1598 }
1599
1600 if (entryexit == LTTNG_KERNEL_SYSCALL_EXIT || entryexit == LTTNG_KERNEL_SYSCALL_ENTRYEXIT) {
1601 ret = create_matching_event_notifiers(event_notifier_enabler,
1602 filter, sc_exit_table, ARRAY_SIZE(sc_exit_table),
1603 SC_TYPE_EXIT);
1604 if (ret)
1605 goto end;
1606
1607 ret = create_unknown_event_notifier(event_notifier_enabler,
1608 SC_TYPE_EXIT);
1609 if (ret)
1610 goto end;
1611
1612 ret = create_matching_event_notifiers(event_notifier_enabler,
1613 filter, compat_sc_exit_table, ARRAY_SIZE(compat_sc_exit_table),
1614 SC_TYPE_COMPAT_EXIT);
1615 if (ret)
1616 goto end;
1617
1618 ret = create_unknown_event_notifier(event_notifier_enabler,
1619 SC_TYPE_COMPAT_EXIT);
1620 if (ret)
1621 goto end;
1622 }
1623
1624end:
1625 return ret;
1626}
1627
1628/*
1629 * Unregister the syscall event_notifier probes from the callsites.
259b6cb3 1630 */
8a8ac9a8
FD
1631int lttng_syscalls_unregister_event_notifier(
1632 struct lttng_event_notifier_group *event_notifier_group)
1633{
1634 int ret;
1635
1636 /*
1637 * Only register the event_notifier probe on the `sys_enter` callsite for now.
1638 * At the moment, we don't think it's desirable to have one fired
1639 * event_notifier for the entry and one for the exit of a syscall.
1640 */
1641 if (event_notifier_group->sys_enter_registered) {
1642 ret = lttng_wrapper_tracepoint_probe_unregister("sys_enter",
1643 (void *) syscall_entry_event_notifier_probe, event_notifier_group);
1644 if (ret)
1645 return ret;
1646 event_notifier_group->sys_enter_registered = 0;
1647 }
1648 if (event_notifier_group->sys_exit_registered) {
1649 ret = lttng_wrapper_tracepoint_probe_unregister("sys_exit",
1650 (void *) syscall_exit_event_notifier_probe, event_notifier_group);
1651 if (ret)
1652 return ret;
1653 event_notifier_group->sys_enter_registered = 0;
1654 }
1655
1656 kfree(event_notifier_group->event_notifier_syscall_dispatch);
1657 kfree(event_notifier_group->event_notifier_exit_syscall_dispatch);
1658#ifdef CONFIG_COMPAT
1659 kfree(event_notifier_group->event_notifier_compat_syscall_dispatch);
1660 kfree(event_notifier_group->event_notifier_exit_compat_syscall_dispatch);
1661#endif
1662 return 0;
1663}
1664
2d6d88c6 1665int lttng_syscalls_unregister_event(struct lttng_channel *chan)
259b6cb3
MD
1666{
1667 int ret;
1668
1669 if (!chan->sc_table)
1670 return 0;
80f87dd2 1671 if (chan->sys_enter_registered) {
2d9cd7f3 1672 ret = lttng_wrapper_tracepoint_probe_unregister("sys_enter",
2d6d88c6 1673 (void *) syscall_entry_event_probe, chan);
80f87dd2
MD
1674 if (ret)
1675 return ret;
1676 chan->sys_enter_registered = 0;
1677 }
1678 if (chan->sys_exit_registered) {
2d9cd7f3 1679 ret = lttng_wrapper_tracepoint_probe_unregister("sys_exit",
2d6d88c6 1680 (void *) syscall_exit_event_probe, chan);
80f87dd2
MD
1681 if (ret)
1682 return ret;
1683 chan->sys_exit_registered = 0;
1684 }
badfe9f5
MD
1685 return 0;
1686}
1687
2d6d88c6 1688int lttng_syscalls_destroy_event(struct lttng_channel *chan)
badfe9f5 1689{
259b6cb3 1690 kfree(chan->sc_table);
5b7ac358 1691 kfree(chan->sc_exit_table);
49c50022
MD
1692#ifdef CONFIG_COMPAT
1693 kfree(chan->compat_sc_table);
5b7ac358 1694 kfree(chan->compat_sc_exit_table);
49c50022 1695#endif
80f87dd2
MD
1696 kfree(chan->sc_filter);
1697 return 0;
1698}
1699
1700static
1701int get_syscall_nr(const char *syscall_name)
1702{
1703 int syscall_nr = -1;
1704 int i;
1705
1706 for (i = 0; i < ARRAY_SIZE(sc_table); i++) {
1707 const struct trace_syscall_entry *entry;
5b7ac358 1708 const char *it_name;
80f87dd2
MD
1709
1710 entry = &sc_table[i];
1711 if (!entry->desc)
1712 continue;
5b7ac358
MD
1713 it_name = entry->desc->name;
1714 it_name += strlen(SYSCALL_ENTRY_STR);
1715 if (!strcmp(syscall_name, it_name)) {
80f87dd2
MD
1716 syscall_nr = i;
1717 break;
1718 }
1719 }
1720 return syscall_nr;
1721}
1722
1723static
1724int get_compat_syscall_nr(const char *syscall_name)
1725{
1726 int syscall_nr = -1;
1727 int i;
1728
1729 for (i = 0; i < ARRAY_SIZE(compat_sc_table); i++) {
1730 const struct trace_syscall_entry *entry;
5b7ac358 1731 const char *it_name;
80f87dd2
MD
1732
1733 entry = &compat_sc_table[i];
1734 if (!entry->desc)
1735 continue;
5b7ac358
MD
1736 it_name = entry->desc->name;
1737 it_name += strlen(COMPAT_SYSCALL_ENTRY_STR);
1738 if (!strcmp(syscall_name, it_name)) {
80f87dd2
MD
1739 syscall_nr = i;
1740 break;
1741 }
1742 }
1743 return syscall_nr;
1744}
1745
12e579db
MD
1746static
1747uint32_t get_sc_tables_len(void)
1748{
1749 return ARRAY_SIZE(sc_table) + ARRAY_SIZE(compat_sc_table);
1750}
1751
badfe9f5 1752static
ade8a729
FD
1753const char *get_syscall_name(const char *desc_name,
1754 enum lttng_syscall_abi abi,
1755 enum lttng_syscall_entryexit entryexit)
80f87dd2 1756{
badfe9f5 1757 size_t prefix_len = 0;
80f87dd2 1758
80f87dd2 1759
ade8a729 1760 switch (entryexit) {
badfe9f5 1761 case LTTNG_SYSCALL_ENTRY:
ade8a729 1762 switch (abi) {
badfe9f5
MD
1763 case LTTNG_SYSCALL_ABI_NATIVE:
1764 prefix_len = strlen(SYSCALL_ENTRY_STR);
1765 break;
1766 case LTTNG_SYSCALL_ABI_COMPAT:
1767 prefix_len = strlen(COMPAT_SYSCALL_ENTRY_STR);
1768 break;
80f87dd2 1769 }
badfe9f5
MD
1770 break;
1771 case LTTNG_SYSCALL_EXIT:
ade8a729 1772 switch (abi) {
badfe9f5
MD
1773 case LTTNG_SYSCALL_ABI_NATIVE:
1774 prefix_len = strlen(SYSCALL_EXIT_STR);
1775 break;
1776 case LTTNG_SYSCALL_ABI_COMPAT:
1777 prefix_len = strlen(COMPAT_SYSCALL_EXIT_STR);
1778 break;
80f87dd2 1779 }
badfe9f5 1780 break;
80f87dd2 1781 }
badfe9f5 1782 WARN_ON_ONCE(prefix_len == 0);
ade8a729 1783 return desc_name + prefix_len;
badfe9f5
MD
1784}
1785
ade8a729
FD
1786static
1787int lttng_syscall_filter_enable(
1788 struct lttng_syscall_filter *filter,
1789 const char *desc_name, enum lttng_syscall_abi abi,
1790 enum lttng_syscall_entryexit entryexit)
badfe9f5 1791{
badfe9f5
MD
1792 const char *syscall_name;
1793 unsigned long *bitmap;
1794 int syscall_nr;
1795
ade8a729 1796 syscall_name = get_syscall_name(desc_name, abi, entryexit);
badfe9f5 1797
ade8a729 1798 switch (abi) {
badfe9f5
MD
1799 case LTTNG_SYSCALL_ABI_NATIVE:
1800 syscall_nr = get_syscall_nr(syscall_name);
1801 break;
1802 case LTTNG_SYSCALL_ABI_COMPAT:
1803 syscall_nr = get_compat_syscall_nr(syscall_name);
1804 break;
1805 default:
1806 return -EINVAL;
80f87dd2 1807 }
badfe9f5
MD
1808 if (syscall_nr < 0)
1809 return -ENOENT;
1810
ade8a729 1811 switch (entryexit) {
badfe9f5 1812 case LTTNG_SYSCALL_ENTRY:
ade8a729 1813 switch (abi) {
badfe9f5
MD
1814 case LTTNG_SYSCALL_ABI_NATIVE:
1815 bitmap = filter->sc_entry;
1816 break;
1817 case LTTNG_SYSCALL_ABI_COMPAT:
1818 bitmap = filter->sc_compat_entry;
1819 break;
6d9694d8
MD
1820 default:
1821 return -EINVAL;
80f87dd2 1822 }
badfe9f5
MD
1823 break;
1824 case LTTNG_SYSCALL_EXIT:
ade8a729 1825 switch (abi) {
badfe9f5
MD
1826 case LTTNG_SYSCALL_ABI_NATIVE:
1827 bitmap = filter->sc_exit;
1828 break;
1829 case LTTNG_SYSCALL_ABI_COMPAT:
1830 bitmap = filter->sc_compat_exit;
1831 break;
6d9694d8
MD
1832 default:
1833 return -EINVAL;
80f87dd2 1834 }
badfe9f5
MD
1835 break;
1836 default:
1837 return -EINVAL;
80f87dd2 1838 }
badfe9f5
MD
1839 if (test_bit(syscall_nr, bitmap))
1840 return -EEXIST;
1841 bitmap_set(bitmap, syscall_nr, 1);
80f87dd2 1842 return 0;
80f87dd2
MD
1843}
1844
8a8ac9a8
FD
1845int lttng_syscall_filter_enable_event_notifier(
1846 struct lttng_event_notifier *notifier)
1847{
1848 struct lttng_event_notifier_group *group = notifier->group;
1849 unsigned int syscall_id = notifier->u.syscall.syscall_id;
1850 struct hlist_head *dispatch_list;
1851 int ret = 0;
1852
1853 WARN_ON_ONCE(notifier->instrumentation != LTTNG_KERNEL_SYSCALL);
1854
1855 ret = lttng_syscall_filter_enable(group->sc_filter,
1856 notifier->desc->name, notifier->u.syscall.abi,
1857 notifier->u.syscall.entryexit);
1858 if (ret) {
1859 goto end;
1860 }
1861
1862 switch (notifier->u.syscall.entryexit) {
1863 case LTTNG_SYSCALL_ENTRY:
1864 switch (notifier->u.syscall.abi) {
1865 case LTTNG_SYSCALL_ABI_NATIVE:
1866 dispatch_list = &group->event_notifier_syscall_dispatch[syscall_id];
1867 break;
1868 case LTTNG_SYSCALL_ABI_COMPAT:
1869 dispatch_list = &group->event_notifier_compat_syscall_dispatch[syscall_id];
1870 break;
1871 }
1872 break;
1873 case LTTNG_SYSCALL_EXIT:
1874 switch (notifier->u.syscall.abi) {
1875 case LTTNG_SYSCALL_ABI_NATIVE:
1876 dispatch_list = &group->event_notifier_exit_syscall_dispatch[syscall_id];
1877 break;
1878 case LTTNG_SYSCALL_ABI_COMPAT:
1879 dispatch_list = &group->event_notifier_exit_compat_syscall_dispatch[syscall_id];
1880 break;
1881 }
1882 break;
1883 }
1884
1885 hlist_add_head_rcu(&notifier->u.syscall.node, dispatch_list);
1886
1887end:
1888 return ret ;
1889}
1890
ade8a729
FD
1891int lttng_syscall_filter_enable_event(
1892 struct lttng_channel *channel,
badfe9f5 1893 struct lttng_event *event)
80f87dd2 1894{
ade8a729
FD
1895 WARN_ON_ONCE(event->instrumentation != LTTNG_KERNEL_SYSCALL);
1896
1897 return lttng_syscall_filter_enable(channel->sc_filter,
1898 event->desc->name, event->u.syscall.abi,
1899 event->u.syscall.entryexit);
1900}
1901
1902static
1903int lttng_syscall_filter_disable(
1904 struct lttng_syscall_filter *filter,
1905 const char *desc_name, enum lttng_syscall_abi abi,
1906 enum lttng_syscall_entryexit entryexit)
1907{
badfe9f5
MD
1908 const char *syscall_name;
1909 unsigned long *bitmap;
1910 int syscall_nr;
80f87dd2 1911
ade8a729 1912 syscall_name = get_syscall_name(desc_name, abi, entryexit);
80f87dd2 1913
ade8a729 1914 switch (abi) {
badfe9f5
MD
1915 case LTTNG_SYSCALL_ABI_NATIVE:
1916 syscall_nr = get_syscall_nr(syscall_name);
1917 break;
1918 case LTTNG_SYSCALL_ABI_COMPAT:
1919 syscall_nr = get_compat_syscall_nr(syscall_name);
1920 break;
1921 default:
1922 return -EINVAL;
80f87dd2 1923 }
badfe9f5
MD
1924 if (syscall_nr < 0)
1925 return -ENOENT;
80f87dd2 1926
ade8a729 1927 switch (entryexit) {
badfe9f5 1928 case LTTNG_SYSCALL_ENTRY:
ade8a729 1929 switch (abi) {
badfe9f5
MD
1930 case LTTNG_SYSCALL_ABI_NATIVE:
1931 bitmap = filter->sc_entry;
1932 break;
1933 case LTTNG_SYSCALL_ABI_COMPAT:
1934 bitmap = filter->sc_compat_entry;
1935 break;
6d9694d8
MD
1936 default:
1937 return -EINVAL;
80f87dd2 1938 }
badfe9f5
MD
1939 break;
1940 case LTTNG_SYSCALL_EXIT:
ade8a729 1941 switch (abi) {
badfe9f5
MD
1942 case LTTNG_SYSCALL_ABI_NATIVE:
1943 bitmap = filter->sc_exit;
1944 break;
1945 case LTTNG_SYSCALL_ABI_COMPAT:
1946 bitmap = filter->sc_compat_exit;
1947 break;
6d9694d8
MD
1948 default:
1949 return -EINVAL;
80f87dd2 1950 }
badfe9f5
MD
1951 break;
1952 default:
1953 return -EINVAL;
80f87dd2 1954 }
badfe9f5
MD
1955 if (!test_bit(syscall_nr, bitmap))
1956 return -EEXIST;
1957 bitmap_clear(bitmap, syscall_nr, 1);
80f87dd2 1958
badfe9f5 1959 return 0;
259b6cb3 1960}
2d2464bd 1961
8a8ac9a8
FD
1962int lttng_syscall_filter_disable_event_notifier(
1963 struct lttng_event_notifier *notifier)
1964{
1965 struct lttng_event_notifier_group *group = notifier->group;
1966 int ret;
1967
1968 WARN_ON_ONCE(notifier->instrumentation != LTTNG_KERNEL_SYSCALL);
1969
1970 ret = lttng_syscall_filter_disable(group->sc_filter,
1971 notifier->desc->name, notifier->u.syscall.abi,
1972 notifier->u.syscall.entryexit);
1973 WARN_ON_ONCE(ret != 0);
1974
1975 hlist_del_rcu(&notifier->u.syscall.node);
1976 return 0;
1977}
1978
ade8a729
FD
1979int lttng_syscall_filter_disable_event(
1980 struct lttng_channel *channel,
1981 struct lttng_event *event)
1982{
1983 return lttng_syscall_filter_disable(channel->sc_filter,
1984 event->desc->name, event->u.syscall.abi,
1985 event->u.syscall.entryexit);
1986}
1987
2d2464bd
MD
1988static
1989const struct trace_syscall_entry *syscall_list_get_entry(loff_t *pos)
1990{
1991 const struct trace_syscall_entry *entry;
1992 int iter = 0;
1993
1994 for (entry = sc_table;
1995 entry < sc_table + ARRAY_SIZE(sc_table);
1996 entry++) {
1997 if (iter++ >= *pos)
1998 return entry;
1999 }
2000 for (entry = compat_sc_table;
2001 entry < compat_sc_table + ARRAY_SIZE(compat_sc_table);
2002 entry++) {
2003 if (iter++ >= *pos)
2004 return entry;
2005 }
2006 /* End of list */
2007 return NULL;
2008}
2009
2010static
2011void *syscall_list_start(struct seq_file *m, loff_t *pos)
2012{
2013 return (void *) syscall_list_get_entry(pos);
2014}
2015
2016static
2017void *syscall_list_next(struct seq_file *m, void *p, loff_t *ppos)
2018{
2019 (*ppos)++;
2020 return (void *) syscall_list_get_entry(ppos);
2021}
2022
2023static
2024void syscall_list_stop(struct seq_file *m, void *p)
2025{
2026}
2027
12e579db
MD
2028static
2029int get_sc_table(const struct trace_syscall_entry *entry,
2030 const struct trace_syscall_entry **table,
2031 unsigned int *bitness)
2032{
2033 if (entry >= sc_table && entry < sc_table + ARRAY_SIZE(sc_table)) {
2034 if (bitness)
2035 *bitness = BITS_PER_LONG;
2036 if (table)
2037 *table = sc_table;
2038 return 0;
2039 }
2040 if (!(entry >= compat_sc_table
2041 && entry < compat_sc_table + ARRAY_SIZE(compat_sc_table))) {
2042 return -EINVAL;
2043 }
2044 if (bitness)
2045 *bitness = 32;
2046 if (table)
2047 *table = compat_sc_table;
2048 return 0;
2049}
2050
2d2464bd
MD
2051static
2052int syscall_list_show(struct seq_file *m, void *p)
2053{
2054 const struct trace_syscall_entry *table, *entry = p;
2055 unsigned int bitness;
d4291869 2056 unsigned long index;
12e579db 2057 int ret;
d4291869 2058 const char *name;
2d2464bd 2059
12e579db
MD
2060 ret = get_sc_table(entry, &table, &bitness);
2061 if (ret)
2062 return ret;
f4855b46
MD
2063 if (!entry->desc)
2064 return 0;
d4291869
MD
2065 if (table == sc_table) {
2066 index = entry - table;
2067 name = &entry->desc->name[strlen(SYSCALL_ENTRY_STR)];
2068 } else {
2069 index = (entry - table) + ARRAY_SIZE(sc_table);
2070 name = &entry->desc->name[strlen(COMPAT_SYSCALL_ENTRY_STR)];
2071 }
12e579db 2072 seq_printf(m, "syscall { index = %lu; name = %s; bitness = %u; };\n",
d4291869 2073 index, name, bitness);
2d2464bd
MD
2074 return 0;
2075}
2076
2077static
2078const struct seq_operations lttng_syscall_list_seq_ops = {
2079 .start = syscall_list_start,
2080 .next = syscall_list_next,
2081 .stop = syscall_list_stop,
2082 .show = syscall_list_show,
2083};
2084
2085static
2086int lttng_syscall_list_open(struct inode *inode, struct file *file)
2087{
2088 return seq_open(file, &lttng_syscall_list_seq_ops);
2089}
2090
2091const struct file_operations lttng_syscall_list_fops = {
2092 .owner = THIS_MODULE,
2093 .open = lttng_syscall_list_open,
2094 .read = seq_read,
2095 .llseek = seq_lseek,
2096 .release = seq_release,
2097};
12e579db 2098
badfe9f5
MD
2099/*
2100 * A syscall is enabled if it is traced for either entry or exit.
2101 */
12e579db
MD
2102long lttng_channel_syscall_mask(struct lttng_channel *channel,
2103 struct lttng_kernel_syscall_mask __user *usyscall_mask)
2104{
2105 uint32_t len, sc_tables_len, bitmask_len;
2106 int ret = 0, bit;
2107 char *tmp_mask;
2108 struct lttng_syscall_filter *filter;
2109
2110 ret = get_user(len, &usyscall_mask->len);
2111 if (ret)
2112 return ret;
2113 sc_tables_len = get_sc_tables_len();
2114 bitmask_len = ALIGN(sc_tables_len, 8) >> 3;
2115 if (len < sc_tables_len) {
2116 return put_user(sc_tables_len, &usyscall_mask->len);
2117 }
2118 /* Array is large enough, we can copy array to user-space. */
2119 tmp_mask = kzalloc(bitmask_len, GFP_KERNEL);
2120 if (!tmp_mask)
2121 return -ENOMEM;
2122 filter = channel->sc_filter;
2123
2124 for (bit = 0; bit < ARRAY_SIZE(sc_table); bit++) {
e2129868 2125 char state;
2f25059d
MD
2126
2127 if (channel->sc_table) {
badfe9f5
MD
2128 if (!READ_ONCE(channel->syscall_all) && filter)
2129 state = test_bit(bit, filter->sc_entry)
2130 || test_bit(bit, filter->sc_exit);
2f25059d
MD
2131 else
2132 state = 1;
2133 } else {
2134 state = 0;
2135 }
2136 bt_bitfield_write_be(tmp_mask, char, bit, 1, state);
12e579db
MD
2137 }
2138 for (; bit < sc_tables_len; bit++) {
e2129868 2139 char state;
2f25059d
MD
2140
2141 if (channel->compat_sc_table) {
badfe9f5 2142 if (!READ_ONCE(channel->syscall_all) && filter)
2f25059d 2143 state = test_bit(bit - ARRAY_SIZE(sc_table),
badfe9f5
MD
2144 filter->sc_compat_entry)
2145 || test_bit(bit - ARRAY_SIZE(sc_table),
2146 filter->sc_compat_exit);
2f25059d
MD
2147 else
2148 state = 1;
2149 } else {
2150 state = 0;
2151 }
2152 bt_bitfield_write_be(tmp_mask, char, bit, 1, state);
12e579db
MD
2153 }
2154 if (copy_to_user(usyscall_mask->mask, tmp_mask, bitmask_len))
2155 ret = -EFAULT;
2156 kfree(tmp_mask);
2157 return ret;
2158}
082d4946
MD
2159
2160int lttng_abi_syscall_list(void)
2161{
2162 struct file *syscall_list_file;
2163 int file_fd, ret;
2164
4ac10b76 2165 file_fd = lttng_get_unused_fd();
082d4946
MD
2166 if (file_fd < 0) {
2167 ret = file_fd;
2168 goto fd_error;
2169 }
2170
2171 syscall_list_file = anon_inode_getfile("[lttng_syscall_list]",
2172 &lttng_syscall_list_fops,
2173 NULL, O_RDWR);
2174 if (IS_ERR(syscall_list_file)) {
2175 ret = PTR_ERR(syscall_list_file);
2176 goto file_error;
2177 }
2178 ret = lttng_syscall_list_fops.open(NULL, syscall_list_file);
2179 if (ret < 0)
2180 goto open_error;
2181 fd_install(file_fd, syscall_list_file);
082d4946
MD
2182 return file_fd;
2183
2184open_error:
2185 fput(syscall_list_file);
2186file_error:
2187 put_unused_fd(file_fd);
2188fd_error:
2189 return ret;
2190}
This page took 0.144002 seconds and 4 git commands to generate.