1 /* SPDX-License-Identifier: (GPL-2.0 or LGPL-2.1)
5 * LTTng syscall probes.
7 * Copyright (C) 2010-2012 Mathieu Desnoyers <mathieu.desnoyers@efficios.com>
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>
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>
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 #include <lttng-kernel-version.h>
33 # ifndef is_compat_task
34 # define is_compat_task() (0)
38 /* in_compat_syscall appears in kernel 4.6. */
39 #ifndef in_compat_syscall
40 # define in_compat_syscall() is_compat_task()
43 /* in_x32_syscall appears in kernel 4.7. */
44 #if (LTTNG_LINUX_VERSION_CODE < LTTNG_KERNEL_VERSION(4,7,0))
45 # ifdef CONFIG_X86_X32_ABI
46 # define in_x32_syscall() is_x32_task()
57 #define SYSCALL_ENTRY_TOK syscall_entry_
58 #define COMPAT_SYSCALL_ENTRY_TOK compat_syscall_entry_
59 #define SYSCALL_EXIT_TOK syscall_exit_
60 #define COMPAT_SYSCALL_EXIT_TOK compat_syscall_exit_
62 #define SYSCALL_ENTRY_STR __stringify(SYSCALL_ENTRY_TOK)
63 #define COMPAT_SYSCALL_ENTRY_STR __stringify(COMPAT_SYSCALL_ENTRY_TOK)
64 #define SYSCALL_EXIT_STR __stringify(SYSCALL_EXIT_TOK)
65 #define COMPAT_SYSCALL_EXIT_STR __stringify(COMPAT_SYSCALL_EXIT_TOK)
68 void syscall_entry_probe(void *__data
, struct pt_regs
*regs
, long id
);
70 void syscall_exit_probe(void *__data
, struct pt_regs
*regs
, long ret
);
73 * Forward declarations for old kernels.
77 struct oldold_utsname
;
79 struct sel_arg_struct
;
80 struct mmap_arg_struct
;
85 * Forward declaration for kernels >= 5.6
92 #if (LTTNG_LINUX_VERSION_CODE >= LTTNG_KERNEL_VERSION(5,6,0))
93 typedef __kernel_old_time_t
time_t;
96 #ifdef IA32_NR_syscalls
97 #define NR_compat_syscalls IA32_NR_syscalls
99 #define NR_compat_syscalls NR_syscalls
103 * Create LTTng tracepoint probes.
105 #define LTTNG_PACKAGE_BUILD
106 #define CREATE_TRACE_POINTS
107 #define TP_MODULE_NOINIT
108 #define TRACE_INCLUDE_PATH instrumentation/syscalls/headers
110 #define PARAMS(args...) args
112 /* Handle unknown syscalls */
114 #define TRACE_SYSTEM syscalls_unknown
115 #include <instrumentation/syscalls/headers/syscalls_unknown.h>
123 #define sc_in(...) __VA_ARGS__
127 #define sc_inout(...) __VA_ARGS__
129 /* Hijack probe callback for system call enter */
131 #define TP_PROBE_CB(_template) &syscall_entry_probe
132 #define SC_LTTNG_TRACEPOINT_EVENT(_name, _proto, _args, _fields) \
133 LTTNG_TRACEPOINT_EVENT(syscall_entry_##_name, PARAMS(_proto), PARAMS(_args), \
135 #define SC_LTTNG_TRACEPOINT_EVENT_CODE(_name, _proto, _args, _locvar, _code_pre, _fields, _code_post) \
136 LTTNG_TRACEPOINT_EVENT_CODE(syscall_entry_##_name, PARAMS(_proto), PARAMS(_args), \
137 PARAMS(_locvar), PARAMS(_code_pre), \
138 PARAMS(_fields), PARAMS(_code_post))
139 #define SC_LTTNG_TRACEPOINT_EVENT_CLASS_NOARGS(_name, _fields) \
140 LTTNG_TRACEPOINT_EVENT_CLASS_NOARGS(syscall_entry_##_name, PARAMS(_fields))
141 #define SC_LTTNG_TRACEPOINT_EVENT_INSTANCE_NOARGS(_template, _name) \
142 LTTNG_TRACEPOINT_EVENT_INSTANCE_NOARGS(syscall_entry_##_template, syscall_entry_##_name)
143 /* Enumerations only defined at first inclusion. */
144 #define SC_LTTNG_TRACEPOINT_ENUM(_name, _values) \
145 LTTNG_TRACEPOINT_ENUM(_name, PARAMS(_values))
147 #define TRACE_SYSTEM syscall_entry_integers
148 #define TRACE_INCLUDE_FILE syscalls_integers
149 #include <instrumentation/syscalls/headers/syscalls_integers.h>
150 #undef TRACE_INCLUDE_FILE
152 #define TRACE_SYSTEM syscall_entry_pointers
153 #define TRACE_INCLUDE_FILE syscalls_pointers
154 #include <instrumentation/syscalls/headers/syscalls_pointers.h>
155 #undef TRACE_INCLUDE_FILE
157 #undef SC_LTTNG_TRACEPOINT_ENUM
158 #undef SC_LTTNG_TRACEPOINT_EVENT_CODE
159 #undef SC_LTTNG_TRACEPOINT_EVENT
160 #undef SC_LTTNG_TRACEPOINT_EVENT_CLASS_NOARGS
161 #undef SC_LTTNG_TRACEPOINT_EVENT_INSTANCE_NOARGS
163 #undef _TRACE_SYSCALLS_INTEGERS_H
164 #undef _TRACE_SYSCALLS_POINTERS_H
166 /* Hijack probe callback for compat system call enter */
167 #define TP_PROBE_CB(_template) &syscall_entry_probe
168 #define LTTNG_SC_COMPAT
169 #define SC_LTTNG_TRACEPOINT_EVENT(_name, _proto, _args, _fields) \
170 LTTNG_TRACEPOINT_EVENT(compat_syscall_entry_##_name, PARAMS(_proto), PARAMS(_args), \
172 #define SC_LTTNG_TRACEPOINT_EVENT_CODE(_name, _proto, _args, _locvar, _code_pre, _fields, _code_post) \
173 LTTNG_TRACEPOINT_EVENT_CODE(compat_syscall_entry_##_name, PARAMS(_proto), PARAMS(_args), \
174 PARAMS(_locvar), PARAMS(_code_pre), PARAMS(_fields), PARAMS(_code_post))
175 #define SC_LTTNG_TRACEPOINT_EVENT_CLASS_NOARGS(_name, _fields) \
176 LTTNG_TRACEPOINT_EVENT_CLASS_NOARGS(compat_syscall_entry_##_name, PARAMS(_fields))
177 #define SC_LTTNG_TRACEPOINT_EVENT_INSTANCE_NOARGS(_template, _name) \
178 LTTNG_TRACEPOINT_EVENT_INSTANCE_NOARGS(compat_syscall_entry_##_template, \
179 compat_syscall_entry_##_name)
180 /* Enumerations only defined at inital inclusion (not here). */
181 #define SC_LTTNG_TRACEPOINT_ENUM(_name, _values)
182 #define TRACE_SYSTEM compat_syscall_entry_integers
183 #define TRACE_INCLUDE_FILE compat_syscalls_integers
184 #include <instrumentation/syscalls/headers/compat_syscalls_integers.h>
185 #undef TRACE_INCLUDE_FILE
187 #define TRACE_SYSTEM compat_syscall_entry_pointers
188 #define TRACE_INCLUDE_FILE compat_syscalls_pointers
189 #include <instrumentation/syscalls/headers/compat_syscalls_pointers.h>
190 #undef TRACE_INCLUDE_FILE
192 #undef SC_LTTNG_TRACEPOINT_ENUM
193 #undef SC_LTTNG_TRACEPOINT_EVENT_CODE
194 #undef SC_LTTNG_TRACEPOINT_EVENT
195 #undef SC_LTTNG_TRACEPOINT_EVENT_CLASS_NOARGS
196 #undef SC_LTTNG_TRACEPOINT_EVENT_INSTANCE_NOARGS
198 #undef _TRACE_SYSCALLS_INTEGERS_H
199 #undef _TRACE_SYSCALLS_POINTERS_H
200 #undef LTTNG_SC_COMPAT
207 #define sc_exit(...) __VA_ARGS__
211 #define sc_out(...) __VA_ARGS__
213 #define sc_inout(...) __VA_ARGS__
215 /* Hijack probe callback for system call exit */
216 #define TP_PROBE_CB(_template) &syscall_exit_probe
217 #define SC_LTTNG_TRACEPOINT_EVENT(_name, _proto, _args, _fields) \
218 LTTNG_TRACEPOINT_EVENT(syscall_exit_##_name, PARAMS(_proto), PARAMS(_args), \
220 #define SC_LTTNG_TRACEPOINT_EVENT_CODE(_name, _proto, _args, _locvar, _code_pre, _fields, _code_post) \
221 LTTNG_TRACEPOINT_EVENT_CODE(syscall_exit_##_name, PARAMS(_proto), PARAMS(_args), \
222 PARAMS(_locvar), PARAMS(_code_pre), PARAMS(_fields), PARAMS(_code_post))
223 #define SC_LTTNG_TRACEPOINT_EVENT_CLASS_NOARGS(_name, _fields) \
224 LTTNG_TRACEPOINT_EVENT_CLASS_NOARGS(syscall_exit_##_name, PARAMS(_fields))
225 #define SC_LTTNG_TRACEPOINT_EVENT_INSTANCE_NOARGS(_template, _name) \
226 LTTNG_TRACEPOINT_EVENT_INSTANCE_NOARGS(syscall_exit_##_template, \
227 syscall_exit_##_name)
228 /* Enumerations only defined at inital inclusion (not here). */
229 #define SC_LTTNG_TRACEPOINT_ENUM(_name, _values)
230 #define TRACE_SYSTEM syscall_exit_integers
231 #define TRACE_INCLUDE_FILE syscalls_integers
232 #include <instrumentation/syscalls/headers/syscalls_integers.h>
233 #undef TRACE_INCLUDE_FILE
235 #define TRACE_SYSTEM syscall_exit_pointers
236 #define TRACE_INCLUDE_FILE syscalls_pointers
237 #include <instrumentation/syscalls/headers/syscalls_pointers.h>
238 #undef TRACE_INCLUDE_FILE
240 #undef SC_LTTNG_TRACEPOINT_ENUM
241 #undef SC_LTTNG_TRACEPOINT_EVENT_CODE
242 #undef SC_LTTNG_TRACEPOINT_EVENT
243 #undef SC_LTTNG_TRACEPOINT_EVENT_CLASS_NOARGS
244 #undef SC_LTTNG_TRACEPOINT_EVENT_INSTANCE_NOARGS
246 #undef _TRACE_SYSCALLS_INTEGERS_H
247 #undef _TRACE_SYSCALLS_POINTERS_H
250 /* Hijack probe callback for compat system call exit */
251 #define TP_PROBE_CB(_template) &syscall_exit_probe
252 #define LTTNG_SC_COMPAT
253 #define SC_LTTNG_TRACEPOINT_EVENT(_name, _proto, _args, _fields) \
254 LTTNG_TRACEPOINT_EVENT(compat_syscall_exit_##_name, PARAMS(_proto), PARAMS(_args), \
256 #define SC_LTTNG_TRACEPOINT_EVENT_CODE(_name, _proto, _args, _locvar, _code_pre, _fields, _code_post) \
257 LTTNG_TRACEPOINT_EVENT_CODE(compat_syscall_exit_##_name, PARAMS(_proto), PARAMS(_args), \
258 PARAMS(_locvar), PARAMS(_code_pre), PARAMS(_fields), PARAMS(_code_post))
259 #define SC_LTTNG_TRACEPOINT_EVENT_CLASS_NOARGS(_name, _fields) \
260 LTTNG_TRACEPOINT_EVENT_CLASS_NOARGS(compat_syscall_exit_##_name, PARAMS(_fields))
261 #define SC_LTTNG_TRACEPOINT_EVENT_INSTANCE_NOARGS(_template, _name) \
262 LTTNG_TRACEPOINT_EVENT_INSTANCE_NOARGS(compat_syscall_exit_##_template, \
263 compat_syscall_exit_##_name)
264 /* Enumerations only defined at inital inclusion (not here). */
265 #define SC_LTTNG_TRACEPOINT_ENUM(_name, _values)
266 #define TRACE_SYSTEM compat_syscall_exit_integers
267 #define TRACE_INCLUDE_FILE compat_syscalls_integers
268 #include <instrumentation/syscalls/headers/compat_syscalls_integers.h>
269 #undef TRACE_INCLUDE_FILE
271 #define TRACE_SYSTEM compat_syscall_exit_pointers
272 #define TRACE_INCLUDE_FILE compat_syscalls_pointers
273 #include <instrumentation/syscalls/headers/compat_syscalls_pointers.h>
274 #undef TRACE_INCLUDE_FILE
276 #undef SC_LTTNG_TRACEPOINT_ENUM
277 #undef SC_LTTNG_TRACEPOINT_EVENT_CODE
278 #undef SC_LTTNG_TRACEPOINT_EVENT
279 #undef SC_LTTNG_TRACEPOINT_EVENT_CLASS_NOARGS
280 #undef SC_LTTNG_TRACEPOINT_EVENT_INSTANCE_NOARGS
282 #undef _TRACE_SYSCALLS_INTEGERS_H
283 #undef _TRACE_SYSCALLS_POINTERS_H
284 #undef LTTNG_SC_COMPAT
288 #undef TP_MODULE_NOINIT
289 #undef LTTNG_PACKAGE_BUILD
290 #undef CREATE_TRACE_POINTS
292 struct trace_syscall_entry
{
294 const struct lttng_event_desc
*desc
;
295 const struct lttng_event_field
*fields
;
299 #define CREATE_SYSCALL_TABLE
306 #undef TRACE_SYSCALL_TABLE
307 #define TRACE_SYSCALL_TABLE(_template, _name, _nr, _nrargs) \
309 .func = __event_probe__syscall_entry_##_template, \
310 .nrargs = (_nrargs), \
311 .fields = __event_fields___syscall_entry_##_template, \
312 .desc = &__event_desc___syscall_entry_##_name, \
315 /* Syscall enter tracing table */
316 static const struct trace_syscall_entry sc_table
[] = {
317 #include <instrumentation/syscalls/headers/syscalls_integers.h>
318 #include <instrumentation/syscalls/headers/syscalls_pointers.h>
321 #undef TRACE_SYSCALL_TABLE
322 #define TRACE_SYSCALL_TABLE(_template, _name, _nr, _nrargs) \
324 .func = __event_probe__compat_syscall_entry_##_template, \
325 .nrargs = (_nrargs), \
326 .fields = __event_fields___compat_syscall_entry_##_template, \
327 .desc = &__event_desc___compat_syscall_entry_##_name, \
330 /* Compat syscall enter table */
331 const struct trace_syscall_entry compat_sc_table
[] = {
332 #include <instrumentation/syscalls/headers/compat_syscalls_integers.h>
333 #include <instrumentation/syscalls/headers/compat_syscalls_pointers.h>
341 #define sc_exit(...) __VA_ARGS__
343 #undef TRACE_SYSCALL_TABLE
344 #define TRACE_SYSCALL_TABLE(_template, _name, _nr, _nrargs) \
346 .func = __event_probe__syscall_exit_##_template, \
347 .nrargs = (_nrargs), \
348 .fields = __event_fields___syscall_exit_##_template, \
349 .desc = &__event_desc___syscall_exit_##_name, \
352 /* Syscall exit table */
353 static const struct trace_syscall_entry sc_exit_table
[] = {
354 #include <instrumentation/syscalls/headers/syscalls_integers.h>
355 #include <instrumentation/syscalls/headers/syscalls_pointers.h>
358 #undef TRACE_SYSCALL_TABLE
359 #define TRACE_SYSCALL_TABLE(_template, _name, _nr, _nrargs) \
361 .func = __event_probe__compat_syscall_exit_##_template, \
362 .nrargs = (_nrargs), \
363 .fields = __event_fields___compat_syscall_exit_##_template, \
364 .desc = &__event_desc___compat_syscall_exit_##_name, \
367 /* Compat syscall exit table */
368 const struct trace_syscall_entry compat_sc_exit_table
[] = {
369 #include <instrumentation/syscalls/headers/compat_syscalls_integers.h>
370 #include <instrumentation/syscalls/headers/compat_syscalls_pointers.h>
375 #undef CREATE_SYSCALL_TABLE
377 struct lttng_syscall_filter
{
378 DECLARE_BITMAP(sc_entry
, NR_syscalls
);
379 DECLARE_BITMAP(sc_exit
, NR_syscalls
);
380 DECLARE_BITMAP(sc_compat_entry
, NR_compat_syscalls
);
381 DECLARE_BITMAP(sc_compat_exit
, NR_compat_syscalls
);
384 static void syscall_entry_unknown(struct lttng_event
*event
,
385 struct pt_regs
*regs
, unsigned int id
)
387 unsigned long args
[LTTNG_SYSCALL_NR_ARGS
];
389 lttng_syscall_get_arguments(current
, regs
, args
);
390 if (unlikely(in_compat_syscall()))
391 __event_probe__compat_syscall_entry_unknown(event
, id
, args
);
393 __event_probe__syscall_entry_unknown(event
, id
, args
);
396 void syscall_entry_probe(void *__data
, struct pt_regs
*regs
, long id
)
398 struct lttng_channel
*chan
= __data
;
399 struct lttng_event
*event
, *unknown_event
;
400 const struct trace_syscall_entry
*table
, *entry
;
403 #ifdef CONFIG_X86_X32_ABI
404 if (in_x32_syscall()) {
405 /* x32 system calls are not supported. */
409 if (unlikely(in_compat_syscall())) {
410 struct lttng_syscall_filter
*filter
= chan
->sc_filter
;
412 if (id
< 0 || id
>= NR_compat_syscalls
413 || (!READ_ONCE(chan
->syscall_all
) && !test_bit(id
, filter
->sc_compat_entry
))) {
414 /* System call filtered out. */
417 table
= compat_sc_table
;
418 table_len
= ARRAY_SIZE(compat_sc_table
);
419 unknown_event
= chan
->sc_compat_unknown
;
421 struct lttng_syscall_filter
*filter
= chan
->sc_filter
;
423 if (id
< 0 || id
>= NR_syscalls
424 || (!READ_ONCE(chan
->syscall_all
) && !test_bit(id
, filter
->sc_entry
))) {
425 /* System call filtered out. */
429 table_len
= ARRAY_SIZE(sc_table
);
430 unknown_event
= chan
->sc_unknown
;
432 if (unlikely(id
< 0 || id
>= table_len
)) {
433 syscall_entry_unknown(unknown_event
, regs
, id
);
436 if (unlikely(in_compat_syscall()))
437 event
= chan
->compat_sc_table
[id
];
439 event
= chan
->sc_table
[id
];
440 if (unlikely(!event
)) {
441 syscall_entry_unknown(unknown_event
, regs
, id
);
445 WARN_ON_ONCE(!entry
);
447 switch (entry
->nrargs
) {
450 void (*fptr
)(void *__data
) = entry
->func
;
457 void (*fptr
)(void *__data
, unsigned long arg0
) = entry
->func
;
458 unsigned long args
[LTTNG_SYSCALL_NR_ARGS
];
460 lttng_syscall_get_arguments(current
, regs
, args
);
461 fptr(event
, args
[0]);
466 void (*fptr
)(void *__data
,
468 unsigned long arg1
) = entry
->func
;
469 unsigned long args
[LTTNG_SYSCALL_NR_ARGS
];
471 lttng_syscall_get_arguments(current
, regs
, args
);
472 fptr(event
, args
[0], args
[1]);
477 void (*fptr
)(void *__data
,
480 unsigned long arg2
) = entry
->func
;
481 unsigned long args
[LTTNG_SYSCALL_NR_ARGS
];
483 lttng_syscall_get_arguments(current
, regs
, args
);
484 fptr(event
, args
[0], args
[1], args
[2]);
489 void (*fptr
)(void *__data
,
493 unsigned long arg3
) = entry
->func
;
494 unsigned long args
[LTTNG_SYSCALL_NR_ARGS
];
496 lttng_syscall_get_arguments(current
, regs
, args
);
497 fptr(event
, args
[0], args
[1], args
[2], args
[3]);
502 void (*fptr
)(void *__data
,
507 unsigned long arg4
) = entry
->func
;
508 unsigned long args
[LTTNG_SYSCALL_NR_ARGS
];
510 lttng_syscall_get_arguments(current
, regs
, args
);
511 fptr(event
, args
[0], args
[1], args
[2], args
[3], args
[4]);
516 void (*fptr
)(void *__data
,
522 unsigned long arg5
) = entry
->func
;
523 unsigned long args
[LTTNG_SYSCALL_NR_ARGS
];
525 lttng_syscall_get_arguments(current
, regs
, args
);
526 fptr(event
, args
[0], args
[1], args
[2],
527 args
[3], args
[4], args
[5]);
535 static void syscall_exit_unknown(struct lttng_event
*event
,
536 struct pt_regs
*regs
, int id
, long ret
)
538 unsigned long args
[LTTNG_SYSCALL_NR_ARGS
];
540 lttng_syscall_get_arguments(current
, regs
, args
);
541 if (unlikely(in_compat_syscall()))
542 __event_probe__compat_syscall_exit_unknown(event
, id
, ret
,
545 __event_probe__syscall_exit_unknown(event
, id
, ret
, args
);
548 void syscall_exit_probe(void *__data
, struct pt_regs
*regs
, long ret
)
550 struct lttng_channel
*chan
= __data
;
551 struct lttng_event
*event
, *unknown_event
;
552 const struct trace_syscall_entry
*table
, *entry
;
556 #ifdef CONFIG_X86_X32_ABI
557 if (in_x32_syscall()) {
558 /* x32 system calls are not supported. */
562 id
= syscall_get_nr(current
, regs
);
563 if (unlikely(in_compat_syscall())) {
564 struct lttng_syscall_filter
*filter
= chan
->sc_filter
;
566 if (id
< 0 || id
>= NR_compat_syscalls
567 || (!READ_ONCE(chan
->syscall_all
) && !test_bit(id
, filter
->sc_compat_exit
))) {
568 /* System call filtered out. */
571 table
= compat_sc_exit_table
;
572 table_len
= ARRAY_SIZE(compat_sc_exit_table
);
573 unknown_event
= chan
->compat_sc_exit_unknown
;
575 struct lttng_syscall_filter
*filter
= chan
->sc_filter
;
577 if (id
< 0 || id
>= NR_syscalls
578 || (!READ_ONCE(chan
->syscall_all
) && !test_bit(id
, filter
->sc_exit
))) {
579 /* System call filtered out. */
582 table
= sc_exit_table
;
583 table_len
= ARRAY_SIZE(sc_exit_table
);
584 unknown_event
= chan
->sc_exit_unknown
;
586 if (unlikely(id
< 0 || id
>= table_len
)) {
587 syscall_exit_unknown(unknown_event
, regs
, id
, ret
);
590 if (unlikely(in_compat_syscall()))
591 event
= chan
->compat_sc_exit_table
[id
];
593 event
= chan
->sc_exit_table
[id
];
594 if (unlikely(!event
)) {
595 syscall_exit_unknown(unknown_event
, regs
, id
, ret
);
599 WARN_ON_ONCE(!entry
);
601 switch (entry
->nrargs
) {
604 void (*fptr
)(void *__data
, long ret
) = entry
->func
;
611 void (*fptr
)(void *__data
,
613 unsigned long arg0
) = entry
->func
;
614 unsigned long args
[LTTNG_SYSCALL_NR_ARGS
];
616 lttng_syscall_get_arguments(current
, regs
, args
);
617 fptr(event
, ret
, args
[0]);
622 void (*fptr
)(void *__data
,
625 unsigned long arg1
) = entry
->func
;
626 unsigned long args
[LTTNG_SYSCALL_NR_ARGS
];
628 lttng_syscall_get_arguments(current
, regs
, args
);
629 fptr(event
, ret
, args
[0], args
[1]);
634 void (*fptr
)(void *__data
,
638 unsigned long arg2
) = entry
->func
;
639 unsigned long args
[LTTNG_SYSCALL_NR_ARGS
];
641 lttng_syscall_get_arguments(current
, regs
, args
);
642 fptr(event
, ret
, args
[0], args
[1], args
[2]);
647 void (*fptr
)(void *__data
,
652 unsigned long arg3
) = entry
->func
;
653 unsigned long args
[LTTNG_SYSCALL_NR_ARGS
];
655 lttng_syscall_get_arguments(current
, regs
, args
);
656 fptr(event
, ret
, args
[0], args
[1], args
[2], args
[3]);
661 void (*fptr
)(void *__data
,
667 unsigned long arg4
) = entry
->func
;
668 unsigned long args
[LTTNG_SYSCALL_NR_ARGS
];
670 lttng_syscall_get_arguments(current
, regs
, args
);
671 fptr(event
, ret
, args
[0], args
[1], args
[2], args
[3], args
[4]);
676 void (*fptr
)(void *__data
,
683 unsigned long arg5
) = entry
->func
;
684 unsigned long args
[LTTNG_SYSCALL_NR_ARGS
];
686 lttng_syscall_get_arguments(current
, regs
, args
);
687 fptr(event
, ret
, args
[0], args
[1], args
[2],
688 args
[3], args
[4], args
[5]);
697 * noinline to diminish caller stack size.
698 * Should be called with sessions lock held.
701 int fill_table(const struct trace_syscall_entry
*table
, size_t table_len
,
702 struct lttng_event
**chan_table
, struct lttng_channel
*chan
,
703 void *filter
, enum sc_type type
)
705 const struct lttng_event_desc
*desc
;
708 /* Allocate events for each syscall, insert into table */
709 for (i
= 0; i
< table_len
; i
++) {
710 struct lttng_kernel_event ev
;
711 desc
= table
[i
].desc
;
714 /* Unknown syscall */
718 * Skip those already populated by previous failed
719 * register for this channel.
723 memset(&ev
, 0, sizeof(ev
));
726 ev
.u
.syscall
.entryexit
= LTTNG_KERNEL_SYSCALL_ENTRY
;
727 ev
.u
.syscall
.abi
= LTTNG_KERNEL_SYSCALL_ABI_NATIVE
;
730 ev
.u
.syscall
.entryexit
= LTTNG_KERNEL_SYSCALL_EXIT
;
731 ev
.u
.syscall
.abi
= LTTNG_KERNEL_SYSCALL_ABI_NATIVE
;
733 case SC_TYPE_COMPAT_ENTRY
:
734 ev
.u
.syscall
.entryexit
= LTTNG_KERNEL_SYSCALL_ENTRY
;
735 ev
.u
.syscall
.abi
= LTTNG_KERNEL_SYSCALL_ABI_COMPAT
;
737 case SC_TYPE_COMPAT_EXIT
:
738 ev
.u
.syscall
.entryexit
= LTTNG_KERNEL_SYSCALL_EXIT
;
739 ev
.u
.syscall
.abi
= LTTNG_KERNEL_SYSCALL_ABI_COMPAT
;
742 strncpy(ev
.name
, desc
->name
, LTTNG_KERNEL_SYM_NAME_LEN
- 1);
743 ev
.name
[LTTNG_KERNEL_SYM_NAME_LEN
- 1] = '\0';
744 ev
.instrumentation
= LTTNG_KERNEL_SYSCALL
;
745 chan_table
[i
] = _lttng_event_create(chan
, &ev
, filter
,
746 desc
, ev
.instrumentation
);
747 WARN_ON_ONCE(!chan_table
[i
]);
748 if (IS_ERR(chan_table
[i
])) {
750 * If something goes wrong in event registration
751 * after the first one, we have no choice but to
752 * leave the previous events in there, until
753 * deleted by session teardown.
755 return PTR_ERR(chan_table
[i
]);
762 * Should be called with sessions lock held.
764 int lttng_syscalls_register(struct lttng_channel
*chan
, void *filter
)
766 struct lttng_kernel_event ev
;
769 wrapper_vmalloc_sync_mappings();
771 if (!chan
->sc_table
) {
772 /* create syscall table mapping syscall to events */
773 chan
->sc_table
= kzalloc(sizeof(struct lttng_event
*)
774 * ARRAY_SIZE(sc_table
), GFP_KERNEL
);
778 if (!chan
->sc_exit_table
) {
779 /* create syscall table mapping syscall to events */
780 chan
->sc_exit_table
= kzalloc(sizeof(struct lttng_event
*)
781 * ARRAY_SIZE(sc_exit_table
), GFP_KERNEL
);
782 if (!chan
->sc_exit_table
)
788 if (!chan
->compat_sc_table
) {
789 /* create syscall table mapping compat syscall to events */
790 chan
->compat_sc_table
= kzalloc(sizeof(struct lttng_event
*)
791 * ARRAY_SIZE(compat_sc_table
), GFP_KERNEL
);
792 if (!chan
->compat_sc_table
)
796 if (!chan
->compat_sc_exit_table
) {
797 /* create syscall table mapping compat syscall to events */
798 chan
->compat_sc_exit_table
= kzalloc(sizeof(struct lttng_event
*)
799 * ARRAY_SIZE(compat_sc_exit_table
), GFP_KERNEL
);
800 if (!chan
->compat_sc_exit_table
)
804 if (!chan
->sc_unknown
) {
805 const struct lttng_event_desc
*desc
=
806 &__event_desc___syscall_entry_unknown
;
808 memset(&ev
, 0, sizeof(ev
));
809 strncpy(ev
.name
, desc
->name
, LTTNG_KERNEL_SYM_NAME_LEN
);
810 ev
.name
[LTTNG_KERNEL_SYM_NAME_LEN
- 1] = '\0';
811 ev
.instrumentation
= LTTNG_KERNEL_SYSCALL
;
812 ev
.u
.syscall
.entryexit
= LTTNG_KERNEL_SYSCALL_ENTRY
;
813 ev
.u
.syscall
.abi
= LTTNG_KERNEL_SYSCALL_ABI_NATIVE
;
814 chan
->sc_unknown
= _lttng_event_create(chan
, &ev
, filter
,
817 WARN_ON_ONCE(!chan
->sc_unknown
);
818 if (IS_ERR(chan
->sc_unknown
)) {
819 return PTR_ERR(chan
->sc_unknown
);
823 if (!chan
->sc_compat_unknown
) {
824 const struct lttng_event_desc
*desc
=
825 &__event_desc___compat_syscall_entry_unknown
;
827 memset(&ev
, 0, sizeof(ev
));
828 strncpy(ev
.name
, desc
->name
, LTTNG_KERNEL_SYM_NAME_LEN
);
829 ev
.name
[LTTNG_KERNEL_SYM_NAME_LEN
- 1] = '\0';
830 ev
.instrumentation
= LTTNG_KERNEL_SYSCALL
;
831 ev
.u
.syscall
.entryexit
= LTTNG_KERNEL_SYSCALL_ENTRY
;
832 ev
.u
.syscall
.abi
= LTTNG_KERNEL_SYSCALL_ABI_COMPAT
;
833 chan
->sc_compat_unknown
= _lttng_event_create(chan
, &ev
, filter
,
836 WARN_ON_ONCE(!chan
->sc_unknown
);
837 if (IS_ERR(chan
->sc_compat_unknown
)) {
838 return PTR_ERR(chan
->sc_compat_unknown
);
842 if (!chan
->compat_sc_exit_unknown
) {
843 const struct lttng_event_desc
*desc
=
844 &__event_desc___compat_syscall_exit_unknown
;
846 memset(&ev
, 0, sizeof(ev
));
847 strncpy(ev
.name
, desc
->name
, LTTNG_KERNEL_SYM_NAME_LEN
);
848 ev
.name
[LTTNG_KERNEL_SYM_NAME_LEN
- 1] = '\0';
849 ev
.instrumentation
= LTTNG_KERNEL_SYSCALL
;
850 ev
.u
.syscall
.entryexit
= LTTNG_KERNEL_SYSCALL_EXIT
;
851 ev
.u
.syscall
.abi
= LTTNG_KERNEL_SYSCALL_ABI_COMPAT
;
852 chan
->compat_sc_exit_unknown
= _lttng_event_create(chan
, &ev
,
855 WARN_ON_ONCE(!chan
->compat_sc_exit_unknown
);
856 if (IS_ERR(chan
->compat_sc_exit_unknown
)) {
857 return PTR_ERR(chan
->compat_sc_exit_unknown
);
861 if (!chan
->sc_exit_unknown
) {
862 const struct lttng_event_desc
*desc
=
863 &__event_desc___syscall_exit_unknown
;
865 memset(&ev
, 0, sizeof(ev
));
866 strncpy(ev
.name
, desc
->name
, LTTNG_KERNEL_SYM_NAME_LEN
);
867 ev
.name
[LTTNG_KERNEL_SYM_NAME_LEN
- 1] = '\0';
868 ev
.instrumentation
= LTTNG_KERNEL_SYSCALL
;
869 ev
.u
.syscall
.entryexit
= LTTNG_KERNEL_SYSCALL_EXIT
;
870 ev
.u
.syscall
.abi
= LTTNG_KERNEL_SYSCALL_ABI_NATIVE
;
871 chan
->sc_exit_unknown
= _lttng_event_create(chan
, &ev
, filter
,
872 desc
, ev
.instrumentation
);
873 WARN_ON_ONCE(!chan
->sc_exit_unknown
);
874 if (IS_ERR(chan
->sc_exit_unknown
)) {
875 return PTR_ERR(chan
->sc_exit_unknown
);
879 ret
= fill_table(sc_table
, ARRAY_SIZE(sc_table
),
880 chan
->sc_table
, chan
, filter
, SC_TYPE_ENTRY
);
883 ret
= fill_table(sc_exit_table
, ARRAY_SIZE(sc_exit_table
),
884 chan
->sc_exit_table
, chan
, filter
, SC_TYPE_EXIT
);
889 ret
= fill_table(compat_sc_table
, ARRAY_SIZE(compat_sc_table
),
890 chan
->compat_sc_table
, chan
, filter
,
891 SC_TYPE_COMPAT_ENTRY
);
894 ret
= fill_table(compat_sc_exit_table
, ARRAY_SIZE(compat_sc_exit_table
),
895 chan
->compat_sc_exit_table
, chan
, filter
,
896 SC_TYPE_COMPAT_EXIT
);
901 if (!chan
->sc_filter
) {
902 chan
->sc_filter
= kzalloc(sizeof(struct lttng_syscall_filter
),
904 if (!chan
->sc_filter
)
908 if (!chan
->sys_enter_registered
) {
909 ret
= lttng_wrapper_tracepoint_probe_register("sys_enter",
910 (void *) syscall_entry_probe
, chan
);
913 chan
->sys_enter_registered
= 1;
916 * We change the name of sys_exit tracepoint due to namespace
917 * conflict with sys_exit syscall entry.
919 if (!chan
->sys_exit_registered
) {
920 ret
= lttng_wrapper_tracepoint_probe_register("sys_exit",
921 (void *) syscall_exit_probe
, chan
);
923 WARN_ON_ONCE(lttng_wrapper_tracepoint_probe_unregister("sys_enter",
924 (void *) syscall_entry_probe
, chan
));
927 chan
->sys_exit_registered
= 1;
933 * Only called at session destruction.
935 int lttng_syscalls_unregister(struct lttng_channel
*chan
)
941 if (chan
->sys_enter_registered
) {
942 ret
= lttng_wrapper_tracepoint_probe_unregister("sys_enter",
943 (void *) syscall_entry_probe
, chan
);
946 chan
->sys_enter_registered
= 0;
948 if (chan
->sys_exit_registered
) {
949 ret
= lttng_wrapper_tracepoint_probe_unregister("sys_exit",
950 (void *) syscall_exit_probe
, chan
);
953 chan
->sys_exit_registered
= 0;
958 int lttng_syscalls_destroy(struct lttng_channel
*chan
)
960 kfree(chan
->sc_table
);
961 kfree(chan
->sc_exit_table
);
963 kfree(chan
->compat_sc_table
);
964 kfree(chan
->compat_sc_exit_table
);
966 kfree(chan
->sc_filter
);
971 int get_syscall_nr(const char *syscall_name
)
976 for (i
= 0; i
< ARRAY_SIZE(sc_table
); i
++) {
977 const struct trace_syscall_entry
*entry
;
980 entry
= &sc_table
[i
];
983 it_name
= entry
->desc
->name
;
984 it_name
+= strlen(SYSCALL_ENTRY_STR
);
985 if (!strcmp(syscall_name
, it_name
)) {
994 int get_compat_syscall_nr(const char *syscall_name
)
999 for (i
= 0; i
< ARRAY_SIZE(compat_sc_table
); i
++) {
1000 const struct trace_syscall_entry
*entry
;
1001 const char *it_name
;
1003 entry
= &compat_sc_table
[i
];
1006 it_name
= entry
->desc
->name
;
1007 it_name
+= strlen(COMPAT_SYSCALL_ENTRY_STR
);
1008 if (!strcmp(syscall_name
, it_name
)) {
1017 uint32_t get_sc_tables_len(void)
1019 return ARRAY_SIZE(sc_table
) + ARRAY_SIZE(compat_sc_table
);
1023 const char *get_syscall_name(struct lttng_event
*event
)
1025 size_t prefix_len
= 0;
1027 WARN_ON_ONCE(event
->instrumentation
!= LTTNG_KERNEL_SYSCALL
);
1029 switch (event
->u
.syscall
.entryexit
) {
1030 case LTTNG_SYSCALL_ENTRY
:
1031 switch (event
->u
.syscall
.abi
) {
1032 case LTTNG_SYSCALL_ABI_NATIVE
:
1033 prefix_len
= strlen(SYSCALL_ENTRY_STR
);
1035 case LTTNG_SYSCALL_ABI_COMPAT
:
1036 prefix_len
= strlen(COMPAT_SYSCALL_ENTRY_STR
);
1040 case LTTNG_SYSCALL_EXIT
:
1041 switch (event
->u
.syscall
.abi
) {
1042 case LTTNG_SYSCALL_ABI_NATIVE
:
1043 prefix_len
= strlen(SYSCALL_EXIT_STR
);
1045 case LTTNG_SYSCALL_ABI_COMPAT
:
1046 prefix_len
= strlen(COMPAT_SYSCALL_EXIT_STR
);
1051 WARN_ON_ONCE(prefix_len
== 0);
1052 return event
->desc
->name
+ prefix_len
;
1055 int lttng_syscall_filter_enable(struct lttng_channel
*chan
,
1056 struct lttng_event
*event
)
1058 struct lttng_syscall_filter
*filter
= chan
->sc_filter
;
1059 const char *syscall_name
;
1060 unsigned long *bitmap
;
1063 WARN_ON_ONCE(!chan
->sc_table
);
1065 syscall_name
= get_syscall_name(event
);
1067 switch (event
->u
.syscall
.abi
) {
1068 case LTTNG_SYSCALL_ABI_NATIVE
:
1069 syscall_nr
= get_syscall_nr(syscall_name
);
1071 case LTTNG_SYSCALL_ABI_COMPAT
:
1072 syscall_nr
= get_compat_syscall_nr(syscall_name
);
1080 switch (event
->u
.syscall
.entryexit
) {
1081 case LTTNG_SYSCALL_ENTRY
:
1082 switch (event
->u
.syscall
.abi
) {
1083 case LTTNG_SYSCALL_ABI_NATIVE
:
1084 bitmap
= filter
->sc_entry
;
1086 case LTTNG_SYSCALL_ABI_COMPAT
:
1087 bitmap
= filter
->sc_compat_entry
;
1093 case LTTNG_SYSCALL_EXIT
:
1094 switch (event
->u
.syscall
.abi
) {
1095 case LTTNG_SYSCALL_ABI_NATIVE
:
1096 bitmap
= filter
->sc_exit
;
1098 case LTTNG_SYSCALL_ABI_COMPAT
:
1099 bitmap
= filter
->sc_compat_exit
;
1108 if (test_bit(syscall_nr
, bitmap
))
1110 bitmap_set(bitmap
, syscall_nr
, 1);
1114 int lttng_syscall_filter_disable(struct lttng_channel
*chan
,
1115 struct lttng_event
*event
)
1117 struct lttng_syscall_filter
*filter
= chan
->sc_filter
;
1118 const char *syscall_name
;
1119 unsigned long *bitmap
;
1122 WARN_ON_ONCE(!chan
->sc_table
);
1124 syscall_name
= get_syscall_name(event
);
1126 switch (event
->u
.syscall
.abi
) {
1127 case LTTNG_SYSCALL_ABI_NATIVE
:
1128 syscall_nr
= get_syscall_nr(syscall_name
);
1130 case LTTNG_SYSCALL_ABI_COMPAT
:
1131 syscall_nr
= get_compat_syscall_nr(syscall_name
);
1139 switch (event
->u
.syscall
.entryexit
) {
1140 case LTTNG_SYSCALL_ENTRY
:
1141 switch (event
->u
.syscall
.abi
) {
1142 case LTTNG_SYSCALL_ABI_NATIVE
:
1143 bitmap
= filter
->sc_entry
;
1145 case LTTNG_SYSCALL_ABI_COMPAT
:
1146 bitmap
= filter
->sc_compat_entry
;
1152 case LTTNG_SYSCALL_EXIT
:
1153 switch (event
->u
.syscall
.abi
) {
1154 case LTTNG_SYSCALL_ABI_NATIVE
:
1155 bitmap
= filter
->sc_exit
;
1157 case LTTNG_SYSCALL_ABI_COMPAT
:
1158 bitmap
= filter
->sc_compat_exit
;
1167 if (!test_bit(syscall_nr
, bitmap
))
1169 bitmap_clear(bitmap
, syscall_nr
, 1);
1175 const struct trace_syscall_entry
*syscall_list_get_entry(loff_t
*pos
)
1177 const struct trace_syscall_entry
*entry
;
1180 for (entry
= sc_table
;
1181 entry
< sc_table
+ ARRAY_SIZE(sc_table
);
1186 for (entry
= compat_sc_table
;
1187 entry
< compat_sc_table
+ ARRAY_SIZE(compat_sc_table
);
1197 void *syscall_list_start(struct seq_file
*m
, loff_t
*pos
)
1199 return (void *) syscall_list_get_entry(pos
);
1203 void *syscall_list_next(struct seq_file
*m
, void *p
, loff_t
*ppos
)
1206 return (void *) syscall_list_get_entry(ppos
);
1210 void syscall_list_stop(struct seq_file
*m
, void *p
)
1215 int get_sc_table(const struct trace_syscall_entry
*entry
,
1216 const struct trace_syscall_entry
**table
,
1217 unsigned int *bitness
)
1219 if (entry
>= sc_table
&& entry
< sc_table
+ ARRAY_SIZE(sc_table
)) {
1221 *bitness
= BITS_PER_LONG
;
1226 if (!(entry
>= compat_sc_table
1227 && entry
< compat_sc_table
+ ARRAY_SIZE(compat_sc_table
))) {
1233 *table
= compat_sc_table
;
1238 int syscall_list_show(struct seq_file
*m
, void *p
)
1240 const struct trace_syscall_entry
*table
, *entry
= p
;
1241 unsigned int bitness
;
1242 unsigned long index
;
1246 ret
= get_sc_table(entry
, &table
, &bitness
);
1251 if (table
== sc_table
) {
1252 index
= entry
- table
;
1253 name
= &entry
->desc
->name
[strlen(SYSCALL_ENTRY_STR
)];
1255 index
= (entry
- table
) + ARRAY_SIZE(sc_table
);
1256 name
= &entry
->desc
->name
[strlen(COMPAT_SYSCALL_ENTRY_STR
)];
1258 seq_printf(m
, "syscall { index = %lu; name = %s; bitness = %u; };\n",
1259 index
, name
, bitness
);
1264 const struct seq_operations lttng_syscall_list_seq_ops
= {
1265 .start
= syscall_list_start
,
1266 .next
= syscall_list_next
,
1267 .stop
= syscall_list_stop
,
1268 .show
= syscall_list_show
,
1272 int lttng_syscall_list_open(struct inode
*inode
, struct file
*file
)
1274 return seq_open(file
, <tng_syscall_list_seq_ops
);
1277 const struct file_operations lttng_syscall_list_fops
= {
1278 .owner
= THIS_MODULE
,
1279 .open
= lttng_syscall_list_open
,
1281 .llseek
= seq_lseek
,
1282 .release
= seq_release
,
1286 * A syscall is enabled if it is traced for either entry or exit.
1288 long lttng_channel_syscall_mask(struct lttng_channel
*channel
,
1289 struct lttng_kernel_syscall_mask __user
*usyscall_mask
)
1291 uint32_t len
, sc_tables_len
, bitmask_len
;
1294 struct lttng_syscall_filter
*filter
;
1296 ret
= get_user(len
, &usyscall_mask
->len
);
1299 sc_tables_len
= get_sc_tables_len();
1300 bitmask_len
= ALIGN(sc_tables_len
, 8) >> 3;
1301 if (len
< sc_tables_len
) {
1302 return put_user(sc_tables_len
, &usyscall_mask
->len
);
1304 /* Array is large enough, we can copy array to user-space. */
1305 tmp_mask
= kzalloc(bitmask_len
, GFP_KERNEL
);
1308 filter
= channel
->sc_filter
;
1310 for (bit
= 0; bit
< ARRAY_SIZE(sc_table
); bit
++) {
1313 if (channel
->sc_table
) {
1314 if (!READ_ONCE(channel
->syscall_all
) && filter
)
1315 state
= test_bit(bit
, filter
->sc_entry
)
1316 || test_bit(bit
, filter
->sc_exit
);
1322 bt_bitfield_write_be(tmp_mask
, char, bit
, 1, state
);
1324 for (; bit
< sc_tables_len
; bit
++) {
1327 if (channel
->compat_sc_table
) {
1328 if (!READ_ONCE(channel
->syscall_all
) && filter
)
1329 state
= test_bit(bit
- ARRAY_SIZE(sc_table
),
1330 filter
->sc_compat_entry
)
1331 || test_bit(bit
- ARRAY_SIZE(sc_table
),
1332 filter
->sc_compat_exit
);
1338 bt_bitfield_write_be(tmp_mask
, char, bit
, 1, state
);
1340 if (copy_to_user(usyscall_mask
->mask
, tmp_mask
, bitmask_len
))
1346 int lttng_abi_syscall_list(void)
1348 struct file
*syscall_list_file
;
1351 file_fd
= lttng_get_unused_fd();
1357 syscall_list_file
= anon_inode_getfile("[lttng_syscall_list]",
1358 <tng_syscall_list_fops
,
1360 if (IS_ERR(syscall_list_file
)) {
1361 ret
= PTR_ERR(syscall_list_file
);
1364 ret
= lttng_syscall_list_fops
.open(NULL
, syscall_list_file
);
1367 fd_install(file_fd
, syscall_list_file
);
1371 fput(syscall_list_file
);
1373 put_unused_fd(file_fd
);