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