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