Implement event notifiers for syscalls
[lttng-modules.git] / src / lttng-syscalls.c
CommitLineData
b7cdc182 1/* SPDX-License-Identifier: (GPL-2.0-only or LGPL-2.1-only)
9f36eaed 2 *
259b6cb3
MD
3 * lttng-syscalls.c
4 *
2faf7d1b 5 * LTTng syscall probes.
259b6cb3 6 *
886d51a3 7 * Copyright (C) 2010-2012 Mathieu Desnoyers <mathieu.desnoyers@efficios.com>
259b6cb3
MD
8 */
9
10#include <linux/module.h>
11#include <linux/slab.h>
6333ace3 12#include <linux/compat.h>
abc0446a 13#include <linux/err.h>
80f87dd2 14#include <linux/bitmap.h>
7ca580f8
MD
15#include <linux/in.h>
16#include <linux/in6.h>
2d2464bd 17#include <linux/seq_file.h>
d4291869 18#include <linux/stringify.h>
082d4946
MD
19#include <linux/file.h>
20#include <linux/anon_inodes.h>
c8dfb724 21#include <linux/fcntl.h>
3cf55950 22#include <linux/mman.h>
259b6cb3
MD
23#include <asm/ptrace.h>
24#include <asm/syscall.h>
25
a071f25d 26#include <lttng/bitfield.h>
241ae9a8
MD
27#include <wrapper/tracepoint.h>
28#include <wrapper/file.h>
29#include <wrapper/rcu.h>
1b7b9c65 30#include <wrapper/syscall.h>
2df37e95 31#include <lttng/events.h>
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;
1405 struct lttng_enabler *base_enabler = lttng_event_notifier_enabler_as_enabler(
1406 event_notifier_enabler);
1407 struct hlist_head *unknown_dispatch_list;
1408 int ret = 0;
1409 bool found = false;
1410 enum lttng_kernel_syscall_abi abi;
1411 enum lttng_kernel_syscall_entryexit entryexit;
1412 struct hlist_head *head;
1413
1414 switch (type) {
1415 case SC_TYPE_ENTRY:
1416 desc = &__event_desc___syscall_entry_unknown;
1417 unknown_dispatch_list = &group->event_notifier_unknown_syscall_dispatch;
1418 entryexit = LTTNG_KERNEL_SYSCALL_ENTRY;
1419 abi = LTTNG_KERNEL_SYSCALL_ABI_NATIVE;
1420 break;
1421 case SC_TYPE_EXIT:
1422 desc = &__event_desc___syscall_exit_unknown;
1423 unknown_dispatch_list = &group->event_notifier_exit_unknown_syscall_dispatch;
1424 entryexit = LTTNG_KERNEL_SYSCALL_EXIT;
1425 abi = LTTNG_KERNEL_SYSCALL_ABI_NATIVE;
1426 break;
1427 case SC_TYPE_COMPAT_ENTRY:
1428 desc = &__event_desc___compat_syscall_entry_unknown;
1429 unknown_dispatch_list = &group->event_notifier_compat_unknown_syscall_dispatch;
1430 entryexit = LTTNG_KERNEL_SYSCALL_ENTRY;
1431 abi = LTTNG_KERNEL_SYSCALL_ABI_COMPAT;
1432 break;
1433 case SC_TYPE_COMPAT_EXIT:
1434 desc = &__event_desc___compat_syscall_exit_unknown;
1435 unknown_dispatch_list = &group->event_notifier_exit_compat_unknown_syscall_dispatch;
1436 entryexit = LTTNG_KERNEL_SYSCALL_EXIT;
1437 abi = LTTNG_KERNEL_SYSCALL_ABI_COMPAT;
1438 break;
1439 default:
1440 BUG_ON(1);
1441 }
1442
1443 /*
1444 * Check if already created.
1445 */
1446 head = utils_borrow_hash_table_bucket(group->event_notifiers_ht.table,
1447 LTTNG_EVENT_NOTIFIER_HT_SIZE, desc->name);
1448 lttng_hlist_for_each_entry(notifier, head, hlist) {
1449 if (notifier->desc == desc &&
1450 notifier->user_token == base_enabler->user_token)
1451 found = true;
1452 }
1453 if (found)
1454 goto end;
1455
1456 memset(&event_notifier_param, 0, sizeof(event_notifier_param));
1457 strncat(event_notifier_param.event.name, desc->name,
1458 LTTNG_KERNEL_SYM_NAME_LEN - strlen(event_notifier_param.event.name) - 1);
1459
1460 event_notifier_param.event.name[LTTNG_KERNEL_SYM_NAME_LEN - 1] = '\0';
1461
1462 event_notifier_param.event.instrumentation = LTTNG_KERNEL_SYSCALL;
1463 event_notifier_param.event.u.syscall.abi = abi;
1464 event_notifier_param.event.u.syscall.entryexit = entryexit;
1465
1466 notifier = _lttng_event_notifier_create(desc, user_token,
1467 group, &event_notifier_param, NULL,
1468 event_notifier_param.event.instrumentation);
1469 if (IS_ERR(notifier)) {
1470 printk(KERN_INFO "Unable to create unknown notifier %s\n",
1471 desc->name);
1472 ret = -ENOMEM;
1473 goto end;
1474 }
1475
1476 hlist_add_head_rcu(&notifier->u.syscall.node, unknown_dispatch_list);
1477
1478end:
1479 return ret;
1480}
1481
1482static int create_matching_event_notifiers(
1483 struct lttng_event_notifier_enabler *event_notifier_enabler,
1484 void *filter, const struct trace_syscall_entry *table,
1485 size_t table_len, enum sc_type type)
1486{
1487 struct lttng_event_notifier_group *group = event_notifier_enabler->group;
1488 const struct lttng_event_desc *desc;
1489 uint64_t user_token = event_notifier_enabler->base.user_token;
1490 unsigned int i;
1491 int ret = 0;
1492
1493 /* iterate over all syscall and create event_notifier that match */
1494 for (i = 0; i < table_len; i++) {
1495 struct lttng_event_notifier *event_notifier;
1496 struct lttng_kernel_event_notifier event_notifier_param;
1497 struct hlist_head *head;
1498 int found = 0;
1499
1500 desc = table[i].desc;
1501 if (!desc) {
1502 /* Unknown syscall */
1503 continue;
1504 }
1505
1506 if (!lttng_desc_match_enabler(desc,
1507 lttng_event_notifier_enabler_as_enabler(event_notifier_enabler)))
1508 continue;
1509
1510 /*
1511 * Check if already created.
1512 */
1513 head = utils_borrow_hash_table_bucket(group->event_notifiers_ht.table,
1514 LTTNG_EVENT_NOTIFIER_HT_SIZE, desc->name);
1515 lttng_hlist_for_each_entry(event_notifier, head, hlist) {
1516 if (event_notifier->desc == desc
1517 && event_notifier->user_token == event_notifier_enabler->base.user_token)
1518 found = 1;
1519 }
1520 if (found)
1521 continue;
1522
1523 memset(&event_notifier_param, 0, sizeof(event_notifier_param));
1524 switch (type) {
1525 case SC_TYPE_ENTRY:
1526 event_notifier_param.event.u.syscall.entryexit = LTTNG_KERNEL_SYSCALL_ENTRY;
1527 event_notifier_param.event.u.syscall.abi = LTTNG_KERNEL_SYSCALL_ABI_NATIVE;
1528 break;
1529 case SC_TYPE_EXIT:
1530 event_notifier_param.event.u.syscall.entryexit = LTTNG_KERNEL_SYSCALL_EXIT;
1531 event_notifier_param.event.u.syscall.abi = LTTNG_KERNEL_SYSCALL_ABI_NATIVE;
1532 break;
1533 case SC_TYPE_COMPAT_ENTRY:
1534 event_notifier_param.event.u.syscall.entryexit = LTTNG_KERNEL_SYSCALL_ENTRY;
1535 event_notifier_param.event.u.syscall.abi = LTTNG_KERNEL_SYSCALL_ABI_COMPAT;
1536 break;
1537 case SC_TYPE_COMPAT_EXIT:
1538 event_notifier_param.event.u.syscall.entryexit = LTTNG_KERNEL_SYSCALL_EXIT;
1539 event_notifier_param.event.u.syscall.abi = LTTNG_KERNEL_SYSCALL_ABI_COMPAT;
1540 break;
1541 }
1542 strncat(event_notifier_param.event.name, desc->name,
1543 LTTNG_KERNEL_SYM_NAME_LEN - strlen(event_notifier_param.event.name) - 1);
1544 event_notifier_param.event.name[LTTNG_KERNEL_SYM_NAME_LEN - 1] = '\0';
1545 event_notifier_param.event.instrumentation = LTTNG_KERNEL_SYSCALL;
1546
1547 event_notifier = _lttng_event_notifier_create(desc, user_token, group,
1548 &event_notifier_param, filter,
1549 event_notifier_param.event.instrumentation);
1550 if (IS_ERR(event_notifier)) {
1551 printk(KERN_INFO "Unable to create event_notifier %s\n",
1552 desc->name);
1553 ret = -ENOMEM;
1554 goto end;
1555 }
1556
1557 event_notifier->u.syscall.syscall_id = i;
1558 }
1559
1560end:
1561 return ret;
1562
1563}
1564
1565int lttng_syscals_create_matching_event_notifiers(
1566 struct lttng_event_notifier_enabler *event_notifier_enabler,
1567 void *filter)
1568{
1569 int ret;
1570 struct lttng_enabler *base_enabler =
1571 lttng_event_notifier_enabler_as_enabler(event_notifier_enabler);
1572 enum lttng_kernel_syscall_entryexit entryexit =
1573 base_enabler->event_param.u.syscall.entryexit;
1574
1575 if (entryexit == LTTNG_KERNEL_SYSCALL_ENTRY || entryexit == LTTNG_KERNEL_SYSCALL_ENTRYEXIT) {
1576 ret = create_matching_event_notifiers(event_notifier_enabler,
1577 filter, sc_table, ARRAY_SIZE(sc_table), SC_TYPE_ENTRY);
1578 if (ret)
1579 goto end;
1580
1581 ret = create_matching_event_notifiers(event_notifier_enabler,
1582 filter, compat_sc_table, ARRAY_SIZE(compat_sc_table),
1583 SC_TYPE_COMPAT_ENTRY);
1584 if (ret)
1585 goto end;
1586
1587 ret = create_unknown_event_notifier(event_notifier_enabler,
1588 SC_TYPE_ENTRY);
1589 if (ret)
1590 goto end;
1591
1592 ret = create_unknown_event_notifier(event_notifier_enabler,
1593 SC_TYPE_COMPAT_ENTRY);
1594 if (ret)
1595 goto end;
1596 }
1597
1598 if (entryexit == LTTNG_KERNEL_SYSCALL_EXIT || entryexit == LTTNG_KERNEL_SYSCALL_ENTRYEXIT) {
1599 ret = create_matching_event_notifiers(event_notifier_enabler,
1600 filter, sc_exit_table, ARRAY_SIZE(sc_exit_table),
1601 SC_TYPE_EXIT);
1602 if (ret)
1603 goto end;
1604
1605 ret = create_unknown_event_notifier(event_notifier_enabler,
1606 SC_TYPE_EXIT);
1607 if (ret)
1608 goto end;
1609
1610 ret = create_matching_event_notifiers(event_notifier_enabler,
1611 filter, compat_sc_exit_table, ARRAY_SIZE(compat_sc_exit_table),
1612 SC_TYPE_COMPAT_EXIT);
1613 if (ret)
1614 goto end;
1615
1616 ret = create_unknown_event_notifier(event_notifier_enabler,
1617 SC_TYPE_COMPAT_EXIT);
1618 if (ret)
1619 goto end;
1620 }
1621
1622end:
1623 return ret;
1624}
1625
1626/*
1627 * Unregister the syscall event_notifier probes from the callsites.
259b6cb3 1628 */
8a8ac9a8
FD
1629int lttng_syscalls_unregister_event_notifier(
1630 struct lttng_event_notifier_group *event_notifier_group)
1631{
1632 int ret;
1633
1634 /*
1635 * Only register the event_notifier probe on the `sys_enter` callsite for now.
1636 * At the moment, we don't think it's desirable to have one fired
1637 * event_notifier for the entry and one for the exit of a syscall.
1638 */
1639 if (event_notifier_group->sys_enter_registered) {
1640 ret = lttng_wrapper_tracepoint_probe_unregister("sys_enter",
1641 (void *) syscall_entry_event_notifier_probe, event_notifier_group);
1642 if (ret)
1643 return ret;
1644 event_notifier_group->sys_enter_registered = 0;
1645 }
1646 if (event_notifier_group->sys_exit_registered) {
1647 ret = lttng_wrapper_tracepoint_probe_unregister("sys_exit",
1648 (void *) syscall_exit_event_notifier_probe, event_notifier_group);
1649 if (ret)
1650 return ret;
1651 event_notifier_group->sys_enter_registered = 0;
1652 }
1653
1654 kfree(event_notifier_group->event_notifier_syscall_dispatch);
1655 kfree(event_notifier_group->event_notifier_exit_syscall_dispatch);
1656#ifdef CONFIG_COMPAT
1657 kfree(event_notifier_group->event_notifier_compat_syscall_dispatch);
1658 kfree(event_notifier_group->event_notifier_exit_compat_syscall_dispatch);
1659#endif
1660 return 0;
1661}
1662
2d6d88c6 1663int lttng_syscalls_unregister_event(struct lttng_channel *chan)
259b6cb3
MD
1664{
1665 int ret;
1666
1667 if (!chan->sc_table)
1668 return 0;
80f87dd2 1669 if (chan->sys_enter_registered) {
2d9cd7f3 1670 ret = lttng_wrapper_tracepoint_probe_unregister("sys_enter",
2d6d88c6 1671 (void *) syscall_entry_event_probe, chan);
80f87dd2
MD
1672 if (ret)
1673 return ret;
1674 chan->sys_enter_registered = 0;
1675 }
1676 if (chan->sys_exit_registered) {
2d9cd7f3 1677 ret = lttng_wrapper_tracepoint_probe_unregister("sys_exit",
2d6d88c6 1678 (void *) syscall_exit_event_probe, chan);
80f87dd2
MD
1679 if (ret)
1680 return ret;
1681 chan->sys_exit_registered = 0;
1682 }
badfe9f5
MD
1683 return 0;
1684}
1685
2d6d88c6 1686int lttng_syscalls_destroy_event(struct lttng_channel *chan)
badfe9f5 1687{
259b6cb3 1688 kfree(chan->sc_table);
5b7ac358 1689 kfree(chan->sc_exit_table);
49c50022
MD
1690#ifdef CONFIG_COMPAT
1691 kfree(chan->compat_sc_table);
5b7ac358 1692 kfree(chan->compat_sc_exit_table);
49c50022 1693#endif
80f87dd2
MD
1694 kfree(chan->sc_filter);
1695 return 0;
1696}
1697
1698static
1699int get_syscall_nr(const char *syscall_name)
1700{
1701 int syscall_nr = -1;
1702 int i;
1703
1704 for (i = 0; i < ARRAY_SIZE(sc_table); i++) {
1705 const struct trace_syscall_entry *entry;
5b7ac358 1706 const char *it_name;
80f87dd2
MD
1707
1708 entry = &sc_table[i];
1709 if (!entry->desc)
1710 continue;
5b7ac358
MD
1711 it_name = entry->desc->name;
1712 it_name += strlen(SYSCALL_ENTRY_STR);
1713 if (!strcmp(syscall_name, it_name)) {
80f87dd2
MD
1714 syscall_nr = i;
1715 break;
1716 }
1717 }
1718 return syscall_nr;
1719}
1720
1721static
1722int get_compat_syscall_nr(const char *syscall_name)
1723{
1724 int syscall_nr = -1;
1725 int i;
1726
1727 for (i = 0; i < ARRAY_SIZE(compat_sc_table); i++) {
1728 const struct trace_syscall_entry *entry;
5b7ac358 1729 const char *it_name;
80f87dd2
MD
1730
1731 entry = &compat_sc_table[i];
1732 if (!entry->desc)
1733 continue;
5b7ac358
MD
1734 it_name = entry->desc->name;
1735 it_name += strlen(COMPAT_SYSCALL_ENTRY_STR);
1736 if (!strcmp(syscall_name, it_name)) {
80f87dd2
MD
1737 syscall_nr = i;
1738 break;
1739 }
1740 }
1741 return syscall_nr;
1742}
1743
12e579db
MD
1744static
1745uint32_t get_sc_tables_len(void)
1746{
1747 return ARRAY_SIZE(sc_table) + ARRAY_SIZE(compat_sc_table);
1748}
1749
badfe9f5 1750static
ade8a729
FD
1751const char *get_syscall_name(const char *desc_name,
1752 enum lttng_syscall_abi abi,
1753 enum lttng_syscall_entryexit entryexit)
80f87dd2 1754{
badfe9f5 1755 size_t prefix_len = 0;
80f87dd2 1756
80f87dd2 1757
ade8a729 1758 switch (entryexit) {
badfe9f5 1759 case LTTNG_SYSCALL_ENTRY:
ade8a729 1760 switch (abi) {
badfe9f5
MD
1761 case LTTNG_SYSCALL_ABI_NATIVE:
1762 prefix_len = strlen(SYSCALL_ENTRY_STR);
1763 break;
1764 case LTTNG_SYSCALL_ABI_COMPAT:
1765 prefix_len = strlen(COMPAT_SYSCALL_ENTRY_STR);
1766 break;
80f87dd2 1767 }
badfe9f5
MD
1768 break;
1769 case LTTNG_SYSCALL_EXIT:
ade8a729 1770 switch (abi) {
badfe9f5
MD
1771 case LTTNG_SYSCALL_ABI_NATIVE:
1772 prefix_len = strlen(SYSCALL_EXIT_STR);
1773 break;
1774 case LTTNG_SYSCALL_ABI_COMPAT:
1775 prefix_len = strlen(COMPAT_SYSCALL_EXIT_STR);
1776 break;
80f87dd2 1777 }
badfe9f5 1778 break;
80f87dd2 1779 }
badfe9f5 1780 WARN_ON_ONCE(prefix_len == 0);
ade8a729 1781 return desc_name + prefix_len;
badfe9f5
MD
1782}
1783
ade8a729
FD
1784static
1785int lttng_syscall_filter_enable(
1786 struct lttng_syscall_filter *filter,
1787 const char *desc_name, enum lttng_syscall_abi abi,
1788 enum lttng_syscall_entryexit entryexit)
badfe9f5 1789{
badfe9f5
MD
1790 const char *syscall_name;
1791 unsigned long *bitmap;
1792 int syscall_nr;
1793
ade8a729 1794 syscall_name = get_syscall_name(desc_name, abi, entryexit);
badfe9f5 1795
ade8a729 1796 switch (abi) {
badfe9f5
MD
1797 case LTTNG_SYSCALL_ABI_NATIVE:
1798 syscall_nr = get_syscall_nr(syscall_name);
1799 break;
1800 case LTTNG_SYSCALL_ABI_COMPAT:
1801 syscall_nr = get_compat_syscall_nr(syscall_name);
1802 break;
1803 default:
1804 return -EINVAL;
80f87dd2 1805 }
badfe9f5
MD
1806 if (syscall_nr < 0)
1807 return -ENOENT;
1808
ade8a729 1809 switch (entryexit) {
badfe9f5 1810 case LTTNG_SYSCALL_ENTRY:
ade8a729 1811 switch (abi) {
badfe9f5
MD
1812 case LTTNG_SYSCALL_ABI_NATIVE:
1813 bitmap = filter->sc_entry;
1814 break;
1815 case LTTNG_SYSCALL_ABI_COMPAT:
1816 bitmap = filter->sc_compat_entry;
1817 break;
6d9694d8
MD
1818 default:
1819 return -EINVAL;
80f87dd2 1820 }
badfe9f5
MD
1821 break;
1822 case LTTNG_SYSCALL_EXIT:
ade8a729 1823 switch (abi) {
badfe9f5
MD
1824 case LTTNG_SYSCALL_ABI_NATIVE:
1825 bitmap = filter->sc_exit;
1826 break;
1827 case LTTNG_SYSCALL_ABI_COMPAT:
1828 bitmap = filter->sc_compat_exit;
1829 break;
6d9694d8
MD
1830 default:
1831 return -EINVAL;
80f87dd2 1832 }
badfe9f5
MD
1833 break;
1834 default:
1835 return -EINVAL;
80f87dd2 1836 }
badfe9f5
MD
1837 if (test_bit(syscall_nr, bitmap))
1838 return -EEXIST;
1839 bitmap_set(bitmap, syscall_nr, 1);
80f87dd2 1840 return 0;
80f87dd2
MD
1841}
1842
8a8ac9a8
FD
1843int lttng_syscall_filter_enable_event_notifier(
1844 struct lttng_event_notifier *notifier)
1845{
1846 struct lttng_event_notifier_group *group = notifier->group;
1847 unsigned int syscall_id = notifier->u.syscall.syscall_id;
1848 struct hlist_head *dispatch_list;
1849 int ret = 0;
1850
1851 WARN_ON_ONCE(notifier->instrumentation != LTTNG_KERNEL_SYSCALL);
1852
1853 ret = lttng_syscall_filter_enable(group->sc_filter,
1854 notifier->desc->name, notifier->u.syscall.abi,
1855 notifier->u.syscall.entryexit);
1856 if (ret) {
1857 goto end;
1858 }
1859
1860 switch (notifier->u.syscall.entryexit) {
1861 case LTTNG_SYSCALL_ENTRY:
1862 switch (notifier->u.syscall.abi) {
1863 case LTTNG_SYSCALL_ABI_NATIVE:
1864 dispatch_list = &group->event_notifier_syscall_dispatch[syscall_id];
1865 break;
1866 case LTTNG_SYSCALL_ABI_COMPAT:
1867 dispatch_list = &group->event_notifier_compat_syscall_dispatch[syscall_id];
1868 break;
1869 }
1870 break;
1871 case LTTNG_SYSCALL_EXIT:
1872 switch (notifier->u.syscall.abi) {
1873 case LTTNG_SYSCALL_ABI_NATIVE:
1874 dispatch_list = &group->event_notifier_exit_syscall_dispatch[syscall_id];
1875 break;
1876 case LTTNG_SYSCALL_ABI_COMPAT:
1877 dispatch_list = &group->event_notifier_exit_compat_syscall_dispatch[syscall_id];
1878 break;
1879 }
1880 break;
1881 }
1882
1883 hlist_add_head_rcu(&notifier->u.syscall.node, dispatch_list);
1884
1885end:
1886 return ret ;
1887}
1888
ade8a729
FD
1889int lttng_syscall_filter_enable_event(
1890 struct lttng_channel *channel,
badfe9f5 1891 struct lttng_event *event)
80f87dd2 1892{
ade8a729
FD
1893 WARN_ON_ONCE(event->instrumentation != LTTNG_KERNEL_SYSCALL);
1894
1895 return lttng_syscall_filter_enable(channel->sc_filter,
1896 event->desc->name, event->u.syscall.abi,
1897 event->u.syscall.entryexit);
1898}
1899
1900static
1901int lttng_syscall_filter_disable(
1902 struct lttng_syscall_filter *filter,
1903 const char *desc_name, enum lttng_syscall_abi abi,
1904 enum lttng_syscall_entryexit entryexit)
1905{
badfe9f5
MD
1906 const char *syscall_name;
1907 unsigned long *bitmap;
1908 int syscall_nr;
80f87dd2 1909
ade8a729 1910 syscall_name = get_syscall_name(desc_name, abi, entryexit);
80f87dd2 1911
ade8a729 1912 switch (abi) {
badfe9f5
MD
1913 case LTTNG_SYSCALL_ABI_NATIVE:
1914 syscall_nr = get_syscall_nr(syscall_name);
1915 break;
1916 case LTTNG_SYSCALL_ABI_COMPAT:
1917 syscall_nr = get_compat_syscall_nr(syscall_name);
1918 break;
1919 default:
1920 return -EINVAL;
80f87dd2 1921 }
badfe9f5
MD
1922 if (syscall_nr < 0)
1923 return -ENOENT;
80f87dd2 1924
ade8a729 1925 switch (entryexit) {
badfe9f5 1926 case LTTNG_SYSCALL_ENTRY:
ade8a729 1927 switch (abi) {
badfe9f5
MD
1928 case LTTNG_SYSCALL_ABI_NATIVE:
1929 bitmap = filter->sc_entry;
1930 break;
1931 case LTTNG_SYSCALL_ABI_COMPAT:
1932 bitmap = filter->sc_compat_entry;
1933 break;
6d9694d8
MD
1934 default:
1935 return -EINVAL;
80f87dd2 1936 }
badfe9f5
MD
1937 break;
1938 case LTTNG_SYSCALL_EXIT:
ade8a729 1939 switch (abi) {
badfe9f5
MD
1940 case LTTNG_SYSCALL_ABI_NATIVE:
1941 bitmap = filter->sc_exit;
1942 break;
1943 case LTTNG_SYSCALL_ABI_COMPAT:
1944 bitmap = filter->sc_compat_exit;
1945 break;
6d9694d8
MD
1946 default:
1947 return -EINVAL;
80f87dd2 1948 }
badfe9f5
MD
1949 break;
1950 default:
1951 return -EINVAL;
80f87dd2 1952 }
badfe9f5
MD
1953 if (!test_bit(syscall_nr, bitmap))
1954 return -EEXIST;
1955 bitmap_clear(bitmap, syscall_nr, 1);
80f87dd2 1956
badfe9f5 1957 return 0;
259b6cb3 1958}
2d2464bd 1959
8a8ac9a8
FD
1960int lttng_syscall_filter_disable_event_notifier(
1961 struct lttng_event_notifier *notifier)
1962{
1963 struct lttng_event_notifier_group *group = notifier->group;
1964 int ret;
1965
1966 WARN_ON_ONCE(notifier->instrumentation != LTTNG_KERNEL_SYSCALL);
1967
1968 ret = lttng_syscall_filter_disable(group->sc_filter,
1969 notifier->desc->name, notifier->u.syscall.abi,
1970 notifier->u.syscall.entryexit);
1971 WARN_ON_ONCE(ret != 0);
1972
1973 hlist_del_rcu(&notifier->u.syscall.node);
1974 return 0;
1975}
1976
ade8a729
FD
1977int lttng_syscall_filter_disable_event(
1978 struct lttng_channel *channel,
1979 struct lttng_event *event)
1980{
1981 return lttng_syscall_filter_disable(channel->sc_filter,
1982 event->desc->name, event->u.syscall.abi,
1983 event->u.syscall.entryexit);
1984}
1985
2d2464bd
MD
1986static
1987const struct trace_syscall_entry *syscall_list_get_entry(loff_t *pos)
1988{
1989 const struct trace_syscall_entry *entry;
1990 int iter = 0;
1991
1992 for (entry = sc_table;
1993 entry < sc_table + ARRAY_SIZE(sc_table);
1994 entry++) {
1995 if (iter++ >= *pos)
1996 return entry;
1997 }
1998 for (entry = compat_sc_table;
1999 entry < compat_sc_table + ARRAY_SIZE(compat_sc_table);
2000 entry++) {
2001 if (iter++ >= *pos)
2002 return entry;
2003 }
2004 /* End of list */
2005 return NULL;
2006}
2007
2008static
2009void *syscall_list_start(struct seq_file *m, loff_t *pos)
2010{
2011 return (void *) syscall_list_get_entry(pos);
2012}
2013
2014static
2015void *syscall_list_next(struct seq_file *m, void *p, loff_t *ppos)
2016{
2017 (*ppos)++;
2018 return (void *) syscall_list_get_entry(ppos);
2019}
2020
2021static
2022void syscall_list_stop(struct seq_file *m, void *p)
2023{
2024}
2025
12e579db
MD
2026static
2027int get_sc_table(const struct trace_syscall_entry *entry,
2028 const struct trace_syscall_entry **table,
2029 unsigned int *bitness)
2030{
2031 if (entry >= sc_table && entry < sc_table + ARRAY_SIZE(sc_table)) {
2032 if (bitness)
2033 *bitness = BITS_PER_LONG;
2034 if (table)
2035 *table = sc_table;
2036 return 0;
2037 }
2038 if (!(entry >= compat_sc_table
2039 && entry < compat_sc_table + ARRAY_SIZE(compat_sc_table))) {
2040 return -EINVAL;
2041 }
2042 if (bitness)
2043 *bitness = 32;
2044 if (table)
2045 *table = compat_sc_table;
2046 return 0;
2047}
2048
2d2464bd
MD
2049static
2050int syscall_list_show(struct seq_file *m, void *p)
2051{
2052 const struct trace_syscall_entry *table, *entry = p;
2053 unsigned int bitness;
d4291869 2054 unsigned long index;
12e579db 2055 int ret;
d4291869 2056 const char *name;
2d2464bd 2057
12e579db
MD
2058 ret = get_sc_table(entry, &table, &bitness);
2059 if (ret)
2060 return ret;
f4855b46
MD
2061 if (!entry->desc)
2062 return 0;
d4291869
MD
2063 if (table == sc_table) {
2064 index = entry - table;
2065 name = &entry->desc->name[strlen(SYSCALL_ENTRY_STR)];
2066 } else {
2067 index = (entry - table) + ARRAY_SIZE(sc_table);
2068 name = &entry->desc->name[strlen(COMPAT_SYSCALL_ENTRY_STR)];
2069 }
12e579db 2070 seq_printf(m, "syscall { index = %lu; name = %s; bitness = %u; };\n",
d4291869 2071 index, name, bitness);
2d2464bd
MD
2072 return 0;
2073}
2074
2075static
2076const struct seq_operations lttng_syscall_list_seq_ops = {
2077 .start = syscall_list_start,
2078 .next = syscall_list_next,
2079 .stop = syscall_list_stop,
2080 .show = syscall_list_show,
2081};
2082
2083static
2084int lttng_syscall_list_open(struct inode *inode, struct file *file)
2085{
2086 return seq_open(file, &lttng_syscall_list_seq_ops);
2087}
2088
2089const struct file_operations lttng_syscall_list_fops = {
2090 .owner = THIS_MODULE,
2091 .open = lttng_syscall_list_open,
2092 .read = seq_read,
2093 .llseek = seq_lseek,
2094 .release = seq_release,
2095};
12e579db 2096
badfe9f5
MD
2097/*
2098 * A syscall is enabled if it is traced for either entry or exit.
2099 */
12e579db
MD
2100long lttng_channel_syscall_mask(struct lttng_channel *channel,
2101 struct lttng_kernel_syscall_mask __user *usyscall_mask)
2102{
2103 uint32_t len, sc_tables_len, bitmask_len;
2104 int ret = 0, bit;
2105 char *tmp_mask;
2106 struct lttng_syscall_filter *filter;
2107
2108 ret = get_user(len, &usyscall_mask->len);
2109 if (ret)
2110 return ret;
2111 sc_tables_len = get_sc_tables_len();
2112 bitmask_len = ALIGN(sc_tables_len, 8) >> 3;
2113 if (len < sc_tables_len) {
2114 return put_user(sc_tables_len, &usyscall_mask->len);
2115 }
2116 /* Array is large enough, we can copy array to user-space. */
2117 tmp_mask = kzalloc(bitmask_len, GFP_KERNEL);
2118 if (!tmp_mask)
2119 return -ENOMEM;
2120 filter = channel->sc_filter;
2121
2122 for (bit = 0; bit < ARRAY_SIZE(sc_table); bit++) {
e2129868 2123 char state;
2f25059d
MD
2124
2125 if (channel->sc_table) {
badfe9f5
MD
2126 if (!READ_ONCE(channel->syscall_all) && filter)
2127 state = test_bit(bit, filter->sc_entry)
2128 || test_bit(bit, filter->sc_exit);
2f25059d
MD
2129 else
2130 state = 1;
2131 } else {
2132 state = 0;
2133 }
2134 bt_bitfield_write_be(tmp_mask, char, bit, 1, state);
12e579db
MD
2135 }
2136 for (; bit < sc_tables_len; bit++) {
e2129868 2137 char state;
2f25059d
MD
2138
2139 if (channel->compat_sc_table) {
badfe9f5 2140 if (!READ_ONCE(channel->syscall_all) && filter)
2f25059d 2141 state = test_bit(bit - ARRAY_SIZE(sc_table),
badfe9f5
MD
2142 filter->sc_compat_entry)
2143 || test_bit(bit - ARRAY_SIZE(sc_table),
2144 filter->sc_compat_exit);
2f25059d
MD
2145 else
2146 state = 1;
2147 } else {
2148 state = 0;
2149 }
2150 bt_bitfield_write_be(tmp_mask, char, bit, 1, state);
12e579db
MD
2151 }
2152 if (copy_to_user(usyscall_mask->mask, tmp_mask, bitmask_len))
2153 ret = -EFAULT;
2154 kfree(tmp_mask);
2155 return ret;
2156}
082d4946
MD
2157
2158int lttng_abi_syscall_list(void)
2159{
2160 struct file *syscall_list_file;
2161 int file_fd, ret;
2162
4ac10b76 2163 file_fd = lttng_get_unused_fd();
082d4946
MD
2164 if (file_fd < 0) {
2165 ret = file_fd;
2166 goto fd_error;
2167 }
2168
2169 syscall_list_file = anon_inode_getfile("[lttng_syscall_list]",
2170 &lttng_syscall_list_fops,
2171 NULL, O_RDWR);
2172 if (IS_ERR(syscall_list_file)) {
2173 ret = PTR_ERR(syscall_list_file);
2174 goto file_error;
2175 }
2176 ret = lttng_syscall_list_fops.open(NULL, syscall_list_file);
2177 if (ret < 0)
2178 goto open_error;
2179 fd_install(file_fd, syscall_list_file);
082d4946
MD
2180 return file_fd;
2181
2182open_error:
2183 fput(syscall_list_file);
2184file_error:
2185 put_unused_fd(file_fd);
2186fd_error:
2187 return ret;
2188}
This page took 0.146169 seconds and 4 git commands to generate.