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