Explicitly skip tracing x32 system calls
[lttng-modules.git] / lttng-syscalls.c
1 /* SPDX-License-Identifier: (GPL-2.0 or LGPL-2.1)
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 <asm/ptrace.h>
22 #include <asm/syscall.h>
23
24 #include <lib/bitfield.h>
25 #include <wrapper/tracepoint.h>
26 #include <wrapper/file.h>
27 #include <wrapper/rcu.h>
28 #include <wrapper/syscall.h>
29 #include <lttng-events.h>
30
31 #ifndef CONFIG_COMPAT
32 # ifndef is_compat_task
33 # define is_compat_task() (0)
34 # endif
35 #endif
36
37 /* in_compat_syscall appears in kernel 4.6. */
38 #ifndef in_compat_syscall
39 #define in_compat_syscall() is_compat_task()
40 #endif
41
42 enum sc_type {
43 SC_TYPE_ENTRY,
44 SC_TYPE_EXIT,
45 SC_TYPE_COMPAT_ENTRY,
46 SC_TYPE_COMPAT_EXIT,
47 };
48
49 #define SYSCALL_ENTRY_TOK syscall_entry_
50 #define COMPAT_SYSCALL_ENTRY_TOK compat_syscall_entry_
51 #define SYSCALL_EXIT_TOK syscall_exit_
52 #define COMPAT_SYSCALL_EXIT_TOK compat_syscall_exit_
53
54 #define SYSCALL_ENTRY_STR __stringify(SYSCALL_ENTRY_TOK)
55 #define COMPAT_SYSCALL_ENTRY_STR __stringify(COMPAT_SYSCALL_ENTRY_TOK)
56 #define SYSCALL_EXIT_STR __stringify(SYSCALL_EXIT_TOK)
57 #define COMPAT_SYSCALL_EXIT_STR __stringify(COMPAT_SYSCALL_EXIT_TOK)
58
59 static
60 void syscall_entry_probe(void *__data, struct pt_regs *regs, long id);
61 static
62 void syscall_exit_probe(void *__data, struct pt_regs *regs, long ret);
63
64 /*
65 * Forward declarations for old kernels.
66 */
67 struct mmsghdr;
68 struct rlimit64;
69 struct oldold_utsname;
70 struct old_utsname;
71 struct sel_arg_struct;
72 struct mmap_arg_struct;
73 struct file_handle;
74 struct user_msghdr;
75
76 /*
77 * Forward declaration for kernels >= 5.6
78 */
79 struct timex;
80 struct timeval;
81 struct itimerval;
82 struct itimerspec;
83
84 #if (LTTNG_LINUX_VERSION_CODE >= LTTNG_KERNEL_VERSION(5,6,0))
85 typedef __kernel_old_time_t time_t;
86 #endif
87
88 #ifdef IA32_NR_syscalls
89 #define NR_compat_syscalls IA32_NR_syscalls
90 #else
91 #define NR_compat_syscalls NR_syscalls
92 #endif
93
94 /*
95 * Create LTTng tracepoint probes.
96 */
97 #define LTTNG_PACKAGE_BUILD
98 #define CREATE_TRACE_POINTS
99 #define TP_MODULE_NOINIT
100 #define TRACE_INCLUDE_PATH instrumentation/syscalls/headers
101
102 #define PARAMS(args...) args
103
104 /* Handle unknown syscalls */
105 #undef TRACE_SYSTEM
106 #define TRACE_SYSTEM syscalls_unknown
107 #include <instrumentation/syscalls/headers/syscalls_unknown.h>
108 #undef TRACE_SYSTEM
109
110 #define SC_ENTER
111
112 #undef sc_exit
113 #define sc_exit(...)
114 #undef sc_in
115 #define sc_in(...) __VA_ARGS__
116 #undef sc_out
117 #define sc_out(...)
118 #undef sc_inout
119 #define sc_inout(...) __VA_ARGS__
120
121 /* Hijack probe callback for system call enter */
122 #undef TP_PROBE_CB
123 #define TP_PROBE_CB(_template) &syscall_entry_probe
124 #define SC_LTTNG_TRACEPOINT_EVENT(_name, _proto, _args, _fields) \
125 LTTNG_TRACEPOINT_EVENT(syscall_entry_##_name, PARAMS(_proto), PARAMS(_args), \
126 PARAMS(_fields))
127 #define SC_LTTNG_TRACEPOINT_EVENT_CODE(_name, _proto, _args, _locvar, _code_pre, _fields, _code_post) \
128 LTTNG_TRACEPOINT_EVENT_CODE(syscall_entry_##_name, PARAMS(_proto), PARAMS(_args), \
129 PARAMS(_locvar), PARAMS(_code_pre), \
130 PARAMS(_fields), PARAMS(_code_post))
131 #define SC_LTTNG_TRACEPOINT_EVENT_CLASS_NOARGS(_name, _fields) \
132 LTTNG_TRACEPOINT_EVENT_CLASS_NOARGS(syscall_entry_##_name, PARAMS(_fields))
133 #define SC_LTTNG_TRACEPOINT_EVENT_INSTANCE_NOARGS(_template, _name) \
134 LTTNG_TRACEPOINT_EVENT_INSTANCE_NOARGS(syscall_entry_##_template, syscall_entry_##_name)
135 /* Enumerations only defined at first inclusion. */
136 #define SC_LTTNG_TRACEPOINT_ENUM(_name, _values) \
137 LTTNG_TRACEPOINT_ENUM(_name, PARAMS(_values))
138 #undef TRACE_SYSTEM
139 #define TRACE_SYSTEM syscall_entry_integers
140 #define TRACE_INCLUDE_FILE syscalls_integers
141 #include <instrumentation/syscalls/headers/syscalls_integers.h>
142 #undef TRACE_INCLUDE_FILE
143 #undef TRACE_SYSTEM
144 #define TRACE_SYSTEM syscall_entry_pointers
145 #define TRACE_INCLUDE_FILE syscalls_pointers
146 #include <instrumentation/syscalls/headers/syscalls_pointers.h>
147 #undef TRACE_INCLUDE_FILE
148 #undef TRACE_SYSTEM
149 #undef SC_LTTNG_TRACEPOINT_ENUM
150 #undef SC_LTTNG_TRACEPOINT_EVENT_CODE
151 #undef SC_LTTNG_TRACEPOINT_EVENT
152 #undef SC_LTTNG_TRACEPOINT_EVENT_CLASS_NOARGS
153 #undef SC_LTTNG_TRACEPOINT_EVENT_INSTANCE_NOARGS
154 #undef TP_PROBE_CB
155 #undef _TRACE_SYSCALLS_INTEGERS_H
156 #undef _TRACE_SYSCALLS_POINTERS_H
157
158 /* Hijack probe callback for compat system call enter */
159 #define TP_PROBE_CB(_template) &syscall_entry_probe
160 #define LTTNG_SC_COMPAT
161 #define SC_LTTNG_TRACEPOINT_EVENT(_name, _proto, _args, _fields) \
162 LTTNG_TRACEPOINT_EVENT(compat_syscall_entry_##_name, PARAMS(_proto), PARAMS(_args), \
163 PARAMS(_fields))
164 #define SC_LTTNG_TRACEPOINT_EVENT_CODE(_name, _proto, _args, _locvar, _code_pre, _fields, _code_post) \
165 LTTNG_TRACEPOINT_EVENT_CODE(compat_syscall_entry_##_name, PARAMS(_proto), PARAMS(_args), \
166 PARAMS(_locvar), PARAMS(_code_pre), PARAMS(_fields), PARAMS(_code_post))
167 #define SC_LTTNG_TRACEPOINT_EVENT_CLASS_NOARGS(_name, _fields) \
168 LTTNG_TRACEPOINT_EVENT_CLASS_NOARGS(compat_syscall_entry_##_name, PARAMS(_fields))
169 #define SC_LTTNG_TRACEPOINT_EVENT_INSTANCE_NOARGS(_template, _name) \
170 LTTNG_TRACEPOINT_EVENT_INSTANCE_NOARGS(compat_syscall_entry_##_template, \
171 compat_syscall_entry_##_name)
172 /* Enumerations only defined at inital inclusion (not here). */
173 #define SC_LTTNG_TRACEPOINT_ENUM(_name, _values)
174 #define TRACE_SYSTEM compat_syscall_entry_integers
175 #define TRACE_INCLUDE_FILE compat_syscalls_integers
176 #include <instrumentation/syscalls/headers/compat_syscalls_integers.h>
177 #undef TRACE_INCLUDE_FILE
178 #undef TRACE_SYSTEM
179 #define TRACE_SYSTEM compat_syscall_entry_pointers
180 #define TRACE_INCLUDE_FILE compat_syscalls_pointers
181 #include <instrumentation/syscalls/headers/compat_syscalls_pointers.h>
182 #undef TRACE_INCLUDE_FILE
183 #undef TRACE_SYSTEM
184 #undef SC_LTTNG_TRACEPOINT_ENUM
185 #undef SC_LTTNG_TRACEPOINT_EVENT_CODE
186 #undef SC_LTTNG_TRACEPOINT_EVENT
187 #undef SC_LTTNG_TRACEPOINT_EVENT_CLASS_NOARGS
188 #undef SC_LTTNG_TRACEPOINT_EVENT_INSTANCE_NOARGS
189 #undef TP_PROBE_CB
190 #undef _TRACE_SYSCALLS_INTEGERS_H
191 #undef _TRACE_SYSCALLS_POINTERS_H
192 #undef LTTNG_SC_COMPAT
193
194 #undef SC_ENTER
195
196 #define SC_EXIT
197
198 #undef sc_exit
199 #define sc_exit(...) __VA_ARGS__
200 #undef sc_in
201 #define sc_in(...)
202 #undef sc_out
203 #define sc_out(...) __VA_ARGS__
204 #undef sc_inout
205 #define sc_inout(...) __VA_ARGS__
206
207 /* Hijack probe callback for system call exit */
208 #define TP_PROBE_CB(_template) &syscall_exit_probe
209 #define SC_LTTNG_TRACEPOINT_EVENT(_name, _proto, _args, _fields) \
210 LTTNG_TRACEPOINT_EVENT(syscall_exit_##_name, PARAMS(_proto), PARAMS(_args), \
211 PARAMS(_fields))
212 #define SC_LTTNG_TRACEPOINT_EVENT_CODE(_name, _proto, _args, _locvar, _code_pre, _fields, _code_post) \
213 LTTNG_TRACEPOINT_EVENT_CODE(syscall_exit_##_name, PARAMS(_proto), PARAMS(_args), \
214 PARAMS(_locvar), PARAMS(_code_pre), PARAMS(_fields), PARAMS(_code_post))
215 #define SC_LTTNG_TRACEPOINT_EVENT_CLASS_NOARGS(_name, _fields) \
216 LTTNG_TRACEPOINT_EVENT_CLASS_NOARGS(syscall_exit_##_name, PARAMS(_fields))
217 #define SC_LTTNG_TRACEPOINT_EVENT_INSTANCE_NOARGS(_template, _name) \
218 LTTNG_TRACEPOINT_EVENT_INSTANCE_NOARGS(syscall_exit_##_template, \
219 syscall_exit_##_name)
220 /* Enumerations only defined at inital inclusion (not here). */
221 #define SC_LTTNG_TRACEPOINT_ENUM(_name, _values)
222 #define TRACE_SYSTEM syscall_exit_integers
223 #define TRACE_INCLUDE_FILE syscalls_integers
224 #include <instrumentation/syscalls/headers/syscalls_integers.h>
225 #undef TRACE_INCLUDE_FILE
226 #undef TRACE_SYSTEM
227 #define TRACE_SYSTEM syscall_exit_pointers
228 #define TRACE_INCLUDE_FILE syscalls_pointers
229 #include <instrumentation/syscalls/headers/syscalls_pointers.h>
230 #undef TRACE_INCLUDE_FILE
231 #undef TRACE_SYSTEM
232 #undef SC_LTTNG_TRACEPOINT_ENUM
233 #undef SC_LTTNG_TRACEPOINT_EVENT_CODE
234 #undef SC_LTTNG_TRACEPOINT_EVENT
235 #undef SC_LTTNG_TRACEPOINT_EVENT_CLASS_NOARGS
236 #undef SC_LTTNG_TRACEPOINT_EVENT_INSTANCE_NOARGS
237 #undef TP_PROBE_CB
238 #undef _TRACE_SYSCALLS_INTEGERS_H
239 #undef _TRACE_SYSCALLS_POINTERS_H
240
241
242 /* Hijack probe callback for compat system call exit */
243 #define TP_PROBE_CB(_template) &syscall_exit_probe
244 #define LTTNG_SC_COMPAT
245 #define SC_LTTNG_TRACEPOINT_EVENT(_name, _proto, _args, _fields) \
246 LTTNG_TRACEPOINT_EVENT(compat_syscall_exit_##_name, PARAMS(_proto), PARAMS(_args), \
247 PARAMS(_fields))
248 #define SC_LTTNG_TRACEPOINT_EVENT_CODE(_name, _proto, _args, _locvar, _code_pre, _fields, _code_post) \
249 LTTNG_TRACEPOINT_EVENT_CODE(compat_syscall_exit_##_name, PARAMS(_proto), PARAMS(_args), \
250 PARAMS(_locvar), PARAMS(_code_pre), PARAMS(_fields), PARAMS(_code_post))
251 #define SC_LTTNG_TRACEPOINT_EVENT_CLASS_NOARGS(_name, _fields) \
252 LTTNG_TRACEPOINT_EVENT_CLASS_NOARGS(compat_syscall_exit_##_name, PARAMS(_fields))
253 #define SC_LTTNG_TRACEPOINT_EVENT_INSTANCE_NOARGS(_template, _name) \
254 LTTNG_TRACEPOINT_EVENT_INSTANCE_NOARGS(compat_syscall_exit_##_template, \
255 compat_syscall_exit_##_name)
256 /* Enumerations only defined at inital inclusion (not here). */
257 #define SC_LTTNG_TRACEPOINT_ENUM(_name, _values)
258 #define TRACE_SYSTEM compat_syscall_exit_integers
259 #define TRACE_INCLUDE_FILE compat_syscalls_integers
260 #include <instrumentation/syscalls/headers/compat_syscalls_integers.h>
261 #undef TRACE_INCLUDE_FILE
262 #undef TRACE_SYSTEM
263 #define TRACE_SYSTEM compat_syscall_exit_pointers
264 #define TRACE_INCLUDE_FILE compat_syscalls_pointers
265 #include <instrumentation/syscalls/headers/compat_syscalls_pointers.h>
266 #undef TRACE_INCLUDE_FILE
267 #undef TRACE_SYSTEM
268 #undef SC_LTTNG_TRACEPOINT_ENUM
269 #undef SC_LTTNG_TRACEPOINT_EVENT_CODE
270 #undef SC_LTTNG_TRACEPOINT_EVENT
271 #undef SC_LTTNG_TRACEPOINT_EVENT_CLASS_NOARGS
272 #undef SC_LTTNG_TRACEPOINT_EVENT_INSTANCE_NOARGS
273 #undef TP_PROBE_CB
274 #undef _TRACE_SYSCALLS_INTEGERS_H
275 #undef _TRACE_SYSCALLS_POINTERS_H
276 #undef LTTNG_SC_COMPAT
277
278 #undef SC_EXIT
279
280 #undef TP_MODULE_NOINIT
281 #undef LTTNG_PACKAGE_BUILD
282 #undef CREATE_TRACE_POINTS
283
284 struct trace_syscall_entry {
285 void *func;
286 const struct lttng_event_desc *desc;
287 const struct lttng_event_field *fields;
288 unsigned int nrargs;
289 };
290
291 #define CREATE_SYSCALL_TABLE
292
293 #define SC_ENTER
294
295 #undef sc_exit
296 #define sc_exit(...)
297
298 #undef TRACE_SYSCALL_TABLE
299 #define TRACE_SYSCALL_TABLE(_template, _name, _nr, _nrargs) \
300 [ _nr ] = { \
301 .func = __event_probe__syscall_entry_##_template, \
302 .nrargs = (_nrargs), \
303 .fields = __event_fields___syscall_entry_##_template, \
304 .desc = &__event_desc___syscall_entry_##_name, \
305 },
306
307 /* Syscall enter tracing table */
308 static const struct trace_syscall_entry sc_table[] = {
309 #include <instrumentation/syscalls/headers/syscalls_integers.h>
310 #include <instrumentation/syscalls/headers/syscalls_pointers.h>
311 };
312
313 #undef TRACE_SYSCALL_TABLE
314 #define TRACE_SYSCALL_TABLE(_template, _name, _nr, _nrargs) \
315 [ _nr ] = { \
316 .func = __event_probe__compat_syscall_entry_##_template, \
317 .nrargs = (_nrargs), \
318 .fields = __event_fields___compat_syscall_entry_##_template, \
319 .desc = &__event_desc___compat_syscall_entry_##_name, \
320 },
321
322 /* Compat syscall enter table */
323 const struct trace_syscall_entry compat_sc_table[] = {
324 #include <instrumentation/syscalls/headers/compat_syscalls_integers.h>
325 #include <instrumentation/syscalls/headers/compat_syscalls_pointers.h>
326 };
327
328 #undef SC_ENTER
329
330 #define SC_EXIT
331
332 #undef sc_exit
333 #define sc_exit(...) __VA_ARGS__
334
335 #undef TRACE_SYSCALL_TABLE
336 #define TRACE_SYSCALL_TABLE(_template, _name, _nr, _nrargs) \
337 [ _nr ] = { \
338 .func = __event_probe__syscall_exit_##_template, \
339 .nrargs = (_nrargs), \
340 .fields = __event_fields___syscall_exit_##_template, \
341 .desc = &__event_desc___syscall_exit_##_name, \
342 },
343
344 /* Syscall exit table */
345 static const struct trace_syscall_entry sc_exit_table[] = {
346 #include <instrumentation/syscalls/headers/syscalls_integers.h>
347 #include <instrumentation/syscalls/headers/syscalls_pointers.h>
348 };
349
350 #undef TRACE_SYSCALL_TABLE
351 #define TRACE_SYSCALL_TABLE(_template, _name, _nr, _nrargs) \
352 [ _nr ] = { \
353 .func = __event_probe__compat_syscall_exit_##_template, \
354 .nrargs = (_nrargs), \
355 .fields = __event_fields___compat_syscall_exit_##_template, \
356 .desc = &__event_desc___compat_syscall_exit_##_name, \
357 },
358
359 /* Compat syscall exit table */
360 const struct trace_syscall_entry compat_sc_exit_table[] = {
361 #include <instrumentation/syscalls/headers/compat_syscalls_integers.h>
362 #include <instrumentation/syscalls/headers/compat_syscalls_pointers.h>
363 };
364
365 #undef SC_EXIT
366
367 #undef CREATE_SYSCALL_TABLE
368
369 struct lttng_syscall_filter {
370 DECLARE_BITMAP(sc_entry, NR_syscalls);
371 DECLARE_BITMAP(sc_exit, NR_syscalls);
372 DECLARE_BITMAP(sc_compat_entry, NR_compat_syscalls);
373 DECLARE_BITMAP(sc_compat_exit, NR_compat_syscalls);
374 };
375
376 static void syscall_entry_unknown(struct lttng_event *event,
377 struct pt_regs *regs, unsigned int id)
378 {
379 unsigned long args[LTTNG_SYSCALL_NR_ARGS];
380
381 lttng_syscall_get_arguments(current, regs, args);
382 if (unlikely(in_compat_syscall()))
383 __event_probe__compat_syscall_entry_unknown(event, id, args);
384 else
385 __event_probe__syscall_entry_unknown(event, id, args);
386 }
387
388 void syscall_entry_probe(void *__data, struct pt_regs *regs, long id)
389 {
390 struct lttng_channel *chan = __data;
391 struct lttng_event *event, *unknown_event;
392 const struct trace_syscall_entry *table, *entry;
393 size_t table_len;
394
395 #ifdef CONFIG_X86_X32_ABI
396 if (in_x32_syscall()) {
397 /* x32 system calls are not supported. */
398 return;
399 }
400 #endif
401 if (unlikely(in_compat_syscall())) {
402 struct lttng_syscall_filter *filter = chan->sc_filter;
403
404 if (id < 0 || id >= NR_compat_syscalls
405 || (!READ_ONCE(chan->syscall_all) && !test_bit(id, filter->sc_compat_entry))) {
406 /* System call filtered out. */
407 return;
408 }
409 table = compat_sc_table;
410 table_len = ARRAY_SIZE(compat_sc_table);
411 unknown_event = chan->sc_compat_unknown;
412 } else {
413 struct lttng_syscall_filter *filter = chan->sc_filter;
414
415 if (id < 0 || id >= NR_syscalls
416 || (!READ_ONCE(chan->syscall_all) && !test_bit(id, filter->sc_entry))) {
417 /* System call filtered out. */
418 return;
419 }
420 table = sc_table;
421 table_len = ARRAY_SIZE(sc_table);
422 unknown_event = chan->sc_unknown;
423 }
424 if (unlikely(id < 0 || id >= table_len)) {
425 syscall_entry_unknown(unknown_event, regs, id);
426 return;
427 }
428 if (unlikely(in_compat_syscall()))
429 event = chan->compat_sc_table[id];
430 else
431 event = chan->sc_table[id];
432 if (unlikely(!event)) {
433 syscall_entry_unknown(unknown_event, regs, id);
434 return;
435 }
436 entry = &table[id];
437 WARN_ON_ONCE(!entry);
438
439 switch (entry->nrargs) {
440 case 0:
441 {
442 void (*fptr)(void *__data) = entry->func;
443
444 fptr(event);
445 break;
446 }
447 case 1:
448 {
449 void (*fptr)(void *__data, unsigned long arg0) = entry->func;
450 unsigned long args[LTTNG_SYSCALL_NR_ARGS];
451
452 lttng_syscall_get_arguments(current, regs, args);
453 fptr(event, args[0]);
454 break;
455 }
456 case 2:
457 {
458 void (*fptr)(void *__data,
459 unsigned long arg0,
460 unsigned long arg1) = entry->func;
461 unsigned long args[LTTNG_SYSCALL_NR_ARGS];
462
463 lttng_syscall_get_arguments(current, regs, args);
464 fptr(event, args[0], args[1]);
465 break;
466 }
467 case 3:
468 {
469 void (*fptr)(void *__data,
470 unsigned long arg0,
471 unsigned long arg1,
472 unsigned long arg2) = entry->func;
473 unsigned long args[LTTNG_SYSCALL_NR_ARGS];
474
475 lttng_syscall_get_arguments(current, regs, args);
476 fptr(event, args[0], args[1], args[2]);
477 break;
478 }
479 case 4:
480 {
481 void (*fptr)(void *__data,
482 unsigned long arg0,
483 unsigned long arg1,
484 unsigned long arg2,
485 unsigned long arg3) = entry->func;
486 unsigned long args[LTTNG_SYSCALL_NR_ARGS];
487
488 lttng_syscall_get_arguments(current, regs, args);
489 fptr(event, args[0], args[1], args[2], args[3]);
490 break;
491 }
492 case 5:
493 {
494 void (*fptr)(void *__data,
495 unsigned long arg0,
496 unsigned long arg1,
497 unsigned long arg2,
498 unsigned long arg3,
499 unsigned long arg4) = entry->func;
500 unsigned long args[LTTNG_SYSCALL_NR_ARGS];
501
502 lttng_syscall_get_arguments(current, regs, args);
503 fptr(event, args[0], args[1], args[2], args[3], args[4]);
504 break;
505 }
506 case 6:
507 {
508 void (*fptr)(void *__data,
509 unsigned long arg0,
510 unsigned long arg1,
511 unsigned long arg2,
512 unsigned long arg3,
513 unsigned long arg4,
514 unsigned long arg5) = entry->func;
515 unsigned long args[LTTNG_SYSCALL_NR_ARGS];
516
517 lttng_syscall_get_arguments(current, regs, args);
518 fptr(event, args[0], args[1], args[2],
519 args[3], args[4], args[5]);
520 break;
521 }
522 default:
523 break;
524 }
525 }
526
527 static void syscall_exit_unknown(struct lttng_event *event,
528 struct pt_regs *regs, int id, long ret)
529 {
530 unsigned long args[LTTNG_SYSCALL_NR_ARGS];
531
532 lttng_syscall_get_arguments(current, regs, args);
533 if (unlikely(in_compat_syscall()))
534 __event_probe__compat_syscall_exit_unknown(event, id, ret,
535 args);
536 else
537 __event_probe__syscall_exit_unknown(event, id, ret, args);
538 }
539
540 void syscall_exit_probe(void *__data, struct pt_regs *regs, long ret)
541 {
542 struct lttng_channel *chan = __data;
543 struct lttng_event *event, *unknown_event;
544 const struct trace_syscall_entry *table, *entry;
545 size_t table_len;
546 long id;
547
548 #ifdef CONFIG_X86_X32_ABI
549 if (in_x32_syscall()) {
550 /* x32 system calls are not supported. */
551 return;
552 }
553 #endif
554 id = syscall_get_nr(current, regs);
555 if (unlikely(in_compat_syscall())) {
556 struct lttng_syscall_filter *filter = chan->sc_filter;
557
558 if (id < 0 || id >= NR_compat_syscalls
559 || (!READ_ONCE(chan->syscall_all) && !test_bit(id, filter->sc_compat_exit))) {
560 /* System call filtered out. */
561 return;
562 }
563 table = compat_sc_exit_table;
564 table_len = ARRAY_SIZE(compat_sc_exit_table);
565 unknown_event = chan->compat_sc_exit_unknown;
566 } else {
567 struct lttng_syscall_filter *filter = chan->sc_filter;
568
569 if (id < 0 || id >= NR_syscalls
570 || (!READ_ONCE(chan->syscall_all) && !test_bit(id, filter->sc_exit))) {
571 /* System call filtered out. */
572 return;
573 }
574 table = sc_exit_table;
575 table_len = ARRAY_SIZE(sc_exit_table);
576 unknown_event = chan->sc_exit_unknown;
577 }
578 if (unlikely(id < 0 || id >= table_len)) {
579 syscall_exit_unknown(unknown_event, regs, id, ret);
580 return;
581 }
582 if (unlikely(in_compat_syscall()))
583 event = chan->compat_sc_exit_table[id];
584 else
585 event = chan->sc_exit_table[id];
586 if (unlikely(!event)) {
587 syscall_exit_unknown(unknown_event, regs, id, ret);
588 return;
589 }
590 entry = &table[id];
591 WARN_ON_ONCE(!entry);
592
593 switch (entry->nrargs) {
594 case 0:
595 {
596 void (*fptr)(void *__data, long ret) = entry->func;
597
598 fptr(event, ret);
599 break;
600 }
601 case 1:
602 {
603 void (*fptr)(void *__data,
604 long ret,
605 unsigned long arg0) = entry->func;
606 unsigned long args[LTTNG_SYSCALL_NR_ARGS];
607
608 lttng_syscall_get_arguments(current, regs, args);
609 fptr(event, ret, args[0]);
610 break;
611 }
612 case 2:
613 {
614 void (*fptr)(void *__data,
615 long ret,
616 unsigned long arg0,
617 unsigned long arg1) = entry->func;
618 unsigned long args[LTTNG_SYSCALL_NR_ARGS];
619
620 lttng_syscall_get_arguments(current, regs, args);
621 fptr(event, ret, args[0], args[1]);
622 break;
623 }
624 case 3:
625 {
626 void (*fptr)(void *__data,
627 long ret,
628 unsigned long arg0,
629 unsigned long arg1,
630 unsigned long arg2) = entry->func;
631 unsigned long args[LTTNG_SYSCALL_NR_ARGS];
632
633 lttng_syscall_get_arguments(current, regs, args);
634 fptr(event, ret, args[0], args[1], args[2]);
635 break;
636 }
637 case 4:
638 {
639 void (*fptr)(void *__data,
640 long ret,
641 unsigned long arg0,
642 unsigned long arg1,
643 unsigned long arg2,
644 unsigned long arg3) = entry->func;
645 unsigned long args[LTTNG_SYSCALL_NR_ARGS];
646
647 lttng_syscall_get_arguments(current, regs, args);
648 fptr(event, ret, args[0], args[1], args[2], args[3]);
649 break;
650 }
651 case 5:
652 {
653 void (*fptr)(void *__data,
654 long ret,
655 unsigned long arg0,
656 unsigned long arg1,
657 unsigned long arg2,
658 unsigned long arg3,
659 unsigned long arg4) = entry->func;
660 unsigned long args[LTTNG_SYSCALL_NR_ARGS];
661
662 lttng_syscall_get_arguments(current, regs, args);
663 fptr(event, ret, args[0], args[1], args[2], args[3], args[4]);
664 break;
665 }
666 case 6:
667 {
668 void (*fptr)(void *__data,
669 long ret,
670 unsigned long arg0,
671 unsigned long arg1,
672 unsigned long arg2,
673 unsigned long arg3,
674 unsigned long arg4,
675 unsigned long arg5) = entry->func;
676 unsigned long args[LTTNG_SYSCALL_NR_ARGS];
677
678 lttng_syscall_get_arguments(current, regs, args);
679 fptr(event, ret, args[0], args[1], args[2],
680 args[3], args[4], args[5]);
681 break;
682 }
683 default:
684 break;
685 }
686 }
687
688 /*
689 * noinline to diminish caller stack size.
690 * Should be called with sessions lock held.
691 */
692 static
693 int fill_table(const struct trace_syscall_entry *table, size_t table_len,
694 struct lttng_event **chan_table, struct lttng_channel *chan,
695 void *filter, enum sc_type type)
696 {
697 const struct lttng_event_desc *desc;
698 unsigned int i;
699
700 /* Allocate events for each syscall, insert into table */
701 for (i = 0; i < table_len; i++) {
702 struct lttng_kernel_event ev;
703 desc = table[i].desc;
704
705 if (!desc) {
706 /* Unknown syscall */
707 continue;
708 }
709 /*
710 * Skip those already populated by previous failed
711 * register for this channel.
712 */
713 if (chan_table[i])
714 continue;
715 memset(&ev, 0, sizeof(ev));
716 switch (type) {
717 case SC_TYPE_ENTRY:
718 ev.u.syscall.entryexit = LTTNG_KERNEL_SYSCALL_ENTRY;
719 ev.u.syscall.abi = LTTNG_KERNEL_SYSCALL_ABI_NATIVE;
720 break;
721 case SC_TYPE_EXIT:
722 ev.u.syscall.entryexit = LTTNG_KERNEL_SYSCALL_EXIT;
723 ev.u.syscall.abi = LTTNG_KERNEL_SYSCALL_ABI_NATIVE;
724 break;
725 case SC_TYPE_COMPAT_ENTRY:
726 ev.u.syscall.entryexit = LTTNG_KERNEL_SYSCALL_ENTRY;
727 ev.u.syscall.abi = LTTNG_KERNEL_SYSCALL_ABI_COMPAT;
728 break;
729 case SC_TYPE_COMPAT_EXIT:
730 ev.u.syscall.entryexit = LTTNG_KERNEL_SYSCALL_EXIT;
731 ev.u.syscall.abi = LTTNG_KERNEL_SYSCALL_ABI_COMPAT;
732 break;
733 }
734 strncpy(ev.name, desc->name, LTTNG_KERNEL_SYM_NAME_LEN - 1);
735 ev.name[LTTNG_KERNEL_SYM_NAME_LEN - 1] = '\0';
736 ev.instrumentation = LTTNG_KERNEL_SYSCALL;
737 chan_table[i] = _lttng_event_create(chan, &ev, filter,
738 desc, ev.instrumentation);
739 WARN_ON_ONCE(!chan_table[i]);
740 if (IS_ERR(chan_table[i])) {
741 /*
742 * If something goes wrong in event registration
743 * after the first one, we have no choice but to
744 * leave the previous events in there, until
745 * deleted by session teardown.
746 */
747 return PTR_ERR(chan_table[i]);
748 }
749 }
750 return 0;
751 }
752
753 /*
754 * Should be called with sessions lock held.
755 */
756 int lttng_syscalls_register(struct lttng_channel *chan, void *filter)
757 {
758 struct lttng_kernel_event ev;
759 int ret;
760
761 wrapper_vmalloc_sync_mappings();
762
763 if (!chan->sc_table) {
764 /* create syscall table mapping syscall to events */
765 chan->sc_table = kzalloc(sizeof(struct lttng_event *)
766 * ARRAY_SIZE(sc_table), GFP_KERNEL);
767 if (!chan->sc_table)
768 return -ENOMEM;
769 }
770 if (!chan->sc_exit_table) {
771 /* create syscall table mapping syscall to events */
772 chan->sc_exit_table = kzalloc(sizeof(struct lttng_event *)
773 * ARRAY_SIZE(sc_exit_table), GFP_KERNEL);
774 if (!chan->sc_exit_table)
775 return -ENOMEM;
776 }
777
778
779 #ifdef CONFIG_COMPAT
780 if (!chan->compat_sc_table) {
781 /* create syscall table mapping compat syscall to events */
782 chan->compat_sc_table = kzalloc(sizeof(struct lttng_event *)
783 * ARRAY_SIZE(compat_sc_table), GFP_KERNEL);
784 if (!chan->compat_sc_table)
785 return -ENOMEM;
786 }
787
788 if (!chan->compat_sc_exit_table) {
789 /* create syscall table mapping compat syscall to events */
790 chan->compat_sc_exit_table = kzalloc(sizeof(struct lttng_event *)
791 * ARRAY_SIZE(compat_sc_exit_table), GFP_KERNEL);
792 if (!chan->compat_sc_exit_table)
793 return -ENOMEM;
794 }
795 #endif
796 if (!chan->sc_unknown) {
797 const struct lttng_event_desc *desc =
798 &__event_desc___syscall_entry_unknown;
799
800 memset(&ev, 0, sizeof(ev));
801 strncpy(ev.name, desc->name, LTTNG_KERNEL_SYM_NAME_LEN);
802 ev.name[LTTNG_KERNEL_SYM_NAME_LEN - 1] = '\0';
803 ev.instrumentation = LTTNG_KERNEL_SYSCALL;
804 ev.u.syscall.entryexit = LTTNG_KERNEL_SYSCALL_ENTRY;
805 ev.u.syscall.abi = LTTNG_KERNEL_SYSCALL_ABI_NATIVE;
806 chan->sc_unknown = _lttng_event_create(chan, &ev, filter,
807 desc,
808 ev.instrumentation);
809 WARN_ON_ONCE(!chan->sc_unknown);
810 if (IS_ERR(chan->sc_unknown)) {
811 return PTR_ERR(chan->sc_unknown);
812 }
813 }
814
815 if (!chan->sc_compat_unknown) {
816 const struct lttng_event_desc *desc =
817 &__event_desc___compat_syscall_entry_unknown;
818
819 memset(&ev, 0, sizeof(ev));
820 strncpy(ev.name, desc->name, LTTNG_KERNEL_SYM_NAME_LEN);
821 ev.name[LTTNG_KERNEL_SYM_NAME_LEN - 1] = '\0';
822 ev.instrumentation = LTTNG_KERNEL_SYSCALL;
823 ev.u.syscall.entryexit = LTTNG_KERNEL_SYSCALL_ENTRY;
824 ev.u.syscall.abi = LTTNG_KERNEL_SYSCALL_ABI_COMPAT;
825 chan->sc_compat_unknown = _lttng_event_create(chan, &ev, filter,
826 desc,
827 ev.instrumentation);
828 WARN_ON_ONCE(!chan->sc_unknown);
829 if (IS_ERR(chan->sc_compat_unknown)) {
830 return PTR_ERR(chan->sc_compat_unknown);
831 }
832 }
833
834 if (!chan->compat_sc_exit_unknown) {
835 const struct lttng_event_desc *desc =
836 &__event_desc___compat_syscall_exit_unknown;
837
838 memset(&ev, 0, sizeof(ev));
839 strncpy(ev.name, desc->name, LTTNG_KERNEL_SYM_NAME_LEN);
840 ev.name[LTTNG_KERNEL_SYM_NAME_LEN - 1] = '\0';
841 ev.instrumentation = LTTNG_KERNEL_SYSCALL;
842 ev.u.syscall.entryexit = LTTNG_KERNEL_SYSCALL_EXIT;
843 ev.u.syscall.abi = LTTNG_KERNEL_SYSCALL_ABI_COMPAT;
844 chan->compat_sc_exit_unknown = _lttng_event_create(chan, &ev,
845 filter, desc,
846 ev.instrumentation);
847 WARN_ON_ONCE(!chan->compat_sc_exit_unknown);
848 if (IS_ERR(chan->compat_sc_exit_unknown)) {
849 return PTR_ERR(chan->compat_sc_exit_unknown);
850 }
851 }
852
853 if (!chan->sc_exit_unknown) {
854 const struct lttng_event_desc *desc =
855 &__event_desc___syscall_exit_unknown;
856
857 memset(&ev, 0, sizeof(ev));
858 strncpy(ev.name, desc->name, LTTNG_KERNEL_SYM_NAME_LEN);
859 ev.name[LTTNG_KERNEL_SYM_NAME_LEN - 1] = '\0';
860 ev.instrumentation = LTTNG_KERNEL_SYSCALL;
861 ev.u.syscall.entryexit = LTTNG_KERNEL_SYSCALL_EXIT;
862 ev.u.syscall.abi = LTTNG_KERNEL_SYSCALL_ABI_NATIVE;
863 chan->sc_exit_unknown = _lttng_event_create(chan, &ev, filter,
864 desc, ev.instrumentation);
865 WARN_ON_ONCE(!chan->sc_exit_unknown);
866 if (IS_ERR(chan->sc_exit_unknown)) {
867 return PTR_ERR(chan->sc_exit_unknown);
868 }
869 }
870
871 ret = fill_table(sc_table, ARRAY_SIZE(sc_table),
872 chan->sc_table, chan, filter, SC_TYPE_ENTRY);
873 if (ret)
874 return ret;
875 ret = fill_table(sc_exit_table, ARRAY_SIZE(sc_exit_table),
876 chan->sc_exit_table, chan, filter, SC_TYPE_EXIT);
877 if (ret)
878 return ret;
879
880 #ifdef CONFIG_COMPAT
881 ret = fill_table(compat_sc_table, ARRAY_SIZE(compat_sc_table),
882 chan->compat_sc_table, chan, filter,
883 SC_TYPE_COMPAT_ENTRY);
884 if (ret)
885 return ret;
886 ret = fill_table(compat_sc_exit_table, ARRAY_SIZE(compat_sc_exit_table),
887 chan->compat_sc_exit_table, chan, filter,
888 SC_TYPE_COMPAT_EXIT);
889 if (ret)
890 return ret;
891 #endif
892
893 if (!chan->sc_filter) {
894 chan->sc_filter = kzalloc(sizeof(struct lttng_syscall_filter),
895 GFP_KERNEL);
896 if (!chan->sc_filter)
897 return -ENOMEM;
898 }
899
900 if (!chan->sys_enter_registered) {
901 ret = lttng_wrapper_tracepoint_probe_register("sys_enter",
902 (void *) syscall_entry_probe, chan);
903 if (ret)
904 return ret;
905 chan->sys_enter_registered = 1;
906 }
907 /*
908 * We change the name of sys_exit tracepoint due to namespace
909 * conflict with sys_exit syscall entry.
910 */
911 if (!chan->sys_exit_registered) {
912 ret = lttng_wrapper_tracepoint_probe_register("sys_exit",
913 (void *) syscall_exit_probe, chan);
914 if (ret) {
915 WARN_ON_ONCE(lttng_wrapper_tracepoint_probe_unregister("sys_enter",
916 (void *) syscall_entry_probe, chan));
917 return ret;
918 }
919 chan->sys_exit_registered = 1;
920 }
921 return ret;
922 }
923
924 /*
925 * Only called at session destruction.
926 */
927 int lttng_syscalls_unregister(struct lttng_channel *chan)
928 {
929 int ret;
930
931 if (!chan->sc_table)
932 return 0;
933 if (chan->sys_enter_registered) {
934 ret = lttng_wrapper_tracepoint_probe_unregister("sys_enter",
935 (void *) syscall_entry_probe, chan);
936 if (ret)
937 return ret;
938 chan->sys_enter_registered = 0;
939 }
940 if (chan->sys_exit_registered) {
941 ret = lttng_wrapper_tracepoint_probe_unregister("sys_exit",
942 (void *) syscall_exit_probe, chan);
943 if (ret)
944 return ret;
945 chan->sys_exit_registered = 0;
946 }
947 return 0;
948 }
949
950 int lttng_syscalls_destroy(struct lttng_channel *chan)
951 {
952 kfree(chan->sc_table);
953 kfree(chan->sc_exit_table);
954 #ifdef CONFIG_COMPAT
955 kfree(chan->compat_sc_table);
956 kfree(chan->compat_sc_exit_table);
957 #endif
958 kfree(chan->sc_filter);
959 return 0;
960 }
961
962 static
963 int get_syscall_nr(const char *syscall_name)
964 {
965 int syscall_nr = -1;
966 int i;
967
968 for (i = 0; i < ARRAY_SIZE(sc_table); i++) {
969 const struct trace_syscall_entry *entry;
970 const char *it_name;
971
972 entry = &sc_table[i];
973 if (!entry->desc)
974 continue;
975 it_name = entry->desc->name;
976 it_name += strlen(SYSCALL_ENTRY_STR);
977 if (!strcmp(syscall_name, it_name)) {
978 syscall_nr = i;
979 break;
980 }
981 }
982 return syscall_nr;
983 }
984
985 static
986 int get_compat_syscall_nr(const char *syscall_name)
987 {
988 int syscall_nr = -1;
989 int i;
990
991 for (i = 0; i < ARRAY_SIZE(compat_sc_table); i++) {
992 const struct trace_syscall_entry *entry;
993 const char *it_name;
994
995 entry = &compat_sc_table[i];
996 if (!entry->desc)
997 continue;
998 it_name = entry->desc->name;
999 it_name += strlen(COMPAT_SYSCALL_ENTRY_STR);
1000 if (!strcmp(syscall_name, it_name)) {
1001 syscall_nr = i;
1002 break;
1003 }
1004 }
1005 return syscall_nr;
1006 }
1007
1008 static
1009 uint32_t get_sc_tables_len(void)
1010 {
1011 return ARRAY_SIZE(sc_table) + ARRAY_SIZE(compat_sc_table);
1012 }
1013
1014 static
1015 const char *get_syscall_name(struct lttng_event *event)
1016 {
1017 size_t prefix_len = 0;
1018
1019 WARN_ON_ONCE(event->instrumentation != LTTNG_KERNEL_SYSCALL);
1020
1021 switch (event->u.syscall.entryexit) {
1022 case LTTNG_SYSCALL_ENTRY:
1023 switch (event->u.syscall.abi) {
1024 case LTTNG_SYSCALL_ABI_NATIVE:
1025 prefix_len = strlen(SYSCALL_ENTRY_STR);
1026 break;
1027 case LTTNG_SYSCALL_ABI_COMPAT:
1028 prefix_len = strlen(COMPAT_SYSCALL_ENTRY_STR);
1029 break;
1030 }
1031 break;
1032 case LTTNG_SYSCALL_EXIT:
1033 switch (event->u.syscall.abi) {
1034 case LTTNG_SYSCALL_ABI_NATIVE:
1035 prefix_len = strlen(SYSCALL_EXIT_STR);
1036 break;
1037 case LTTNG_SYSCALL_ABI_COMPAT:
1038 prefix_len = strlen(COMPAT_SYSCALL_EXIT_STR);
1039 break;
1040 }
1041 break;
1042 }
1043 WARN_ON_ONCE(prefix_len == 0);
1044 return event->desc->name + prefix_len;
1045 }
1046
1047 int lttng_syscall_filter_enable(struct lttng_channel *chan,
1048 struct lttng_event *event)
1049 {
1050 struct lttng_syscall_filter *filter = chan->sc_filter;
1051 const char *syscall_name;
1052 unsigned long *bitmap;
1053 int syscall_nr;
1054
1055 WARN_ON_ONCE(!chan->sc_table);
1056
1057 syscall_name = get_syscall_name(event);
1058
1059 switch (event->u.syscall.abi) {
1060 case LTTNG_SYSCALL_ABI_NATIVE:
1061 syscall_nr = get_syscall_nr(syscall_name);
1062 break;
1063 case LTTNG_SYSCALL_ABI_COMPAT:
1064 syscall_nr = get_compat_syscall_nr(syscall_name);
1065 break;
1066 default:
1067 return -EINVAL;
1068 }
1069 if (syscall_nr < 0)
1070 return -ENOENT;
1071
1072 switch (event->u.syscall.entryexit) {
1073 case LTTNG_SYSCALL_ENTRY:
1074 switch (event->u.syscall.abi) {
1075 case LTTNG_SYSCALL_ABI_NATIVE:
1076 bitmap = filter->sc_entry;
1077 break;
1078 case LTTNG_SYSCALL_ABI_COMPAT:
1079 bitmap = filter->sc_compat_entry;
1080 break;
1081 default:
1082 return -EINVAL;
1083 }
1084 break;
1085 case LTTNG_SYSCALL_EXIT:
1086 switch (event->u.syscall.abi) {
1087 case LTTNG_SYSCALL_ABI_NATIVE:
1088 bitmap = filter->sc_exit;
1089 break;
1090 case LTTNG_SYSCALL_ABI_COMPAT:
1091 bitmap = filter->sc_compat_exit;
1092 break;
1093 default:
1094 return -EINVAL;
1095 }
1096 break;
1097 default:
1098 return -EINVAL;
1099 }
1100 if (test_bit(syscall_nr, bitmap))
1101 return -EEXIST;
1102 bitmap_set(bitmap, syscall_nr, 1);
1103 return 0;
1104 }
1105
1106 int lttng_syscall_filter_disable(struct lttng_channel *chan,
1107 struct lttng_event *event)
1108 {
1109 struct lttng_syscall_filter *filter = chan->sc_filter;
1110 const char *syscall_name;
1111 unsigned long *bitmap;
1112 int syscall_nr;
1113
1114 WARN_ON_ONCE(!chan->sc_table);
1115
1116 syscall_name = get_syscall_name(event);
1117
1118 switch (event->u.syscall.abi) {
1119 case LTTNG_SYSCALL_ABI_NATIVE:
1120 syscall_nr = get_syscall_nr(syscall_name);
1121 break;
1122 case LTTNG_SYSCALL_ABI_COMPAT:
1123 syscall_nr = get_compat_syscall_nr(syscall_name);
1124 break;
1125 default:
1126 return -EINVAL;
1127 }
1128 if (syscall_nr < 0)
1129 return -ENOENT;
1130
1131 switch (event->u.syscall.entryexit) {
1132 case LTTNG_SYSCALL_ENTRY:
1133 switch (event->u.syscall.abi) {
1134 case LTTNG_SYSCALL_ABI_NATIVE:
1135 bitmap = filter->sc_entry;
1136 break;
1137 case LTTNG_SYSCALL_ABI_COMPAT:
1138 bitmap = filter->sc_compat_entry;
1139 break;
1140 default:
1141 return -EINVAL;
1142 }
1143 break;
1144 case LTTNG_SYSCALL_EXIT:
1145 switch (event->u.syscall.abi) {
1146 case LTTNG_SYSCALL_ABI_NATIVE:
1147 bitmap = filter->sc_exit;
1148 break;
1149 case LTTNG_SYSCALL_ABI_COMPAT:
1150 bitmap = filter->sc_compat_exit;
1151 break;
1152 default:
1153 return -EINVAL;
1154 }
1155 break;
1156 default:
1157 return -EINVAL;
1158 }
1159 if (!test_bit(syscall_nr, bitmap))
1160 return -EEXIST;
1161 bitmap_clear(bitmap, syscall_nr, 1);
1162
1163 return 0;
1164 }
1165
1166 static
1167 const struct trace_syscall_entry *syscall_list_get_entry(loff_t *pos)
1168 {
1169 const struct trace_syscall_entry *entry;
1170 int iter = 0;
1171
1172 for (entry = sc_table;
1173 entry < sc_table + ARRAY_SIZE(sc_table);
1174 entry++) {
1175 if (iter++ >= *pos)
1176 return entry;
1177 }
1178 for (entry = compat_sc_table;
1179 entry < compat_sc_table + ARRAY_SIZE(compat_sc_table);
1180 entry++) {
1181 if (iter++ >= *pos)
1182 return entry;
1183 }
1184 /* End of list */
1185 return NULL;
1186 }
1187
1188 static
1189 void *syscall_list_start(struct seq_file *m, loff_t *pos)
1190 {
1191 return (void *) syscall_list_get_entry(pos);
1192 }
1193
1194 static
1195 void *syscall_list_next(struct seq_file *m, void *p, loff_t *ppos)
1196 {
1197 (*ppos)++;
1198 return (void *) syscall_list_get_entry(ppos);
1199 }
1200
1201 static
1202 void syscall_list_stop(struct seq_file *m, void *p)
1203 {
1204 }
1205
1206 static
1207 int get_sc_table(const struct trace_syscall_entry *entry,
1208 const struct trace_syscall_entry **table,
1209 unsigned int *bitness)
1210 {
1211 if (entry >= sc_table && entry < sc_table + ARRAY_SIZE(sc_table)) {
1212 if (bitness)
1213 *bitness = BITS_PER_LONG;
1214 if (table)
1215 *table = sc_table;
1216 return 0;
1217 }
1218 if (!(entry >= compat_sc_table
1219 && entry < compat_sc_table + ARRAY_SIZE(compat_sc_table))) {
1220 return -EINVAL;
1221 }
1222 if (bitness)
1223 *bitness = 32;
1224 if (table)
1225 *table = compat_sc_table;
1226 return 0;
1227 }
1228
1229 static
1230 int syscall_list_show(struct seq_file *m, void *p)
1231 {
1232 const struct trace_syscall_entry *table, *entry = p;
1233 unsigned int bitness;
1234 unsigned long index;
1235 int ret;
1236 const char *name;
1237
1238 ret = get_sc_table(entry, &table, &bitness);
1239 if (ret)
1240 return ret;
1241 if (!entry->desc)
1242 return 0;
1243 if (table == sc_table) {
1244 index = entry - table;
1245 name = &entry->desc->name[strlen(SYSCALL_ENTRY_STR)];
1246 } else {
1247 index = (entry - table) + ARRAY_SIZE(sc_table);
1248 name = &entry->desc->name[strlen(COMPAT_SYSCALL_ENTRY_STR)];
1249 }
1250 seq_printf(m, "syscall { index = %lu; name = %s; bitness = %u; };\n",
1251 index, name, bitness);
1252 return 0;
1253 }
1254
1255 static
1256 const struct seq_operations lttng_syscall_list_seq_ops = {
1257 .start = syscall_list_start,
1258 .next = syscall_list_next,
1259 .stop = syscall_list_stop,
1260 .show = syscall_list_show,
1261 };
1262
1263 static
1264 int lttng_syscall_list_open(struct inode *inode, struct file *file)
1265 {
1266 return seq_open(file, &lttng_syscall_list_seq_ops);
1267 }
1268
1269 const struct file_operations lttng_syscall_list_fops = {
1270 .owner = THIS_MODULE,
1271 .open = lttng_syscall_list_open,
1272 .read = seq_read,
1273 .llseek = seq_lseek,
1274 .release = seq_release,
1275 };
1276
1277 /*
1278 * A syscall is enabled if it is traced for either entry or exit.
1279 */
1280 long lttng_channel_syscall_mask(struct lttng_channel *channel,
1281 struct lttng_kernel_syscall_mask __user *usyscall_mask)
1282 {
1283 uint32_t len, sc_tables_len, bitmask_len;
1284 int ret = 0, bit;
1285 char *tmp_mask;
1286 struct lttng_syscall_filter *filter;
1287
1288 ret = get_user(len, &usyscall_mask->len);
1289 if (ret)
1290 return ret;
1291 sc_tables_len = get_sc_tables_len();
1292 bitmask_len = ALIGN(sc_tables_len, 8) >> 3;
1293 if (len < sc_tables_len) {
1294 return put_user(sc_tables_len, &usyscall_mask->len);
1295 }
1296 /* Array is large enough, we can copy array to user-space. */
1297 tmp_mask = kzalloc(bitmask_len, GFP_KERNEL);
1298 if (!tmp_mask)
1299 return -ENOMEM;
1300 filter = channel->sc_filter;
1301
1302 for (bit = 0; bit < ARRAY_SIZE(sc_table); bit++) {
1303 char state;
1304
1305 if (channel->sc_table) {
1306 if (!READ_ONCE(channel->syscall_all) && filter)
1307 state = test_bit(bit, filter->sc_entry)
1308 || test_bit(bit, filter->sc_exit);
1309 else
1310 state = 1;
1311 } else {
1312 state = 0;
1313 }
1314 bt_bitfield_write_be(tmp_mask, char, bit, 1, state);
1315 }
1316 for (; bit < sc_tables_len; bit++) {
1317 char state;
1318
1319 if (channel->compat_sc_table) {
1320 if (!READ_ONCE(channel->syscall_all) && filter)
1321 state = test_bit(bit - ARRAY_SIZE(sc_table),
1322 filter->sc_compat_entry)
1323 || test_bit(bit - ARRAY_SIZE(sc_table),
1324 filter->sc_compat_exit);
1325 else
1326 state = 1;
1327 } else {
1328 state = 0;
1329 }
1330 bt_bitfield_write_be(tmp_mask, char, bit, 1, state);
1331 }
1332 if (copy_to_user(usyscall_mask->mask, tmp_mask, bitmask_len))
1333 ret = -EFAULT;
1334 kfree(tmp_mask);
1335 return ret;
1336 }
1337
1338 int lttng_abi_syscall_list(void)
1339 {
1340 struct file *syscall_list_file;
1341 int file_fd, ret;
1342
1343 file_fd = lttng_get_unused_fd();
1344 if (file_fd < 0) {
1345 ret = file_fd;
1346 goto fd_error;
1347 }
1348
1349 syscall_list_file = anon_inode_getfile("[lttng_syscall_list]",
1350 &lttng_syscall_list_fops,
1351 NULL, O_RDWR);
1352 if (IS_ERR(syscall_list_file)) {
1353 ret = PTR_ERR(syscall_list_file);
1354 goto file_error;
1355 }
1356 ret = lttng_syscall_list_fops.open(NULL, syscall_list_file);
1357 if (ret < 0)
1358 goto open_error;
1359 fd_install(file_fd, syscall_list_file);
1360 return file_fd;
1361
1362 open_error:
1363 fput(syscall_list_file);
1364 file_error:
1365 put_unused_fd(file_fd);
1366 fd_error:
1367 return ret;
1368 }
This page took 0.061175 seconds and 4 git commands to generate.