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"
100 #define sc_in(...) __VA_ARGS__
104 #define sc_inout(...) __VA_ARGS__
106 /* Hijack probe callback for system call enter */
108 #define TP_PROBE_CB(_template) &syscall_entry_probe
109 #define SC_TRACE_EVENT(_name, _proto, _args, _struct, _assign, _printk) \
110 TRACE_EVENT(syscall_enter_##_name, PARAMS(_proto), PARAMS(_args),\
111 PARAMS(_struct), PARAMS(_assign), PARAMS(_printk))
112 #define SC_DECLARE_EVENT_CLASS_NOARGS(_name, _struct, _assign, _printk) \
113 DECLARE_EVENT_CLASS_NOARGS(syscall_enter_##_name, PARAMS(_struct), PARAMS(_assign),\
115 #define SC_DEFINE_EVENT_NOARGS(_template, _name) \
116 DEFINE_EVENT_NOARGS(syscall_enter_##_template, syscall_enter_##_name)
118 #define TRACE_SYSTEM syscall_enter_integers
119 #define TRACE_INCLUDE_FILE syscalls_integers
120 #include "instrumentation/syscalls/headers/syscalls_integers.h"
121 #undef TRACE_INCLUDE_FILE
123 #define TRACE_SYSTEM syscall_enter_pointers
124 #define TRACE_INCLUDE_FILE syscalls_pointers
125 #include "instrumentation/syscalls/headers/syscalls_pointers.h"
126 #undef TRACE_INCLUDE_FILE
128 #undef SC_TRACE_EVENT
129 #undef SC_DECLARE_EVENT_CLASS_NOARGS
130 #undef SC_DEFINE_EVENT_NOARGS
132 #undef _TRACE_SYSCALLS_integers_H
133 #undef _TRACE_SYSCALLS_pointers_H
136 /* Hijack probe callback for compat system call enter */
137 #define TP_PROBE_CB(_template) &syscall_entry_probe
138 #define SC_TRACE_EVENT(_name, _proto, _args, _struct, _assign, _printk) \
139 TRACE_EVENT(compat_syscall_enter_##_name, PARAMS(_proto), PARAMS(_args), \
140 PARAMS(_struct), PARAMS(_assign), \
142 #define SC_DECLARE_EVENT_CLASS_NOARGS(_name, _struct, _assign, _printk) \
143 DECLARE_EVENT_CLASS_NOARGS(compat_syscall_enter_##_name, PARAMS(_struct), \
144 PARAMS(_assign), PARAMS(_printk))
145 #define SC_DEFINE_EVENT_NOARGS(_template, _name) \
146 DEFINE_EVENT_NOARGS(compat_syscall_enter_##_template, \
147 compat_syscall_enter_##_name)
148 #define TRACE_SYSTEM compat_syscall_enter_integers
149 #define TRACE_INCLUDE_FILE compat_syscalls_integers
150 #include "instrumentation/syscalls/headers/compat_syscalls_integers.h"
151 #undef TRACE_INCLUDE_FILE
153 #define TRACE_SYSTEM compat_syscall_enter_pointers
154 #define TRACE_INCLUDE_FILE compat_syscalls_pointers
155 #include "instrumentation/syscalls/headers/compat_syscalls_pointers.h"
156 #undef TRACE_INCLUDE_FILE
158 #undef SC_TRACE_EVENT
159 #undef SC_DECLARE_EVENT_CLASS_NOARGS
160 #undef SC_DEFINE_EVENT_NOARGS
162 #undef _TRACE_SYSCALLS_integers_H
163 #undef _TRACE_SYSCALLS_pointers_H
170 #define sc_exit(...) __VA_ARGS__
174 #define sc_out(...) __VA_ARGS__
176 #define sc_inout(...) __VA_ARGS__
178 /* Hijack probe callback for system call exit */
179 #define TP_PROBE_CB(_template) &syscall_exit_probe
180 #define SC_TRACE_EVENT(_name, _proto, _args, _struct, _assign, _printk) \
181 TRACE_EVENT(syscall_exit_##_name, PARAMS(_proto), PARAMS(_args),\
182 PARAMS(_struct), PARAMS(_assign), PARAMS(_printk))
183 #define SC_DECLARE_EVENT_CLASS_NOARGS(_name, _struct, _assign, _printk) \
184 DECLARE_EVENT_CLASS_NOARGS(syscall_exit_##_name, PARAMS(_struct), \
185 PARAMS(_assign), PARAMS(_printk))
186 #define SC_DEFINE_EVENT_NOARGS(_template, _name) \
187 DEFINE_EVENT_NOARGS(syscall_exit_##_template, \
188 syscall_exit_##_name)
189 #define TRACE_SYSTEM syscall_exit_integers
190 #define TRACE_INCLUDE_FILE syscalls_integers
191 #include "instrumentation/syscalls/headers/syscalls_integers.h"
192 #undef TRACE_INCLUDE_FILE
194 #define TRACE_SYSTEM syscall_exit_pointers
195 #define TRACE_INCLUDE_FILE syscalls_pointers
196 #include "instrumentation/syscalls/headers/syscalls_pointers.h"
197 #undef TRACE_INCLUDE_FILE
199 #undef SC_TRACE_EVENT
200 #undef SC_DECLARE_EVENT_CLASS_NOARGS
201 #undef SC_DEFINE_EVENT_NOARGS
203 #undef _TRACE_SYSCALLS_integers_H
204 #undef _TRACE_SYSCALLS_pointers_H
207 /* Hijack probe callback for compat system call exit */
208 #define TP_PROBE_CB(_template) &syscall_exit_probe
209 #define SC_TRACE_EVENT(_name, _proto, _args, _struct, _assign, _printk) \
210 TRACE_EVENT(compat_syscall_exit_##_name, PARAMS(_proto), PARAMS(_args), \
211 PARAMS(_struct), PARAMS(_assign), PARAMS(_printk))
212 #define SC_DECLARE_EVENT_CLASS_NOARGS(_name, _struct, _assign, _printk) \
213 DECLARE_EVENT_CLASS_NOARGS(compat_syscall_exit_##_name, PARAMS(_struct), \
214 PARAMS(_assign), PARAMS(_printk))
215 #define SC_DEFINE_EVENT_NOARGS(_template, _name) \
216 DEFINE_EVENT_NOARGS(compat_syscall_exit_##_template, \
217 compat_syscall_exit_##_name)
218 #define TRACE_SYSTEM compat_syscall_exit_integers
219 #define TRACE_INCLUDE_FILE compat_syscalls_integers
220 #include "instrumentation/syscalls/headers/compat_syscalls_integers.h"
221 #undef TRACE_INCLUDE_FILE
223 #define TRACE_SYSTEM compat_syscall_exit_pointers
224 #define TRACE_INCLUDE_FILE compat_syscalls_pointers
225 #include "instrumentation/syscalls/headers/compat_syscalls_pointers.h"
226 #undef TRACE_INCLUDE_FILE
228 #undef SC_TRACE_EVENT
229 #undef SC_DECLARE_EVENT_CLASS_NOARGS
230 #undef SC_DEFINE_EVENT_NOARGS
232 #undef _TRACE_SYSCALLS_integers_H
233 #undef _TRACE_SYSCALLS_pointers_H
237 #undef TP_MODULE_NOINIT
238 #undef LTTNG_PACKAGE_BUILD
239 #undef CREATE_TRACE_POINTS
241 struct trace_syscall_entry
{
243 const struct lttng_event_desc
*desc
;
244 const struct lttng_event_field
*fields
;
248 #define CREATE_SYSCALL_TABLE
255 #undef TRACE_SYSCALL_TABLE
256 #define TRACE_SYSCALL_TABLE(_template, _name, _nr, _nrargs) \
258 .func = __event_probe__syscall_enter_##_template, \
259 .nrargs = (_nrargs), \
260 .fields = __event_fields___syscall_enter_##_template, \
261 .desc = &__event_desc___syscall_enter_##_name, \
264 /* Syscall enter tracing table */
265 static const struct trace_syscall_entry sc_table
[] = {
266 #include "instrumentation/syscalls/headers/syscalls_integers.h"
267 #include "instrumentation/syscalls/headers/syscalls_pointers.h"
270 #undef TRACE_SYSCALL_TABLE
271 #define TRACE_SYSCALL_TABLE(_template, _name, _nr, _nrargs) \
273 .func = __event_probe__compat_syscall_enter_##_template, \
274 .nrargs = (_nrargs), \
275 .fields = __event_fields___compat_syscall_enter_##_template, \
276 .desc = &__event_desc___compat_syscall_enter_##_name, \
279 /* Compat syscall enter table */
280 const struct trace_syscall_entry compat_sc_table
[] = {
281 #include "instrumentation/syscalls/headers/compat_syscalls_integers.h"
282 #include "instrumentation/syscalls/headers/compat_syscalls_pointers.h"
290 #define sc_exit(...) __VA_ARGS__
292 #undef TRACE_SYSCALL_TABLE
293 #define TRACE_SYSCALL_TABLE(_template, _name, _nr, _nrargs) \
295 .func = __event_probe__syscall_exit_##_template, \
296 .nrargs = (_nrargs), \
297 .fields = __event_fields___syscall_exit_##_template, \
298 .desc = &__event_desc___syscall_exit_##_name, \
301 /* Syscall exit table */
302 static const struct trace_syscall_entry sc_exit_table
[] = {
303 #include "instrumentation/syscalls/headers/syscalls_integers.h"
304 #include "instrumentation/syscalls/headers/syscalls_pointers.h"
307 #undef TRACE_SYSCALL_TABLE
308 #define TRACE_SYSCALL_TABLE(_template, _name, _nr, _nrargs) \
310 .func = __event_probe__compat_syscall_exit_##_template, \
311 .nrargs = (_nrargs), \
312 .fields = __event_fields___compat_syscall_exit_##_template, \
313 .desc = &__event_desc___compat_syscall_exit_##_name, \
316 /* Compat syscall exit table */
317 const struct trace_syscall_entry compat_sc_exit_table
[] = {
318 #include "instrumentation/syscalls/headers/compat_syscalls_integers.h"
319 #include "instrumentation/syscalls/headers/compat_syscalls_pointers.h"
324 #undef CREATE_SYSCALL_TABLE
326 struct lttng_syscall_filter
{
327 DECLARE_BITMAP(sc
, NR_syscalls
);
328 DECLARE_BITMAP(sc_compat
, NR_compat_syscalls
);
331 static void syscall_entry_unknown(struct lttng_event
*event
,
332 struct pt_regs
*regs
, unsigned int id
)
334 unsigned long args
[UNKNOWN_SYSCALL_NRARGS
];
336 syscall_get_arguments(current
, regs
, 0, UNKNOWN_SYSCALL_NRARGS
, args
);
337 if (unlikely(is_compat_task()))
338 __event_probe__compat_syscall_enter_unknown(event
, id
, args
);
340 __event_probe__syscall_enter_unknown(event
, id
, args
);
343 void syscall_entry_probe(void *__data
, struct pt_regs
*regs
, long id
)
345 struct lttng_channel
*chan
= __data
;
346 struct lttng_event
*event
, *unknown_event
;
347 const struct trace_syscall_entry
*table
, *entry
;
350 if (unlikely(is_compat_task())) {
351 struct lttng_syscall_filter
*filter
;
353 filter
= rcu_dereference(chan
->sc_filter
);
355 if (id
>= NR_compat_syscalls
356 || !test_bit(id
, filter
->sc_compat
)) {
357 /* System call filtered out. */
361 table
= compat_sc_table
;
362 table_len
= ARRAY_SIZE(compat_sc_table
);
363 unknown_event
= chan
->sc_compat_unknown
;
365 struct lttng_syscall_filter
*filter
;
367 filter
= rcu_dereference(chan
->sc_filter
);
369 if (id
>= NR_syscalls
370 || !test_bit(id
, filter
->sc
)) {
371 /* System call filtered out. */
376 table_len
= ARRAY_SIZE(sc_table
);
377 unknown_event
= chan
->sc_unknown
;
379 if (unlikely(id
>= table_len
)) {
380 syscall_entry_unknown(unknown_event
, regs
, id
);
383 if (unlikely(is_compat_task()))
384 event
= chan
->compat_sc_table
[id
];
386 event
= chan
->sc_table
[id
];
387 if (unlikely(!event
)) {
388 syscall_entry_unknown(unknown_event
, regs
, id
);
392 WARN_ON_ONCE(!entry
);
394 switch (entry
->nrargs
) {
397 void (*fptr
)(void *__data
) = entry
->func
;
404 void (*fptr
)(void *__data
, unsigned long arg0
) = entry
->func
;
405 unsigned long args
[1];
407 syscall_get_arguments(current
, regs
, 0, entry
->nrargs
, args
);
408 fptr(event
, args
[0]);
413 void (*fptr
)(void *__data
,
415 unsigned long arg1
) = entry
->func
;
416 unsigned long args
[2];
418 syscall_get_arguments(current
, regs
, 0, entry
->nrargs
, args
);
419 fptr(event
, args
[0], args
[1]);
424 void (*fptr
)(void *__data
,
427 unsigned long arg2
) = entry
->func
;
428 unsigned long args
[3];
430 syscall_get_arguments(current
, regs
, 0, entry
->nrargs
, args
);
431 fptr(event
, args
[0], args
[1], args
[2]);
436 void (*fptr
)(void *__data
,
440 unsigned long arg3
) = entry
->func
;
441 unsigned long args
[4];
443 syscall_get_arguments(current
, regs
, 0, entry
->nrargs
, args
);
444 fptr(event
, args
[0], args
[1], args
[2], args
[3]);
449 void (*fptr
)(void *__data
,
454 unsigned long arg4
) = entry
->func
;
455 unsigned long args
[5];
457 syscall_get_arguments(current
, regs
, 0, entry
->nrargs
, args
);
458 fptr(event
, args
[0], args
[1], args
[2], args
[3], args
[4]);
463 void (*fptr
)(void *__data
,
469 unsigned long arg5
) = entry
->func
;
470 unsigned long args
[6];
472 syscall_get_arguments(current
, regs
, 0, entry
->nrargs
, args
);
473 fptr(event
, args
[0], args
[1], args
[2],
474 args
[3], args
[4], args
[5]);
482 static void syscall_exit_unknown(struct lttng_event
*event
,
483 struct pt_regs
*regs
, unsigned int id
, long ret
)
485 unsigned long args
[UNKNOWN_SYSCALL_NRARGS
];
487 syscall_get_arguments(current
, regs
, 0, UNKNOWN_SYSCALL_NRARGS
, args
);
488 if (unlikely(is_compat_task()))
489 __event_probe__compat_syscall_exit_unknown(event
, id
, ret
,
492 __event_probe__syscall_exit_unknown(event
, id
, ret
, args
);
495 void syscall_exit_probe(void *__data
, struct pt_regs
*regs
, long ret
)
497 struct lttng_channel
*chan
= __data
;
498 struct lttng_event
*event
, *unknown_event
;
499 const struct trace_syscall_entry
*table
, *entry
;
503 id
= syscall_get_nr(current
, regs
);
504 if (unlikely(is_compat_task())) {
505 struct lttng_syscall_filter
*filter
;
507 filter
= rcu_dereference(chan
->sc_filter
);
509 if (id
>= NR_compat_syscalls
510 || !test_bit(id
, filter
->sc_compat
)) {
511 /* System call filtered out. */
515 table
= compat_sc_exit_table
;
516 table_len
= ARRAY_SIZE(compat_sc_exit_table
);
517 unknown_event
= chan
->compat_sc_exit_unknown
;
519 struct lttng_syscall_filter
*filter
;
521 filter
= rcu_dereference(chan
->sc_filter
);
523 if (id
>= NR_syscalls
524 || !test_bit(id
, filter
->sc
)) {
525 /* System call filtered out. */
529 table
= sc_exit_table
;
530 table_len
= ARRAY_SIZE(sc_exit_table
);
531 unknown_event
= chan
->sc_exit_unknown
;
533 if (unlikely(id
>= table_len
)) {
534 syscall_exit_unknown(unknown_event
, regs
, id
, ret
);
537 if (unlikely(is_compat_task()))
538 event
= chan
->compat_sc_exit_table
[id
];
540 event
= chan
->sc_exit_table
[id
];
541 if (unlikely(!event
)) {
542 syscall_exit_unknown(unknown_event
, regs
, id
, ret
);
546 WARN_ON_ONCE(!entry
);
548 switch (entry
->nrargs
) {
551 void (*fptr
)(void *__data
, long ret
) = entry
->func
;
558 void (*fptr
)(void *__data
,
560 unsigned long arg0
) = entry
->func
;
561 unsigned long args
[1];
563 syscall_get_arguments(current
, regs
, 0, entry
->nrargs
, args
);
564 fptr(event
, ret
, args
[0]);
569 void (*fptr
)(void *__data
,
572 unsigned long arg1
) = entry
->func
;
573 unsigned long args
[2];
575 syscall_get_arguments(current
, regs
, 0, entry
->nrargs
, args
);
576 fptr(event
, ret
, args
[0], args
[1]);
581 void (*fptr
)(void *__data
,
585 unsigned long arg2
) = entry
->func
;
586 unsigned long args
[3];
588 syscall_get_arguments(current
, regs
, 0, entry
->nrargs
, args
);
589 fptr(event
, ret
, args
[0], args
[1], args
[2]);
594 void (*fptr
)(void *__data
,
599 unsigned long arg3
) = entry
->func
;
600 unsigned long args
[4];
602 syscall_get_arguments(current
, regs
, 0, entry
->nrargs
, args
);
603 fptr(event
, ret
, args
[0], args
[1], args
[2], args
[3]);
608 void (*fptr
)(void *__data
,
614 unsigned long arg4
) = entry
->func
;
615 unsigned long args
[5];
617 syscall_get_arguments(current
, regs
, 0, entry
->nrargs
, args
);
618 fptr(event
, ret
, args
[0], args
[1], args
[2], args
[3], args
[4]);
623 void (*fptr
)(void *__data
,
630 unsigned long arg5
) = entry
->func
;
631 unsigned long args
[6];
633 syscall_get_arguments(current
, regs
, 0, entry
->nrargs
, args
);
634 fptr(event
, ret
, args
[0], args
[1], args
[2],
635 args
[3], args
[4], args
[5]);
643 /* noinline to diminish caller stack size */
645 int fill_table(const struct trace_syscall_entry
*table
, size_t table_len
,
646 struct lttng_event
**chan_table
, struct lttng_channel
*chan
,
647 void *filter
, enum sc_type type
)
649 const struct lttng_event_desc
*desc
;
652 /* Allocate events for each syscall, insert into table */
653 for (i
= 0; i
< table_len
; i
++) {
654 struct lttng_kernel_event ev
;
655 desc
= table
[i
].desc
;
658 /* Unknown syscall */
662 * Skip those already populated by previous failed
663 * register for this channel.
667 memset(&ev
, 0, sizeof(ev
));
670 strncpy(ev
.name
, SYSCALL_ENTRY_STR
,
671 LTTNG_KERNEL_SYM_NAME_LEN
);
674 strncpy(ev
.name
, SYSCALL_EXIT_STR
,
675 LTTNG_KERNEL_SYM_NAME_LEN
);
677 case SC_TYPE_COMPAT_ENTRY
:
678 strncpy(ev
.name
, COMPAT_SYSCALL_ENTRY_STR
,
679 LTTNG_KERNEL_SYM_NAME_LEN
);
681 case SC_TYPE_COMPAT_EXIT
:
682 strncpy(ev
.name
, COMPAT_SYSCALL_EXIT_STR
,
683 LTTNG_KERNEL_SYM_NAME_LEN
);
689 strncat(ev
.name
, desc
->name
,
690 LTTNG_KERNEL_SYM_NAME_LEN
- strlen(ev
.name
) - 1);
691 ev
.name
[LTTNG_KERNEL_SYM_NAME_LEN
- 1] = '\0';
692 ev
.instrumentation
= LTTNG_KERNEL_NOOP
;
693 chan_table
[i
] = lttng_event_create(chan
, &ev
, filter
,
695 WARN_ON_ONCE(!chan_table
[i
]);
696 if (IS_ERR(chan_table
[i
])) {
698 * If something goes wrong in event registration
699 * after the first one, we have no choice but to
700 * leave the previous events in there, until
701 * deleted by session teardown.
703 return PTR_ERR(chan_table
[i
]);
709 int lttng_syscalls_register(struct lttng_channel
*chan
, void *filter
)
711 struct lttng_kernel_event ev
;
714 wrapper_vmalloc_sync_all();
716 if (!chan
->sc_table
) {
717 /* create syscall table mapping syscall to events */
718 chan
->sc_table
= kzalloc(sizeof(struct lttng_event
*)
719 * ARRAY_SIZE(sc_table
), GFP_KERNEL
);
723 if (!chan
->sc_exit_table
) {
724 /* create syscall table mapping syscall to events */
725 chan
->sc_exit_table
= kzalloc(sizeof(struct lttng_event
*)
726 * ARRAY_SIZE(sc_exit_table
), GFP_KERNEL
);
727 if (!chan
->sc_exit_table
)
733 if (!chan
->compat_sc_table
) {
734 /* create syscall table mapping compat syscall to events */
735 chan
->compat_sc_table
= kzalloc(sizeof(struct lttng_event
*)
736 * ARRAY_SIZE(compat_sc_table
), GFP_KERNEL
);
737 if (!chan
->compat_sc_table
)
741 if (!chan
->compat_sc_exit_table
) {
742 /* create syscall table mapping compat syscall to events */
743 chan
->compat_sc_exit_table
= kzalloc(sizeof(struct lttng_event
*)
744 * ARRAY_SIZE(compat_sc_exit_table
), GFP_KERNEL
);
745 if (!chan
->compat_sc_exit_table
)
749 if (!chan
->sc_unknown
) {
750 const struct lttng_event_desc
*desc
=
751 &__event_desc___syscall_enter_unknown
;
753 memset(&ev
, 0, sizeof(ev
));
754 strncpy(ev
.name
, desc
->name
, LTTNG_KERNEL_SYM_NAME_LEN
);
755 ev
.name
[LTTNG_KERNEL_SYM_NAME_LEN
- 1] = '\0';
756 ev
.instrumentation
= LTTNG_KERNEL_NOOP
;
757 chan
->sc_unknown
= lttng_event_create(chan
, &ev
, filter
,
759 WARN_ON_ONCE(!chan
->sc_unknown
);
760 if (IS_ERR(chan
->sc_unknown
)) {
761 return PTR_ERR(chan
->sc_unknown
);
765 if (!chan
->sc_compat_unknown
) {
766 const struct lttng_event_desc
*desc
=
767 &__event_desc___compat_syscall_enter_unknown
;
769 memset(&ev
, 0, sizeof(ev
));
770 strncpy(ev
.name
, desc
->name
, LTTNG_KERNEL_SYM_NAME_LEN
);
771 ev
.name
[LTTNG_KERNEL_SYM_NAME_LEN
- 1] = '\0';
772 ev
.instrumentation
= LTTNG_KERNEL_NOOP
;
773 chan
->sc_compat_unknown
= lttng_event_create(chan
, &ev
, filter
,
775 WARN_ON_ONCE(!chan
->sc_unknown
);
776 if (IS_ERR(chan
->sc_compat_unknown
)) {
777 return PTR_ERR(chan
->sc_compat_unknown
);
781 if (!chan
->compat_sc_exit_unknown
) {
782 const struct lttng_event_desc
*desc
=
783 &__event_desc___compat_syscall_exit_unknown
;
785 memset(&ev
, 0, sizeof(ev
));
786 strncpy(ev
.name
, desc
->name
, LTTNG_KERNEL_SYM_NAME_LEN
);
787 ev
.name
[LTTNG_KERNEL_SYM_NAME_LEN
- 1] = '\0';
788 ev
.instrumentation
= LTTNG_KERNEL_NOOP
;
789 chan
->compat_sc_exit_unknown
= lttng_event_create(chan
, &ev
,
791 WARN_ON_ONCE(!chan
->compat_sc_exit_unknown
);
792 if (IS_ERR(chan
->compat_sc_exit_unknown
)) {
793 return PTR_ERR(chan
->compat_sc_exit_unknown
);
797 if (!chan
->sc_exit_unknown
) {
798 const struct lttng_event_desc
*desc
=
799 &__event_desc___syscall_exit_unknown
;
801 memset(&ev
, 0, sizeof(ev
));
802 strncpy(ev
.name
, desc
->name
, LTTNG_KERNEL_SYM_NAME_LEN
);
803 ev
.name
[LTTNG_KERNEL_SYM_NAME_LEN
- 1] = '\0';
804 ev
.instrumentation
= LTTNG_KERNEL_NOOP
;
805 chan
->sc_exit_unknown
= lttng_event_create(chan
, &ev
, filter
,
807 WARN_ON_ONCE(!chan
->sc_exit_unknown
);
808 if (IS_ERR(chan
->sc_exit_unknown
)) {
809 return PTR_ERR(chan
->sc_exit_unknown
);
813 ret
= fill_table(sc_table
, ARRAY_SIZE(sc_table
),
814 chan
->sc_table
, chan
, filter
, SC_TYPE_ENTRY
);
817 ret
= fill_table(sc_exit_table
, ARRAY_SIZE(sc_exit_table
),
818 chan
->sc_exit_table
, chan
, filter
, SC_TYPE_EXIT
);
823 ret
= fill_table(compat_sc_table
, ARRAY_SIZE(compat_sc_table
),
824 chan
->compat_sc_table
, chan
, filter
,
825 SC_TYPE_COMPAT_ENTRY
);
828 ret
= fill_table(compat_sc_exit_table
, ARRAY_SIZE(compat_sc_exit_table
),
829 chan
->compat_sc_exit_table
, chan
, filter
,
830 SC_TYPE_COMPAT_EXIT
);
834 if (!chan
->sys_enter_registered
) {
835 ret
= lttng_wrapper_tracepoint_probe_register("sys_enter",
836 (void *) syscall_entry_probe
, chan
);
839 chan
->sys_enter_registered
= 1;
842 * We change the name of sys_exit tracepoint due to namespace
843 * conflict with sys_exit syscall entry.
845 if (!chan
->sys_exit_registered
) {
846 ret
= lttng_wrapper_tracepoint_probe_register("sys_exit",
847 (void *) syscall_exit_probe
, chan
);
849 WARN_ON_ONCE(lttng_wrapper_tracepoint_probe_unregister("sys_enter",
850 (void *) syscall_entry_probe
, chan
));
853 chan
->sys_exit_registered
= 1;
859 * Only called at session destruction.
861 int lttng_syscalls_unregister(struct lttng_channel
*chan
)
867 if (chan
->sys_enter_registered
) {
868 ret
= lttng_wrapper_tracepoint_probe_unregister("sys_exit",
869 (void *) syscall_exit_probe
, chan
);
872 chan
->sys_enter_registered
= 0;
874 if (chan
->sys_exit_registered
) {
875 ret
= lttng_wrapper_tracepoint_probe_unregister("sys_enter",
876 (void *) syscall_entry_probe
, chan
);
879 chan
->sys_exit_registered
= 0;
881 /* lttng_event destroy will be performed by lttng_session_destroy() */
882 kfree(chan
->sc_table
);
883 kfree(chan
->sc_exit_table
);
885 kfree(chan
->compat_sc_table
);
886 kfree(chan
->compat_sc_exit_table
);
888 kfree(chan
->sc_filter
);
893 int get_syscall_nr(const char *syscall_name
)
898 for (i
= 0; i
< ARRAY_SIZE(sc_table
); i
++) {
899 const struct trace_syscall_entry
*entry
;
902 entry
= &sc_table
[i
];
905 it_name
= entry
->desc
->name
;
906 it_name
+= strlen(SYSCALL_ENTRY_STR
);
907 if (!strcmp(syscall_name
, it_name
)) {
916 int get_compat_syscall_nr(const char *syscall_name
)
921 for (i
= 0; i
< ARRAY_SIZE(compat_sc_table
); i
++) {
922 const struct trace_syscall_entry
*entry
;
925 entry
= &compat_sc_table
[i
];
928 it_name
= entry
->desc
->name
;
929 it_name
+= strlen(COMPAT_SYSCALL_ENTRY_STR
);
930 if (!strcmp(syscall_name
, it_name
)) {
938 int lttng_syscall_filter_enable(struct lttng_channel
*chan
,
941 int syscall_nr
, compat_syscall_nr
, ret
;
942 struct lttng_syscall_filter
*filter
;
944 WARN_ON_ONCE(!chan
->sc_table
);
947 /* Enable all system calls by removing filter */
948 if (chan
->sc_filter
) {
949 filter
= chan
->sc_filter
;
950 rcu_assign_pointer(chan
->sc_filter
, NULL
);
954 chan
->syscall_all
= 1;
958 if (!chan
->sc_filter
) {
959 if (chan
->syscall_all
) {
961 * All syscalls are already enabled.
965 filter
= kzalloc(sizeof(struct lttng_syscall_filter
),
970 filter
= chan
->sc_filter
;
972 syscall_nr
= get_syscall_nr(name
);
973 compat_syscall_nr
= get_compat_syscall_nr(name
);
974 if (syscall_nr
< 0 && compat_syscall_nr
< 0) {
978 if (syscall_nr
>= 0) {
979 if (test_bit(syscall_nr
, filter
->sc
)) {
983 bitmap_set(filter
->sc
, syscall_nr
, 1);
985 if (compat_syscall_nr
>= 0) {
986 if (test_bit(compat_syscall_nr
, filter
->sc_compat
)) {
990 bitmap_set(filter
->sc_compat
, compat_syscall_nr
, 1);
992 if (!chan
->sc_filter
)
993 rcu_assign_pointer(chan
->sc_filter
, filter
);
997 if (!chan
->sc_filter
)
1002 int lttng_syscall_filter_disable(struct lttng_channel
*chan
,
1005 int syscall_nr
, compat_syscall_nr
, ret
;
1006 struct lttng_syscall_filter
*filter
;
1008 WARN_ON_ONCE(!chan
->sc_table
);
1010 if (!chan
->sc_filter
) {
1011 filter
= kzalloc(sizeof(struct lttng_syscall_filter
),
1015 /* Trace all system calls, then apply disable. */
1016 bitmap_set(filter
->sc
, 0, NR_syscalls
);
1017 bitmap_set(filter
->sc_compat
, 0, NR_compat_syscalls
);
1019 filter
= chan
->sc_filter
;
1022 syscall_nr
= get_syscall_nr(name
);
1023 compat_syscall_nr
= get_compat_syscall_nr(name
);
1024 if (syscall_nr
< 0 && compat_syscall_nr
< 0) {
1028 if (syscall_nr
>= 0) {
1029 if (!test_bit(syscall_nr
, chan
->sc_filter
->sc
)) {
1033 bitmap_clear(chan
->sc_filter
->sc
, syscall_nr
, 1);
1035 if (compat_syscall_nr
>= 0) {
1036 if (!test_bit(compat_syscall_nr
, chan
->sc_filter
->sc_compat
)) {
1040 bitmap_clear(chan
->sc_filter
->sc_compat
, compat_syscall_nr
, 1);
1042 if (!chan
->sc_filter
)
1043 rcu_assign_pointer(chan
->sc_filter
, filter
);
1044 chan
->syscall_all
= 0;
1048 if (!chan
->sc_filter
)