4 * LTTng syscall probes.
6 * Copyright (C) 2010-2012 Mathieu Desnoyers <mathieu.desnoyers@efficios.com>
8 * This library is free software; you can redistribute it and/or
9 * modify it under the terms of the GNU Lesser General Public
10 * License as published by the Free Software Foundation; only
11 * version 2.1 of the License.
13 * This library is distributed in the hope that it will be useful,
14 * but WITHOUT ANY WARRANTY; without even the implied warranty of
15 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
16 * Lesser General Public License for more details.
18 * You should have received a copy of the GNU Lesser General Public
19 * License along with this library; if not, write to the Free Software
20 * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
23 #include <linux/module.h>
24 #include <linux/slab.h>
25 #include <linux/compat.h>
26 #include <linux/err.h>
27 #include <linux/bitmap.h>
28 #include <asm/ptrace.h>
29 #include <asm/syscall.h>
31 #include "wrapper/tracepoint.h"
32 #include "lttng-events.h"
35 # ifndef is_compat_task
36 # define is_compat_task() (0)
47 #define SYSCALL_ENTRY_STR "syscall_entry_"
48 #define COMPAT_SYSCALL_ENTRY_STR "compat_syscall_entry_"
49 #define SYSCALL_EXIT_STR "syscall_exit_"
50 #define COMPAT_SYSCALL_EXIT_STR "compat_syscall_exit_"
53 void syscall_entry_probe(void *__data
, struct pt_regs
*regs
, long id
);
55 void syscall_exit_probe(void *__data
, struct pt_regs
*regs
, long ret
);
58 * Forward declarations for old kernels.
62 struct oldold_utsname
;
64 struct sel_arg_struct
;
65 struct mmap_arg_struct
;
67 #ifdef IA32_NR_syscalls
68 #define NR_compat_syscalls IA32_NR_syscalls
70 #define NR_compat_syscalls NR_syscalls
74 * Take care of NOARGS not supported by mainline.
76 #define DECLARE_EVENT_CLASS_NOARGS(name, tstruct, assign, print)
77 #define DEFINE_EVENT_NOARGS(template, name)
78 #define TRACE_EVENT_NOARGS(name, struct, assign, print)
81 * Create LTTng tracepoint probes.
83 #define LTTNG_PACKAGE_BUILD
84 #define CREATE_TRACE_POINTS
85 #define TP_MODULE_NOINIT
86 #define TRACE_INCLUDE_PATH ../instrumentation/syscalls/headers
88 #define PARAMS(args...) args
90 /* Handle unknown syscalls */
91 #define TRACE_SYSTEM syscalls_unknown
92 #include "instrumentation/syscalls/headers/syscalls_unknown.h"
98 #define SC_EXIT_PROTO(...)
100 #define SC_EXIT_ARGS(...)
104 /* Hijack probe callback for system call enter */
106 #define TP_PROBE_CB(_template) &syscall_entry_probe
107 #define SC_TRACE_EVENT(_name, _proto, _args, _struct, _assign, _printk) \
108 TRACE_EVENT(syscall_enter_##_name, PARAMS(_proto), PARAMS(_args),\
109 PARAMS(_struct), PARAMS(_assign), PARAMS(_printk))
110 #define SC_DECLARE_EVENT_CLASS_NOARGS(_name, _struct, _assign, _printk) \
111 DECLARE_EVENT_CLASS_NOARGS(syscall_enter_##_name, PARAMS(_struct), PARAMS(_assign),\
113 #define SC_DEFINE_EVENT_NOARGS(_template, _name) \
114 DEFINE_EVENT_NOARGS(syscall_enter_##_template, syscall_enter_##_name)
116 #define TRACE_SYSTEM syscall_enter_integers
117 #define TRACE_INCLUDE_FILE syscalls_integers
118 #include "instrumentation/syscalls/headers/syscalls_integers.h"
119 #undef TRACE_INCLUDE_FILE
121 #define TRACE_SYSTEM syscall_enter_pointers
122 #define TRACE_INCLUDE_FILE syscalls_pointers
123 #include "instrumentation/syscalls/headers/syscalls_pointers.h"
124 #undef TRACE_INCLUDE_FILE
126 #undef SC_TRACE_EVENT
127 #undef SC_DECLARE_EVENT_CLASS_NOARGS
128 #undef SC_DEFINE_EVENT_NOARGS
130 #undef _TRACE_SYSCALLS_integers_H
131 #undef _TRACE_SYSCALLS_pointers_H
134 /* Hijack probe callback for compat system call enter */
135 #define TP_PROBE_CB(_template) &syscall_entry_probe
136 #define SC_TRACE_EVENT(_name, _proto, _args, _struct, _assign, _printk) \
137 TRACE_EVENT(compat_syscall_enter_##_name, PARAMS(_proto), PARAMS(_args), \
138 PARAMS(_struct), PARAMS(_assign), \
140 #define SC_DECLARE_EVENT_CLASS_NOARGS(_name, _struct, _assign, _printk) \
141 DECLARE_EVENT_CLASS_NOARGS(compat_syscall_enter_##_name, PARAMS(_struct), \
142 PARAMS(_assign), PARAMS(_printk))
143 #define SC_DEFINE_EVENT_NOARGS(_template, _name) \
144 DEFINE_EVENT_NOARGS(compat_syscall_enter_##_template, \
145 compat_syscall_enter_##_name)
146 #define TRACE_SYSTEM compat_syscall_enter_integers
147 #define TRACE_INCLUDE_FILE compat_syscalls_integers
148 #include "instrumentation/syscalls/headers/compat_syscalls_integers.h"
149 #undef TRACE_INCLUDE_FILE
151 #define TRACE_SYSTEM compat_syscall_enter_pointers
152 #define TRACE_INCLUDE_FILE compat_syscalls_pointers
153 #include "instrumentation/syscalls/headers/compat_syscalls_pointers.h"
154 #undef TRACE_INCLUDE_FILE
156 #undef SC_TRACE_EVENT
157 #undef SC_DECLARE_EVENT_CLASS_NOARGS
158 #undef SC_DEFINE_EVENT_NOARGS
160 #undef _TRACE_SYSCALLS_integers_H
161 #undef _TRACE_SYSCALLS_pointers_H
168 #define SC_EXIT_PROTO(...) __VA_ARGS__
170 #define SC_EXIT_ARGS(...) __VA_ARGS__
172 #define sc_exit(...) __VA_ARGS__
174 /* Hijack probe callback for system call exit */
175 #define TP_PROBE_CB(_template) &syscall_exit_probe
176 #define SC_TRACE_EVENT(_name, _proto, _args, _struct, _assign, _printk) \
177 TRACE_EVENT(syscall_exit_##_name, PARAMS(_proto), PARAMS(_args),\
178 PARAMS(_struct), PARAMS(_assign), PARAMS(_printk))
179 #define SC_DECLARE_EVENT_CLASS_NOARGS(_name, _struct, _assign, _printk) \
180 DECLARE_EVENT_CLASS_NOARGS(syscall_exit_##_name, PARAMS(_struct), \
181 PARAMS(_assign), PARAMS(_printk))
182 #define SC_DEFINE_EVENT_NOARGS(_template, _name) \
183 DEFINE_EVENT_NOARGS(syscall_exit_##_template, \
184 syscall_exit_##_name)
185 #define TRACE_SYSTEM syscall_exit_integers
186 #define TRACE_INCLUDE_FILE syscalls_integers
187 #include "instrumentation/syscalls/headers/syscalls_integers.h"
188 #undef TRACE_INCLUDE_FILE
190 #define TRACE_SYSTEM syscall_exit_pointers
191 #define TRACE_INCLUDE_FILE syscalls_pointers
192 #include "instrumentation/syscalls/headers/syscalls_pointers.h"
193 #undef TRACE_INCLUDE_FILE
195 #undef SC_TRACE_EVENT
196 #undef SC_DECLARE_EVENT_CLASS_NOARGS
197 #undef SC_DEFINE_EVENT_NOARGS
199 #undef _TRACE_SYSCALLS_integers_H
200 #undef _TRACE_SYSCALLS_pointers_H
203 /* Hijack probe callback for compat system call exit */
204 #define TP_PROBE_CB(_template) &syscall_exit_probe
205 #define SC_TRACE_EVENT(_name, _proto, _args, _struct, _assign, _printk) \
206 TRACE_EVENT(compat_syscall_exit_##_name, PARAMS(_proto), PARAMS(_args), \
207 PARAMS(_struct), PARAMS(_assign), PARAMS(_printk))
208 #define SC_DECLARE_EVENT_CLASS_NOARGS(_name, _struct, _assign, _printk) \
209 DECLARE_EVENT_CLASS_NOARGS(compat_syscall_exit_##_name, PARAMS(_struct), \
210 PARAMS(_assign), PARAMS(_printk))
211 #define SC_DEFINE_EVENT_NOARGS(_template, _name) \
212 DEFINE_EVENT_NOARGS(compat_syscall_exit_##_template, \
213 compat_syscall_exit_##_name)
214 #define TRACE_SYSTEM compat_syscall_exit_integers
215 #define TRACE_INCLUDE_FILE compat_syscalls_integers
216 #include "instrumentation/syscalls/headers/compat_syscalls_integers.h"
217 #undef TRACE_INCLUDE_FILE
219 #define TRACE_SYSTEM compat_syscall_exit_pointers
220 #define TRACE_INCLUDE_FILE compat_syscalls_pointers
221 #include "instrumentation/syscalls/headers/compat_syscalls_pointers.h"
222 #undef TRACE_INCLUDE_FILE
224 #undef SC_TRACE_EVENT
225 #undef SC_DECLARE_EVENT_CLASS_NOARGS
226 #undef SC_DEFINE_EVENT_NOARGS
228 #undef _TRACE_SYSCALLS_integers_H
229 #undef _TRACE_SYSCALLS_pointers_H
233 #undef TP_MODULE_NOINIT
234 #undef LTTNG_PACKAGE_BUILD
235 #undef CREATE_TRACE_POINTS
237 struct trace_syscall_entry
{
239 const struct lttng_event_desc
*desc
;
240 const struct lttng_event_field
*fields
;
244 #define CREATE_SYSCALL_TABLE
251 #undef TRACE_SYSCALL_TABLE
252 #define TRACE_SYSCALL_TABLE(_template, _name, _nr, _nrargs) \
254 .func = __event_probe__syscall_enter_##_template, \
255 .nrargs = (_nrargs), \
256 .fields = __event_fields___syscall_enter_##_template, \
257 .desc = &__event_desc___syscall_enter_##_name, \
260 /* Syscall enter tracing table */
261 static const struct trace_syscall_entry sc_table
[] = {
262 #include "instrumentation/syscalls/headers/syscalls_integers.h"
263 #include "instrumentation/syscalls/headers/syscalls_pointers.h"
266 #undef TRACE_SYSCALL_TABLE
267 #define TRACE_SYSCALL_TABLE(_template, _name, _nr, _nrargs) \
269 .func = __event_probe__compat_syscall_enter_##_template, \
270 .nrargs = (_nrargs), \
271 .fields = __event_fields___compat_syscall_enter_##_template, \
272 .desc = &__event_desc___compat_syscall_enter_##_name, \
275 /* Compat syscall enter table */
276 const struct trace_syscall_entry compat_sc_table
[] = {
277 #include "instrumentation/syscalls/headers/compat_syscalls_integers.h"
278 #include "instrumentation/syscalls/headers/compat_syscalls_pointers.h"
286 #define sc_exit(...) __VA_ARGS__
288 #undef TRACE_SYSCALL_TABLE
289 #define TRACE_SYSCALL_TABLE(_template, _name, _nr, _nrargs) \
291 .func = __event_probe__syscall_exit_##_template, \
292 .nrargs = (_nrargs), \
293 .fields = __event_fields___syscall_exit_##_template, \
294 .desc = &__event_desc___syscall_exit_##_name, \
297 /* Syscall exit table */
298 static const struct trace_syscall_entry sc_exit_table
[] = {
299 #include "instrumentation/syscalls/headers/syscalls_integers.h"
300 #include "instrumentation/syscalls/headers/syscalls_pointers.h"
303 #undef TRACE_SYSCALL_TABLE
304 #define TRACE_SYSCALL_TABLE(_template, _name, _nr, _nrargs) \
306 .func = __event_probe__compat_syscall_exit_##_template, \
307 .nrargs = (_nrargs), \
308 .fields = __event_fields___compat_syscall_exit_##_template, \
309 .desc = &__event_desc___compat_syscall_exit_##_name, \
312 /* Compat syscall exit table */
313 const struct trace_syscall_entry compat_sc_exit_table
[] = {
314 #include "instrumentation/syscalls/headers/compat_syscalls_integers.h"
315 #include "instrumentation/syscalls/headers/compat_syscalls_pointers.h"
320 #undef CREATE_SYSCALL_TABLE
322 struct lttng_syscall_filter
{
323 DECLARE_BITMAP(sc
, NR_syscalls
);
324 DECLARE_BITMAP(sc_compat
, NR_compat_syscalls
);
327 static void syscall_entry_unknown(struct lttng_event
*event
,
328 struct pt_regs
*regs
, unsigned int id
)
330 unsigned long args
[UNKNOWN_SYSCALL_NRARGS
];
332 syscall_get_arguments(current
, regs
, 0, UNKNOWN_SYSCALL_NRARGS
, args
);
333 if (unlikely(is_compat_task()))
334 __event_probe__compat_syscall_enter_unknown(event
, id
, args
);
336 __event_probe__syscall_enter_unknown(event
, id
, args
);
339 void syscall_entry_probe(void *__data
, struct pt_regs
*regs
, long id
)
341 struct lttng_channel
*chan
= __data
;
342 struct lttng_event
*event
, *unknown_event
;
343 const struct trace_syscall_entry
*table
, *entry
;
346 if (unlikely(is_compat_task())) {
347 struct lttng_syscall_filter
*filter
;
349 filter
= rcu_dereference(chan
->sc_filter
);
351 if (id
>= NR_compat_syscalls
352 || !test_bit(id
, filter
->sc_compat
)) {
353 /* System call filtered out. */
357 table
= compat_sc_table
;
358 table_len
= ARRAY_SIZE(compat_sc_table
);
359 unknown_event
= chan
->sc_compat_unknown
;
361 struct lttng_syscall_filter
*filter
;
363 filter
= rcu_dereference(chan
->sc_filter
);
365 if (id
>= NR_syscalls
366 || !test_bit(id
, filter
->sc
)) {
367 /* System call filtered out. */
372 table_len
= ARRAY_SIZE(sc_table
);
373 unknown_event
= chan
->sc_unknown
;
375 if (unlikely(id
>= table_len
)) {
376 syscall_entry_unknown(unknown_event
, regs
, id
);
379 if (unlikely(is_compat_task()))
380 event
= chan
->compat_sc_table
[id
];
382 event
= chan
->sc_table
[id
];
383 if (unlikely(!event
)) {
384 syscall_entry_unknown(unknown_event
, regs
, id
);
388 WARN_ON_ONCE(!entry
);
390 switch (entry
->nrargs
) {
393 void (*fptr
)(void *__data
) = entry
->func
;
400 void (*fptr
)(void *__data
, unsigned long arg0
) = entry
->func
;
401 unsigned long args
[1];
403 syscall_get_arguments(current
, regs
, 0, entry
->nrargs
, args
);
404 fptr(event
, args
[0]);
409 void (*fptr
)(void *__data
,
411 unsigned long arg1
) = entry
->func
;
412 unsigned long args
[2];
414 syscall_get_arguments(current
, regs
, 0, entry
->nrargs
, args
);
415 fptr(event
, args
[0], args
[1]);
420 void (*fptr
)(void *__data
,
423 unsigned long arg2
) = entry
->func
;
424 unsigned long args
[3];
426 syscall_get_arguments(current
, regs
, 0, entry
->nrargs
, args
);
427 fptr(event
, args
[0], args
[1], args
[2]);
432 void (*fptr
)(void *__data
,
436 unsigned long arg3
) = entry
->func
;
437 unsigned long args
[4];
439 syscall_get_arguments(current
, regs
, 0, entry
->nrargs
, args
);
440 fptr(event
, args
[0], args
[1], args
[2], args
[3]);
445 void (*fptr
)(void *__data
,
450 unsigned long arg4
) = entry
->func
;
451 unsigned long args
[5];
453 syscall_get_arguments(current
, regs
, 0, entry
->nrargs
, args
);
454 fptr(event
, args
[0], args
[1], args
[2], args
[3], args
[4]);
459 void (*fptr
)(void *__data
,
465 unsigned long arg5
) = entry
->func
;
466 unsigned long args
[6];
468 syscall_get_arguments(current
, regs
, 0, entry
->nrargs
, args
);
469 fptr(event
, args
[0], args
[1], args
[2],
470 args
[3], args
[4], args
[5]);
478 static void syscall_exit_unknown(struct lttng_event
*event
,
479 struct pt_regs
*regs
, unsigned int id
, long ret
)
481 unsigned long args
[UNKNOWN_SYSCALL_NRARGS
];
483 syscall_get_arguments(current
, regs
, 0, UNKNOWN_SYSCALL_NRARGS
, args
);
484 if (unlikely(is_compat_task()))
485 __event_probe__compat_syscall_exit_unknown(event
, id
, ret
,
488 __event_probe__syscall_exit_unknown(event
, id
, ret
, args
);
491 void syscall_exit_probe(void *__data
, struct pt_regs
*regs
, long ret
)
493 struct lttng_channel
*chan
= __data
;
494 struct lttng_event
*event
, *unknown_event
;
495 const struct trace_syscall_entry
*table
, *entry
;
499 id
= syscall_get_nr(current
, regs
);
500 if (unlikely(is_compat_task())) {
501 struct lttng_syscall_filter
*filter
;
503 filter
= rcu_dereference(chan
->sc_filter
);
505 if (id
>= NR_compat_syscalls
506 || !test_bit(id
, filter
->sc_compat
)) {
507 /* System call filtered out. */
511 table
= compat_sc_exit_table
;
512 table_len
= ARRAY_SIZE(compat_sc_exit_table
);
513 unknown_event
= chan
->compat_sc_exit_unknown
;
515 struct lttng_syscall_filter
*filter
;
517 filter
= rcu_dereference(chan
->sc_filter
);
519 if (id
>= NR_syscalls
520 || !test_bit(id
, filter
->sc
)) {
521 /* System call filtered out. */
525 table
= sc_exit_table
;
526 table_len
= ARRAY_SIZE(sc_exit_table
);
527 unknown_event
= chan
->sc_exit_unknown
;
529 if (unlikely(id
>= table_len
)) {
530 syscall_exit_unknown(unknown_event
, regs
, id
, ret
);
533 if (unlikely(is_compat_task()))
534 event
= chan
->compat_sc_exit_table
[id
];
536 event
= chan
->sc_exit_table
[id
];
537 if (unlikely(!event
)) {
538 syscall_exit_unknown(unknown_event
, regs
, id
, ret
);
542 WARN_ON_ONCE(!entry
);
544 switch (entry
->nrargs
) {
547 void (*fptr
)(void *__data
, long ret
) = entry
->func
;
554 void (*fptr
)(void *__data
,
556 unsigned long arg0
) = entry
->func
;
557 unsigned long args
[1];
559 syscall_get_arguments(current
, regs
, 0, entry
->nrargs
, args
);
560 fptr(event
, ret
, args
[0]);
565 void (*fptr
)(void *__data
,
568 unsigned long arg1
) = entry
->func
;
569 unsigned long args
[2];
571 syscall_get_arguments(current
, regs
, 0, entry
->nrargs
, args
);
572 fptr(event
, ret
, args
[0], args
[1]);
577 void (*fptr
)(void *__data
,
581 unsigned long arg2
) = entry
->func
;
582 unsigned long args
[3];
584 syscall_get_arguments(current
, regs
, 0, entry
->nrargs
, args
);
585 fptr(event
, ret
, args
[0], args
[1], args
[2]);
590 void (*fptr
)(void *__data
,
595 unsigned long arg3
) = entry
->func
;
596 unsigned long args
[4];
598 syscall_get_arguments(current
, regs
, 0, entry
->nrargs
, args
);
599 fptr(event
, ret
, args
[0], args
[1], args
[2], args
[3]);
604 void (*fptr
)(void *__data
,
610 unsigned long arg4
) = entry
->func
;
611 unsigned long args
[5];
613 syscall_get_arguments(current
, regs
, 0, entry
->nrargs
, args
);
614 fptr(event
, ret
, args
[0], args
[1], args
[2], args
[3], args
[4]);
619 void (*fptr
)(void *__data
,
626 unsigned long arg5
) = entry
->func
;
627 unsigned long args
[6];
629 syscall_get_arguments(current
, regs
, 0, entry
->nrargs
, args
);
630 fptr(event
, ret
, args
[0], args
[1], args
[2],
631 args
[3], args
[4], args
[5]);
639 /* noinline to diminish caller stack size */
641 int fill_table(const struct trace_syscall_entry
*table
, size_t table_len
,
642 struct lttng_event
**chan_table
, struct lttng_channel
*chan
,
643 void *filter
, enum sc_type type
)
645 const struct lttng_event_desc
*desc
;
648 /* Allocate events for each syscall, insert into table */
649 for (i
= 0; i
< table_len
; i
++) {
650 struct lttng_kernel_event ev
;
651 desc
= table
[i
].desc
;
654 /* Unknown syscall */
658 * Skip those already populated by previous failed
659 * register for this channel.
663 memset(&ev
, 0, sizeof(ev
));
666 strncpy(ev
.name
, SYSCALL_ENTRY_STR
,
667 LTTNG_KERNEL_SYM_NAME_LEN
);
670 strncpy(ev
.name
, SYSCALL_EXIT_STR
,
671 LTTNG_KERNEL_SYM_NAME_LEN
);
673 case SC_TYPE_COMPAT_ENTRY
:
674 strncpy(ev
.name
, COMPAT_SYSCALL_ENTRY_STR
,
675 LTTNG_KERNEL_SYM_NAME_LEN
);
677 case SC_TYPE_COMPAT_EXIT
:
678 strncpy(ev
.name
, COMPAT_SYSCALL_EXIT_STR
,
679 LTTNG_KERNEL_SYM_NAME_LEN
);
685 strncat(ev
.name
, desc
->name
,
686 LTTNG_KERNEL_SYM_NAME_LEN
- strlen(ev
.name
) - 1);
687 ev
.name
[LTTNG_KERNEL_SYM_NAME_LEN
- 1] = '\0';
688 ev
.instrumentation
= LTTNG_KERNEL_NOOP
;
689 chan_table
[i
] = lttng_event_create(chan
, &ev
, filter
,
691 WARN_ON_ONCE(!chan_table
[i
]);
692 if (IS_ERR(chan_table
[i
])) {
694 * If something goes wrong in event registration
695 * after the first one, we have no choice but to
696 * leave the previous events in there, until
697 * deleted by session teardown.
699 return PTR_ERR(chan_table
[i
]);
705 int lttng_syscalls_register(struct lttng_channel
*chan
, void *filter
)
707 struct lttng_kernel_event ev
;
710 wrapper_vmalloc_sync_all();
712 if (!chan
->sc_table
) {
713 /* create syscall table mapping syscall to events */
714 chan
->sc_table
= kzalloc(sizeof(struct lttng_event
*)
715 * ARRAY_SIZE(sc_table
), GFP_KERNEL
);
719 if (!chan
->sc_exit_table
) {
720 /* create syscall table mapping syscall to events */
721 chan
->sc_exit_table
= kzalloc(sizeof(struct lttng_event
*)
722 * ARRAY_SIZE(sc_exit_table
), GFP_KERNEL
);
723 if (!chan
->sc_exit_table
)
729 if (!chan
->compat_sc_table
) {
730 /* create syscall table mapping compat syscall to events */
731 chan
->compat_sc_table
= kzalloc(sizeof(struct lttng_event
*)
732 * ARRAY_SIZE(compat_sc_table
), GFP_KERNEL
);
733 if (!chan
->compat_sc_table
)
737 if (!chan
->compat_sc_exit_table
) {
738 /* create syscall table mapping compat syscall to events */
739 chan
->compat_sc_exit_table
= kzalloc(sizeof(struct lttng_event
*)
740 * ARRAY_SIZE(compat_sc_exit_table
), GFP_KERNEL
);
741 if (!chan
->compat_sc_exit_table
)
745 if (!chan
->sc_unknown
) {
746 const struct lttng_event_desc
*desc
=
747 &__event_desc___syscall_enter_unknown
;
749 memset(&ev
, 0, sizeof(ev
));
750 strncpy(ev
.name
, desc
->name
, LTTNG_KERNEL_SYM_NAME_LEN
);
751 ev
.name
[LTTNG_KERNEL_SYM_NAME_LEN
- 1] = '\0';
752 ev
.instrumentation
= LTTNG_KERNEL_NOOP
;
753 chan
->sc_unknown
= lttng_event_create(chan
, &ev
, filter
,
755 WARN_ON_ONCE(!chan
->sc_unknown
);
756 if (IS_ERR(chan
->sc_unknown
)) {
757 return PTR_ERR(chan
->sc_unknown
);
761 if (!chan
->sc_compat_unknown
) {
762 const struct lttng_event_desc
*desc
=
763 &__event_desc___compat_syscall_enter_unknown
;
765 memset(&ev
, 0, sizeof(ev
));
766 strncpy(ev
.name
, desc
->name
, LTTNG_KERNEL_SYM_NAME_LEN
);
767 ev
.name
[LTTNG_KERNEL_SYM_NAME_LEN
- 1] = '\0';
768 ev
.instrumentation
= LTTNG_KERNEL_NOOP
;
769 chan
->sc_compat_unknown
= lttng_event_create(chan
, &ev
, filter
,
771 WARN_ON_ONCE(!chan
->sc_unknown
);
772 if (IS_ERR(chan
->sc_compat_unknown
)) {
773 return PTR_ERR(chan
->sc_compat_unknown
);
777 if (!chan
->compat_sc_exit_unknown
) {
778 const struct lttng_event_desc
*desc
=
779 &__event_desc___compat_syscall_exit_unknown
;
781 memset(&ev
, 0, sizeof(ev
));
782 strncpy(ev
.name
, desc
->name
, LTTNG_KERNEL_SYM_NAME_LEN
);
783 ev
.name
[LTTNG_KERNEL_SYM_NAME_LEN
- 1] = '\0';
784 ev
.instrumentation
= LTTNG_KERNEL_NOOP
;
785 chan
->compat_sc_exit_unknown
= lttng_event_create(chan
, &ev
,
787 WARN_ON_ONCE(!chan
->compat_sc_exit_unknown
);
788 if (IS_ERR(chan
->compat_sc_exit_unknown
)) {
789 return PTR_ERR(chan
->compat_sc_exit_unknown
);
793 if (!chan
->sc_exit_unknown
) {
794 const struct lttng_event_desc
*desc
=
795 &__event_desc___syscall_exit_unknown
;
797 memset(&ev
, 0, sizeof(ev
));
798 strncpy(ev
.name
, desc
->name
, LTTNG_KERNEL_SYM_NAME_LEN
);
799 ev
.name
[LTTNG_KERNEL_SYM_NAME_LEN
- 1] = '\0';
800 ev
.instrumentation
= LTTNG_KERNEL_NOOP
;
801 chan
->sc_exit_unknown
= lttng_event_create(chan
, &ev
, filter
,
803 WARN_ON_ONCE(!chan
->sc_exit_unknown
);
804 if (IS_ERR(chan
->sc_exit_unknown
)) {
805 return PTR_ERR(chan
->sc_exit_unknown
);
809 ret
= fill_table(sc_table
, ARRAY_SIZE(sc_table
),
810 chan
->sc_table
, chan
, filter
, SC_TYPE_ENTRY
);
813 ret
= fill_table(sc_exit_table
, ARRAY_SIZE(sc_exit_table
),
814 chan
->sc_exit_table
, chan
, filter
, SC_TYPE_EXIT
);
819 ret
= fill_table(compat_sc_table
, ARRAY_SIZE(compat_sc_table
),
820 chan
->compat_sc_table
, chan
, filter
,
821 SC_TYPE_COMPAT_ENTRY
);
824 ret
= fill_table(compat_sc_exit_table
, ARRAY_SIZE(compat_sc_exit_table
),
825 chan
->compat_sc_exit_table
, chan
, filter
,
826 SC_TYPE_COMPAT_EXIT
);
830 if (!chan
->sys_enter_registered
) {
831 ret
= lttng_wrapper_tracepoint_probe_register("sys_enter",
832 (void *) syscall_entry_probe
, chan
);
835 chan
->sys_enter_registered
= 1;
838 * We change the name of sys_exit tracepoint due to namespace
839 * conflict with sys_exit syscall entry.
841 if (!chan
->sys_exit_registered
) {
842 ret
= lttng_wrapper_tracepoint_probe_register("sys_exit",
843 (void *) syscall_exit_probe
, chan
);
845 WARN_ON_ONCE(lttng_wrapper_tracepoint_probe_unregister("sys_enter",
846 (void *) syscall_entry_probe
, chan
));
849 chan
->sys_exit_registered
= 1;
855 * Only called at session destruction.
857 int lttng_syscalls_unregister(struct lttng_channel
*chan
)
863 if (chan
->sys_enter_registered
) {
864 ret
= lttng_wrapper_tracepoint_probe_unregister("sys_exit",
865 (void *) syscall_exit_probe
, chan
);
868 chan
->sys_enter_registered
= 0;
870 if (chan
->sys_exit_registered
) {
871 ret
= lttng_wrapper_tracepoint_probe_unregister("sys_enter",
872 (void *) syscall_entry_probe
, chan
);
875 chan
->sys_exit_registered
= 0;
877 /* lttng_event destroy will be performed by lttng_session_destroy() */
878 kfree(chan
->sc_table
);
879 kfree(chan
->sc_exit_table
);
881 kfree(chan
->compat_sc_table
);
882 kfree(chan
->compat_sc_exit_table
);
884 kfree(chan
->sc_filter
);
889 int get_syscall_nr(const char *syscall_name
)
894 for (i
= 0; i
< ARRAY_SIZE(sc_table
); i
++) {
895 const struct trace_syscall_entry
*entry
;
898 entry
= &sc_table
[i
];
901 it_name
= entry
->desc
->name
;
902 it_name
+= strlen(SYSCALL_ENTRY_STR
);
903 if (!strcmp(syscall_name
, it_name
)) {
912 int get_compat_syscall_nr(const char *syscall_name
)
917 for (i
= 0; i
< ARRAY_SIZE(compat_sc_table
); i
++) {
918 const struct trace_syscall_entry
*entry
;
921 entry
= &compat_sc_table
[i
];
924 it_name
= entry
->desc
->name
;
925 it_name
+= strlen(COMPAT_SYSCALL_ENTRY_STR
);
926 if (!strcmp(syscall_name
, it_name
)) {
934 int lttng_syscall_filter_enable(struct lttng_channel
*chan
,
937 int syscall_nr
, compat_syscall_nr
, ret
;
938 struct lttng_syscall_filter
*filter
;
940 WARN_ON_ONCE(!chan
->sc_table
);
943 /* Enable all system calls by removing filter */
944 if (chan
->sc_filter
) {
945 filter
= chan
->sc_filter
;
946 rcu_assign_pointer(chan
->sc_filter
, NULL
);
950 chan
->syscall_all
= 1;
954 if (!chan
->sc_filter
) {
955 if (chan
->syscall_all
) {
957 * All syscalls are already enabled.
961 filter
= kzalloc(sizeof(struct lttng_syscall_filter
),
966 filter
= chan
->sc_filter
;
968 syscall_nr
= get_syscall_nr(name
);
969 compat_syscall_nr
= get_compat_syscall_nr(name
);
970 if (syscall_nr
< 0 && compat_syscall_nr
< 0) {
974 if (syscall_nr
>= 0) {
975 if (test_bit(syscall_nr
, filter
->sc
)) {
979 bitmap_set(filter
->sc
, syscall_nr
, 1);
981 if (compat_syscall_nr
>= 0) {
982 if (test_bit(compat_syscall_nr
, filter
->sc_compat
)) {
986 bitmap_set(filter
->sc_compat
, compat_syscall_nr
, 1);
988 if (!chan
->sc_filter
)
989 rcu_assign_pointer(chan
->sc_filter
, filter
);
993 if (!chan
->sc_filter
)
998 int lttng_syscall_filter_disable(struct lttng_channel
*chan
,
1001 int syscall_nr
, compat_syscall_nr
, ret
;
1002 struct lttng_syscall_filter
*filter
;
1004 WARN_ON_ONCE(!chan
->sc_table
);
1006 if (!chan
->sc_filter
) {
1007 filter
= kzalloc(sizeof(struct lttng_syscall_filter
),
1011 /* Trace all system calls, then apply disable. */
1012 bitmap_set(filter
->sc
, 0, NR_syscalls
);
1013 bitmap_set(filter
->sc_compat
, 0, NR_compat_syscalls
);
1015 filter
= chan
->sc_filter
;
1018 syscall_nr
= get_syscall_nr(name
);
1019 compat_syscall_nr
= get_compat_syscall_nr(name
);
1020 if (syscall_nr
< 0 && compat_syscall_nr
< 0) {
1024 if (syscall_nr
>= 0) {
1025 if (!test_bit(syscall_nr
, chan
->sc_filter
->sc
)) {
1029 bitmap_clear(chan
->sc_filter
->sc
, syscall_nr
, 1);
1031 if (compat_syscall_nr
>= 0) {
1032 if (!test_bit(compat_syscall_nr
, chan
->sc_filter
->sc_compat
)) {
1036 bitmap_clear(chan
->sc_filter
->sc_compat
, compat_syscall_nr
, 1);
1038 if (!chan
->sc_filter
)
1039 rcu_assign_pointer(chan
->sc_filter
, filter
);
1040 chan
->syscall_all
= 0;
1044 if (!chan
->sc_filter
)