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