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