Namespace syscall code relating to events
[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>
259b6cb3 32
6333ace3 33#ifndef CONFIG_COMPAT
bfa949bf
MD
34# ifndef is_compat_task
35# define is_compat_task() (0)
36# endif
6333ace3
MD
37#endif
38
1aa3298b
MD
39/* in_compat_syscall appears in kernel 4.6. */
40#ifndef in_compat_syscall
41 #define in_compat_syscall() is_compat_task()
42#endif
43
5b7ac358
MD
44enum sc_type {
45 SC_TYPE_ENTRY,
46 SC_TYPE_EXIT,
47 SC_TYPE_COMPAT_ENTRY,
48 SC_TYPE_COMPAT_EXIT,
49};
50
d4291869
MD
51#define SYSCALL_ENTRY_TOK syscall_entry_
52#define COMPAT_SYSCALL_ENTRY_TOK compat_syscall_entry_
53#define SYSCALL_EXIT_TOK syscall_exit_
54#define COMPAT_SYSCALL_EXIT_TOK compat_syscall_exit_
55
56#define SYSCALL_ENTRY_STR __stringify(SYSCALL_ENTRY_TOK)
57#define COMPAT_SYSCALL_ENTRY_STR __stringify(COMPAT_SYSCALL_ENTRY_TOK)
58#define SYSCALL_EXIT_STR __stringify(SYSCALL_EXIT_TOK)
59#define COMPAT_SYSCALL_EXIT_STR __stringify(COMPAT_SYSCALL_EXIT_TOK)
5b7ac358 60
a93244f8 61static
2d6d88c6 62void syscall_entry_event_probe(void *__data, struct pt_regs *regs, long id);
5b7ac358 63static
2d6d88c6 64void syscall_exit_event_probe(void *__data, struct pt_regs *regs, long ret);
259b6cb3 65
3a523f5b
MD
66/*
67 * Forward declarations for old kernels.
68 */
69struct mmsghdr;
70struct rlimit64;
71struct oldold_utsname;
72struct old_utsname;
73struct sel_arg_struct;
74struct mmap_arg_struct;
c0b71117 75struct file_handle;
a292e6f1 76struct user_msghdr;
3a523f5b 77
9eb15e8b
MJ
78/*
79 * Forward declaration for kernels >= 5.6
80 */
81struct timex;
edfdcb68
MJ
82struct timeval;
83struct itimerval;
84struct itimerspec;
85
86#if (LINUX_VERSION_CODE >= KERNEL_VERSION(5,6,0))
87typedef __kernel_old_time_t time_t;
88#endif
9eb15e8b 89
80f87dd2
MD
90#ifdef IA32_NR_syscalls
91#define NR_compat_syscalls IA32_NR_syscalls
92#else
93#define NR_compat_syscalls NR_syscalls
94#endif
95
259b6cb3
MD
96/*
97 * Create LTTng tracepoint probes.
98 */
99#define LTTNG_PACKAGE_BUILD
100#define CREATE_TRACE_POINTS
2655f9ad 101#define TP_MODULE_NOINIT
c075712b 102#define TRACE_INCLUDE_PATH instrumentation/syscalls/headers
259b6cb3 103
a93244f8
MD
104#define PARAMS(args...) args
105
5b7ac358 106/* Handle unknown syscalls */
72a52753 107#undef TRACE_SYSTEM
5b7ac358 108#define TRACE_SYSTEM syscalls_unknown
241ae9a8 109#include <instrumentation/syscalls/headers/syscalls_unknown.h>
5b7ac358
MD
110#undef TRACE_SYSTEM
111
fc4f7161
MD
112#define SC_ENTER
113
fc4f7161
MD
114#undef sc_exit
115#define sc_exit(...)
b75d00c4
MD
116#undef sc_in
117#define sc_in(...) __VA_ARGS__
118#undef sc_out
119#define sc_out(...)
120#undef sc_inout
121#define sc_inout(...) __VA_ARGS__
5b7ac358
MD
122
123/* Hijack probe callback for system call enter */
a93244f8 124#undef TP_PROBE_CB
2d6d88c6 125#define TP_PROBE_CB(_template) &syscall_entry_event_probe
57ede728 126#define SC_LTTNG_TRACEPOINT_EVENT(_name, _proto, _args, _fields) \
d4291869 127 LTTNG_TRACEPOINT_EVENT(syscall_entry_##_name, PARAMS(_proto), PARAMS(_args), \
57ede728 128 PARAMS(_fields))
265822ae 129#define SC_LTTNG_TRACEPOINT_EVENT_CODE(_name, _proto, _args, _locvar, _code_pre, _fields, _code_post) \
d4291869 130 LTTNG_TRACEPOINT_EVENT_CODE(syscall_entry_##_name, PARAMS(_proto), PARAMS(_args), \
265822ae
MD
131 PARAMS(_locvar), PARAMS(_code_pre), \
132 PARAMS(_fields), PARAMS(_code_post))
57ede728
MD
133#define SC_LTTNG_TRACEPOINT_EVENT_CLASS_NOARGS(_name, _fields) \
134 LTTNG_TRACEPOINT_EVENT_CLASS_NOARGS(syscall_entry_##_name, PARAMS(_fields))
cb3ef14c 135#define SC_LTTNG_TRACEPOINT_EVENT_INSTANCE_NOARGS(_template, _name) \
d4291869 136 LTTNG_TRACEPOINT_EVENT_INSTANCE_NOARGS(syscall_entry_##_template, syscall_entry_##_name)
141ddf28
MD
137/* Enumerations only defined at first inclusion. */
138#define SC_LTTNG_TRACEPOINT_ENUM(_name, _values) \
139 LTTNG_TRACEPOINT_ENUM(_name, PARAMS(_values))
a93244f8 140#undef TRACE_SYSTEM
d4291869 141#define TRACE_SYSTEM syscall_entry_integers
5b7ac358 142#define TRACE_INCLUDE_FILE syscalls_integers
241ae9a8 143#include <instrumentation/syscalls/headers/syscalls_integers.h>
5b7ac358 144#undef TRACE_INCLUDE_FILE
a93244f8 145#undef TRACE_SYSTEM
d4291869 146#define TRACE_SYSTEM syscall_entry_pointers
5b7ac358 147#define TRACE_INCLUDE_FILE syscalls_pointers
241ae9a8 148#include <instrumentation/syscalls/headers/syscalls_pointers.h>
5b7ac358 149#undef TRACE_INCLUDE_FILE
a93244f8 150#undef TRACE_SYSTEM
141ddf28 151#undef SC_LTTNG_TRACEPOINT_ENUM
cb3ef14c
MD
152#undef SC_LTTNG_TRACEPOINT_EVENT_CODE
153#undef SC_LTTNG_TRACEPOINT_EVENT
154#undef SC_LTTNG_TRACEPOINT_EVENT_CLASS_NOARGS
155#undef SC_LTTNG_TRACEPOINT_EVENT_INSTANCE_NOARGS
5b7ac358 156#undef TP_PROBE_CB
3bc29f0a
MD
157#undef _TRACE_SYSCALLS_INTEGERS_H
158#undef _TRACE_SYSCALLS_POINTERS_H
5b7ac358
MD
159
160/* Hijack probe callback for compat system call enter */
2d6d88c6 161#define TP_PROBE_CB(_template) &syscall_entry_event_probe
771af27e 162#define LTTNG_SC_COMPAT
57ede728 163#define SC_LTTNG_TRACEPOINT_EVENT(_name, _proto, _args, _fields) \
d4291869 164 LTTNG_TRACEPOINT_EVENT(compat_syscall_entry_##_name, PARAMS(_proto), PARAMS(_args), \
57ede728 165 PARAMS(_fields))
265822ae 166#define SC_LTTNG_TRACEPOINT_EVENT_CODE(_name, _proto, _args, _locvar, _code_pre, _fields, _code_post) \
d4291869 167 LTTNG_TRACEPOINT_EVENT_CODE(compat_syscall_entry_##_name, PARAMS(_proto), PARAMS(_args), \
265822ae 168 PARAMS(_locvar), PARAMS(_code_pre), PARAMS(_fields), PARAMS(_code_post))
57ede728
MD
169#define SC_LTTNG_TRACEPOINT_EVENT_CLASS_NOARGS(_name, _fields) \
170 LTTNG_TRACEPOINT_EVENT_CLASS_NOARGS(compat_syscall_entry_##_name, PARAMS(_fields))
cb3ef14c 171#define SC_LTTNG_TRACEPOINT_EVENT_INSTANCE_NOARGS(_template, _name) \
d4291869
MD
172 LTTNG_TRACEPOINT_EVENT_INSTANCE_NOARGS(compat_syscall_entry_##_template, \
173 compat_syscall_entry_##_name)
141ddf28
MD
174/* Enumerations only defined at inital inclusion (not here). */
175#define SC_LTTNG_TRACEPOINT_ENUM(_name, _values)
d4291869 176#define TRACE_SYSTEM compat_syscall_entry_integers
5b7ac358 177#define TRACE_INCLUDE_FILE compat_syscalls_integers
241ae9a8 178#include <instrumentation/syscalls/headers/compat_syscalls_integers.h>
5b7ac358
MD
179#undef TRACE_INCLUDE_FILE
180#undef TRACE_SYSTEM
d4291869 181#define TRACE_SYSTEM compat_syscall_entry_pointers
5b7ac358 182#define TRACE_INCLUDE_FILE compat_syscalls_pointers
241ae9a8 183#include <instrumentation/syscalls/headers/compat_syscalls_pointers.h>
5b7ac358
MD
184#undef TRACE_INCLUDE_FILE
185#undef TRACE_SYSTEM
141ddf28 186#undef SC_LTTNG_TRACEPOINT_ENUM
cb3ef14c
MD
187#undef SC_LTTNG_TRACEPOINT_EVENT_CODE
188#undef SC_LTTNG_TRACEPOINT_EVENT
189#undef SC_LTTNG_TRACEPOINT_EVENT_CLASS_NOARGS
190#undef SC_LTTNG_TRACEPOINT_EVENT_INSTANCE_NOARGS
5b7ac358 191#undef TP_PROBE_CB
3bc29f0a
MD
192#undef _TRACE_SYSCALLS_INTEGERS_H
193#undef _TRACE_SYSCALLS_POINTERS_H
771af27e 194#undef LTTNG_SC_COMPAT
5b7ac358 195
fc4f7161
MD
196#undef SC_ENTER
197
198#define SC_EXIT
199
fc4f7161
MD
200#undef sc_exit
201#define sc_exit(...) __VA_ARGS__
b75d00c4
MD
202#undef sc_in
203#define sc_in(...)
204#undef sc_out
205#define sc_out(...) __VA_ARGS__
206#undef sc_inout
207#define sc_inout(...) __VA_ARGS__
5b7ac358
MD
208
209/* Hijack probe callback for system call exit */
2d6d88c6 210#define TP_PROBE_CB(_template) &syscall_exit_event_probe
57ede728 211#define SC_LTTNG_TRACEPOINT_EVENT(_name, _proto, _args, _fields) \
3bc29f0a 212 LTTNG_TRACEPOINT_EVENT(syscall_exit_##_name, PARAMS(_proto), PARAMS(_args), \
57ede728 213 PARAMS(_fields))
265822ae 214#define SC_LTTNG_TRACEPOINT_EVENT_CODE(_name, _proto, _args, _locvar, _code_pre, _fields, _code_post) \
3bc29f0a 215 LTTNG_TRACEPOINT_EVENT_CODE(syscall_exit_##_name, PARAMS(_proto), PARAMS(_args), \
265822ae 216 PARAMS(_locvar), PARAMS(_code_pre), PARAMS(_fields), PARAMS(_code_post))
57ede728
MD
217#define SC_LTTNG_TRACEPOINT_EVENT_CLASS_NOARGS(_name, _fields) \
218 LTTNG_TRACEPOINT_EVENT_CLASS_NOARGS(syscall_exit_##_name, PARAMS(_fields))
cb3ef14c
MD
219#define SC_LTTNG_TRACEPOINT_EVENT_INSTANCE_NOARGS(_template, _name) \
220 LTTNG_TRACEPOINT_EVENT_INSTANCE_NOARGS(syscall_exit_##_template, \
5b7ac358 221 syscall_exit_##_name)
141ddf28
MD
222/* Enumerations only defined at inital inclusion (not here). */
223#define SC_LTTNG_TRACEPOINT_ENUM(_name, _values)
5b7ac358
MD
224#define TRACE_SYSTEM syscall_exit_integers
225#define TRACE_INCLUDE_FILE syscalls_integers
241ae9a8 226#include <instrumentation/syscalls/headers/syscalls_integers.h>
5b7ac358
MD
227#undef TRACE_INCLUDE_FILE
228#undef TRACE_SYSTEM
229#define TRACE_SYSTEM syscall_exit_pointers
230#define TRACE_INCLUDE_FILE syscalls_pointers
241ae9a8 231#include <instrumentation/syscalls/headers/syscalls_pointers.h>
5b7ac358
MD
232#undef TRACE_INCLUDE_FILE
233#undef TRACE_SYSTEM
141ddf28 234#undef SC_LTTNG_TRACEPOINT_ENUM
cb3ef14c
MD
235#undef SC_LTTNG_TRACEPOINT_EVENT_CODE
236#undef SC_LTTNG_TRACEPOINT_EVENT
237#undef SC_LTTNG_TRACEPOINT_EVENT_CLASS_NOARGS
238#undef SC_LTTNG_TRACEPOINT_EVENT_INSTANCE_NOARGS
5b7ac358 239#undef TP_PROBE_CB
3bc29f0a
MD
240#undef _TRACE_SYSCALLS_INTEGERS_H
241#undef _TRACE_SYSCALLS_POINTERS_H
5b7ac358
MD
242
243
244/* Hijack probe callback for compat system call exit */
2d6d88c6 245#define TP_PROBE_CB(_template) &syscall_exit_event_probe
771af27e 246#define LTTNG_SC_COMPAT
57ede728 247#define SC_LTTNG_TRACEPOINT_EVENT(_name, _proto, _args, _fields) \
3bc29f0a 248 LTTNG_TRACEPOINT_EVENT(compat_syscall_exit_##_name, PARAMS(_proto), PARAMS(_args), \
57ede728 249 PARAMS(_fields))
265822ae 250#define SC_LTTNG_TRACEPOINT_EVENT_CODE(_name, _proto, _args, _locvar, _code_pre, _fields, _code_post) \
3bc29f0a 251 LTTNG_TRACEPOINT_EVENT_CODE(compat_syscall_exit_##_name, PARAMS(_proto), PARAMS(_args), \
265822ae 252 PARAMS(_locvar), PARAMS(_code_pre), PARAMS(_fields), PARAMS(_code_post))
57ede728
MD
253#define SC_LTTNG_TRACEPOINT_EVENT_CLASS_NOARGS(_name, _fields) \
254 LTTNG_TRACEPOINT_EVENT_CLASS_NOARGS(compat_syscall_exit_##_name, PARAMS(_fields))
cb3ef14c 255#define SC_LTTNG_TRACEPOINT_EVENT_INSTANCE_NOARGS(_template, _name) \
3bc29f0a 256 LTTNG_TRACEPOINT_EVENT_INSTANCE_NOARGS(compat_syscall_exit_##_template, \
5b7ac358 257 compat_syscall_exit_##_name)
141ddf28
MD
258/* Enumerations only defined at inital inclusion (not here). */
259#define SC_LTTNG_TRACEPOINT_ENUM(_name, _values)
5b7ac358
MD
260#define TRACE_SYSTEM compat_syscall_exit_integers
261#define TRACE_INCLUDE_FILE compat_syscalls_integers
241ae9a8 262#include <instrumentation/syscalls/headers/compat_syscalls_integers.h>
5b7ac358 263#undef TRACE_INCLUDE_FILE
a93244f8 264#undef TRACE_SYSTEM
5b7ac358
MD
265#define TRACE_SYSTEM compat_syscall_exit_pointers
266#define TRACE_INCLUDE_FILE compat_syscalls_pointers
241ae9a8 267#include <instrumentation/syscalls/headers/compat_syscalls_pointers.h>
5b7ac358 268#undef TRACE_INCLUDE_FILE
a93244f8 269#undef TRACE_SYSTEM
141ddf28 270#undef SC_LTTNG_TRACEPOINT_ENUM
cb3ef14c
MD
271#undef SC_LTTNG_TRACEPOINT_EVENT_CODE
272#undef SC_LTTNG_TRACEPOINT_EVENT
273#undef SC_LTTNG_TRACEPOINT_EVENT_CLASS_NOARGS
274#undef SC_LTTNG_TRACEPOINT_EVENT_INSTANCE_NOARGS
a93244f8 275#undef TP_PROBE_CB
3bc29f0a
MD
276#undef _TRACE_SYSCALLS_INTEGERS_H
277#undef _TRACE_SYSCALLS_POINTERS_H
771af27e 278#undef LTTNG_SC_COMPAT
5b7ac358 279
fc4f7161 280#undef SC_EXIT
259b6cb3 281
2655f9ad 282#undef TP_MODULE_NOINIT
259b6cb3
MD
283#undef LTTNG_PACKAGE_BUILD
284#undef CREATE_TRACE_POINTS
285
a93244f8 286struct trace_syscall_entry {
2d6d88c6 287 void *event_func;
a93244f8
MD
288 const struct lttng_event_desc *desc;
289 const struct lttng_event_field *fields;
290 unsigned int nrargs;
291};
292
293#define CREATE_SYSCALL_TABLE
294
fc4f7161
MD
295#define SC_ENTER
296
297#undef sc_exit
298#define sc_exit(...)
299
259b6cb3 300#undef TRACE_SYSCALL_TABLE
f7bdf4db 301#define TRACE_SYSCALL_TABLE(_template, _name, _nr, _nrargs) \
259b6cb3 302 [ _nr ] = { \
2d6d88c6 303 .event_func = __event_probe__syscall_entry_##_template, \
259b6cb3 304 .nrargs = (_nrargs), \
d4291869
MD
305 .fields = __event_fields___syscall_entry_##_template, \
306 .desc = &__event_desc___syscall_entry_##_name, \
259b6cb3
MD
307 },
308
2d6d88c6 309/* Event syscall enter tracing table */
49c50022 310static const struct trace_syscall_entry sc_table[] = {
241ae9a8
MD
311#include <instrumentation/syscalls/headers/syscalls_integers.h>
312#include <instrumentation/syscalls/headers/syscalls_pointers.h>
259b6cb3
MD
313};
314
a93244f8
MD
315#undef TRACE_SYSCALL_TABLE
316#define TRACE_SYSCALL_TABLE(_template, _name, _nr, _nrargs) \
317 [ _nr ] = { \
2d6d88c6 318 .event_func = __event_probe__compat_syscall_entry_##_template, \
a93244f8 319 .nrargs = (_nrargs), \
d4291869
MD
320 .fields = __event_fields___compat_syscall_entry_##_template, \
321 .desc = &__event_desc___compat_syscall_entry_##_name, \
a93244f8
MD
322 },
323
2d6d88c6 324/* Event compat syscall enter table */
a93244f8 325const struct trace_syscall_entry compat_sc_table[] = {
241ae9a8
MD
326#include <instrumentation/syscalls/headers/compat_syscalls_integers.h>
327#include <instrumentation/syscalls/headers/compat_syscalls_pointers.h>
a93244f8 328};
259b6cb3 329
fc4f7161
MD
330#undef SC_ENTER
331
332#define SC_EXIT
333
334#undef sc_exit
335#define sc_exit(...) __VA_ARGS__
336
5b7ac358
MD
337#undef TRACE_SYSCALL_TABLE
338#define TRACE_SYSCALL_TABLE(_template, _name, _nr, _nrargs) \
339 [ _nr ] = { \
2d6d88c6 340 .event_func = __event_probe__syscall_exit_##_template, \
5b7ac358
MD
341 .nrargs = (_nrargs), \
342 .fields = __event_fields___syscall_exit_##_template, \
343 .desc = &__event_desc___syscall_exit_##_name, \
344 },
345
2d6d88c6 346/* Event syscall exit table */
5b7ac358 347static const struct trace_syscall_entry sc_exit_table[] = {
241ae9a8
MD
348#include <instrumentation/syscalls/headers/syscalls_integers.h>
349#include <instrumentation/syscalls/headers/syscalls_pointers.h>
5b7ac358
MD
350};
351
352#undef TRACE_SYSCALL_TABLE
353#define TRACE_SYSCALL_TABLE(_template, _name, _nr, _nrargs) \
354 [ _nr ] = { \
2d6d88c6 355 .event_func = __event_probe__compat_syscall_exit_##_template, \
5b7ac358
MD
356 .nrargs = (_nrargs), \
357 .fields = __event_fields___compat_syscall_exit_##_template, \
358 .desc = &__event_desc___compat_syscall_exit_##_name, \
359 },
360
2d6d88c6 361/* Event compat syscall exit table */
5b7ac358 362const struct trace_syscall_entry compat_sc_exit_table[] = {
241ae9a8
MD
363#include <instrumentation/syscalls/headers/compat_syscalls_integers.h>
364#include <instrumentation/syscalls/headers/compat_syscalls_pointers.h>
5b7ac358
MD
365};
366
fc4f7161
MD
367#undef SC_EXIT
368
a93244f8 369#undef CREATE_SYSCALL_TABLE
2faf7d1b 370
80f87dd2 371struct lttng_syscall_filter {
badfe9f5
MD
372 DECLARE_BITMAP(sc_entry, NR_syscalls);
373 DECLARE_BITMAP(sc_exit, NR_syscalls);
374 DECLARE_BITMAP(sc_compat_entry, NR_compat_syscalls);
375 DECLARE_BITMAP(sc_compat_exit, NR_compat_syscalls);
80f87dd2
MD
376};
377
2d6d88c6 378static void syscall_entry_event_unknown(struct lttng_event *event,
f405cfce
MD
379 struct pt_regs *regs, unsigned int id)
380{
1b7b9c65 381 unsigned long args[LTTNG_SYSCALL_NR_ARGS];
f405cfce 382
1b7b9c65 383 lttng_syscall_get_arguments(current, regs, args);
1aa3298b 384 if (unlikely(in_compat_syscall()))
d4291869 385 __event_probe__compat_syscall_entry_unknown(event, id, args);
a93244f8 386 else
d4291869 387 __event_probe__syscall_entry_unknown(event, id, args);
f405cfce
MD
388}
389
2d6d88c6 390void syscall_entry_event_probe(void *__data, struct pt_regs *regs, long id)
259b6cb3 391{
a90917c3
MD
392 struct lttng_channel *chan = __data;
393 struct lttng_event *event, *unknown_event;
49c50022
MD
394 const struct trace_syscall_entry *table, *entry;
395 size_t table_len;
259b6cb3 396
1aa3298b 397 if (unlikely(in_compat_syscall())) {
badfe9f5
MD
398 struct lttng_syscall_filter *filter = chan->sc_filter;
399
400 if (id < 0 || id >= NR_compat_syscalls
401 || (!READ_ONCE(chan->syscall_all) && !test_bit(id, filter->sc_compat_entry))) {
402 /* System call filtered out. */
403 return;
80f87dd2 404 }
49c50022 405 table = compat_sc_table;
a93244f8 406 table_len = ARRAY_SIZE(compat_sc_table);
49c50022
MD
407 unknown_event = chan->sc_compat_unknown;
408 } else {
badfe9f5
MD
409 struct lttng_syscall_filter *filter = chan->sc_filter;
410
411 if (id < 0 || id >= NR_syscalls
412 || (!READ_ONCE(chan->syscall_all) && !test_bit(id, filter->sc_entry))) {
413 /* System call filtered out. */
414 return;
80f87dd2 415 }
49c50022
MD
416 table = sc_table;
417 table_len = ARRAY_SIZE(sc_table);
418 unknown_event = chan->sc_unknown;
b76dc1a0 419 }
74f7b56a 420 if (unlikely(id < 0 || id >= table_len)) {
2d6d88c6 421 syscall_entry_event_unknown(unknown_event, regs, id);
259b6cb3 422 return;
f405cfce 423 }
1aa3298b 424 if (unlikely(in_compat_syscall()))
49c50022
MD
425 event = chan->compat_sc_table[id];
426 else
427 event = chan->sc_table[id];
f405cfce 428 if (unlikely(!event)) {
2d6d88c6 429 syscall_entry_event_unknown(unknown_event, regs, id);
f405cfce
MD
430 return;
431 }
49c50022 432 entry = &table[id];
f405cfce 433 WARN_ON_ONCE(!entry);
259b6cb3
MD
434
435 switch (entry->nrargs) {
436 case 0:
437 {
2d6d88c6 438 void (*fptr)(void *__data) = entry->event_func;
259b6cb3
MD
439
440 fptr(event);
441 break;
442 }
443 case 1:
444 {
2d6d88c6 445 void (*fptr)(void *__data, unsigned long arg0) = entry->event_func;
1b7b9c65 446 unsigned long args[LTTNG_SYSCALL_NR_ARGS];
259b6cb3 447
1b7b9c65 448 lttng_syscall_get_arguments(current, regs, args);
259b6cb3
MD
449 fptr(event, args[0]);
450 break;
451 }
452 case 2:
453 {
454 void (*fptr)(void *__data,
455 unsigned long arg0,
2d6d88c6 456 unsigned long arg1) = entry->event_func;
1b7b9c65 457 unsigned long args[LTTNG_SYSCALL_NR_ARGS];
259b6cb3 458
1b7b9c65 459 lttng_syscall_get_arguments(current, regs, args);
259b6cb3
MD
460 fptr(event, args[0], args[1]);
461 break;
462 }
463 case 3:
464 {
465 void (*fptr)(void *__data,
466 unsigned long arg0,
467 unsigned long arg1,
2d6d88c6 468 unsigned long arg2) = entry->event_func;
1b7b9c65 469 unsigned long args[LTTNG_SYSCALL_NR_ARGS];
259b6cb3 470
1b7b9c65 471 lttng_syscall_get_arguments(current, regs, args);
259b6cb3
MD
472 fptr(event, args[0], args[1], args[2]);
473 break;
474 }
475 case 4:
476 {
477 void (*fptr)(void *__data,
478 unsigned long arg0,
479 unsigned long arg1,
480 unsigned long arg2,
2d6d88c6 481 unsigned long arg3) = entry->event_func;
1b7b9c65 482 unsigned long args[LTTNG_SYSCALL_NR_ARGS];
259b6cb3 483
1b7b9c65 484 lttng_syscall_get_arguments(current, regs, args);
259b6cb3
MD
485 fptr(event, args[0], args[1], args[2], args[3]);
486 break;
487 }
488 case 5:
489 {
490 void (*fptr)(void *__data,
491 unsigned long arg0,
492 unsigned long arg1,
493 unsigned long arg2,
494 unsigned long arg3,
2d6d88c6 495 unsigned long arg4) = entry->event_func;
1b7b9c65 496 unsigned long args[LTTNG_SYSCALL_NR_ARGS];
259b6cb3 497
1b7b9c65 498 lttng_syscall_get_arguments(current, regs, args);
259b6cb3
MD
499 fptr(event, args[0], args[1], args[2], args[3], args[4]);
500 break;
501 }
502 case 6:
503 {
504 void (*fptr)(void *__data,
505 unsigned long arg0,
506 unsigned long arg1,
507 unsigned long arg2,
508 unsigned long arg3,
509 unsigned long arg4,
2d6d88c6 510 unsigned long arg5) = entry->event_func;
1b7b9c65 511 unsigned long args[LTTNG_SYSCALL_NR_ARGS];
259b6cb3 512
1b7b9c65 513 lttng_syscall_get_arguments(current, regs, args);
259b6cb3
MD
514 fptr(event, args[0], args[1], args[2],
515 args[3], args[4], args[5]);
516 break;
517 }
518 default:
519 break;
520 }
521}
522
2d6d88c6 523static void syscall_exit_event_unknown(struct lttng_event *event,
74f7b56a 524 struct pt_regs *regs, int id, long ret)
5b7ac358 525{
1b7b9c65 526 unsigned long args[LTTNG_SYSCALL_NR_ARGS];
5b7ac358 527
1b7b9c65 528 lttng_syscall_get_arguments(current, regs, args);
1aa3298b 529 if (unlikely(in_compat_syscall()))
5b7ac358
MD
530 __event_probe__compat_syscall_exit_unknown(event, id, ret,
531 args);
532 else
533 __event_probe__syscall_exit_unknown(event, id, ret, args);
534}
535
2d6d88c6 536void syscall_exit_event_probe(void *__data, struct pt_regs *regs, long ret)
5b7ac358
MD
537{
538 struct lttng_channel *chan = __data;
539 struct lttng_event *event, *unknown_event;
540 const struct trace_syscall_entry *table, *entry;
541 size_t table_len;
542 long id;
543
544 id = syscall_get_nr(current, regs);
1aa3298b 545 if (unlikely(in_compat_syscall())) {
badfe9f5
MD
546 struct lttng_syscall_filter *filter = chan->sc_filter;
547
548 if (id < 0 || id >= NR_compat_syscalls
549 || (!READ_ONCE(chan->syscall_all) && !test_bit(id, filter->sc_compat_exit))) {
550 /* System call filtered out. */
551 return;
5b7ac358
MD
552 }
553 table = compat_sc_exit_table;
554 table_len = ARRAY_SIZE(compat_sc_exit_table);
555 unknown_event = chan->compat_sc_exit_unknown;
556 } else {
badfe9f5
MD
557 struct lttng_syscall_filter *filter = chan->sc_filter;
558
559 if (id < 0 || id >= NR_syscalls
560 || (!READ_ONCE(chan->syscall_all) && !test_bit(id, filter->sc_exit))) {
561 /* System call filtered out. */
562 return;
5b7ac358
MD
563 }
564 table = sc_exit_table;
565 table_len = ARRAY_SIZE(sc_exit_table);
566 unknown_event = chan->sc_exit_unknown;
567 }
74f7b56a 568 if (unlikely(id < 0 || id >= table_len)) {
2d6d88c6 569 syscall_exit_event_unknown(unknown_event, regs, id, ret);
5b7ac358
MD
570 return;
571 }
1aa3298b 572 if (unlikely(in_compat_syscall()))
5b7ac358
MD
573 event = chan->compat_sc_exit_table[id];
574 else
575 event = chan->sc_exit_table[id];
576 if (unlikely(!event)) {
2d6d88c6 577 syscall_exit_event_unknown(unknown_event, regs, id, ret);
5b7ac358
MD
578 return;
579 }
580 entry = &table[id];
581 WARN_ON_ONCE(!entry);
582
583 switch (entry->nrargs) {
584 case 0:
585 {
2d6d88c6 586 void (*fptr)(void *__data, long ret) = entry->event_func;
5b7ac358 587
fc4f7161 588 fptr(event, ret);
5b7ac358
MD
589 break;
590 }
591 case 1:
592 {
593 void (*fptr)(void *__data,
fc4f7161 594 long ret,
2d6d88c6 595 unsigned long arg0) = entry->event_func;
1b7b9c65 596 unsigned long args[LTTNG_SYSCALL_NR_ARGS];
5b7ac358 597
1b7b9c65 598 lttng_syscall_get_arguments(current, regs, args);
fc4f7161 599 fptr(event, ret, args[0]);
5b7ac358
MD
600 break;
601 }
602 case 2:
603 {
604 void (*fptr)(void *__data,
fc4f7161 605 long ret,
5b7ac358 606 unsigned long arg0,
2d6d88c6 607 unsigned long arg1) = entry->event_func;
1b7b9c65 608 unsigned long args[LTTNG_SYSCALL_NR_ARGS];
5b7ac358 609
1b7b9c65 610 lttng_syscall_get_arguments(current, regs, args);
fc4f7161 611 fptr(event, ret, args[0], args[1]);
5b7ac358
MD
612 break;
613 }
614 case 3:
615 {
616 void (*fptr)(void *__data,
fc4f7161 617 long ret,
5b7ac358
MD
618 unsigned long arg0,
619 unsigned long arg1,
2d6d88c6 620 unsigned long arg2) = entry->event_func;
1b7b9c65 621 unsigned long args[LTTNG_SYSCALL_NR_ARGS];
5b7ac358 622
1b7b9c65 623 lttng_syscall_get_arguments(current, regs, args);
fc4f7161 624 fptr(event, ret, args[0], args[1], args[2]);
5b7ac358
MD
625 break;
626 }
627 case 4:
628 {
629 void (*fptr)(void *__data,
fc4f7161 630 long ret,
5b7ac358
MD
631 unsigned long arg0,
632 unsigned long arg1,
633 unsigned long arg2,
2d6d88c6 634 unsigned long arg3) = entry->event_func;
1b7b9c65 635 unsigned long args[LTTNG_SYSCALL_NR_ARGS];
5b7ac358 636
1b7b9c65 637 lttng_syscall_get_arguments(current, regs, args);
fc4f7161 638 fptr(event, ret, args[0], args[1], args[2], args[3]);
5b7ac358
MD
639 break;
640 }
641 case 5:
642 {
643 void (*fptr)(void *__data,
fc4f7161 644 long ret,
5b7ac358
MD
645 unsigned long arg0,
646 unsigned long arg1,
647 unsigned long arg2,
648 unsigned long arg3,
2d6d88c6 649 unsigned long arg4) = entry->event_func;
1b7b9c65 650 unsigned long args[LTTNG_SYSCALL_NR_ARGS];
5b7ac358 651
1b7b9c65 652 lttng_syscall_get_arguments(current, regs, args);
fc4f7161 653 fptr(event, ret, args[0], args[1], args[2], args[3], args[4]);
5b7ac358
MD
654 break;
655 }
656 case 6:
657 {
658 void (*fptr)(void *__data,
fc4f7161 659 long ret,
5b7ac358
MD
660 unsigned long arg0,
661 unsigned long arg1,
662 unsigned long arg2,
663 unsigned long arg3,
664 unsigned long arg4,
2d6d88c6 665 unsigned long arg5) = entry->event_func;
1b7b9c65 666 unsigned long args[LTTNG_SYSCALL_NR_ARGS];
5b7ac358 667
1b7b9c65 668 lttng_syscall_get_arguments(current, regs, args);
fc4f7161 669 fptr(event, ret, args[0], args[1], args[2],
5b7ac358
MD
670 args[3], args[4], args[5]);
671 break;
672 }
673 default:
674 break;
675 }
676}
677
33a39a3c
MD
678/*
679 * noinline to diminish caller stack size.
680 * Should be called with sessions lock held.
681 */
49c50022 682static
2d6d88c6 683int fill_event_table(const struct trace_syscall_entry *table, size_t table_len,
5b7ac358
MD
684 struct lttng_event **chan_table, struct lttng_channel *chan,
685 void *filter, enum sc_type type)
259b6cb3 686{
2a0c4816 687 const struct lttng_event_desc *desc;
259b6cb3 688 unsigned int i;
49c50022
MD
689
690 /* Allocate events for each syscall, insert into table */
691 for (i = 0; i < table_len; i++) {
692 struct lttng_kernel_event ev;
2a0c4816 693 desc = table[i].desc;
49c50022
MD
694
695 if (!desc) {
696 /* Unknown syscall */
697 continue;
698 }
699 /*
700 * Skip those already populated by previous failed
701 * register for this channel.
702 */
703 if (chan_table[i])
704 continue;
705 memset(&ev, 0, sizeof(ev));
5b7ac358
MD
706 switch (type) {
707 case SC_TYPE_ENTRY:
badfe9f5
MD
708 ev.u.syscall.entryexit = LTTNG_KERNEL_SYSCALL_ENTRY;
709 ev.u.syscall.abi = LTTNG_KERNEL_SYSCALL_ABI_NATIVE;
5b7ac358
MD
710 break;
711 case SC_TYPE_EXIT:
badfe9f5
MD
712 ev.u.syscall.entryexit = LTTNG_KERNEL_SYSCALL_EXIT;
713 ev.u.syscall.abi = LTTNG_KERNEL_SYSCALL_ABI_NATIVE;
5b7ac358
MD
714 break;
715 case SC_TYPE_COMPAT_ENTRY:
badfe9f5
MD
716 ev.u.syscall.entryexit = LTTNG_KERNEL_SYSCALL_ENTRY;
717 ev.u.syscall.abi = LTTNG_KERNEL_SYSCALL_ABI_COMPAT;
5b7ac358
MD
718 break;
719 case SC_TYPE_COMPAT_EXIT:
badfe9f5
MD
720 ev.u.syscall.entryexit = LTTNG_KERNEL_SYSCALL_EXIT;
721 ev.u.syscall.abi = LTTNG_KERNEL_SYSCALL_ABI_COMPAT;
5b7ac358
MD
722 break;
723 }
092ffe97 724 strncpy(ev.name, desc->name, LTTNG_KERNEL_SYM_NAME_LEN - 1);
f8695253 725 ev.name[LTTNG_KERNEL_SYM_NAME_LEN - 1] = '\0';
33a39a3c
MD
726 ev.instrumentation = LTTNG_KERNEL_SYSCALL;
727 chan_table[i] = _lttng_event_create(chan, &ev, filter,
3c997079 728 desc, ev.instrumentation);
abc0446a
MD
729 WARN_ON_ONCE(!chan_table[i]);
730 if (IS_ERR(chan_table[i])) {
49c50022
MD
731 /*
732 * If something goes wrong in event registration
733 * after the first one, we have no choice but to
734 * leave the previous events in there, until
735 * deleted by session teardown.
736 */
abc0446a 737 return PTR_ERR(chan_table[i]);
49c50022
MD
738 }
739 }
740 return 0;
741}
742
33a39a3c
MD
743/*
744 * Should be called with sessions lock held.
745 */
2d6d88c6 746int lttng_syscalls_register_event(struct lttng_channel *chan, void *filter)
49c50022 747{
2a0c4816 748 struct lttng_kernel_event ev;
259b6cb3
MD
749 int ret;
750
263b6c88 751 wrapper_vmalloc_sync_mappings();
259b6cb3
MD
752
753 if (!chan->sc_table) {
754 /* create syscall table mapping syscall to events */
a90917c3 755 chan->sc_table = kzalloc(sizeof(struct lttng_event *)
259b6cb3
MD
756 * ARRAY_SIZE(sc_table), GFP_KERNEL);
757 if (!chan->sc_table)
758 return -ENOMEM;
759 }
5b7ac358
MD
760 if (!chan->sc_exit_table) {
761 /* create syscall table mapping syscall to events */
762 chan->sc_exit_table = kzalloc(sizeof(struct lttng_event *)
763 * ARRAY_SIZE(sc_exit_table), GFP_KERNEL);
764 if (!chan->sc_exit_table)
765 return -ENOMEM;
766 }
767
259b6cb3 768
49c50022
MD
769#ifdef CONFIG_COMPAT
770 if (!chan->compat_sc_table) {
771 /* create syscall table mapping compat syscall to events */
a90917c3 772 chan->compat_sc_table = kzalloc(sizeof(struct lttng_event *)
a93244f8 773 * ARRAY_SIZE(compat_sc_table), GFP_KERNEL);
49c50022
MD
774 if (!chan->compat_sc_table)
775 return -ENOMEM;
776 }
5b7ac358
MD
777
778 if (!chan->compat_sc_exit_table) {
779 /* create syscall table mapping compat syscall to events */
780 chan->compat_sc_exit_table = kzalloc(sizeof(struct lttng_event *)
781 * ARRAY_SIZE(compat_sc_exit_table), GFP_KERNEL);
782 if (!chan->compat_sc_exit_table)
783 return -ENOMEM;
784 }
49c50022 785#endif
f405cfce 786 if (!chan->sc_unknown) {
f405cfce 787 const struct lttng_event_desc *desc =
d4291869 788 &__event_desc___syscall_entry_unknown;
2f804c0a 789
f405cfce 790 memset(&ev, 0, sizeof(ev));
f8695253
MD
791 strncpy(ev.name, desc->name, LTTNG_KERNEL_SYM_NAME_LEN);
792 ev.name[LTTNG_KERNEL_SYM_NAME_LEN - 1] = '\0';
33a39a3c 793 ev.instrumentation = LTTNG_KERNEL_SYSCALL;
badfe9f5
MD
794 ev.u.syscall.entryexit = LTTNG_KERNEL_SYSCALL_ENTRY;
795 ev.u.syscall.abi = LTTNG_KERNEL_SYSCALL_ABI_NATIVE;
33a39a3c 796 chan->sc_unknown = _lttng_event_create(chan, &ev, filter,
3c997079
MD
797 desc,
798 ev.instrumentation);
abc0446a
MD
799 WARN_ON_ONCE(!chan->sc_unknown);
800 if (IS_ERR(chan->sc_unknown)) {
801 return PTR_ERR(chan->sc_unknown);
f405cfce
MD
802 }
803 }
804
b76dc1a0 805 if (!chan->sc_compat_unknown) {
b76dc1a0 806 const struct lttng_event_desc *desc =
d4291869 807 &__event_desc___compat_syscall_entry_unknown;
b76dc1a0
MD
808
809 memset(&ev, 0, sizeof(ev));
f8695253
MD
810 strncpy(ev.name, desc->name, LTTNG_KERNEL_SYM_NAME_LEN);
811 ev.name[LTTNG_KERNEL_SYM_NAME_LEN - 1] = '\0';
33a39a3c 812 ev.instrumentation = LTTNG_KERNEL_SYSCALL;
badfe9f5
MD
813 ev.u.syscall.entryexit = LTTNG_KERNEL_SYSCALL_ENTRY;
814 ev.u.syscall.abi = LTTNG_KERNEL_SYSCALL_ABI_COMPAT;
33a39a3c 815 chan->sc_compat_unknown = _lttng_event_create(chan, &ev, filter,
3c997079
MD
816 desc,
817 ev.instrumentation);
abc0446a
MD
818 WARN_ON_ONCE(!chan->sc_unknown);
819 if (IS_ERR(chan->sc_compat_unknown)) {
820 return PTR_ERR(chan->sc_compat_unknown);
b76dc1a0
MD
821 }
822 }
823
5b7ac358 824 if (!chan->compat_sc_exit_unknown) {
2f804c0a 825 const struct lttng_event_desc *desc =
5b7ac358 826 &__event_desc___compat_syscall_exit_unknown;
2f804c0a
MD
827
828 memset(&ev, 0, sizeof(ev));
f8695253
MD
829 strncpy(ev.name, desc->name, LTTNG_KERNEL_SYM_NAME_LEN);
830 ev.name[LTTNG_KERNEL_SYM_NAME_LEN - 1] = '\0';
33a39a3c 831 ev.instrumentation = LTTNG_KERNEL_SYSCALL;
badfe9f5
MD
832 ev.u.syscall.entryexit = LTTNG_KERNEL_SYSCALL_EXIT;
833 ev.u.syscall.abi = LTTNG_KERNEL_SYSCALL_ABI_COMPAT;
33a39a3c 834 chan->compat_sc_exit_unknown = _lttng_event_create(chan, &ev,
3c997079
MD
835 filter, desc,
836 ev.instrumentation);
5b7ac358
MD
837 WARN_ON_ONCE(!chan->compat_sc_exit_unknown);
838 if (IS_ERR(chan->compat_sc_exit_unknown)) {
839 return PTR_ERR(chan->compat_sc_exit_unknown);
840 }
841 }
842
843 if (!chan->sc_exit_unknown) {
844 const struct lttng_event_desc *desc =
845 &__event_desc___syscall_exit_unknown;
846
847 memset(&ev, 0, sizeof(ev));
848 strncpy(ev.name, desc->name, LTTNG_KERNEL_SYM_NAME_LEN);
849 ev.name[LTTNG_KERNEL_SYM_NAME_LEN - 1] = '\0';
33a39a3c 850 ev.instrumentation = LTTNG_KERNEL_SYSCALL;
badfe9f5
MD
851 ev.u.syscall.entryexit = LTTNG_KERNEL_SYSCALL_EXIT;
852 ev.u.syscall.abi = LTTNG_KERNEL_SYSCALL_ABI_NATIVE;
33a39a3c 853 chan->sc_exit_unknown = _lttng_event_create(chan, &ev, filter,
3c997079 854 desc, ev.instrumentation);
5b7ac358
MD
855 WARN_ON_ONCE(!chan->sc_exit_unknown);
856 if (IS_ERR(chan->sc_exit_unknown)) {
857 return PTR_ERR(chan->sc_exit_unknown);
2f804c0a
MD
858 }
859 }
860
2d6d88c6 861 ret = fill_event_table(sc_table, ARRAY_SIZE(sc_table),
5b7ac358
MD
862 chan->sc_table, chan, filter, SC_TYPE_ENTRY);
863 if (ret)
864 return ret;
2d6d88c6 865 ret = fill_event_table(sc_exit_table, ARRAY_SIZE(sc_exit_table),
5b7ac358 866 chan->sc_exit_table, chan, filter, SC_TYPE_EXIT);
49c50022
MD
867 if (ret)
868 return ret;
5b7ac358 869
49c50022 870#ifdef CONFIG_COMPAT
2d6d88c6 871 ret = fill_event_table(compat_sc_table, ARRAY_SIZE(compat_sc_table),
5b7ac358
MD
872 chan->compat_sc_table, chan, filter,
873 SC_TYPE_COMPAT_ENTRY);
874 if (ret)
875 return ret;
2d6d88c6 876 ret = fill_event_table(compat_sc_exit_table, ARRAY_SIZE(compat_sc_exit_table),
5b7ac358
MD
877 chan->compat_sc_exit_table, chan, filter,
878 SC_TYPE_COMPAT_EXIT);
49c50022
MD
879 if (ret)
880 return ret;
881#endif
badfe9f5
MD
882
883 if (!chan->sc_filter) {
884 chan->sc_filter = kzalloc(sizeof(struct lttng_syscall_filter),
885 GFP_KERNEL);
886 if (!chan->sc_filter)
887 return -ENOMEM;
888 }
889
80f87dd2
MD
890 if (!chan->sys_enter_registered) {
891 ret = lttng_wrapper_tracepoint_probe_register("sys_enter",
2d6d88c6 892 (void *) syscall_entry_event_probe, chan);
80f87dd2
MD
893 if (ret)
894 return ret;
895 chan->sys_enter_registered = 1;
896 }
63728b02
MD
897 /*
898 * We change the name of sys_exit tracepoint due to namespace
899 * conflict with sys_exit syscall entry.
900 */
80f87dd2
MD
901 if (!chan->sys_exit_registered) {
902 ret = lttng_wrapper_tracepoint_probe_register("sys_exit",
2d6d88c6 903 (void *) syscall_exit_event_probe, chan);
80f87dd2
MD
904 if (ret) {
905 WARN_ON_ONCE(lttng_wrapper_tracepoint_probe_unregister("sys_enter",
2d6d88c6 906 (void *) syscall_entry_event_probe, chan));
80f87dd2
MD
907 return ret;
908 }
909 chan->sys_exit_registered = 1;
63728b02 910 }
259b6cb3
MD
911 return ret;
912}
913
914/*
915 * Only called at session destruction.
916 */
2d6d88c6 917int lttng_syscalls_unregister_event(struct lttng_channel *chan)
259b6cb3
MD
918{
919 int ret;
920
921 if (!chan->sc_table)
922 return 0;
80f87dd2 923 if (chan->sys_enter_registered) {
2d9cd7f3 924 ret = lttng_wrapper_tracepoint_probe_unregister("sys_enter",
2d6d88c6 925 (void *) syscall_entry_event_probe, chan);
80f87dd2
MD
926 if (ret)
927 return ret;
928 chan->sys_enter_registered = 0;
929 }
930 if (chan->sys_exit_registered) {
2d9cd7f3 931 ret = lttng_wrapper_tracepoint_probe_unregister("sys_exit",
2d6d88c6 932 (void *) syscall_exit_event_probe, chan);
80f87dd2
MD
933 if (ret)
934 return ret;
935 chan->sys_exit_registered = 0;
936 }
badfe9f5
MD
937 return 0;
938}
939
2d6d88c6 940int lttng_syscalls_destroy_event(struct lttng_channel *chan)
badfe9f5 941{
259b6cb3 942 kfree(chan->sc_table);
5b7ac358 943 kfree(chan->sc_exit_table);
49c50022
MD
944#ifdef CONFIG_COMPAT
945 kfree(chan->compat_sc_table);
5b7ac358 946 kfree(chan->compat_sc_exit_table);
49c50022 947#endif
80f87dd2
MD
948 kfree(chan->sc_filter);
949 return 0;
950}
951
952static
953int get_syscall_nr(const char *syscall_name)
954{
955 int syscall_nr = -1;
956 int i;
957
958 for (i = 0; i < ARRAY_SIZE(sc_table); i++) {
959 const struct trace_syscall_entry *entry;
5b7ac358 960 const char *it_name;
80f87dd2
MD
961
962 entry = &sc_table[i];
963 if (!entry->desc)
964 continue;
5b7ac358
MD
965 it_name = entry->desc->name;
966 it_name += strlen(SYSCALL_ENTRY_STR);
967 if (!strcmp(syscall_name, it_name)) {
80f87dd2
MD
968 syscall_nr = i;
969 break;
970 }
971 }
972 return syscall_nr;
973}
974
975static
976int get_compat_syscall_nr(const char *syscall_name)
977{
978 int syscall_nr = -1;
979 int i;
980
981 for (i = 0; i < ARRAY_SIZE(compat_sc_table); i++) {
982 const struct trace_syscall_entry *entry;
5b7ac358 983 const char *it_name;
80f87dd2
MD
984
985 entry = &compat_sc_table[i];
986 if (!entry->desc)
987 continue;
5b7ac358
MD
988 it_name = entry->desc->name;
989 it_name += strlen(COMPAT_SYSCALL_ENTRY_STR);
990 if (!strcmp(syscall_name, it_name)) {
80f87dd2
MD
991 syscall_nr = i;
992 break;
993 }
994 }
995 return syscall_nr;
996}
997
12e579db
MD
998static
999uint32_t get_sc_tables_len(void)
1000{
1001 return ARRAY_SIZE(sc_table) + ARRAY_SIZE(compat_sc_table);
1002}
1003
badfe9f5
MD
1004static
1005const char *get_syscall_name(struct lttng_event *event)
80f87dd2 1006{
badfe9f5 1007 size_t prefix_len = 0;
80f87dd2 1008
badfe9f5 1009 WARN_ON_ONCE(event->instrumentation != LTTNG_KERNEL_SYSCALL);
80f87dd2 1010
badfe9f5
MD
1011 switch (event->u.syscall.entryexit) {
1012 case LTTNG_SYSCALL_ENTRY:
1013 switch (event->u.syscall.abi) {
1014 case LTTNG_SYSCALL_ABI_NATIVE:
1015 prefix_len = strlen(SYSCALL_ENTRY_STR);
1016 break;
1017 case LTTNG_SYSCALL_ABI_COMPAT:
1018 prefix_len = strlen(COMPAT_SYSCALL_ENTRY_STR);
1019 break;
80f87dd2 1020 }
badfe9f5
MD
1021 break;
1022 case LTTNG_SYSCALL_EXIT:
1023 switch (event->u.syscall.abi) {
1024 case LTTNG_SYSCALL_ABI_NATIVE:
1025 prefix_len = strlen(SYSCALL_EXIT_STR);
1026 break;
1027 case LTTNG_SYSCALL_ABI_COMPAT:
1028 prefix_len = strlen(COMPAT_SYSCALL_EXIT_STR);
1029 break;
80f87dd2 1030 }
badfe9f5 1031 break;
80f87dd2 1032 }
badfe9f5
MD
1033 WARN_ON_ONCE(prefix_len == 0);
1034 return event->desc->name + prefix_len;
1035}
1036
2d6d88c6 1037int lttng_syscall_filter_enable_event(struct lttng_channel *chan,
badfe9f5
MD
1038 struct lttng_event *event)
1039{
1040 struct lttng_syscall_filter *filter = chan->sc_filter;
1041 const char *syscall_name;
1042 unsigned long *bitmap;
1043 int syscall_nr;
1044
1045 WARN_ON_ONCE(!chan->sc_table);
1046
1047 syscall_name = get_syscall_name(event);
1048
1049 switch (event->u.syscall.abi) {
1050 case LTTNG_SYSCALL_ABI_NATIVE:
1051 syscall_nr = get_syscall_nr(syscall_name);
1052 break;
1053 case LTTNG_SYSCALL_ABI_COMPAT:
1054 syscall_nr = get_compat_syscall_nr(syscall_name);
1055 break;
1056 default:
1057 return -EINVAL;
80f87dd2 1058 }
badfe9f5
MD
1059 if (syscall_nr < 0)
1060 return -ENOENT;
1061
badfe9f5
MD
1062 switch (event->u.syscall.entryexit) {
1063 case LTTNG_SYSCALL_ENTRY:
1064 switch (event->u.syscall.abi) {
1065 case LTTNG_SYSCALL_ABI_NATIVE:
1066 bitmap = filter->sc_entry;
1067 break;
1068 case LTTNG_SYSCALL_ABI_COMPAT:
1069 bitmap = filter->sc_compat_entry;
1070 break;
6d9694d8
MD
1071 default:
1072 return -EINVAL;
80f87dd2 1073 }
badfe9f5
MD
1074 break;
1075 case LTTNG_SYSCALL_EXIT:
1076 switch (event->u.syscall.abi) {
1077 case LTTNG_SYSCALL_ABI_NATIVE:
1078 bitmap = filter->sc_exit;
1079 break;
1080 case LTTNG_SYSCALL_ABI_COMPAT:
1081 bitmap = filter->sc_compat_exit;
1082 break;
6d9694d8
MD
1083 default:
1084 return -EINVAL;
80f87dd2 1085 }
badfe9f5
MD
1086 break;
1087 default:
1088 return -EINVAL;
80f87dd2 1089 }
badfe9f5
MD
1090 if (test_bit(syscall_nr, bitmap))
1091 return -EEXIST;
1092 bitmap_set(bitmap, syscall_nr, 1);
80f87dd2 1093 return 0;
80f87dd2
MD
1094}
1095
2d6d88c6 1096int lttng_syscall_filter_disable_event(struct lttng_channel *chan,
badfe9f5 1097 struct lttng_event *event)
80f87dd2 1098{
badfe9f5
MD
1099 struct lttng_syscall_filter *filter = chan->sc_filter;
1100 const char *syscall_name;
1101 unsigned long *bitmap;
1102 int syscall_nr;
80f87dd2
MD
1103
1104 WARN_ON_ONCE(!chan->sc_table);
1105
badfe9f5
MD
1106 syscall_name = get_syscall_name(event);
1107
1108 switch (event->u.syscall.abi) {
1109 case LTTNG_SYSCALL_ABI_NATIVE:
1110 syscall_nr = get_syscall_nr(syscall_name);
1111 break;
1112 case LTTNG_SYSCALL_ABI_COMPAT:
1113 syscall_nr = get_compat_syscall_nr(syscall_name);
1114 break;
1115 default:
1116 return -EINVAL;
80f87dd2 1117 }
badfe9f5
MD
1118 if (syscall_nr < 0)
1119 return -ENOENT;
80f87dd2 1120
badfe9f5
MD
1121 switch (event->u.syscall.entryexit) {
1122 case LTTNG_SYSCALL_ENTRY:
1123 switch (event->u.syscall.abi) {
1124 case LTTNG_SYSCALL_ABI_NATIVE:
1125 bitmap = filter->sc_entry;
1126 break;
1127 case LTTNG_SYSCALL_ABI_COMPAT:
1128 bitmap = filter->sc_compat_entry;
1129 break;
6d9694d8
MD
1130 default:
1131 return -EINVAL;
80f87dd2 1132 }
badfe9f5
MD
1133 break;
1134 case LTTNG_SYSCALL_EXIT:
1135 switch (event->u.syscall.abi) {
1136 case LTTNG_SYSCALL_ABI_NATIVE:
1137 bitmap = filter->sc_exit;
1138 break;
1139 case LTTNG_SYSCALL_ABI_COMPAT:
1140 bitmap = filter->sc_compat_exit;
1141 break;
6d9694d8
MD
1142 default:
1143 return -EINVAL;
80f87dd2 1144 }
badfe9f5
MD
1145 break;
1146 default:
1147 return -EINVAL;
80f87dd2 1148 }
badfe9f5
MD
1149 if (!test_bit(syscall_nr, bitmap))
1150 return -EEXIST;
1151 bitmap_clear(bitmap, syscall_nr, 1);
80f87dd2 1152
badfe9f5 1153 return 0;
259b6cb3 1154}
2d2464bd
MD
1155
1156static
1157const struct trace_syscall_entry *syscall_list_get_entry(loff_t *pos)
1158{
1159 const struct trace_syscall_entry *entry;
1160 int iter = 0;
1161
1162 for (entry = sc_table;
1163 entry < sc_table + ARRAY_SIZE(sc_table);
1164 entry++) {
1165 if (iter++ >= *pos)
1166 return entry;
1167 }
1168 for (entry = compat_sc_table;
1169 entry < compat_sc_table + ARRAY_SIZE(compat_sc_table);
1170 entry++) {
1171 if (iter++ >= *pos)
1172 return entry;
1173 }
1174 /* End of list */
1175 return NULL;
1176}
1177
1178static
1179void *syscall_list_start(struct seq_file *m, loff_t *pos)
1180{
1181 return (void *) syscall_list_get_entry(pos);
1182}
1183
1184static
1185void *syscall_list_next(struct seq_file *m, void *p, loff_t *ppos)
1186{
1187 (*ppos)++;
1188 return (void *) syscall_list_get_entry(ppos);
1189}
1190
1191static
1192void syscall_list_stop(struct seq_file *m, void *p)
1193{
1194}
1195
12e579db
MD
1196static
1197int get_sc_table(const struct trace_syscall_entry *entry,
1198 const struct trace_syscall_entry **table,
1199 unsigned int *bitness)
1200{
1201 if (entry >= sc_table && entry < sc_table + ARRAY_SIZE(sc_table)) {
1202 if (bitness)
1203 *bitness = BITS_PER_LONG;
1204 if (table)
1205 *table = sc_table;
1206 return 0;
1207 }
1208 if (!(entry >= compat_sc_table
1209 && entry < compat_sc_table + ARRAY_SIZE(compat_sc_table))) {
1210 return -EINVAL;
1211 }
1212 if (bitness)
1213 *bitness = 32;
1214 if (table)
1215 *table = compat_sc_table;
1216 return 0;
1217}
1218
2d2464bd
MD
1219static
1220int syscall_list_show(struct seq_file *m, void *p)
1221{
1222 const struct trace_syscall_entry *table, *entry = p;
1223 unsigned int bitness;
d4291869 1224 unsigned long index;
12e579db 1225 int ret;
d4291869 1226 const char *name;
2d2464bd 1227
12e579db
MD
1228 ret = get_sc_table(entry, &table, &bitness);
1229 if (ret)
1230 return ret;
f4855b46
MD
1231 if (!entry->desc)
1232 return 0;
d4291869
MD
1233 if (table == sc_table) {
1234 index = entry - table;
1235 name = &entry->desc->name[strlen(SYSCALL_ENTRY_STR)];
1236 } else {
1237 index = (entry - table) + ARRAY_SIZE(sc_table);
1238 name = &entry->desc->name[strlen(COMPAT_SYSCALL_ENTRY_STR)];
1239 }
12e579db 1240 seq_printf(m, "syscall { index = %lu; name = %s; bitness = %u; };\n",
d4291869 1241 index, name, bitness);
2d2464bd
MD
1242 return 0;
1243}
1244
1245static
1246const struct seq_operations lttng_syscall_list_seq_ops = {
1247 .start = syscall_list_start,
1248 .next = syscall_list_next,
1249 .stop = syscall_list_stop,
1250 .show = syscall_list_show,
1251};
1252
1253static
1254int lttng_syscall_list_open(struct inode *inode, struct file *file)
1255{
1256 return seq_open(file, &lttng_syscall_list_seq_ops);
1257}
1258
1259const struct file_operations lttng_syscall_list_fops = {
1260 .owner = THIS_MODULE,
1261 .open = lttng_syscall_list_open,
1262 .read = seq_read,
1263 .llseek = seq_lseek,
1264 .release = seq_release,
1265};
12e579db 1266
badfe9f5
MD
1267/*
1268 * A syscall is enabled if it is traced for either entry or exit.
1269 */
12e579db
MD
1270long lttng_channel_syscall_mask(struct lttng_channel *channel,
1271 struct lttng_kernel_syscall_mask __user *usyscall_mask)
1272{
1273 uint32_t len, sc_tables_len, bitmask_len;
1274 int ret = 0, bit;
1275 char *tmp_mask;
1276 struct lttng_syscall_filter *filter;
1277
1278 ret = get_user(len, &usyscall_mask->len);
1279 if (ret)
1280 return ret;
1281 sc_tables_len = get_sc_tables_len();
1282 bitmask_len = ALIGN(sc_tables_len, 8) >> 3;
1283 if (len < sc_tables_len) {
1284 return put_user(sc_tables_len, &usyscall_mask->len);
1285 }
1286 /* Array is large enough, we can copy array to user-space. */
1287 tmp_mask = kzalloc(bitmask_len, GFP_KERNEL);
1288 if (!tmp_mask)
1289 return -ENOMEM;
1290 filter = channel->sc_filter;
1291
1292 for (bit = 0; bit < ARRAY_SIZE(sc_table); bit++) {
e2129868 1293 char state;
2f25059d
MD
1294
1295 if (channel->sc_table) {
badfe9f5
MD
1296 if (!READ_ONCE(channel->syscall_all) && filter)
1297 state = test_bit(bit, filter->sc_entry)
1298 || test_bit(bit, filter->sc_exit);
2f25059d
MD
1299 else
1300 state = 1;
1301 } else {
1302 state = 0;
1303 }
1304 bt_bitfield_write_be(tmp_mask, char, bit, 1, state);
12e579db
MD
1305 }
1306 for (; bit < sc_tables_len; bit++) {
e2129868 1307 char state;
2f25059d
MD
1308
1309 if (channel->compat_sc_table) {
badfe9f5 1310 if (!READ_ONCE(channel->syscall_all) && filter)
2f25059d 1311 state = test_bit(bit - ARRAY_SIZE(sc_table),
badfe9f5
MD
1312 filter->sc_compat_entry)
1313 || test_bit(bit - ARRAY_SIZE(sc_table),
1314 filter->sc_compat_exit);
2f25059d
MD
1315 else
1316 state = 1;
1317 } else {
1318 state = 0;
1319 }
1320 bt_bitfield_write_be(tmp_mask, char, bit, 1, state);
12e579db
MD
1321 }
1322 if (copy_to_user(usyscall_mask->mask, tmp_mask, bitmask_len))
1323 ret = -EFAULT;
1324 kfree(tmp_mask);
1325 return ret;
1326}
082d4946
MD
1327
1328int lttng_abi_syscall_list(void)
1329{
1330 struct file *syscall_list_file;
1331 int file_fd, ret;
1332
4ac10b76 1333 file_fd = lttng_get_unused_fd();
082d4946
MD
1334 if (file_fd < 0) {
1335 ret = file_fd;
1336 goto fd_error;
1337 }
1338
1339 syscall_list_file = anon_inode_getfile("[lttng_syscall_list]",
1340 &lttng_syscall_list_fops,
1341 NULL, O_RDWR);
1342 if (IS_ERR(syscall_list_file)) {
1343 ret = PTR_ERR(syscall_list_file);
1344 goto file_error;
1345 }
1346 ret = lttng_syscall_list_fops.open(NULL, syscall_list_file);
1347 if (ret < 0)
1348 goto open_error;
1349 fd_install(file_fd, syscall_list_file);
082d4946
MD
1350 return file_fd;
1351
1352open_error:
1353 fput(syscall_list_file);
1354file_error:
1355 put_unused_fd(file_fd);
1356fd_error:
1357 return ret;
1358}
This page took 0.11209 seconds and 4 git commands to generate.