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