Implement event notifier error 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 uint64_t error_counter_index = event_notifier_enabler->error_counter_index;
1406 struct lttng_enabler *base_enabler = lttng_event_notifier_enabler_as_enabler(
1407 event_notifier_enabler);
1408 struct hlist_head *unknown_dispatch_list;
1409 int ret = 0;
1410 bool found = false;
1411 enum lttng_kernel_syscall_abi abi;
1412 enum lttng_kernel_syscall_entryexit entryexit;
1413 struct hlist_head *head;
1414
1415 switch (type) {
1416 case SC_TYPE_ENTRY:
1417 desc = &__event_desc___syscall_entry_unknown;
1418 unknown_dispatch_list = &group->event_notifier_unknown_syscall_dispatch;
1419 entryexit = LTTNG_KERNEL_SYSCALL_ENTRY;
1420 abi = LTTNG_KERNEL_SYSCALL_ABI_NATIVE;
1421 break;
1422 case SC_TYPE_EXIT:
1423 desc = &__event_desc___syscall_exit_unknown;
1424 unknown_dispatch_list = &group->event_notifier_exit_unknown_syscall_dispatch;
1425 entryexit = LTTNG_KERNEL_SYSCALL_EXIT;
1426 abi = LTTNG_KERNEL_SYSCALL_ABI_NATIVE;
1427 break;
1428 case SC_TYPE_COMPAT_ENTRY:
1429 desc = &__event_desc___compat_syscall_entry_unknown;
1430 unknown_dispatch_list = &group->event_notifier_compat_unknown_syscall_dispatch;
1431 entryexit = LTTNG_KERNEL_SYSCALL_ENTRY;
1432 abi = LTTNG_KERNEL_SYSCALL_ABI_COMPAT;
1433 break;
1434 case SC_TYPE_COMPAT_EXIT:
1435 desc = &__event_desc___compat_syscall_exit_unknown;
1436 unknown_dispatch_list = &group->event_notifier_exit_compat_unknown_syscall_dispatch;
1437 entryexit = LTTNG_KERNEL_SYSCALL_EXIT;
1438 abi = LTTNG_KERNEL_SYSCALL_ABI_COMPAT;
1439 break;
1440 default:
1441 BUG_ON(1);
1442 }
1443
1444 /*
1445 * Check if already created.
1446 */
1447 head = utils_borrow_hash_table_bucket(group->event_notifiers_ht.table,
1448 LTTNG_EVENT_NOTIFIER_HT_SIZE, desc->name);
1449 lttng_hlist_for_each_entry(notifier, head, hlist) {
1450 if (notifier->desc == desc &&
1451 notifier->user_token == base_enabler->user_token)
1452 found = true;
1453 }
1454 if (found)
1455 goto end;
1456
1457 memset(&event_notifier_param, 0, sizeof(event_notifier_param));
1458 strncat(event_notifier_param.event.name, desc->name,
1459 LTTNG_KERNEL_SYM_NAME_LEN - strlen(event_notifier_param.event.name) - 1);
1460
1461 event_notifier_param.event.name[LTTNG_KERNEL_SYM_NAME_LEN - 1] = '\0';
1462
1463 event_notifier_param.event.instrumentation = LTTNG_KERNEL_SYSCALL;
1464 event_notifier_param.event.u.syscall.abi = abi;
1465 event_notifier_param.event.u.syscall.entryexit = entryexit;
1466
1467 notifier = _lttng_event_notifier_create(desc, user_token,
1468 error_counter_index, group, &event_notifier_param, NULL,
1469 event_notifier_param.event.instrumentation);
1470 if (IS_ERR(notifier)) {
1471 printk(KERN_INFO "Unable to create unknown notifier %s\n",
1472 desc->name);
1473 ret = -ENOMEM;
1474 goto end;
1475 }
1476
1477 hlist_add_head_rcu(&notifier->u.syscall.node, unknown_dispatch_list);
1478
1479end:
1480 return ret;
1481}
1482
1483static int create_matching_event_notifiers(
1484 struct lttng_event_notifier_enabler *event_notifier_enabler,
1485 void *filter, const struct trace_syscall_entry *table,
1486 size_t table_len, enum sc_type type)
1487{
1488 struct lttng_event_notifier_group *group = event_notifier_enabler->group;
1489 const struct lttng_event_desc *desc;
1490 uint64_t user_token = event_notifier_enabler->base.user_token;
1491 uint64_t error_counter_index = event_notifier_enabler->error_counter_index;
1492 unsigned int i;
1493 int ret = 0;
1494
1495 /* iterate over all syscall and create event_notifier that match */
1496 for (i = 0; i < table_len; i++) {
1497 struct lttng_event_notifier *event_notifier;
1498 struct lttng_kernel_event_notifier event_notifier_param;
1499 struct hlist_head *head;
1500 int found = 0;
1501
1502 desc = table[i].desc;
1503 if (!desc) {
1504 /* Unknown syscall */
1505 continue;
1506 }
1507
1508 if (!lttng_desc_match_enabler(desc,
1509 lttng_event_notifier_enabler_as_enabler(event_notifier_enabler)))
1510 continue;
1511
1512 /*
1513 * Check if already created.
1514 */
1515 head = utils_borrow_hash_table_bucket(group->event_notifiers_ht.table,
1516 LTTNG_EVENT_NOTIFIER_HT_SIZE, desc->name);
1517 lttng_hlist_for_each_entry(event_notifier, head, hlist) {
1518 if (event_notifier->desc == desc
1519 && event_notifier->user_token == event_notifier_enabler->base.user_token)
1520 found = 1;
1521 }
1522 if (found)
1523 continue;
1524
1525 memset(&event_notifier_param, 0, sizeof(event_notifier_param));
1526 switch (type) {
1527 case SC_TYPE_ENTRY:
1528 event_notifier_param.event.u.syscall.entryexit = LTTNG_KERNEL_SYSCALL_ENTRY;
1529 event_notifier_param.event.u.syscall.abi = LTTNG_KERNEL_SYSCALL_ABI_NATIVE;
1530 break;
1531 case SC_TYPE_EXIT:
1532 event_notifier_param.event.u.syscall.entryexit = LTTNG_KERNEL_SYSCALL_EXIT;
1533 event_notifier_param.event.u.syscall.abi = LTTNG_KERNEL_SYSCALL_ABI_NATIVE;
1534 break;
1535 case SC_TYPE_COMPAT_ENTRY:
1536 event_notifier_param.event.u.syscall.entryexit = LTTNG_KERNEL_SYSCALL_ENTRY;
1537 event_notifier_param.event.u.syscall.abi = LTTNG_KERNEL_SYSCALL_ABI_COMPAT;
1538 break;
1539 case SC_TYPE_COMPAT_EXIT:
1540 event_notifier_param.event.u.syscall.entryexit = LTTNG_KERNEL_SYSCALL_EXIT;
1541 event_notifier_param.event.u.syscall.abi = LTTNG_KERNEL_SYSCALL_ABI_COMPAT;
1542 break;
1543 }
1544 strncat(event_notifier_param.event.name, desc->name,
1545 LTTNG_KERNEL_SYM_NAME_LEN - strlen(event_notifier_param.event.name) - 1);
1546 event_notifier_param.event.name[LTTNG_KERNEL_SYM_NAME_LEN - 1] = '\0';
1547 event_notifier_param.event.instrumentation = LTTNG_KERNEL_SYSCALL;
1548
1549 event_notifier = _lttng_event_notifier_create(desc, user_token,
1550 error_counter_index, group, &event_notifier_param,
1551 filter, event_notifier_param.event.instrumentation);
1552 if (IS_ERR(event_notifier)) {
1553 printk(KERN_INFO "Unable to create event_notifier %s\n",
1554 desc->name);
1555 ret = -ENOMEM;
1556 goto end;
1557 }
1558
1559 event_notifier->u.syscall.syscall_id = i;
1560 }
1561
1562end:
1563 return ret;
1564
1565}
1566
1567int lttng_syscals_create_matching_event_notifiers(
1568 struct lttng_event_notifier_enabler *event_notifier_enabler,
1569 void *filter)
1570{
1571 int ret;
1572 struct lttng_enabler *base_enabler =
1573 lttng_event_notifier_enabler_as_enabler(event_notifier_enabler);
1574 enum lttng_kernel_syscall_entryexit entryexit =
1575 base_enabler->event_param.u.syscall.entryexit;
1576
1577 if (entryexit == LTTNG_KERNEL_SYSCALL_ENTRY || entryexit == LTTNG_KERNEL_SYSCALL_ENTRYEXIT) {
1578 ret = create_matching_event_notifiers(event_notifier_enabler,
1579 filter, sc_table, ARRAY_SIZE(sc_table), SC_TYPE_ENTRY);
1580 if (ret)
1581 goto end;
1582
1583 ret = create_matching_event_notifiers(event_notifier_enabler,
1584 filter, compat_sc_table, ARRAY_SIZE(compat_sc_table),
1585 SC_TYPE_COMPAT_ENTRY);
1586 if (ret)
1587 goto end;
1588
1589 ret = create_unknown_event_notifier(event_notifier_enabler,
1590 SC_TYPE_ENTRY);
1591 if (ret)
1592 goto end;
1593
1594 ret = create_unknown_event_notifier(event_notifier_enabler,
1595 SC_TYPE_COMPAT_ENTRY);
1596 if (ret)
1597 goto end;
1598 }
1599
1600 if (entryexit == LTTNG_KERNEL_SYSCALL_EXIT || entryexit == LTTNG_KERNEL_SYSCALL_ENTRYEXIT) {
1601 ret = create_matching_event_notifiers(event_notifier_enabler,
1602 filter, sc_exit_table, ARRAY_SIZE(sc_exit_table),
1603 SC_TYPE_EXIT);
1604 if (ret)
1605 goto end;
1606
1607 ret = create_unknown_event_notifier(event_notifier_enabler,
1608 SC_TYPE_EXIT);
1609 if (ret)
1610 goto end;
1611
1612 ret = create_matching_event_notifiers(event_notifier_enabler,
1613 filter, compat_sc_exit_table, ARRAY_SIZE(compat_sc_exit_table),
1614 SC_TYPE_COMPAT_EXIT);
1615 if (ret)
1616 goto end;
1617
1618 ret = create_unknown_event_notifier(event_notifier_enabler,
1619 SC_TYPE_COMPAT_EXIT);
1620 if (ret)
1621 goto end;
1622 }
1623
1624end:
1625 return ret;
1626}
1627
1628/*
1629 * Unregister the syscall event_notifier probes from the callsites.
1630 */
1631int lttng_syscalls_unregister_event_notifier(
1632 struct lttng_event_notifier_group *event_notifier_group)
1633{
1634 int ret;
1635
1636 /*
1637 * Only register the event_notifier probe on the `sys_enter` callsite for now.
1638 * At the moment, we don't think it's desirable to have one fired
1639 * event_notifier for the entry and one for the exit of a syscall.
1640 */
1641 if (event_notifier_group->sys_enter_registered) {
1642 ret = lttng_wrapper_tracepoint_probe_unregister("sys_enter",
1643 (void *) syscall_entry_event_notifier_probe, event_notifier_group);
1644 if (ret)
1645 return ret;
1646 event_notifier_group->sys_enter_registered = 0;
1647 }
1648 if (event_notifier_group->sys_exit_registered) {
1649 ret = lttng_wrapper_tracepoint_probe_unregister("sys_exit",
1650 (void *) syscall_exit_event_notifier_probe, event_notifier_group);
1651 if (ret)
1652 return ret;
1653 event_notifier_group->sys_enter_registered = 0;
1654 }
1655
1656 kfree(event_notifier_group->event_notifier_syscall_dispatch);
1657 kfree(event_notifier_group->event_notifier_exit_syscall_dispatch);
1658#ifdef CONFIG_COMPAT
1659 kfree(event_notifier_group->event_notifier_compat_syscall_dispatch);
1660 kfree(event_notifier_group->event_notifier_exit_compat_syscall_dispatch);
1661#endif
1662 return 0;
1663}
1664
1665int lttng_syscalls_unregister_event(struct lttng_channel *chan)
1666{
1667 int ret;
1668
1669 if (!chan->sc_table)
1670 return 0;
1671 if (chan->sys_enter_registered) {
1672 ret = lttng_wrapper_tracepoint_probe_unregister("sys_enter",
1673 (void *) syscall_entry_event_probe, chan);
1674 if (ret)
1675 return ret;
1676 chan->sys_enter_registered = 0;
1677 }
1678 if (chan->sys_exit_registered) {
1679 ret = lttng_wrapper_tracepoint_probe_unregister("sys_exit",
1680 (void *) syscall_exit_event_probe, chan);
1681 if (ret)
1682 return ret;
1683 chan->sys_exit_registered = 0;
1684 }
1685 return 0;
1686}
1687
1688int lttng_syscalls_destroy_event(struct lttng_channel *chan)
1689{
1690 kfree(chan->sc_table);
1691 kfree(chan->sc_exit_table);
1692#ifdef CONFIG_COMPAT
1693 kfree(chan->compat_sc_table);
1694 kfree(chan->compat_sc_exit_table);
1695#endif
1696 kfree(chan->sc_filter);
1697 return 0;
1698}
1699
1700static
1701int get_syscall_nr(const char *syscall_name)
1702{
1703 int syscall_nr = -1;
1704 int i;
1705
1706 for (i = 0; i < ARRAY_SIZE(sc_table); i++) {
1707 const struct trace_syscall_entry *entry;
1708 const char *it_name;
1709
1710 entry = &sc_table[i];
1711 if (!entry->desc)
1712 continue;
1713 it_name = entry->desc->name;
1714 it_name += strlen(SYSCALL_ENTRY_STR);
1715 if (!strcmp(syscall_name, it_name)) {
1716 syscall_nr = i;
1717 break;
1718 }
1719 }
1720 return syscall_nr;
1721}
1722
1723static
1724int get_compat_syscall_nr(const char *syscall_name)
1725{
1726 int syscall_nr = -1;
1727 int i;
1728
1729 for (i = 0; i < ARRAY_SIZE(compat_sc_table); i++) {
1730 const struct trace_syscall_entry *entry;
1731 const char *it_name;
1732
1733 entry = &compat_sc_table[i];
1734 if (!entry->desc)
1735 continue;
1736 it_name = entry->desc->name;
1737 it_name += strlen(COMPAT_SYSCALL_ENTRY_STR);
1738 if (!strcmp(syscall_name, it_name)) {
1739 syscall_nr = i;
1740 break;
1741 }
1742 }
1743 return syscall_nr;
1744}
1745
1746static
1747uint32_t get_sc_tables_len(void)
1748{
1749 return ARRAY_SIZE(sc_table) + ARRAY_SIZE(compat_sc_table);
1750}
1751
1752static
1753const char *get_syscall_name(const char *desc_name,
1754 enum lttng_syscall_abi abi,
1755 enum lttng_syscall_entryexit entryexit)
1756{
1757 size_t prefix_len = 0;
1758
1759
1760 switch (entryexit) {
1761 case LTTNG_SYSCALL_ENTRY:
1762 switch (abi) {
1763 case LTTNG_SYSCALL_ABI_NATIVE:
1764 prefix_len = strlen(SYSCALL_ENTRY_STR);
1765 break;
1766 case LTTNG_SYSCALL_ABI_COMPAT:
1767 prefix_len = strlen(COMPAT_SYSCALL_ENTRY_STR);
1768 break;
1769 }
1770 break;
1771 case LTTNG_SYSCALL_EXIT:
1772 switch (abi) {
1773 case LTTNG_SYSCALL_ABI_NATIVE:
1774 prefix_len = strlen(SYSCALL_EXIT_STR);
1775 break;
1776 case LTTNG_SYSCALL_ABI_COMPAT:
1777 prefix_len = strlen(COMPAT_SYSCALL_EXIT_STR);
1778 break;
1779 }
1780 break;
1781 }
1782 WARN_ON_ONCE(prefix_len == 0);
1783 return desc_name + prefix_len;
1784}
1785
1786static
1787int lttng_syscall_filter_enable(
1788 struct lttng_syscall_filter *filter,
1789 const char *desc_name, enum lttng_syscall_abi abi,
1790 enum lttng_syscall_entryexit entryexit)
1791{
1792 const char *syscall_name;
1793 unsigned long *bitmap;
1794 int syscall_nr;
1795
1796 syscall_name = get_syscall_name(desc_name, abi, entryexit);
1797
1798 switch (abi) {
1799 case LTTNG_SYSCALL_ABI_NATIVE:
1800 syscall_nr = get_syscall_nr(syscall_name);
1801 break;
1802 case LTTNG_SYSCALL_ABI_COMPAT:
1803 syscall_nr = get_compat_syscall_nr(syscall_name);
1804 break;
1805 default:
1806 return -EINVAL;
1807 }
1808 if (syscall_nr < 0)
1809 return -ENOENT;
1810
1811 switch (entryexit) {
1812 case LTTNG_SYSCALL_ENTRY:
1813 switch (abi) {
1814 case LTTNG_SYSCALL_ABI_NATIVE:
1815 bitmap = filter->sc_entry;
1816 break;
1817 case LTTNG_SYSCALL_ABI_COMPAT:
1818 bitmap = filter->sc_compat_entry;
1819 break;
1820 default:
1821 return -EINVAL;
1822 }
1823 break;
1824 case LTTNG_SYSCALL_EXIT:
1825 switch (abi) {
1826 case LTTNG_SYSCALL_ABI_NATIVE:
1827 bitmap = filter->sc_exit;
1828 break;
1829 case LTTNG_SYSCALL_ABI_COMPAT:
1830 bitmap = filter->sc_compat_exit;
1831 break;
1832 default:
1833 return -EINVAL;
1834 }
1835 break;
1836 default:
1837 return -EINVAL;
1838 }
1839 if (test_bit(syscall_nr, bitmap))
1840 return -EEXIST;
1841 bitmap_set(bitmap, syscall_nr, 1);
1842 return 0;
1843}
1844
1845int lttng_syscall_filter_enable_event_notifier(
1846 struct lttng_event_notifier *notifier)
1847{
1848 struct lttng_event_notifier_group *group = notifier->group;
1849 unsigned int syscall_id = notifier->u.syscall.syscall_id;
1850 struct hlist_head *dispatch_list;
1851 int ret = 0;
1852
1853 WARN_ON_ONCE(notifier->instrumentation != LTTNG_KERNEL_SYSCALL);
1854
1855 ret = lttng_syscall_filter_enable(group->sc_filter,
1856 notifier->desc->name, notifier->u.syscall.abi,
1857 notifier->u.syscall.entryexit);
1858 if (ret) {
1859 goto end;
1860 }
1861
1862 switch (notifier->u.syscall.entryexit) {
1863 case LTTNG_SYSCALL_ENTRY:
1864 switch (notifier->u.syscall.abi) {
1865 case LTTNG_SYSCALL_ABI_NATIVE:
1866 dispatch_list = &group->event_notifier_syscall_dispatch[syscall_id];
1867 break;
1868 case LTTNG_SYSCALL_ABI_COMPAT:
1869 dispatch_list = &group->event_notifier_compat_syscall_dispatch[syscall_id];
1870 break;
1871 }
1872 break;
1873 case LTTNG_SYSCALL_EXIT:
1874 switch (notifier->u.syscall.abi) {
1875 case LTTNG_SYSCALL_ABI_NATIVE:
1876 dispatch_list = &group->event_notifier_exit_syscall_dispatch[syscall_id];
1877 break;
1878 case LTTNG_SYSCALL_ABI_COMPAT:
1879 dispatch_list = &group->event_notifier_exit_compat_syscall_dispatch[syscall_id];
1880 break;
1881 }
1882 break;
1883 }
1884
1885 hlist_add_head_rcu(&notifier->u.syscall.node, dispatch_list);
1886
1887end:
1888 return ret ;
1889}
1890
1891int lttng_syscall_filter_enable_event(
1892 struct lttng_channel *channel,
1893 struct lttng_event *event)
1894{
1895 WARN_ON_ONCE(event->instrumentation != LTTNG_KERNEL_SYSCALL);
1896
1897 return lttng_syscall_filter_enable(channel->sc_filter,
1898 event->desc->name, event->u.syscall.abi,
1899 event->u.syscall.entryexit);
1900}
1901
1902static
1903int lttng_syscall_filter_disable(
1904 struct lttng_syscall_filter *filter,
1905 const char *desc_name, enum lttng_syscall_abi abi,
1906 enum lttng_syscall_entryexit entryexit)
1907{
1908 const char *syscall_name;
1909 unsigned long *bitmap;
1910 int syscall_nr;
1911
1912 syscall_name = get_syscall_name(desc_name, abi, entryexit);
1913
1914 switch (abi) {
1915 case LTTNG_SYSCALL_ABI_NATIVE:
1916 syscall_nr = get_syscall_nr(syscall_name);
1917 break;
1918 case LTTNG_SYSCALL_ABI_COMPAT:
1919 syscall_nr = get_compat_syscall_nr(syscall_name);
1920 break;
1921 default:
1922 return -EINVAL;
1923 }
1924 if (syscall_nr < 0)
1925 return -ENOENT;
1926
1927 switch (entryexit) {
1928 case LTTNG_SYSCALL_ENTRY:
1929 switch (abi) {
1930 case LTTNG_SYSCALL_ABI_NATIVE:
1931 bitmap = filter->sc_entry;
1932 break;
1933 case LTTNG_SYSCALL_ABI_COMPAT:
1934 bitmap = filter->sc_compat_entry;
1935 break;
1936 default:
1937 return -EINVAL;
1938 }
1939 break;
1940 case LTTNG_SYSCALL_EXIT:
1941 switch (abi) {
1942 case LTTNG_SYSCALL_ABI_NATIVE:
1943 bitmap = filter->sc_exit;
1944 break;
1945 case LTTNG_SYSCALL_ABI_COMPAT:
1946 bitmap = filter->sc_compat_exit;
1947 break;
1948 default:
1949 return -EINVAL;
1950 }
1951 break;
1952 default:
1953 return -EINVAL;
1954 }
1955 if (!test_bit(syscall_nr, bitmap))
1956 return -EEXIST;
1957 bitmap_clear(bitmap, syscall_nr, 1);
1958
1959 return 0;
1960}
1961
1962int lttng_syscall_filter_disable_event_notifier(
1963 struct lttng_event_notifier *notifier)
1964{
1965 struct lttng_event_notifier_group *group = notifier->group;
1966 int ret;
1967
1968 WARN_ON_ONCE(notifier->instrumentation != LTTNG_KERNEL_SYSCALL);
1969
1970 ret = lttng_syscall_filter_disable(group->sc_filter,
1971 notifier->desc->name, notifier->u.syscall.abi,
1972 notifier->u.syscall.entryexit);
1973 WARN_ON_ONCE(ret != 0);
1974
1975 hlist_del_rcu(&notifier->u.syscall.node);
1976 return 0;
1977}
1978
1979int lttng_syscall_filter_disable_event(
1980 struct lttng_channel *channel,
1981 struct lttng_event *event)
1982{
1983 return lttng_syscall_filter_disable(channel->sc_filter,
1984 event->desc->name, event->u.syscall.abi,
1985 event->u.syscall.entryexit);
1986}
1987
1988static
1989const struct trace_syscall_entry *syscall_list_get_entry(loff_t *pos)
1990{
1991 const struct trace_syscall_entry *entry;
1992 int iter = 0;
1993
1994 for (entry = sc_table;
1995 entry < sc_table + ARRAY_SIZE(sc_table);
1996 entry++) {
1997 if (iter++ >= *pos)
1998 return entry;
1999 }
2000 for (entry = compat_sc_table;
2001 entry < compat_sc_table + ARRAY_SIZE(compat_sc_table);
2002 entry++) {
2003 if (iter++ >= *pos)
2004 return entry;
2005 }
2006 /* End of list */
2007 return NULL;
2008}
2009
2010static
2011void *syscall_list_start(struct seq_file *m, loff_t *pos)
2012{
2013 return (void *) syscall_list_get_entry(pos);
2014}
2015
2016static
2017void *syscall_list_next(struct seq_file *m, void *p, loff_t *ppos)
2018{
2019 (*ppos)++;
2020 return (void *) syscall_list_get_entry(ppos);
2021}
2022
2023static
2024void syscall_list_stop(struct seq_file *m, void *p)
2025{
2026}
2027
2028static
2029int get_sc_table(const struct trace_syscall_entry *entry,
2030 const struct trace_syscall_entry **table,
2031 unsigned int *bitness)
2032{
2033 if (entry >= sc_table && entry < sc_table + ARRAY_SIZE(sc_table)) {
2034 if (bitness)
2035 *bitness = BITS_PER_LONG;
2036 if (table)
2037 *table = sc_table;
2038 return 0;
2039 }
2040 if (!(entry >= compat_sc_table
2041 && entry < compat_sc_table + ARRAY_SIZE(compat_sc_table))) {
2042 return -EINVAL;
2043 }
2044 if (bitness)
2045 *bitness = 32;
2046 if (table)
2047 *table = compat_sc_table;
2048 return 0;
2049}
2050
2051static
2052int syscall_list_show(struct seq_file *m, void *p)
2053{
2054 const struct trace_syscall_entry *table, *entry = p;
2055 unsigned int bitness;
2056 unsigned long index;
2057 int ret;
2058 const char *name;
2059
2060 ret = get_sc_table(entry, &table, &bitness);
2061 if (ret)
2062 return ret;
2063 if (!entry->desc)
2064 return 0;
2065 if (table == sc_table) {
2066 index = entry - table;
2067 name = &entry->desc->name[strlen(SYSCALL_ENTRY_STR)];
2068 } else {
2069 index = (entry - table) + ARRAY_SIZE(sc_table);
2070 name = &entry->desc->name[strlen(COMPAT_SYSCALL_ENTRY_STR)];
2071 }
2072 seq_printf(m, "syscall { index = %lu; name = %s; bitness = %u; };\n",
2073 index, name, bitness);
2074 return 0;
2075}
2076
2077static
2078const struct seq_operations lttng_syscall_list_seq_ops = {
2079 .start = syscall_list_start,
2080 .next = syscall_list_next,
2081 .stop = syscall_list_stop,
2082 .show = syscall_list_show,
2083};
2084
2085static
2086int lttng_syscall_list_open(struct inode *inode, struct file *file)
2087{
2088 return seq_open(file, &lttng_syscall_list_seq_ops);
2089}
2090
2091const struct file_operations lttng_syscall_list_fops = {
2092 .owner = THIS_MODULE,
2093 .open = lttng_syscall_list_open,
2094 .read = seq_read,
2095 .llseek = seq_lseek,
2096 .release = seq_release,
2097};
2098
2099/*
2100 * A syscall is enabled if it is traced for either entry or exit.
2101 */
2102long lttng_channel_syscall_mask(struct lttng_channel *channel,
2103 struct lttng_kernel_syscall_mask __user *usyscall_mask)
2104{
2105 uint32_t len, sc_tables_len, bitmask_len;
2106 int ret = 0, bit;
2107 char *tmp_mask;
2108 struct lttng_syscall_filter *filter;
2109
2110 ret = get_user(len, &usyscall_mask->len);
2111 if (ret)
2112 return ret;
2113 sc_tables_len = get_sc_tables_len();
2114 bitmask_len = ALIGN(sc_tables_len, 8) >> 3;
2115 if (len < sc_tables_len) {
2116 return put_user(sc_tables_len, &usyscall_mask->len);
2117 }
2118 /* Array is large enough, we can copy array to user-space. */
2119 tmp_mask = kzalloc(bitmask_len, GFP_KERNEL);
2120 if (!tmp_mask)
2121 return -ENOMEM;
2122 filter = channel->sc_filter;
2123
2124 for (bit = 0; bit < ARRAY_SIZE(sc_table); bit++) {
2125 char state;
2126
2127 if (channel->sc_table) {
2128 if (!READ_ONCE(channel->syscall_all) && filter)
2129 state = test_bit(bit, filter->sc_entry)
2130 || test_bit(bit, filter->sc_exit);
2131 else
2132 state = 1;
2133 } else {
2134 state = 0;
2135 }
2136 bt_bitfield_write_be(tmp_mask, char, bit, 1, state);
2137 }
2138 for (; bit < sc_tables_len; bit++) {
2139 char state;
2140
2141 if (channel->compat_sc_table) {
2142 if (!READ_ONCE(channel->syscall_all) && filter)
2143 state = test_bit(bit - ARRAY_SIZE(sc_table),
2144 filter->sc_compat_entry)
2145 || test_bit(bit - ARRAY_SIZE(sc_table),
2146 filter->sc_compat_exit);
2147 else
2148 state = 1;
2149 } else {
2150 state = 0;
2151 }
2152 bt_bitfield_write_be(tmp_mask, char, bit, 1, state);
2153 }
2154 if (copy_to_user(usyscall_mask->mask, tmp_mask, bitmask_len))
2155 ret = -EFAULT;
2156 kfree(tmp_mask);
2157 return ret;
2158}
2159
2160int lttng_abi_syscall_list(void)
2161{
2162 struct file *syscall_list_file;
2163 int file_fd, ret;
2164
2165 file_fd = lttng_get_unused_fd();
2166 if (file_fd < 0) {
2167 ret = file_fd;
2168 goto fd_error;
2169 }
2170
2171 syscall_list_file = anon_inode_getfile("[lttng_syscall_list]",
2172 &lttng_syscall_list_fops,
2173 NULL, O_RDWR);
2174 if (IS_ERR(syscall_list_file)) {
2175 ret = PTR_ERR(syscall_list_file);
2176 goto file_error;
2177 }
2178 ret = lttng_syscall_list_fops.open(NULL, syscall_list_file);
2179 if (ret < 0)
2180 goto open_error;
2181 fd_install(file_fd, syscall_list_file);
2182 return file_fd;
2183
2184open_error:
2185 fput(syscall_list_file);
2186file_error:
2187 put_unused_fd(file_fd);
2188fd_error:
2189 return ret;
2190}
This page took 0.029994 seconds and 4 git commands to generate.