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