Fix: handle default switch case with -EINVAL in lttng-syscalls
[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 lttng_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 lttng_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 lttng_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 lttng_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 lttng_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 lttng_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 lttng_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 lttng_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 lttng_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 lttng_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 lttng_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 lttng_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 lttng_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 lttng_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 lttng_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 lttng_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 default:
1939 ret = -EINVAL;
1940 goto end;
1941 }
1942 break;
1943 case LTTNG_SYSCALL_EXIT:
1944 switch (notifier->u.syscall.abi) {
1945 case LTTNG_SYSCALL_ABI_NATIVE:
1946 dispatch_list = &group->event_notifier_exit_syscall_dispatch[syscall_id];
1947 break;
1948 case LTTNG_SYSCALL_ABI_COMPAT:
1949 dispatch_list = &group->event_notifier_exit_compat_syscall_dispatch[syscall_id];
1950 break;
1951 default:
1952 ret = -EINVAL;
1953 goto end;
1954 }
1955 break;
1956 default:
1957 ret = -EINVAL;
1958 goto end;
1959 }
1960
1961 hlist_add_head_rcu(&notifier->u.syscall.node, dispatch_list);
1962
1963 end:
1964 return ret ;
1965 }
1966
1967 int lttng_syscall_filter_enable_event(
1968 struct lttng_channel *channel,
1969 struct lttng_event *event)
1970 {
1971 WARN_ON_ONCE(event->instrumentation != LTTNG_KERNEL_SYSCALL);
1972
1973 return lttng_syscall_filter_enable(channel->sc_filter,
1974 event->desc->name, event->u.syscall.abi,
1975 event->u.syscall.entryexit);
1976 }
1977
1978 static
1979 int lttng_syscall_filter_disable(
1980 struct lttng_syscall_filter *filter,
1981 const char *desc_name, enum lttng_syscall_abi abi,
1982 enum lttng_syscall_entryexit entryexit)
1983 {
1984 const char *syscall_name;
1985 unsigned long *bitmap;
1986 int syscall_nr;
1987
1988 syscall_name = get_syscall_name(desc_name, abi, entryexit);
1989
1990 switch (abi) {
1991 case LTTNG_SYSCALL_ABI_NATIVE:
1992 syscall_nr = get_syscall_nr(syscall_name);
1993 break;
1994 case LTTNG_SYSCALL_ABI_COMPAT:
1995 syscall_nr = get_compat_syscall_nr(syscall_name);
1996 break;
1997 default:
1998 return -EINVAL;
1999 }
2000 if (syscall_nr < 0)
2001 return -ENOENT;
2002
2003 switch (entryexit) {
2004 case LTTNG_SYSCALL_ENTRY:
2005 switch (abi) {
2006 case LTTNG_SYSCALL_ABI_NATIVE:
2007 bitmap = filter->sc_entry;
2008 break;
2009 case LTTNG_SYSCALL_ABI_COMPAT:
2010 bitmap = filter->sc_compat_entry;
2011 break;
2012 default:
2013 return -EINVAL;
2014 }
2015 break;
2016 case LTTNG_SYSCALL_EXIT:
2017 switch (abi) {
2018 case LTTNG_SYSCALL_ABI_NATIVE:
2019 bitmap = filter->sc_exit;
2020 break;
2021 case LTTNG_SYSCALL_ABI_COMPAT:
2022 bitmap = filter->sc_compat_exit;
2023 break;
2024 default:
2025 return -EINVAL;
2026 }
2027 break;
2028 default:
2029 return -EINVAL;
2030 }
2031 if (!test_bit(syscall_nr, bitmap))
2032 return -EEXIST;
2033 bitmap_clear(bitmap, syscall_nr, 1);
2034
2035 return 0;
2036 }
2037
2038 int lttng_syscall_filter_disable_event_notifier(
2039 struct lttng_event_notifier *notifier)
2040 {
2041 struct lttng_event_notifier_group *group = notifier->group;
2042 int ret;
2043
2044 WARN_ON_ONCE(notifier->instrumentation != LTTNG_KERNEL_SYSCALL);
2045
2046 ret = lttng_syscall_filter_disable(group->sc_filter,
2047 notifier->desc->name, notifier->u.syscall.abi,
2048 notifier->u.syscall.entryexit);
2049 WARN_ON_ONCE(ret != 0);
2050
2051 hlist_del_rcu(&notifier->u.syscall.node);
2052 return 0;
2053 }
2054
2055 int lttng_syscall_filter_disable_event(
2056 struct lttng_channel *channel,
2057 struct lttng_event *event)
2058 {
2059 return lttng_syscall_filter_disable(channel->sc_filter,
2060 event->desc->name, event->u.syscall.abi,
2061 event->u.syscall.entryexit);
2062 }
2063
2064 static
2065 const struct trace_syscall_entry *syscall_list_get_entry(loff_t *pos)
2066 {
2067 const struct trace_syscall_entry *entry;
2068 int iter = 0;
2069
2070 for (entry = sc_table;
2071 entry < sc_table + ARRAY_SIZE(sc_table);
2072 entry++) {
2073 if (iter++ >= *pos)
2074 return entry;
2075 }
2076 for (entry = compat_sc_table;
2077 entry < compat_sc_table + ARRAY_SIZE(compat_sc_table);
2078 entry++) {
2079 if (iter++ >= *pos)
2080 return entry;
2081 }
2082 /* End of list */
2083 return NULL;
2084 }
2085
2086 static
2087 void *syscall_list_start(struct seq_file *m, loff_t *pos)
2088 {
2089 return (void *) syscall_list_get_entry(pos);
2090 }
2091
2092 static
2093 void *syscall_list_next(struct seq_file *m, void *p, loff_t *ppos)
2094 {
2095 (*ppos)++;
2096 return (void *) syscall_list_get_entry(ppos);
2097 }
2098
2099 static
2100 void syscall_list_stop(struct seq_file *m, void *p)
2101 {
2102 }
2103
2104 static
2105 int get_sc_table(const struct trace_syscall_entry *entry,
2106 const struct trace_syscall_entry **table,
2107 unsigned int *bitness)
2108 {
2109 if (entry >= sc_table && entry < sc_table + ARRAY_SIZE(sc_table)) {
2110 if (bitness)
2111 *bitness = BITS_PER_LONG;
2112 if (table)
2113 *table = sc_table;
2114 return 0;
2115 }
2116 if (!(entry >= compat_sc_table
2117 && entry < compat_sc_table + ARRAY_SIZE(compat_sc_table))) {
2118 return -EINVAL;
2119 }
2120 if (bitness)
2121 *bitness = 32;
2122 if (table)
2123 *table = compat_sc_table;
2124 return 0;
2125 }
2126
2127 static
2128 int syscall_list_show(struct seq_file *m, void *p)
2129 {
2130 const struct trace_syscall_entry *table, *entry = p;
2131 unsigned int bitness;
2132 unsigned long index;
2133 int ret;
2134 const char *name;
2135
2136 ret = get_sc_table(entry, &table, &bitness);
2137 if (ret)
2138 return ret;
2139 if (!entry->desc)
2140 return 0;
2141 if (table == sc_table) {
2142 index = entry - table;
2143 name = &entry->desc->name[strlen(SYSCALL_ENTRY_STR)];
2144 } else {
2145 index = (entry - table) + ARRAY_SIZE(sc_table);
2146 name = &entry->desc->name[strlen(COMPAT_SYSCALL_ENTRY_STR)];
2147 }
2148 seq_printf(m, "syscall { index = %lu; name = %s; bitness = %u; };\n",
2149 index, name, bitness);
2150 return 0;
2151 }
2152
2153 static
2154 const struct seq_operations lttng_syscall_list_seq_ops = {
2155 .start = syscall_list_start,
2156 .next = syscall_list_next,
2157 .stop = syscall_list_stop,
2158 .show = syscall_list_show,
2159 };
2160
2161 static
2162 int lttng_syscall_list_open(struct inode *inode, struct file *file)
2163 {
2164 return seq_open(file, &lttng_syscall_list_seq_ops);
2165 }
2166
2167 const struct file_operations lttng_syscall_list_fops = {
2168 .owner = THIS_MODULE,
2169 .open = lttng_syscall_list_open,
2170 .read = seq_read,
2171 .llseek = seq_lseek,
2172 .release = seq_release,
2173 };
2174
2175 /*
2176 * A syscall is enabled if it is traced for either entry or exit.
2177 */
2178 long lttng_channel_syscall_mask(struct lttng_channel *channel,
2179 struct lttng_kernel_syscall_mask __user *usyscall_mask)
2180 {
2181 uint32_t len, sc_tables_len, bitmask_len;
2182 int ret = 0, bit;
2183 char *tmp_mask;
2184 struct lttng_syscall_filter *filter;
2185
2186 ret = get_user(len, &usyscall_mask->len);
2187 if (ret)
2188 return ret;
2189 sc_tables_len = get_sc_tables_len();
2190 bitmask_len = ALIGN(sc_tables_len, 8) >> 3;
2191 if (len < sc_tables_len) {
2192 return put_user(sc_tables_len, &usyscall_mask->len);
2193 }
2194 /* Array is large enough, we can copy array to user-space. */
2195 tmp_mask = kzalloc(bitmask_len, GFP_KERNEL);
2196 if (!tmp_mask)
2197 return -ENOMEM;
2198 filter = channel->sc_filter;
2199
2200 for (bit = 0; bit < ARRAY_SIZE(sc_table); bit++) {
2201 char state;
2202
2203 if (channel->sc_table) {
2204 if (!(READ_ONCE(channel->syscall_all_entry)
2205 || READ_ONCE(channel->syscall_all_exit)) && filter)
2206 state = test_bit(bit, filter->sc_entry)
2207 || test_bit(bit, filter->sc_exit);
2208 else
2209 state = 1;
2210 } else {
2211 state = 0;
2212 }
2213 bt_bitfield_write_be(tmp_mask, char, bit, 1, state);
2214 }
2215 for (; bit < sc_tables_len; bit++) {
2216 char state;
2217
2218 if (channel->compat_sc_table) {
2219 if (!(READ_ONCE(channel->syscall_all_entry)
2220 || READ_ONCE(channel->syscall_all_exit)) && filter)
2221 state = test_bit(bit - ARRAY_SIZE(sc_table),
2222 filter->sc_compat_entry)
2223 || test_bit(bit - ARRAY_SIZE(sc_table),
2224 filter->sc_compat_exit);
2225 else
2226 state = 1;
2227 } else {
2228 state = 0;
2229 }
2230 bt_bitfield_write_be(tmp_mask, char, bit, 1, state);
2231 }
2232 if (copy_to_user(usyscall_mask->mask, tmp_mask, bitmask_len))
2233 ret = -EFAULT;
2234 kfree(tmp_mask);
2235 return ret;
2236 }
2237
2238 int lttng_abi_syscall_list(void)
2239 {
2240 struct file *syscall_list_file;
2241 int file_fd, ret;
2242
2243 file_fd = lttng_get_unused_fd();
2244 if (file_fd < 0) {
2245 ret = file_fd;
2246 goto fd_error;
2247 }
2248
2249 syscall_list_file = anon_inode_getfile("[lttng_syscall_list]",
2250 &lttng_syscall_list_fops,
2251 NULL, O_RDWR);
2252 if (IS_ERR(syscall_list_file)) {
2253 ret = PTR_ERR(syscall_list_file);
2254 goto file_error;
2255 }
2256 ret = lttng_syscall_list_fops.open(NULL, syscall_list_file);
2257 if (ret < 0)
2258 goto open_error;
2259 fd_install(file_fd, syscall_list_file);
2260 return file_fd;
2261
2262 open_error:
2263 fput(syscall_list_file);
2264 file_error:
2265 put_unused_fd(file_fd);
2266 fd_error:
2267 return ret;
2268 }
This page took 0.108624 seconds and 4 git commands to generate.