Fix: notifier: use store-release/load-acquire for error counter
[lttng-modules.git] / src / lttng-syscalls.c
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
45 enum 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
62 static
63 void syscall_entry_event_probe(void *__data, struct pt_regs *regs, long id);
64 static
65 void syscall_exit_event_probe(void *__data, struct pt_regs *regs, long ret);
66
67 static
68 void syscall_entry_event_notifier_probe(void *__data, struct pt_regs *regs,
69 long id);
70 static
71 void syscall_exit_event_notifier_probe(void *__data, struct pt_regs *regs,
72 long ret);
73
74 /*
75 * Forward declarations for old kernels.
76 */
77 struct mmsghdr;
78 struct rlimit64;
79 struct oldold_utsname;
80 struct old_utsname;
81 struct sel_arg_struct;
82 struct mmap_arg_struct;
83 struct file_handle;
84 struct user_msghdr;
85
86 /*
87 * Forward declaration for kernels >= 5.6
88 */
89 struct timex;
90 struct timeval;
91 struct itimerval;
92 struct itimerspec;
93
94 #if (LINUX_VERSION_CODE >= KERNEL_VERSION(5,6,0))
95 typedef __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
294 struct 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 */
320 static 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 */
336 const 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 */
359 static 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 */
375 const 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
384 struct 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
391 static void syscall_entry_event_unknown(struct hlist_head *unknown_action_list_head,
392 struct pt_regs *regs, long id)
393 {
394 unsigned long args[LTTNG_SYSCALL_NR_ARGS];
395 struct lttng_event *event;
396
397 lttng_syscall_get_arguments(current, regs, args);
398 hlist_for_each_entry_rcu(event, unknown_action_list_head, u.syscall.node) {
399 if (unlikely(in_compat_syscall()))
400 __event_probe__compat_syscall_entry_unknown(event, id, args);
401 else
402 __event_probe__syscall_entry_unknown(event, id, args);
403 }
404 }
405
406 static void syscall_entry_event_notifier_unknown(
407 struct hlist_head *unknown_dispatch_list_head,
408 struct pt_regs *regs, long id)
409 {
410 unsigned long args[LTTNG_SYSCALL_NR_ARGS];
411 struct lttng_event_notifier *notifier;
412
413 lttng_syscall_get_arguments(current, regs, args);
414 lttng_hlist_for_each_entry_rcu(notifier, unknown_dispatch_list_head, u.syscall.node) {
415 if (unlikely(in_compat_syscall()))
416 __event_notifier_probe__compat_syscall_entry_unknown(notifier, id, args);
417 else
418 __event_notifier_probe__syscall_entry_unknown(notifier, id, args);
419 }
420 }
421
422 static void syscall_exit_event_notifier_unknown(
423 struct hlist_head *unknown_dispatch_list_head,
424 struct pt_regs *regs, long id, long ret)
425 {
426 unsigned long args[LTTNG_SYSCALL_NR_ARGS];
427 struct lttng_event_notifier *notifier;
428
429 lttng_syscall_get_arguments(current, regs, args);
430 lttng_hlist_for_each_entry_rcu(notifier, unknown_dispatch_list_head, u.syscall.node) {
431 if (unlikely(in_compat_syscall()))
432 __event_notifier_probe__compat_syscall_exit_unknown(notifier, id, ret, args);
433 else
434 __event_notifier_probe__syscall_exit_unknown(notifier, id, ret, args);
435 }
436 }
437
438 static __always_inline
439 void syscall_entry_call_func(struct hlist_head *action_list,
440 void *func, unsigned int nrargs,
441 struct pt_regs *regs)
442 {
443 struct lttng_event *event;
444
445 switch (nrargs) {
446 case 0:
447 {
448 void (*fptr)(void *__data) = func;
449
450 hlist_for_each_entry_rcu(event, action_list, u.syscall.node)
451 fptr(event);
452 break;
453 }
454 case 1:
455 {
456 void (*fptr)(void *__data, unsigned long arg0) = func;
457 unsigned long args[LTTNG_SYSCALL_NR_ARGS];
458
459 lttng_syscall_get_arguments(current, regs, args);
460 hlist_for_each_entry_rcu(event, action_list, u.syscall.node)
461 fptr(event, args[0]);
462 break;
463 }
464 case 2:
465 {
466 void (*fptr)(void *__data,
467 unsigned long arg0,
468 unsigned long arg1) = func;
469 unsigned long args[LTTNG_SYSCALL_NR_ARGS];
470
471 lttng_syscall_get_arguments(current, regs, args);
472 hlist_for_each_entry_rcu(event, action_list, u.syscall.node)
473 fptr(event, args[0], args[1]);
474 break;
475 }
476 case 3:
477 {
478 void (*fptr)(void *__data,
479 unsigned long arg0,
480 unsigned long arg1,
481 unsigned long arg2) = func;
482 unsigned long args[LTTNG_SYSCALL_NR_ARGS];
483
484 lttng_syscall_get_arguments(current, regs, args);
485 hlist_for_each_entry_rcu(event, action_list, u.syscall.node)
486 fptr(event, args[0], args[1], args[2]);
487 break;
488 }
489 case 4:
490 {
491 void (*fptr)(void *__data,
492 unsigned long arg0,
493 unsigned long arg1,
494 unsigned long arg2,
495 unsigned long arg3) = func;
496 unsigned long args[LTTNG_SYSCALL_NR_ARGS];
497
498 lttng_syscall_get_arguments(current, regs, args);
499 hlist_for_each_entry_rcu(event, action_list, u.syscall.node)
500 fptr(event, args[0], args[1], args[2], args[3]);
501 break;
502 }
503 case 5:
504 {
505 void (*fptr)(void *__data,
506 unsigned long arg0,
507 unsigned long arg1,
508 unsigned long arg2,
509 unsigned long arg3,
510 unsigned long arg4) = func;
511 unsigned long args[LTTNG_SYSCALL_NR_ARGS];
512
513 lttng_syscall_get_arguments(current, regs, args);
514 hlist_for_each_entry_rcu(event, action_list, u.syscall.node)
515 fptr(event, args[0], args[1], args[2], args[3], args[4]);
516 break;
517 }
518 case 6:
519 {
520 void (*fptr)(void *__data,
521 unsigned long arg0,
522 unsigned long arg1,
523 unsigned long arg2,
524 unsigned long arg3,
525 unsigned long arg4,
526 unsigned long arg5) = func;
527 unsigned long args[LTTNG_SYSCALL_NR_ARGS];
528
529 lttng_syscall_get_arguments(current, regs, args);
530 hlist_for_each_entry_rcu(event, action_list, u.syscall.node)
531 fptr(event, args[0], args[1], args[2],
532 args[3], args[4], args[5]);
533 break;
534 }
535 default:
536 break;
537 }
538 }
539
540 static __always_inline
541 void syscall_entry_event_notifier_call_func(struct hlist_head *dispatch_list,
542 void *func, unsigned int nrargs, struct pt_regs *regs)
543 {
544 struct lttng_event_notifier *notifier;
545
546 switch (nrargs) {
547 case 0:
548 {
549 void (*fptr)(void *__data) = func;
550
551 lttng_hlist_for_each_entry_rcu(notifier, dispatch_list, u.syscall.node)
552 fptr(notifier);
553 break;
554 }
555 case 1:
556 {
557 void (*fptr)(void *__data, unsigned long arg0) = func;
558 unsigned long args[LTTNG_SYSCALL_NR_ARGS];
559
560 lttng_syscall_get_arguments(current, regs, args);
561 lttng_hlist_for_each_entry_rcu(notifier, dispatch_list, u.syscall.node)
562 fptr(notifier, args[0]);
563 break;
564 }
565 case 2:
566 {
567 void (*fptr)(void *__data,
568 unsigned long arg0,
569 unsigned long arg1) = 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]);
575 break;
576 }
577 case 3:
578 {
579 void (*fptr)(void *__data,
580 unsigned long arg0,
581 unsigned long arg1,
582 unsigned long arg2) = func;
583 unsigned long args[LTTNG_SYSCALL_NR_ARGS];
584
585 lttng_syscall_get_arguments(current, regs, args);
586 lttng_hlist_for_each_entry_rcu(notifier, dispatch_list, u.syscall.node)
587 fptr(notifier, args[0], args[1], args[2]);
588 break;
589 }
590 case 4:
591 {
592 void (*fptr)(void *__data,
593 unsigned long arg0,
594 unsigned long arg1,
595 unsigned long arg2,
596 unsigned long arg3) = func;
597 unsigned long args[LTTNG_SYSCALL_NR_ARGS];
598
599 lttng_syscall_get_arguments(current, regs, args);
600 lttng_hlist_for_each_entry_rcu(notifier, dispatch_list, u.syscall.node)
601 fptr(notifier, args[0], args[1], args[2], args[3]);
602 break;
603 }
604 case 5:
605 {
606 void (*fptr)(void *__data,
607 unsigned long arg0,
608 unsigned long arg1,
609 unsigned long arg2,
610 unsigned long arg3,
611 unsigned long arg4) = func;
612 unsigned long args[LTTNG_SYSCALL_NR_ARGS];
613
614 lttng_syscall_get_arguments(current, regs, args);
615 lttng_hlist_for_each_entry_rcu(notifier, dispatch_list, u.syscall.node)
616 fptr(notifier, args[0], args[1], args[2], args[3], args[4]);
617 break;
618 }
619 case 6:
620 {
621 void (*fptr)(void *__data,
622 unsigned long arg0,
623 unsigned long arg1,
624 unsigned long arg2,
625 unsigned long arg3,
626 unsigned long arg4,
627 unsigned long arg5) = func;
628 unsigned long args[LTTNG_SYSCALL_NR_ARGS];
629
630 lttng_syscall_get_arguments(current, regs, args);
631 lttng_hlist_for_each_entry_rcu(notifier, dispatch_list, u.syscall.node)
632 fptr(notifier, args[0], args[1], args[2], args[3], args[4], args[5]);
633 break;
634 }
635 default:
636 break;
637 }
638 }
639
640 void syscall_entry_event_probe(void *__data, struct pt_regs *regs, long id)
641 {
642 struct lttng_channel *chan = __data;
643 struct hlist_head *action_list, *unknown_action_list;
644 const struct trace_syscall_entry *table, *entry;
645 size_t table_len;
646
647 if (unlikely(in_compat_syscall())) {
648 struct lttng_syscall_filter *filter = chan->sc_filter;
649
650 if (id < 0 || id >= NR_compat_syscalls
651 || (!READ_ONCE(chan->syscall_all_entry) && !test_bit(id, filter->sc_compat_entry))) {
652 /* System call filtered out. */
653 return;
654 }
655 table = compat_sc_table;
656 table_len = ARRAY_SIZE(compat_sc_table);
657 unknown_action_list = &chan->sc_compat_unknown;
658 } else {
659 struct lttng_syscall_filter *filter = chan->sc_filter;
660
661 if (id < 0 || id >= NR_syscalls
662 || (!READ_ONCE(chan->syscall_all_entry) && !test_bit(id, filter->sc_entry))) {
663 /* System call filtered out. */
664 return;
665 }
666 table = sc_table;
667 table_len = ARRAY_SIZE(sc_table);
668 unknown_action_list = &chan->sc_unknown;
669 }
670 if (unlikely(id < 0 || id >= table_len)) {
671 syscall_entry_event_unknown(unknown_action_list, regs, id);
672 return;
673 }
674
675 entry = &table[id];
676 if (!entry->event_func) {
677 syscall_entry_event_unknown(unknown_action_list, regs, id);
678 return;
679 }
680
681 if (unlikely(in_compat_syscall())) {
682 action_list = &chan->compat_sc_table[id];
683 } else {
684 action_list = &chan->sc_table[id];
685 }
686 if (unlikely(hlist_empty(action_list)))
687 return;
688
689 syscall_entry_call_func(action_list, entry->event_func, entry->nrargs, regs);
690 }
691
692 void syscall_entry_event_notifier_probe(void *__data, struct pt_regs *regs,
693 long id)
694 {
695 struct lttng_event_notifier_group *group = __data;
696 const struct trace_syscall_entry *table, *entry;
697 struct hlist_head *dispatch_list, *unknown_dispatch_list;
698 size_t table_len;
699
700 if (unlikely(in_compat_syscall())) {
701 struct lttng_syscall_filter *filter = group->sc_filter;
702
703 if (id < 0 || id >= NR_compat_syscalls
704 || (!READ_ONCE(group->syscall_all_entry) &&
705 !test_bit(id, filter->sc_compat_entry))) {
706 /* System call filtered out. */
707 return;
708 }
709 table = compat_sc_table;
710 table_len = ARRAY_SIZE(compat_sc_table);
711 unknown_dispatch_list = &group->event_notifier_compat_unknown_syscall_dispatch;
712 } else {
713 struct lttng_syscall_filter *filter = group->sc_filter;
714
715 if (id < 0 || id >= NR_syscalls
716 || (!READ_ONCE(group->syscall_all_entry) &&
717 !test_bit(id, filter->sc_entry))) {
718 /* System call filtered out. */
719 return;
720 }
721 table = sc_table;
722 table_len = ARRAY_SIZE(sc_table);
723 unknown_dispatch_list = &group->event_notifier_unknown_syscall_dispatch;
724 }
725 /* Check if the syscall id is out of bound. */
726 if (unlikely(id < 0 || id >= table_len)) {
727 syscall_entry_event_notifier_unknown(unknown_dispatch_list,
728 regs, id);
729 return;
730 }
731
732 entry = &table[id];
733 if (!entry->event_notifier_func) {
734 syscall_entry_event_notifier_unknown(unknown_dispatch_list,
735 regs, id);
736 return;
737 }
738
739 if (unlikely(in_compat_syscall())) {
740 dispatch_list = &group->event_notifier_compat_syscall_dispatch[id];
741 } else {
742 dispatch_list = &group->event_notifier_syscall_dispatch[id];
743 }
744 if (unlikely(hlist_empty(dispatch_list)))
745 return;
746
747 syscall_entry_event_notifier_call_func(dispatch_list,
748 entry->event_notifier_func, entry->nrargs, regs);
749 }
750
751 static void syscall_exit_event_unknown(struct hlist_head *unknown_action_list_head,
752 struct pt_regs *regs, long id, long ret)
753 {
754 unsigned long args[LTTNG_SYSCALL_NR_ARGS];
755 struct lttng_event *event;
756
757 lttng_syscall_get_arguments(current, regs, args);
758 hlist_for_each_entry_rcu(event, unknown_action_list_head, u.syscall.node) {
759 if (unlikely(in_compat_syscall()))
760 __event_probe__compat_syscall_exit_unknown(event, id, ret,
761 args);
762 else
763 __event_probe__syscall_exit_unknown(event, id, ret, args);
764 }
765 }
766
767 static __always_inline
768 void syscall_exit_call_func(struct hlist_head *action_list,
769 void *func, unsigned int nrargs,
770 struct pt_regs *regs, long ret)
771 {
772 struct lttng_event *event;
773
774 switch (nrargs) {
775 case 0:
776 {
777 void (*fptr)(void *__data, long ret) = func;
778
779 hlist_for_each_entry_rcu(event, action_list, u.syscall.node)
780 fptr(event, ret);
781 break;
782 }
783 case 1:
784 {
785 void (*fptr)(void *__data,
786 long ret,
787 unsigned long arg0) = func;
788 unsigned long args[LTTNG_SYSCALL_NR_ARGS];
789
790 lttng_syscall_get_arguments(current, regs, args);
791 hlist_for_each_entry_rcu(event, action_list, u.syscall.node)
792 fptr(event, ret, args[0]);
793 break;
794 }
795 case 2:
796 {
797 void (*fptr)(void *__data,
798 long ret,
799 unsigned long arg0,
800 unsigned long arg1) = func;
801 unsigned long args[LTTNG_SYSCALL_NR_ARGS];
802
803 lttng_syscall_get_arguments(current, regs, args);
804 hlist_for_each_entry_rcu(event, action_list, u.syscall.node)
805 fptr(event, ret, args[0], args[1]);
806 break;
807 }
808 case 3:
809 {
810 void (*fptr)(void *__data,
811 long ret,
812 unsigned long arg0,
813 unsigned long arg1,
814 unsigned long arg2) = func;
815 unsigned long args[LTTNG_SYSCALL_NR_ARGS];
816
817 lttng_syscall_get_arguments(current, regs, args);
818 hlist_for_each_entry_rcu(event, action_list, u.syscall.node)
819 fptr(event, ret, args[0], args[1], args[2]);
820 break;
821 }
822 case 4:
823 {
824 void (*fptr)(void *__data,
825 long ret,
826 unsigned long arg0,
827 unsigned long arg1,
828 unsigned long arg2,
829 unsigned long arg3) = func;
830 unsigned long args[LTTNG_SYSCALL_NR_ARGS];
831
832 lttng_syscall_get_arguments(current, regs, args);
833 hlist_for_each_entry_rcu(event, action_list, u.syscall.node)
834 fptr(event, ret, args[0], args[1], args[2], args[3]);
835 break;
836 }
837 case 5:
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,
845 unsigned long arg4) = func;
846 unsigned long args[LTTNG_SYSCALL_NR_ARGS];
847
848 lttng_syscall_get_arguments(current, regs, args);
849 hlist_for_each_entry_rcu(event, action_list, u.syscall.node)
850 fptr(event, ret, args[0], args[1], args[2], args[3], args[4]);
851 break;
852 }
853 case 6:
854 {
855 void (*fptr)(void *__data,
856 long ret,
857 unsigned long arg0,
858 unsigned long arg1,
859 unsigned long arg2,
860 unsigned long arg3,
861 unsigned long arg4,
862 unsigned long arg5) = func;
863 unsigned long args[LTTNG_SYSCALL_NR_ARGS];
864
865 lttng_syscall_get_arguments(current, regs, args);
866 hlist_for_each_entry_rcu(event, action_list, u.syscall.node)
867 fptr(event, ret, args[0], args[1], args[2],
868 args[3], args[4], args[5]);
869 break;
870 }
871 default:
872 break;
873 }
874 }
875
876 void syscall_exit_event_probe(void *__data, struct pt_regs *regs, long ret)
877 {
878 struct lttng_channel *chan = __data;
879 struct hlist_head *action_list, *unknown_action_list;
880 const struct trace_syscall_entry *table, *entry;
881 size_t table_len;
882 long id;
883
884 id = syscall_get_nr(current, regs);
885
886 if (unlikely(in_compat_syscall())) {
887 struct lttng_syscall_filter *filter = chan->sc_filter;
888
889 if (id < 0 || id >= NR_compat_syscalls
890 || (!READ_ONCE(chan->syscall_all_exit) && !test_bit(id, filter->sc_compat_exit))) {
891 /* System call filtered out. */
892 return;
893 }
894 table = compat_sc_exit_table;
895 table_len = ARRAY_SIZE(compat_sc_exit_table);
896 unknown_action_list = &chan->compat_sc_exit_unknown;
897 } else {
898 struct lttng_syscall_filter *filter = chan->sc_filter;
899
900 if (id < 0 || id >= NR_syscalls
901 || (!READ_ONCE(chan->syscall_all_exit) && !test_bit(id, filter->sc_exit))) {
902 /* System call filtered out. */
903 return;
904 }
905 table = sc_exit_table;
906 table_len = ARRAY_SIZE(sc_exit_table);
907 unknown_action_list = &chan->sc_exit_unknown;
908 }
909 if (unlikely(id < 0 || id >= table_len)) {
910 syscall_exit_event_unknown(unknown_action_list, regs, id, ret);
911 return;
912 }
913
914 entry = &table[id];
915 if (!entry->event_func) {
916 syscall_exit_event_unknown(unknown_action_list, regs, id, ret);
917 return;
918 }
919
920 if (unlikely(in_compat_syscall())) {
921 action_list = &chan->compat_sc_exit_table[id];
922 } else {
923 action_list = &chan->sc_exit_table[id];
924 }
925 if (unlikely(hlist_empty(action_list)))
926 return;
927
928 syscall_exit_call_func(action_list, entry->event_func, entry->nrargs,
929 regs, ret);
930 }
931
932 static __always_inline
933 void syscall_exit_event_notifier_call_func(struct hlist_head *dispatch_list,
934 void *func, unsigned int nrargs, struct pt_regs *regs, long ret)
935 {
936 struct lttng_event_notifier *notifier;
937
938 switch (nrargs) {
939 case 0:
940 {
941 void (*fptr)(void *__data, long ret) = func;
942
943 lttng_hlist_for_each_entry_rcu(notifier, dispatch_list, u.syscall.node)
944 fptr(notifier, ret);
945 break;
946 }
947 case 1:
948 {
949 void (*fptr)(void *__data, long ret, unsigned long arg0) = func;
950 unsigned long args[LTTNG_SYSCALL_NR_ARGS];
951
952 lttng_syscall_get_arguments(current, regs, args);
953 lttng_hlist_for_each_entry_rcu(notifier, dispatch_list, u.syscall.node)
954 fptr(notifier, ret, args[0]);
955 break;
956 }
957 case 2:
958 {
959 void (*fptr)(void *__data,
960 long ret,
961 unsigned long arg0,
962 unsigned long arg1) = func;
963 unsigned long args[LTTNG_SYSCALL_NR_ARGS];
964
965 lttng_syscall_get_arguments(current, regs, args);
966 lttng_hlist_for_each_entry_rcu(notifier, dispatch_list, u.syscall.node)
967 fptr(notifier, ret, args[0], args[1]);
968 break;
969 }
970 case 3:
971 {
972 void (*fptr)(void *__data,
973 long ret,
974 unsigned long arg0,
975 unsigned long arg1,
976 unsigned long arg2) = func;
977 unsigned long args[LTTNG_SYSCALL_NR_ARGS];
978
979 lttng_syscall_get_arguments(current, regs, args);
980 lttng_hlist_for_each_entry_rcu(notifier, dispatch_list, u.syscall.node)
981 fptr(notifier, ret, args[0], args[1], args[2]);
982 break;
983 }
984 case 4:
985 {
986 void (*fptr)(void *__data,
987 long ret,
988 unsigned long arg0,
989 unsigned long arg1,
990 unsigned long arg2,
991 unsigned long arg3) = func;
992 unsigned long args[LTTNG_SYSCALL_NR_ARGS];
993
994 lttng_syscall_get_arguments(current, regs, args);
995 lttng_hlist_for_each_entry_rcu(notifier, dispatch_list, u.syscall.node)
996 fptr(notifier, ret, args[0], args[1], args[2], args[3]);
997 break;
998 }
999 case 5:
1000 {
1001 void (*fptr)(void *__data,
1002 long ret,
1003 unsigned long arg0,
1004 unsigned long arg1,
1005 unsigned long arg2,
1006 unsigned long arg3,
1007 unsigned long arg4) = func;
1008 unsigned long args[LTTNG_SYSCALL_NR_ARGS];
1009
1010 lttng_syscall_get_arguments(current, regs, args);
1011 lttng_hlist_for_each_entry_rcu(notifier, dispatch_list, u.syscall.node)
1012 fptr(notifier, ret, args[0], args[1], args[2], args[3], args[4]);
1013 break;
1014 }
1015 case 6:
1016 {
1017 void (*fptr)(void *__data,
1018 long ret,
1019 unsigned long arg0,
1020 unsigned long arg1,
1021 unsigned long arg2,
1022 unsigned long arg3,
1023 unsigned long arg4,
1024 unsigned long arg5) = func;
1025 unsigned long args[LTTNG_SYSCALL_NR_ARGS];
1026
1027 lttng_syscall_get_arguments(current, regs, args);
1028 lttng_hlist_for_each_entry_rcu(notifier, dispatch_list, u.syscall.node)
1029 fptr(notifier, ret, args[0], args[1], args[2], args[3], args[4], args[5]);
1030 break;
1031 }
1032 default:
1033 break;
1034 }
1035 }
1036
1037 static
1038 void syscall_exit_event_notifier_probe(void *__data, struct pt_regs *regs,
1039 long ret)
1040 {
1041 struct lttng_event_notifier_group *group = __data;
1042 const struct trace_syscall_entry *table, *entry;
1043 struct hlist_head *dispatch_list, *unknown_dispatch_list;
1044 size_t table_len;
1045 long id;
1046
1047 id = syscall_get_nr(current, regs);
1048
1049 if (unlikely(in_compat_syscall())) {
1050 struct lttng_syscall_filter *filter = group->sc_filter;
1051
1052 if (id < 0 || id >= NR_compat_syscalls
1053 || (!READ_ONCE(group->syscall_all_exit) &&
1054 !test_bit(id, filter->sc_compat_exit))) {
1055 /* System call filtered out. */
1056 return;
1057 }
1058 table = compat_sc_exit_table;
1059 table_len = ARRAY_SIZE(compat_sc_exit_table);
1060 unknown_dispatch_list = &group->event_notifier_exit_compat_unknown_syscall_dispatch;
1061 } else {
1062 struct lttng_syscall_filter *filter = group->sc_filter;
1063
1064 if (id < 0 || id >= NR_syscalls
1065 || (!READ_ONCE(group->syscall_all_exit) &&
1066 !test_bit(id, filter->sc_exit))) {
1067 /* System call filtered out. */
1068 return;
1069 }
1070 table = sc_exit_table;
1071 table_len = ARRAY_SIZE(sc_exit_table);
1072 unknown_dispatch_list = &group->event_notifier_exit_unknown_syscall_dispatch;
1073 }
1074 /* Check if the syscall id is out of bound. */
1075 if (unlikely(id < 0 || id >= table_len)) {
1076 syscall_exit_event_notifier_unknown(unknown_dispatch_list,
1077 regs, id, ret);
1078 return;
1079 }
1080
1081 entry = &table[id];
1082 if (!entry->event_notifier_func) {
1083 syscall_entry_event_notifier_unknown(unknown_dispatch_list,
1084 regs, id);
1085 return;
1086 }
1087
1088 if (unlikely(in_compat_syscall())) {
1089 dispatch_list = &group->event_notifier_exit_compat_syscall_dispatch[id];
1090 } else {
1091 dispatch_list = &group->event_notifier_exit_syscall_dispatch[id];
1092 }
1093 if (unlikely(hlist_empty(dispatch_list)))
1094 return;
1095
1096 syscall_exit_event_notifier_call_func(dispatch_list,
1097 entry->event_notifier_func, entry->nrargs, regs, ret);
1098 }
1099 /*
1100 * noinline to diminish caller stack size.
1101 * Should be called with sessions lock held.
1102 */
1103 static
1104 int lttng_create_syscall_event_if_missing(const struct trace_syscall_entry *table, size_t table_len,
1105 struct hlist_head *chan_table, struct lttng_event_enabler *event_enabler,
1106 void *filter, enum sc_type type)
1107 {
1108 struct lttng_channel *chan = event_enabler->chan;
1109 struct lttng_session *session = chan->session;
1110 unsigned int i;
1111
1112 /* Allocate events for each syscall matching enabler, insert into table */
1113 for (i = 0; i < table_len; i++) {
1114 const struct lttng_event_desc *desc = table[i].desc;
1115 struct lttng_kernel_event ev;
1116 struct lttng_event *event;
1117 struct hlist_head *head;
1118 bool found = false;
1119
1120 if (!desc) {
1121 /* Unknown syscall */
1122 continue;
1123 }
1124 if (lttng_desc_match_enabler(desc,
1125 lttng_event_enabler_as_enabler(event_enabler)) <= 0)
1126 continue;
1127 /*
1128 * Check if already created.
1129 */
1130 head = utils_borrow_hash_table_bucket(
1131 session->events_ht.table, LTTNG_EVENT_HT_SIZE,
1132 desc->name);
1133 lttng_hlist_for_each_entry(event, head, hlist) {
1134 if (event->desc == desc
1135 && event->chan == event_enabler->chan)
1136 found = true;
1137 }
1138 if (found)
1139 continue;
1140
1141 /* We need to create an event for this syscall/enabler. */
1142 memset(&ev, 0, sizeof(ev));
1143 switch (type) {
1144 case SC_TYPE_ENTRY:
1145 ev.u.syscall.entryexit = LTTNG_KERNEL_SYSCALL_ENTRY;
1146 ev.u.syscall.abi = LTTNG_KERNEL_SYSCALL_ABI_NATIVE;
1147 break;
1148 case SC_TYPE_EXIT:
1149 ev.u.syscall.entryexit = LTTNG_KERNEL_SYSCALL_EXIT;
1150 ev.u.syscall.abi = LTTNG_KERNEL_SYSCALL_ABI_NATIVE;
1151 break;
1152 case SC_TYPE_COMPAT_ENTRY:
1153 ev.u.syscall.entryexit = LTTNG_KERNEL_SYSCALL_ENTRY;
1154 ev.u.syscall.abi = LTTNG_KERNEL_SYSCALL_ABI_COMPAT;
1155 break;
1156 case SC_TYPE_COMPAT_EXIT:
1157 ev.u.syscall.entryexit = LTTNG_KERNEL_SYSCALL_EXIT;
1158 ev.u.syscall.abi = LTTNG_KERNEL_SYSCALL_ABI_COMPAT;
1159 break;
1160 }
1161 strncpy(ev.name, desc->name, LTTNG_KERNEL_SYM_NAME_LEN - 1);
1162 ev.name[LTTNG_KERNEL_SYM_NAME_LEN - 1] = '\0';
1163 ev.instrumentation = LTTNG_KERNEL_SYSCALL;
1164 event = _lttng_event_create(chan, &ev, filter,
1165 desc, ev.instrumentation);
1166 WARN_ON_ONCE(!event);
1167 if (IS_ERR(event)) {
1168 /*
1169 * If something goes wrong in event registration
1170 * after the first one, we have no choice but to
1171 * leave the previous events in there, until
1172 * deleted by session teardown.
1173 */
1174 return PTR_ERR(event);
1175 }
1176 hlist_add_head(&event->u.syscall.node, &chan_table[i]);
1177 }
1178 return 0;
1179 }
1180
1181 /*
1182 * Should be called with sessions lock held.
1183 */
1184 int lttng_syscalls_register_event(struct lttng_event_enabler *event_enabler, void *filter)
1185 {
1186 struct lttng_channel *chan = event_enabler->chan;
1187 struct lttng_kernel_event ev;
1188 int ret;
1189
1190 wrapper_vmalloc_sync_mappings();
1191
1192 if (!chan->sc_table) {
1193 /* create syscall table mapping syscall to events */
1194 chan->sc_table = kzalloc(sizeof(struct lttng_event *)
1195 * ARRAY_SIZE(sc_table), GFP_KERNEL);
1196 if (!chan->sc_table)
1197 return -ENOMEM;
1198 }
1199 if (!chan->sc_exit_table) {
1200 /* create syscall table mapping syscall to events */
1201 chan->sc_exit_table = kzalloc(sizeof(struct lttng_event *)
1202 * ARRAY_SIZE(sc_exit_table), GFP_KERNEL);
1203 if (!chan->sc_exit_table)
1204 return -ENOMEM;
1205 }
1206
1207
1208 #ifdef CONFIG_COMPAT
1209 if (!chan->compat_sc_table) {
1210 /* create syscall table mapping compat syscall to events */
1211 chan->compat_sc_table = kzalloc(sizeof(struct lttng_event *)
1212 * ARRAY_SIZE(compat_sc_table), GFP_KERNEL);
1213 if (!chan->compat_sc_table)
1214 return -ENOMEM;
1215 }
1216
1217 if (!chan->compat_sc_exit_table) {
1218 /* create syscall table mapping compat syscall to events */
1219 chan->compat_sc_exit_table = kzalloc(sizeof(struct lttng_event *)
1220 * ARRAY_SIZE(compat_sc_exit_table), GFP_KERNEL);
1221 if (!chan->compat_sc_exit_table)
1222 return -ENOMEM;
1223 }
1224 #endif
1225 if (hlist_empty(&chan->sc_unknown)) {
1226 const struct lttng_event_desc *desc =
1227 &__event_desc___syscall_entry_unknown;
1228 struct lttng_event *event;
1229
1230 memset(&ev, 0, sizeof(ev));
1231 strncpy(ev.name, desc->name, LTTNG_KERNEL_SYM_NAME_LEN);
1232 ev.name[LTTNG_KERNEL_SYM_NAME_LEN - 1] = '\0';
1233 ev.instrumentation = LTTNG_KERNEL_SYSCALL;
1234 ev.u.syscall.entryexit = LTTNG_KERNEL_SYSCALL_ENTRY;
1235 ev.u.syscall.abi = LTTNG_KERNEL_SYSCALL_ABI_NATIVE;
1236 event = _lttng_event_create(chan, &ev, filter, desc,
1237 ev.instrumentation);
1238 WARN_ON_ONCE(!event);
1239 if (IS_ERR(event)) {
1240 return PTR_ERR(event);
1241 }
1242 hlist_add_head(&event->u.syscall.node, &chan->sc_unknown);
1243 }
1244
1245 if (hlist_empty(&chan->sc_compat_unknown)) {
1246 const struct lttng_event_desc *desc =
1247 &__event_desc___compat_syscall_entry_unknown;
1248 struct lttng_event *event;
1249
1250 memset(&ev, 0, sizeof(ev));
1251 strncpy(ev.name, desc->name, LTTNG_KERNEL_SYM_NAME_LEN);
1252 ev.name[LTTNG_KERNEL_SYM_NAME_LEN - 1] = '\0';
1253 ev.instrumentation = LTTNG_KERNEL_SYSCALL;
1254 ev.u.syscall.entryexit = LTTNG_KERNEL_SYSCALL_ENTRY;
1255 ev.u.syscall.abi = LTTNG_KERNEL_SYSCALL_ABI_COMPAT;
1256 event = _lttng_event_create(chan, &ev, filter, desc,
1257 ev.instrumentation);
1258 WARN_ON_ONCE(!event);
1259 if (IS_ERR(event)) {
1260 return PTR_ERR(event);
1261 }
1262 hlist_add_head(&event->u.syscall.node, &chan->sc_compat_unknown);
1263 }
1264
1265 if (hlist_empty(&chan->compat_sc_exit_unknown)) {
1266 const struct lttng_event_desc *desc =
1267 &__event_desc___compat_syscall_exit_unknown;
1268 struct lttng_event *event;
1269
1270 memset(&ev, 0, sizeof(ev));
1271 strncpy(ev.name, desc->name, LTTNG_KERNEL_SYM_NAME_LEN);
1272 ev.name[LTTNG_KERNEL_SYM_NAME_LEN - 1] = '\0';
1273 ev.instrumentation = LTTNG_KERNEL_SYSCALL;
1274 ev.u.syscall.entryexit = LTTNG_KERNEL_SYSCALL_EXIT;
1275 ev.u.syscall.abi = LTTNG_KERNEL_SYSCALL_ABI_COMPAT;
1276 event = _lttng_event_create(chan, &ev, filter, desc,
1277 ev.instrumentation);
1278 WARN_ON_ONCE(!event);
1279 if (IS_ERR(event)) {
1280 return PTR_ERR(event);
1281 }
1282 hlist_add_head(&event->u.syscall.node, &chan->compat_sc_exit_unknown);
1283 }
1284
1285 if (hlist_empty(&chan->sc_exit_unknown)) {
1286 const struct lttng_event_desc *desc =
1287 &__event_desc___syscall_exit_unknown;
1288 struct lttng_event *event;
1289
1290 memset(&ev, 0, sizeof(ev));
1291 strncpy(ev.name, desc->name, LTTNG_KERNEL_SYM_NAME_LEN);
1292 ev.name[LTTNG_KERNEL_SYM_NAME_LEN - 1] = '\0';
1293 ev.instrumentation = LTTNG_KERNEL_SYSCALL;
1294 ev.u.syscall.entryexit = LTTNG_KERNEL_SYSCALL_EXIT;
1295 ev.u.syscall.abi = LTTNG_KERNEL_SYSCALL_ABI_NATIVE;
1296 event = _lttng_event_create(chan, &ev, filter, desc,
1297 ev.instrumentation);
1298 WARN_ON_ONCE(!event);
1299 if (IS_ERR(event)) {
1300 return PTR_ERR(event);
1301 }
1302 hlist_add_head(&event->u.syscall.node, &chan->sc_exit_unknown);
1303 }
1304
1305 ret = lttng_create_syscall_event_if_missing(sc_table, ARRAY_SIZE(sc_table),
1306 chan->sc_table, event_enabler, filter, SC_TYPE_ENTRY);
1307 if (ret)
1308 return ret;
1309 ret = lttng_create_syscall_event_if_missing(sc_exit_table, ARRAY_SIZE(sc_exit_table),
1310 chan->sc_exit_table, event_enabler, filter, SC_TYPE_EXIT);
1311 if (ret)
1312 return ret;
1313
1314 #ifdef CONFIG_COMPAT
1315 ret = lttng_create_syscall_event_if_missing(compat_sc_table, ARRAY_SIZE(compat_sc_table),
1316 chan->compat_sc_table, event_enabler, filter,
1317 SC_TYPE_COMPAT_ENTRY);
1318 if (ret)
1319 return ret;
1320 ret = lttng_create_syscall_event_if_missing(compat_sc_exit_table, ARRAY_SIZE(compat_sc_exit_table),
1321 chan->compat_sc_exit_table, event_enabler, filter,
1322 SC_TYPE_COMPAT_EXIT);
1323 if (ret)
1324 return ret;
1325 #endif
1326
1327 if (!chan->sc_filter) {
1328 chan->sc_filter = kzalloc(sizeof(struct lttng_syscall_filter),
1329 GFP_KERNEL);
1330 if (!chan->sc_filter)
1331 return -ENOMEM;
1332 }
1333
1334 if (!chan->sys_enter_registered) {
1335 ret = lttng_wrapper_tracepoint_probe_register("sys_enter",
1336 (void *) syscall_entry_event_probe, chan);
1337 if (ret)
1338 return ret;
1339 chan->sys_enter_registered = 1;
1340 }
1341 /*
1342 * We change the name of sys_exit tracepoint due to namespace
1343 * conflict with sys_exit syscall entry.
1344 */
1345 if (!chan->sys_exit_registered) {
1346 ret = lttng_wrapper_tracepoint_probe_register("sys_exit",
1347 (void *) syscall_exit_event_probe, chan);
1348 if (ret) {
1349 WARN_ON_ONCE(lttng_wrapper_tracepoint_probe_unregister("sys_enter",
1350 (void *) syscall_entry_event_probe, chan));
1351 return ret;
1352 }
1353 chan->sys_exit_registered = 1;
1354 }
1355 return ret;
1356 }
1357
1358 /*
1359 * Should be called with sessions lock held.
1360 */
1361 int lttng_syscalls_register_event_notifier(
1362 struct lttng_event_notifier_enabler *event_notifier_enabler,
1363 void *filter)
1364 {
1365 struct lttng_event_notifier_group *group = event_notifier_enabler->group;
1366 unsigned int i;
1367 int ret = 0;
1368
1369 wrapper_vmalloc_sync_mappings();
1370
1371 if (!group->event_notifier_syscall_dispatch) {
1372 group->event_notifier_syscall_dispatch =
1373 kzalloc(sizeof(struct hlist_head) * ARRAY_SIZE(sc_table),
1374 GFP_KERNEL);
1375 if (!group->event_notifier_syscall_dispatch)
1376 return -ENOMEM;
1377
1378 /* Initialize all list_head */
1379 for (i = 0; i < ARRAY_SIZE(sc_table); i++)
1380 INIT_HLIST_HEAD(&group->event_notifier_syscall_dispatch[i]);
1381
1382 /* Init the unknown syscall notifier list. */
1383 INIT_HLIST_HEAD(&group->event_notifier_unknown_syscall_dispatch);
1384 }
1385
1386 if (!group->event_notifier_exit_syscall_dispatch) {
1387 group->event_notifier_exit_syscall_dispatch =
1388 kzalloc(sizeof(struct hlist_head) * ARRAY_SIZE(sc_table),
1389 GFP_KERNEL);
1390 if (!group->event_notifier_exit_syscall_dispatch)
1391 return -ENOMEM;
1392
1393 /* Initialize all list_head */
1394 for (i = 0; i < ARRAY_SIZE(sc_table); i++)
1395 INIT_HLIST_HEAD(&group->event_notifier_exit_syscall_dispatch[i]);
1396
1397 /* Init the unknown exit syscall notifier list. */
1398 INIT_HLIST_HEAD(&group->event_notifier_exit_unknown_syscall_dispatch);
1399 }
1400
1401 #ifdef CONFIG_COMPAT
1402 if (!group->event_notifier_compat_syscall_dispatch) {
1403 group->event_notifier_compat_syscall_dispatch =
1404 kzalloc(sizeof(struct hlist_head) * ARRAY_SIZE(compat_sc_table),
1405 GFP_KERNEL);
1406 if (!group->event_notifier_syscall_dispatch)
1407 return -ENOMEM;
1408
1409 /* Initialize all list_head */
1410 for (i = 0; i < ARRAY_SIZE(compat_sc_table); i++)
1411 INIT_HLIST_HEAD(&group->event_notifier_compat_syscall_dispatch[i]);
1412
1413 /* Init the unknown syscall notifier list. */
1414 INIT_HLIST_HEAD(&group->event_notifier_compat_unknown_syscall_dispatch);
1415 }
1416
1417 if (!group->event_notifier_exit_compat_syscall_dispatch) {
1418 group->event_notifier_exit_compat_syscall_dispatch =
1419 kzalloc(sizeof(struct hlist_head) * ARRAY_SIZE(compat_sc_exit_table),
1420 GFP_KERNEL);
1421 if (!group->event_notifier_exit_syscall_dispatch)
1422 return -ENOMEM;
1423
1424 /* Initialize all list_head */
1425 for (i = 0; i < ARRAY_SIZE(compat_sc_exit_table); i++)
1426 INIT_HLIST_HEAD(&group->event_notifier_exit_compat_syscall_dispatch[i]);
1427
1428 /* Init the unknown exit syscall notifier list. */
1429 INIT_HLIST_HEAD(&group->event_notifier_exit_compat_unknown_syscall_dispatch);
1430 }
1431 #endif
1432
1433 if (!group->sc_filter) {
1434 group->sc_filter = kzalloc(sizeof(struct lttng_syscall_filter),
1435 GFP_KERNEL);
1436 if (!group->sc_filter)
1437 return -ENOMEM;
1438 }
1439
1440 if (!group->sys_enter_registered) {
1441 ret = lttng_wrapper_tracepoint_probe_register("sys_enter",
1442 (void *) syscall_entry_event_notifier_probe, group);
1443 if (ret)
1444 return ret;
1445 group->sys_enter_registered = 1;
1446 }
1447
1448 if (!group->sys_exit_registered) {
1449 ret = lttng_wrapper_tracepoint_probe_register("sys_exit",
1450 (void *) syscall_exit_event_notifier_probe, group);
1451 if (ret) {
1452 WARN_ON_ONCE(lttng_wrapper_tracepoint_probe_unregister("sys_enter",
1453 (void *) syscall_entry_event_notifier_probe, group));
1454 return ret;
1455 }
1456 group->sys_exit_registered = 1;
1457 }
1458
1459 return ret;
1460 }
1461
1462 static
1463 int create_unknown_event_notifier(
1464 struct lttng_event_notifier_enabler *event_notifier_enabler,
1465 enum sc_type type)
1466 {
1467 struct lttng_event_notifier *notifier;
1468 const struct lttng_event_desc *desc;
1469 struct lttng_event_notifier_group *group = event_notifier_enabler->group;
1470 struct lttng_kernel_event_notifier event_notifier_param;
1471 uint64_t user_token = event_notifier_enabler->base.user_token;
1472 uint64_t error_counter_index = event_notifier_enabler->error_counter_index;
1473 struct lttng_enabler *base_enabler = lttng_event_notifier_enabler_as_enabler(
1474 event_notifier_enabler);
1475 struct hlist_head *unknown_dispatch_list;
1476 int ret = 0;
1477 bool found = false;
1478 enum lttng_kernel_syscall_abi abi;
1479 enum lttng_kernel_syscall_entryexit entryexit;
1480 struct hlist_head *head;
1481
1482 switch (type) {
1483 case SC_TYPE_ENTRY:
1484 desc = &__event_desc___syscall_entry_unknown;
1485 unknown_dispatch_list = &group->event_notifier_unknown_syscall_dispatch;
1486 entryexit = LTTNG_KERNEL_SYSCALL_ENTRY;
1487 abi = LTTNG_KERNEL_SYSCALL_ABI_NATIVE;
1488 break;
1489 case SC_TYPE_EXIT:
1490 desc = &__event_desc___syscall_exit_unknown;
1491 unknown_dispatch_list = &group->event_notifier_exit_unknown_syscall_dispatch;
1492 entryexit = LTTNG_KERNEL_SYSCALL_EXIT;
1493 abi = LTTNG_KERNEL_SYSCALL_ABI_NATIVE;
1494 break;
1495 case SC_TYPE_COMPAT_ENTRY:
1496 desc = &__event_desc___compat_syscall_entry_unknown;
1497 unknown_dispatch_list = &group->event_notifier_compat_unknown_syscall_dispatch;
1498 entryexit = LTTNG_KERNEL_SYSCALL_ENTRY;
1499 abi = LTTNG_KERNEL_SYSCALL_ABI_COMPAT;
1500 break;
1501 case SC_TYPE_COMPAT_EXIT:
1502 desc = &__event_desc___compat_syscall_exit_unknown;
1503 unknown_dispatch_list = &group->event_notifier_exit_compat_unknown_syscall_dispatch;
1504 entryexit = LTTNG_KERNEL_SYSCALL_EXIT;
1505 abi = LTTNG_KERNEL_SYSCALL_ABI_COMPAT;
1506 break;
1507 default:
1508 BUG_ON(1);
1509 }
1510
1511 /*
1512 * Check if already created.
1513 */
1514 head = utils_borrow_hash_table_bucket(group->event_notifiers_ht.table,
1515 LTTNG_EVENT_NOTIFIER_HT_SIZE, desc->name);
1516 lttng_hlist_for_each_entry(notifier, head, hlist) {
1517 if (notifier->desc == desc &&
1518 notifier->user_token == base_enabler->user_token)
1519 found = true;
1520 }
1521 if (found)
1522 goto end;
1523
1524 memset(&event_notifier_param, 0, sizeof(event_notifier_param));
1525 strncat(event_notifier_param.event.name, desc->name,
1526 LTTNG_KERNEL_SYM_NAME_LEN - strlen(event_notifier_param.event.name) - 1);
1527
1528 event_notifier_param.event.name[LTTNG_KERNEL_SYM_NAME_LEN - 1] = '\0';
1529
1530 event_notifier_param.event.instrumentation = LTTNG_KERNEL_SYSCALL;
1531 event_notifier_param.event.u.syscall.abi = abi;
1532 event_notifier_param.event.u.syscall.entryexit = entryexit;
1533
1534 notifier = _lttng_event_notifier_create(desc, user_token,
1535 error_counter_index, group, &event_notifier_param, NULL,
1536 event_notifier_param.event.instrumentation);
1537 if (IS_ERR(notifier)) {
1538 printk(KERN_INFO "Unable to create unknown notifier %s\n",
1539 desc->name);
1540 ret = -ENOMEM;
1541 goto end;
1542 }
1543
1544 hlist_add_head_rcu(&notifier->u.syscall.node, unknown_dispatch_list);
1545
1546 end:
1547 return ret;
1548 }
1549
1550 static int create_matching_event_notifiers(
1551 struct lttng_event_notifier_enabler *event_notifier_enabler,
1552 void *filter, const struct trace_syscall_entry *table,
1553 size_t table_len, enum sc_type type)
1554 {
1555 struct lttng_event_notifier_group *group = event_notifier_enabler->group;
1556 const struct lttng_event_desc *desc;
1557 uint64_t user_token = event_notifier_enabler->base.user_token;
1558 uint64_t error_counter_index = event_notifier_enabler->error_counter_index;
1559 unsigned int i;
1560 int ret = 0;
1561
1562 /* iterate over all syscall and create event_notifier that match */
1563 for (i = 0; i < table_len; i++) {
1564 struct lttng_event_notifier *event_notifier;
1565 struct lttng_kernel_event_notifier event_notifier_param;
1566 struct hlist_head *head;
1567 int found = 0;
1568
1569 desc = table[i].desc;
1570 if (!desc) {
1571 /* Unknown syscall */
1572 continue;
1573 }
1574
1575 if (!lttng_desc_match_enabler(desc,
1576 lttng_event_notifier_enabler_as_enabler(event_notifier_enabler)))
1577 continue;
1578
1579 /*
1580 * Check if already created.
1581 */
1582 head = utils_borrow_hash_table_bucket(group->event_notifiers_ht.table,
1583 LTTNG_EVENT_NOTIFIER_HT_SIZE, desc->name);
1584 lttng_hlist_for_each_entry(event_notifier, head, hlist) {
1585 if (event_notifier->desc == desc
1586 && event_notifier->user_token == event_notifier_enabler->base.user_token)
1587 found = 1;
1588 }
1589 if (found)
1590 continue;
1591
1592 memset(&event_notifier_param, 0, sizeof(event_notifier_param));
1593 switch (type) {
1594 case SC_TYPE_ENTRY:
1595 event_notifier_param.event.u.syscall.entryexit = LTTNG_KERNEL_SYSCALL_ENTRY;
1596 event_notifier_param.event.u.syscall.abi = LTTNG_KERNEL_SYSCALL_ABI_NATIVE;
1597 break;
1598 case SC_TYPE_EXIT:
1599 event_notifier_param.event.u.syscall.entryexit = LTTNG_KERNEL_SYSCALL_EXIT;
1600 event_notifier_param.event.u.syscall.abi = LTTNG_KERNEL_SYSCALL_ABI_NATIVE;
1601 break;
1602 case SC_TYPE_COMPAT_ENTRY:
1603 event_notifier_param.event.u.syscall.entryexit = LTTNG_KERNEL_SYSCALL_ENTRY;
1604 event_notifier_param.event.u.syscall.abi = LTTNG_KERNEL_SYSCALL_ABI_COMPAT;
1605 break;
1606 case SC_TYPE_COMPAT_EXIT:
1607 event_notifier_param.event.u.syscall.entryexit = LTTNG_KERNEL_SYSCALL_EXIT;
1608 event_notifier_param.event.u.syscall.abi = LTTNG_KERNEL_SYSCALL_ABI_COMPAT;
1609 break;
1610 }
1611 strncat(event_notifier_param.event.name, desc->name,
1612 LTTNG_KERNEL_SYM_NAME_LEN - strlen(event_notifier_param.event.name) - 1);
1613 event_notifier_param.event.name[LTTNG_KERNEL_SYM_NAME_LEN - 1] = '\0';
1614 event_notifier_param.event.instrumentation = LTTNG_KERNEL_SYSCALL;
1615
1616 event_notifier = _lttng_event_notifier_create(desc, user_token,
1617 error_counter_index, group, &event_notifier_param,
1618 filter, event_notifier_param.event.instrumentation);
1619 if (IS_ERR(event_notifier)) {
1620 printk(KERN_INFO "Unable to create event_notifier %s\n",
1621 desc->name);
1622 ret = -ENOMEM;
1623 goto end;
1624 }
1625
1626 event_notifier->u.syscall.syscall_id = i;
1627 }
1628
1629 end:
1630 return ret;
1631
1632 }
1633
1634 int lttng_syscals_create_matching_event_notifiers(
1635 struct lttng_event_notifier_enabler *event_notifier_enabler,
1636 void *filter)
1637 {
1638 int ret;
1639 struct lttng_enabler *base_enabler =
1640 lttng_event_notifier_enabler_as_enabler(event_notifier_enabler);
1641 enum lttng_kernel_syscall_entryexit entryexit =
1642 base_enabler->event_param.u.syscall.entryexit;
1643
1644 if (entryexit == LTTNG_KERNEL_SYSCALL_ENTRY || entryexit == LTTNG_KERNEL_SYSCALL_ENTRYEXIT) {
1645 ret = create_matching_event_notifiers(event_notifier_enabler,
1646 filter, sc_table, ARRAY_SIZE(sc_table), SC_TYPE_ENTRY);
1647 if (ret)
1648 goto end;
1649
1650 ret = create_matching_event_notifiers(event_notifier_enabler,
1651 filter, compat_sc_table, ARRAY_SIZE(compat_sc_table),
1652 SC_TYPE_COMPAT_ENTRY);
1653 if (ret)
1654 goto end;
1655
1656 ret = create_unknown_event_notifier(event_notifier_enabler,
1657 SC_TYPE_ENTRY);
1658 if (ret)
1659 goto end;
1660
1661 ret = create_unknown_event_notifier(event_notifier_enabler,
1662 SC_TYPE_COMPAT_ENTRY);
1663 if (ret)
1664 goto end;
1665 }
1666
1667 if (entryexit == LTTNG_KERNEL_SYSCALL_EXIT || entryexit == LTTNG_KERNEL_SYSCALL_ENTRYEXIT) {
1668 ret = create_matching_event_notifiers(event_notifier_enabler,
1669 filter, sc_exit_table, ARRAY_SIZE(sc_exit_table),
1670 SC_TYPE_EXIT);
1671 if (ret)
1672 goto end;
1673
1674 ret = create_unknown_event_notifier(event_notifier_enabler,
1675 SC_TYPE_EXIT);
1676 if (ret)
1677 goto end;
1678
1679 ret = create_matching_event_notifiers(event_notifier_enabler,
1680 filter, compat_sc_exit_table, ARRAY_SIZE(compat_sc_exit_table),
1681 SC_TYPE_COMPAT_EXIT);
1682 if (ret)
1683 goto end;
1684
1685 ret = create_unknown_event_notifier(event_notifier_enabler,
1686 SC_TYPE_COMPAT_EXIT);
1687 if (ret)
1688 goto end;
1689 }
1690
1691 end:
1692 return ret;
1693 }
1694
1695 /*
1696 * Unregister the syscall event_notifier probes from the callsites.
1697 */
1698 int lttng_syscalls_unregister_event_notifier_group(
1699 struct lttng_event_notifier_group *event_notifier_group)
1700 {
1701 int ret;
1702
1703 /*
1704 * Only register the event_notifier probe on the `sys_enter` callsite for now.
1705 * At the moment, we don't think it's desirable to have one fired
1706 * event_notifier for the entry and one for the exit of a syscall.
1707 */
1708 if (event_notifier_group->sys_enter_registered) {
1709 ret = lttng_wrapper_tracepoint_probe_unregister("sys_enter",
1710 (void *) syscall_entry_event_notifier_probe, event_notifier_group);
1711 if (ret)
1712 return ret;
1713 event_notifier_group->sys_enter_registered = 0;
1714 }
1715 if (event_notifier_group->sys_exit_registered) {
1716 ret = lttng_wrapper_tracepoint_probe_unregister("sys_exit",
1717 (void *) syscall_exit_event_notifier_probe, event_notifier_group);
1718 if (ret)
1719 return ret;
1720 event_notifier_group->sys_enter_registered = 0;
1721 }
1722
1723 kfree(event_notifier_group->event_notifier_syscall_dispatch);
1724 kfree(event_notifier_group->event_notifier_exit_syscall_dispatch);
1725 #ifdef CONFIG_COMPAT
1726 kfree(event_notifier_group->event_notifier_compat_syscall_dispatch);
1727 kfree(event_notifier_group->event_notifier_exit_compat_syscall_dispatch);
1728 #endif
1729 return 0;
1730 }
1731
1732 int lttng_syscalls_unregister_channel(struct lttng_channel *chan)
1733 {
1734 int ret;
1735
1736 if (!chan->sc_table)
1737 return 0;
1738 if (chan->sys_enter_registered) {
1739 ret = lttng_wrapper_tracepoint_probe_unregister("sys_enter",
1740 (void *) syscall_entry_event_probe, chan);
1741 if (ret)
1742 return ret;
1743 chan->sys_enter_registered = 0;
1744 }
1745 if (chan->sys_exit_registered) {
1746 ret = lttng_wrapper_tracepoint_probe_unregister("sys_exit",
1747 (void *) syscall_exit_event_probe, chan);
1748 if (ret)
1749 return ret;
1750 chan->sys_exit_registered = 0;
1751 }
1752 return 0;
1753 }
1754
1755 int lttng_syscalls_destroy_event(struct lttng_channel *chan)
1756 {
1757 kfree(chan->sc_table);
1758 kfree(chan->sc_exit_table);
1759 #ifdef CONFIG_COMPAT
1760 kfree(chan->compat_sc_table);
1761 kfree(chan->compat_sc_exit_table);
1762 #endif
1763 kfree(chan->sc_filter);
1764 return 0;
1765 }
1766
1767 static
1768 int get_syscall_nr(const char *syscall_name)
1769 {
1770 int syscall_nr = -1;
1771 int i;
1772
1773 for (i = 0; i < ARRAY_SIZE(sc_table); i++) {
1774 const struct trace_syscall_entry *entry;
1775 const char *it_name;
1776
1777 entry = &sc_table[i];
1778 if (!entry->desc)
1779 continue;
1780 it_name = entry->desc->name;
1781 it_name += strlen(SYSCALL_ENTRY_STR);
1782 if (!strcmp(syscall_name, it_name)) {
1783 syscall_nr = i;
1784 break;
1785 }
1786 }
1787 return syscall_nr;
1788 }
1789
1790 static
1791 int get_compat_syscall_nr(const char *syscall_name)
1792 {
1793 int syscall_nr = -1;
1794 int i;
1795
1796 for (i = 0; i < ARRAY_SIZE(compat_sc_table); i++) {
1797 const struct trace_syscall_entry *entry;
1798 const char *it_name;
1799
1800 entry = &compat_sc_table[i];
1801 if (!entry->desc)
1802 continue;
1803 it_name = entry->desc->name;
1804 it_name += strlen(COMPAT_SYSCALL_ENTRY_STR);
1805 if (!strcmp(syscall_name, it_name)) {
1806 syscall_nr = i;
1807 break;
1808 }
1809 }
1810 return syscall_nr;
1811 }
1812
1813 static
1814 uint32_t get_sc_tables_len(void)
1815 {
1816 return ARRAY_SIZE(sc_table) + ARRAY_SIZE(compat_sc_table);
1817 }
1818
1819 static
1820 const char *get_syscall_name(const char *desc_name,
1821 enum lttng_syscall_abi abi,
1822 enum lttng_syscall_entryexit entryexit)
1823 {
1824 size_t prefix_len = 0;
1825
1826
1827 switch (entryexit) {
1828 case LTTNG_SYSCALL_ENTRY:
1829 switch (abi) {
1830 case LTTNG_SYSCALL_ABI_NATIVE:
1831 prefix_len = strlen(SYSCALL_ENTRY_STR);
1832 break;
1833 case LTTNG_SYSCALL_ABI_COMPAT:
1834 prefix_len = strlen(COMPAT_SYSCALL_ENTRY_STR);
1835 break;
1836 }
1837 break;
1838 case LTTNG_SYSCALL_EXIT:
1839 switch (abi) {
1840 case LTTNG_SYSCALL_ABI_NATIVE:
1841 prefix_len = strlen(SYSCALL_EXIT_STR);
1842 break;
1843 case LTTNG_SYSCALL_ABI_COMPAT:
1844 prefix_len = strlen(COMPAT_SYSCALL_EXIT_STR);
1845 break;
1846 }
1847 break;
1848 }
1849 WARN_ON_ONCE(prefix_len == 0);
1850 return desc_name + prefix_len;
1851 }
1852
1853 static
1854 int lttng_syscall_filter_enable(
1855 struct lttng_syscall_filter *filter,
1856 const char *desc_name, enum lttng_syscall_abi abi,
1857 enum lttng_syscall_entryexit entryexit)
1858 {
1859 const char *syscall_name;
1860 unsigned long *bitmap;
1861 int syscall_nr;
1862
1863 syscall_name = get_syscall_name(desc_name, abi, entryexit);
1864
1865 switch (abi) {
1866 case LTTNG_SYSCALL_ABI_NATIVE:
1867 syscall_nr = get_syscall_nr(syscall_name);
1868 break;
1869 case LTTNG_SYSCALL_ABI_COMPAT:
1870 syscall_nr = get_compat_syscall_nr(syscall_name);
1871 break;
1872 default:
1873 return -EINVAL;
1874 }
1875 if (syscall_nr < 0)
1876 return -ENOENT;
1877
1878 switch (entryexit) {
1879 case LTTNG_SYSCALL_ENTRY:
1880 switch (abi) {
1881 case LTTNG_SYSCALL_ABI_NATIVE:
1882 bitmap = filter->sc_entry;
1883 break;
1884 case LTTNG_SYSCALL_ABI_COMPAT:
1885 bitmap = filter->sc_compat_entry;
1886 break;
1887 default:
1888 return -EINVAL;
1889 }
1890 break;
1891 case LTTNG_SYSCALL_EXIT:
1892 switch (abi) {
1893 case LTTNG_SYSCALL_ABI_NATIVE:
1894 bitmap = filter->sc_exit;
1895 break;
1896 case LTTNG_SYSCALL_ABI_COMPAT:
1897 bitmap = filter->sc_compat_exit;
1898 break;
1899 default:
1900 return -EINVAL;
1901 }
1902 break;
1903 default:
1904 return -EINVAL;
1905 }
1906 if (test_bit(syscall_nr, bitmap))
1907 return -EEXIST;
1908 bitmap_set(bitmap, syscall_nr, 1);
1909 return 0;
1910 }
1911
1912 int lttng_syscall_filter_enable_event_notifier(
1913 struct lttng_event_notifier *notifier)
1914 {
1915 struct lttng_event_notifier_group *group = notifier->group;
1916 unsigned int syscall_id = notifier->u.syscall.syscall_id;
1917 struct hlist_head *dispatch_list;
1918 int ret = 0;
1919
1920 WARN_ON_ONCE(notifier->instrumentation != LTTNG_KERNEL_SYSCALL);
1921
1922 ret = lttng_syscall_filter_enable(group->sc_filter,
1923 notifier->desc->name, notifier->u.syscall.abi,
1924 notifier->u.syscall.entryexit);
1925 if (ret) {
1926 goto end;
1927 }
1928
1929 switch (notifier->u.syscall.entryexit) {
1930 case LTTNG_SYSCALL_ENTRY:
1931 switch (notifier->u.syscall.abi) {
1932 case LTTNG_SYSCALL_ABI_NATIVE:
1933 dispatch_list = &group->event_notifier_syscall_dispatch[syscall_id];
1934 break;
1935 case LTTNG_SYSCALL_ABI_COMPAT:
1936 dispatch_list = &group->event_notifier_compat_syscall_dispatch[syscall_id];
1937 break;
1938 }
1939 break;
1940 case LTTNG_SYSCALL_EXIT:
1941 switch (notifier->u.syscall.abi) {
1942 case LTTNG_SYSCALL_ABI_NATIVE:
1943 dispatch_list = &group->event_notifier_exit_syscall_dispatch[syscall_id];
1944 break;
1945 case LTTNG_SYSCALL_ABI_COMPAT:
1946 dispatch_list = &group->event_notifier_exit_compat_syscall_dispatch[syscall_id];
1947 break;
1948 }
1949 break;
1950 }
1951
1952 hlist_add_head_rcu(&notifier->u.syscall.node, dispatch_list);
1953
1954 end:
1955 return ret ;
1956 }
1957
1958 int lttng_syscall_filter_enable_event(
1959 struct lttng_channel *channel,
1960 struct lttng_event *event)
1961 {
1962 WARN_ON_ONCE(event->instrumentation != LTTNG_KERNEL_SYSCALL);
1963
1964 return lttng_syscall_filter_enable(channel->sc_filter,
1965 event->desc->name, event->u.syscall.abi,
1966 event->u.syscall.entryexit);
1967 }
1968
1969 static
1970 int lttng_syscall_filter_disable(
1971 struct lttng_syscall_filter *filter,
1972 const char *desc_name, enum lttng_syscall_abi abi,
1973 enum lttng_syscall_entryexit entryexit)
1974 {
1975 const char *syscall_name;
1976 unsigned long *bitmap;
1977 int syscall_nr;
1978
1979 syscall_name = get_syscall_name(desc_name, abi, entryexit);
1980
1981 switch (abi) {
1982 case LTTNG_SYSCALL_ABI_NATIVE:
1983 syscall_nr = get_syscall_nr(syscall_name);
1984 break;
1985 case LTTNG_SYSCALL_ABI_COMPAT:
1986 syscall_nr = get_compat_syscall_nr(syscall_name);
1987 break;
1988 default:
1989 return -EINVAL;
1990 }
1991 if (syscall_nr < 0)
1992 return -ENOENT;
1993
1994 switch (entryexit) {
1995 case LTTNG_SYSCALL_ENTRY:
1996 switch (abi) {
1997 case LTTNG_SYSCALL_ABI_NATIVE:
1998 bitmap = filter->sc_entry;
1999 break;
2000 case LTTNG_SYSCALL_ABI_COMPAT:
2001 bitmap = filter->sc_compat_entry;
2002 break;
2003 default:
2004 return -EINVAL;
2005 }
2006 break;
2007 case LTTNG_SYSCALL_EXIT:
2008 switch (abi) {
2009 case LTTNG_SYSCALL_ABI_NATIVE:
2010 bitmap = filter->sc_exit;
2011 break;
2012 case LTTNG_SYSCALL_ABI_COMPAT:
2013 bitmap = filter->sc_compat_exit;
2014 break;
2015 default:
2016 return -EINVAL;
2017 }
2018 break;
2019 default:
2020 return -EINVAL;
2021 }
2022 if (!test_bit(syscall_nr, bitmap))
2023 return -EEXIST;
2024 bitmap_clear(bitmap, syscall_nr, 1);
2025
2026 return 0;
2027 }
2028
2029 int lttng_syscall_filter_disable_event_notifier(
2030 struct lttng_event_notifier *notifier)
2031 {
2032 struct lttng_event_notifier_group *group = notifier->group;
2033 int ret;
2034
2035 WARN_ON_ONCE(notifier->instrumentation != LTTNG_KERNEL_SYSCALL);
2036
2037 ret = lttng_syscall_filter_disable(group->sc_filter,
2038 notifier->desc->name, notifier->u.syscall.abi,
2039 notifier->u.syscall.entryexit);
2040 WARN_ON_ONCE(ret != 0);
2041
2042 hlist_del_rcu(&notifier->u.syscall.node);
2043 return 0;
2044 }
2045
2046 int lttng_syscall_filter_disable_event(
2047 struct lttng_channel *channel,
2048 struct lttng_event *event)
2049 {
2050 return lttng_syscall_filter_disable(channel->sc_filter,
2051 event->desc->name, event->u.syscall.abi,
2052 event->u.syscall.entryexit);
2053 }
2054
2055 static
2056 const struct trace_syscall_entry *syscall_list_get_entry(loff_t *pos)
2057 {
2058 const struct trace_syscall_entry *entry;
2059 int iter = 0;
2060
2061 for (entry = sc_table;
2062 entry < sc_table + ARRAY_SIZE(sc_table);
2063 entry++) {
2064 if (iter++ >= *pos)
2065 return entry;
2066 }
2067 for (entry = compat_sc_table;
2068 entry < compat_sc_table + ARRAY_SIZE(compat_sc_table);
2069 entry++) {
2070 if (iter++ >= *pos)
2071 return entry;
2072 }
2073 /* End of list */
2074 return NULL;
2075 }
2076
2077 static
2078 void *syscall_list_start(struct seq_file *m, loff_t *pos)
2079 {
2080 return (void *) syscall_list_get_entry(pos);
2081 }
2082
2083 static
2084 void *syscall_list_next(struct seq_file *m, void *p, loff_t *ppos)
2085 {
2086 (*ppos)++;
2087 return (void *) syscall_list_get_entry(ppos);
2088 }
2089
2090 static
2091 void syscall_list_stop(struct seq_file *m, void *p)
2092 {
2093 }
2094
2095 static
2096 int get_sc_table(const struct trace_syscall_entry *entry,
2097 const struct trace_syscall_entry **table,
2098 unsigned int *bitness)
2099 {
2100 if (entry >= sc_table && entry < sc_table + ARRAY_SIZE(sc_table)) {
2101 if (bitness)
2102 *bitness = BITS_PER_LONG;
2103 if (table)
2104 *table = sc_table;
2105 return 0;
2106 }
2107 if (!(entry >= compat_sc_table
2108 && entry < compat_sc_table + ARRAY_SIZE(compat_sc_table))) {
2109 return -EINVAL;
2110 }
2111 if (bitness)
2112 *bitness = 32;
2113 if (table)
2114 *table = compat_sc_table;
2115 return 0;
2116 }
2117
2118 static
2119 int syscall_list_show(struct seq_file *m, void *p)
2120 {
2121 const struct trace_syscall_entry *table, *entry = p;
2122 unsigned int bitness;
2123 unsigned long index;
2124 int ret;
2125 const char *name;
2126
2127 ret = get_sc_table(entry, &table, &bitness);
2128 if (ret)
2129 return ret;
2130 if (!entry->desc)
2131 return 0;
2132 if (table == sc_table) {
2133 index = entry - table;
2134 name = &entry->desc->name[strlen(SYSCALL_ENTRY_STR)];
2135 } else {
2136 index = (entry - table) + ARRAY_SIZE(sc_table);
2137 name = &entry->desc->name[strlen(COMPAT_SYSCALL_ENTRY_STR)];
2138 }
2139 seq_printf(m, "syscall { index = %lu; name = %s; bitness = %u; };\n",
2140 index, name, bitness);
2141 return 0;
2142 }
2143
2144 static
2145 const struct seq_operations lttng_syscall_list_seq_ops = {
2146 .start = syscall_list_start,
2147 .next = syscall_list_next,
2148 .stop = syscall_list_stop,
2149 .show = syscall_list_show,
2150 };
2151
2152 static
2153 int lttng_syscall_list_open(struct inode *inode, struct file *file)
2154 {
2155 return seq_open(file, &lttng_syscall_list_seq_ops);
2156 }
2157
2158 const struct file_operations lttng_syscall_list_fops = {
2159 .owner = THIS_MODULE,
2160 .open = lttng_syscall_list_open,
2161 .read = seq_read,
2162 .llseek = seq_lseek,
2163 .release = seq_release,
2164 };
2165
2166 /*
2167 * A syscall is enabled if it is traced for either entry or exit.
2168 */
2169 long lttng_channel_syscall_mask(struct lttng_channel *channel,
2170 struct lttng_kernel_syscall_mask __user *usyscall_mask)
2171 {
2172 uint32_t len, sc_tables_len, bitmask_len;
2173 int ret = 0, bit;
2174 char *tmp_mask;
2175 struct lttng_syscall_filter *filter;
2176
2177 ret = get_user(len, &usyscall_mask->len);
2178 if (ret)
2179 return ret;
2180 sc_tables_len = get_sc_tables_len();
2181 bitmask_len = ALIGN(sc_tables_len, 8) >> 3;
2182 if (len < sc_tables_len) {
2183 return put_user(sc_tables_len, &usyscall_mask->len);
2184 }
2185 /* Array is large enough, we can copy array to user-space. */
2186 tmp_mask = kzalloc(bitmask_len, GFP_KERNEL);
2187 if (!tmp_mask)
2188 return -ENOMEM;
2189 filter = channel->sc_filter;
2190
2191 for (bit = 0; bit < ARRAY_SIZE(sc_table); bit++) {
2192 char state;
2193
2194 if (channel->sc_table) {
2195 if (!(READ_ONCE(channel->syscall_all_entry)
2196 || READ_ONCE(channel->syscall_all_exit)) && filter)
2197 state = test_bit(bit, filter->sc_entry)
2198 || test_bit(bit, filter->sc_exit);
2199 else
2200 state = 1;
2201 } else {
2202 state = 0;
2203 }
2204 bt_bitfield_write_be(tmp_mask, char, bit, 1, state);
2205 }
2206 for (; bit < sc_tables_len; bit++) {
2207 char state;
2208
2209 if (channel->compat_sc_table) {
2210 if (!(READ_ONCE(channel->syscall_all_entry)
2211 || READ_ONCE(channel->syscall_all_exit)) && filter)
2212 state = test_bit(bit - ARRAY_SIZE(sc_table),
2213 filter->sc_compat_entry)
2214 || test_bit(bit - ARRAY_SIZE(sc_table),
2215 filter->sc_compat_exit);
2216 else
2217 state = 1;
2218 } else {
2219 state = 0;
2220 }
2221 bt_bitfield_write_be(tmp_mask, char, bit, 1, state);
2222 }
2223 if (copy_to_user(usyscall_mask->mask, tmp_mask, bitmask_len))
2224 ret = -EFAULT;
2225 kfree(tmp_mask);
2226 return ret;
2227 }
2228
2229 int lttng_abi_syscall_list(void)
2230 {
2231 struct file *syscall_list_file;
2232 int file_fd, ret;
2233
2234 file_fd = lttng_get_unused_fd();
2235 if (file_fd < 0) {
2236 ret = file_fd;
2237 goto fd_error;
2238 }
2239
2240 syscall_list_file = anon_inode_getfile("[lttng_syscall_list]",
2241 &lttng_syscall_list_fops,
2242 NULL, O_RDWR);
2243 if (IS_ERR(syscall_list_file)) {
2244 ret = PTR_ERR(syscall_list_file);
2245 goto file_error;
2246 }
2247 ret = lttng_syscall_list_fops.open(NULL, syscall_list_file);
2248 if (ret < 0)
2249 goto open_error;
2250 fd_install(file_fd, syscall_list_file);
2251 return file_fd;
2252
2253 open_error:
2254 fput(syscall_list_file);
2255 file_error:
2256 put_unused_fd(file_fd);
2257 fd_error:
2258 return ret;
2259 }
This page took 0.075716 seconds and 4 git commands to generate.