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>
29 #include <linux/in6.h>
30 #include <asm/ptrace.h>
31 #include <asm/syscall.h>
33 #include "wrapper/tracepoint.h"
34 #include "lttng-events.h"
37 # ifndef is_compat_task
38 # define is_compat_task() (0)
49 #define SYSCALL_ENTRY_STR "syscall_entry_"
50 #define COMPAT_SYSCALL_ENTRY_STR "compat_syscall_entry_"
51 #define SYSCALL_EXIT_STR "syscall_exit_"
52 #define COMPAT_SYSCALL_EXIT_STR "compat_syscall_exit_"
55 void syscall_entry_probe(void *__data
, struct pt_regs
*regs
, long id
);
57 void syscall_exit_probe(void *__data
, struct pt_regs
*regs
, long ret
);
60 * Forward declarations for old kernels.
64 struct oldold_utsname
;
66 struct sel_arg_struct
;
67 struct mmap_arg_struct
;
69 #ifdef IA32_NR_syscalls
70 #define NR_compat_syscalls IA32_NR_syscalls
72 #define NR_compat_syscalls NR_syscalls
76 * Take care of NOARGS not supported by mainline.
78 #define DECLARE_EVENT_CLASS_NOARGS(name, tstruct, assign, print)
79 #define DEFINE_EVENT_NOARGS(template, name)
80 #define TRACE_EVENT_NOARGS(name, struct, assign, print)
83 * Create LTTng tracepoint probes.
85 #define LTTNG_PACKAGE_BUILD
86 #define CREATE_TRACE_POINTS
87 #define TP_MODULE_NOINIT
88 #define TRACE_INCLUDE_PATH ../instrumentation/syscalls/headers
90 #define PARAMS(args...) args
92 /* Handle unknown syscalls */
93 #define TRACE_SYSTEM syscalls_unknown
94 #include "instrumentation/syscalls/headers/syscalls_unknown.h"
102 #define sc_in(...) __VA_ARGS__
106 #define sc_inout(...) __VA_ARGS__
108 /* Hijack probe callback for system call enter */
110 #define TP_PROBE_CB(_template) &syscall_entry_probe
111 #define SC_TRACE_EVENT(_name, _proto, _args, _struct, _assign, _printk) \
112 TRACE_EVENT(syscall_enter_##_name, PARAMS(_proto), PARAMS(_args),\
113 PARAMS(_struct), PARAMS(_assign), PARAMS(_printk))
114 #define SC_LTTNG_TRACE_EVENT(_name, _proto, _args, _locvar, _code, _struct, _assign, _printk) \
115 LTTNG_TRACE_EVENT(syscall_enter_##_name, PARAMS(_proto), PARAMS(_args),\
116 PARAMS(_locvar), PARAMS(_code),\
117 PARAMS(_struct), PARAMS(_assign), PARAMS(_printk))
118 #define SC_DECLARE_EVENT_CLASS_NOARGS(_name, _struct, _assign, _printk) \
119 DECLARE_EVENT_CLASS_NOARGS(syscall_enter_##_name, PARAMS(_struct), PARAMS(_assign),\
121 #define SC_DEFINE_EVENT_NOARGS(_template, _name) \
122 DEFINE_EVENT_NOARGS(syscall_enter_##_template, syscall_enter_##_name)
124 #define TRACE_SYSTEM syscall_enter_integers
125 #define TRACE_INCLUDE_FILE syscalls_integers
126 #include "instrumentation/syscalls/headers/syscalls_integers.h"
127 #undef TRACE_INCLUDE_FILE
129 #define TRACE_SYSTEM syscall_enter_pointers
130 #define TRACE_INCLUDE_FILE syscalls_pointers
131 #include "instrumentation/syscalls/headers/syscalls_pointers.h"
132 #undef TRACE_INCLUDE_FILE
134 #undef SC_LTTNG_TRACE_EVENT
135 #undef SC_TRACE_EVENT
136 #undef SC_DECLARE_EVENT_CLASS_NOARGS
137 #undef SC_DEFINE_EVENT_NOARGS
139 #undef _TRACE_SYSCALLS_integers_H
140 #undef _TRACE_SYSCALLS_pointers_H
143 /* Hijack probe callback for compat system call enter */
144 #define TP_PROBE_CB(_template) &syscall_entry_probe
145 #define SC_TRACE_EVENT(_name, _proto, _args, _struct, _assign, _printk) \
146 TRACE_EVENT(compat_syscall_enter_##_name, PARAMS(_proto), PARAMS(_args), \
147 PARAMS(_struct), PARAMS(_assign), \
149 #define SC_LTTNG_TRACE_EVENT(_name, _proto, _args, _locvar, _code, _struct, _assign, _printk) \
150 LTTNG_TRACE_EVENT(compat_syscall_enter_##_name, PARAMS(_proto), PARAMS(_args),\
151 PARAMS(_locvar), PARAMS(_code),\
152 PARAMS(_struct), PARAMS(_assign), PARAMS(_printk))
153 #define SC_DECLARE_EVENT_CLASS_NOARGS(_name, _struct, _assign, _printk) \
154 DECLARE_EVENT_CLASS_NOARGS(compat_syscall_enter_##_name, PARAMS(_struct), \
155 PARAMS(_assign), PARAMS(_printk))
156 #define SC_DEFINE_EVENT_NOARGS(_template, _name) \
157 DEFINE_EVENT_NOARGS(compat_syscall_enter_##_template, \
158 compat_syscall_enter_##_name)
159 #define TRACE_SYSTEM compat_syscall_enter_integers
160 #define TRACE_INCLUDE_FILE compat_syscalls_integers
161 #include "instrumentation/syscalls/headers/compat_syscalls_integers.h"
162 #undef TRACE_INCLUDE_FILE
164 #define TRACE_SYSTEM compat_syscall_enter_pointers
165 #define TRACE_INCLUDE_FILE compat_syscalls_pointers
166 #include "instrumentation/syscalls/headers/compat_syscalls_pointers.h"
167 #undef TRACE_INCLUDE_FILE
169 #undef SC_LTTNG_TRACE_EVENT
170 #undef SC_TRACE_EVENT
171 #undef SC_DECLARE_EVENT_CLASS_NOARGS
172 #undef SC_DEFINE_EVENT_NOARGS
174 #undef _TRACE_SYSCALLS_integers_H
175 #undef _TRACE_SYSCALLS_pointers_H
182 #define sc_exit(...) __VA_ARGS__
186 #define sc_out(...) __VA_ARGS__
188 #define sc_inout(...) __VA_ARGS__
190 /* Hijack probe callback for system call exit */
191 #define TP_PROBE_CB(_template) &syscall_exit_probe
192 #define SC_TRACE_EVENT(_name, _proto, _args, _struct, _assign, _printk) \
193 TRACE_EVENT(syscall_exit_##_name, PARAMS(_proto), PARAMS(_args),\
194 PARAMS(_struct), PARAMS(_assign), PARAMS(_printk))
195 #define SC_LTTNG_TRACE_EVENT(_name, _proto, _args, _locvar, _code, _struct, _assign, _printk) \
196 LTTNG_TRACE_EVENT(syscall_exit_##_name, PARAMS(_proto), PARAMS(_args),\
197 PARAMS(_locvar), PARAMS(_code),\
198 PARAMS(_struct), PARAMS(_assign), PARAMS(_printk))
199 #define SC_DECLARE_EVENT_CLASS_NOARGS(_name, _struct, _assign, _printk) \
200 DECLARE_EVENT_CLASS_NOARGS(syscall_exit_##_name, PARAMS(_struct), \
201 PARAMS(_assign), PARAMS(_printk))
202 #define SC_DEFINE_EVENT_NOARGS(_template, _name) \
203 DEFINE_EVENT_NOARGS(syscall_exit_##_template, \
204 syscall_exit_##_name)
205 #define TRACE_SYSTEM syscall_exit_integers
206 #define TRACE_INCLUDE_FILE syscalls_integers
207 #include "instrumentation/syscalls/headers/syscalls_integers.h"
208 #undef TRACE_INCLUDE_FILE
210 #define TRACE_SYSTEM syscall_exit_pointers
211 #define TRACE_INCLUDE_FILE syscalls_pointers
212 #include "instrumentation/syscalls/headers/syscalls_pointers.h"
213 #undef TRACE_INCLUDE_FILE
215 #undef SC_LTTNG_TRACE_EVENT
216 #undef SC_TRACE_EVENT
217 #undef SC_DECLARE_EVENT_CLASS_NOARGS
218 #undef SC_DEFINE_EVENT_NOARGS
220 #undef _TRACE_SYSCALLS_integers_H
221 #undef _TRACE_SYSCALLS_pointers_H
224 /* Hijack probe callback for compat system call exit */
225 #define TP_PROBE_CB(_template) &syscall_exit_probe
226 #define SC_TRACE_EVENT(_name, _proto, _args, _struct, _assign, _printk) \
227 TRACE_EVENT(compat_syscall_exit_##_name, PARAMS(_proto), PARAMS(_args), \
228 PARAMS(_struct), PARAMS(_assign), PARAMS(_printk))
229 #define SC_LTTNG_TRACE_EVENT(_name, _proto, _args, _locvar, _code, _struct, _assign, _printk) \
230 LTTNG_TRACE_EVENT(compat_syscall_exit_##_name, PARAMS(_proto), PARAMS(_args),\
231 PARAMS(_locvar), PARAMS(_code),\
232 PARAMS(_struct), PARAMS(_assign), PARAMS(_printk))
233 #define SC_DECLARE_EVENT_CLASS_NOARGS(_name, _struct, _assign, _printk) \
234 DECLARE_EVENT_CLASS_NOARGS(compat_syscall_exit_##_name, PARAMS(_struct), \
235 PARAMS(_assign), PARAMS(_printk))
236 #define SC_DEFINE_EVENT_NOARGS(_template, _name) \
237 DEFINE_EVENT_NOARGS(compat_syscall_exit_##_template, \
238 compat_syscall_exit_##_name)
239 #define TRACE_SYSTEM compat_syscall_exit_integers
240 #define TRACE_INCLUDE_FILE compat_syscalls_integers
241 #include "instrumentation/syscalls/headers/compat_syscalls_integers.h"
242 #undef TRACE_INCLUDE_FILE
244 #define TRACE_SYSTEM compat_syscall_exit_pointers
245 #define TRACE_INCLUDE_FILE compat_syscalls_pointers
246 #include "instrumentation/syscalls/headers/compat_syscalls_pointers.h"
247 #undef TRACE_INCLUDE_FILE
249 #undef SC_LTTNG_TRACE_EVENT
250 #undef SC_TRACE_EVENT
251 #undef SC_DECLARE_EVENT_CLASS_NOARGS
252 #undef SC_DEFINE_EVENT_NOARGS
254 #undef _TRACE_SYSCALLS_integers_H
255 #undef _TRACE_SYSCALLS_pointers_H
259 #undef TP_MODULE_NOINIT
260 #undef LTTNG_PACKAGE_BUILD
261 #undef CREATE_TRACE_POINTS
263 struct trace_syscall_entry
{
265 const struct lttng_event_desc
*desc
;
266 const struct lttng_event_field
*fields
;
270 #define CREATE_SYSCALL_TABLE
277 #undef TRACE_SYSCALL_TABLE
278 #define TRACE_SYSCALL_TABLE(_template, _name, _nr, _nrargs) \
280 .func = __event_probe__syscall_enter_##_template, \
281 .nrargs = (_nrargs), \
282 .fields = __event_fields___syscall_enter_##_template, \
283 .desc = &__event_desc___syscall_enter_##_name, \
286 /* Syscall enter tracing table */
287 static const struct trace_syscall_entry sc_table
[] = {
288 #include "instrumentation/syscalls/headers/syscalls_integers.h"
289 #include "instrumentation/syscalls/headers/syscalls_pointers.h"
292 #undef TRACE_SYSCALL_TABLE
293 #define TRACE_SYSCALL_TABLE(_template, _name, _nr, _nrargs) \
295 .func = __event_probe__compat_syscall_enter_##_template, \
296 .nrargs = (_nrargs), \
297 .fields = __event_fields___compat_syscall_enter_##_template, \
298 .desc = &__event_desc___compat_syscall_enter_##_name, \
301 /* Compat syscall enter table */
302 const struct trace_syscall_entry compat_sc_table
[] = {
303 #include "instrumentation/syscalls/headers/compat_syscalls_integers.h"
304 #include "instrumentation/syscalls/headers/compat_syscalls_pointers.h"
312 #define sc_exit(...) __VA_ARGS__
314 #undef TRACE_SYSCALL_TABLE
315 #define TRACE_SYSCALL_TABLE(_template, _name, _nr, _nrargs) \
317 .func = __event_probe__syscall_exit_##_template, \
318 .nrargs = (_nrargs), \
319 .fields = __event_fields___syscall_exit_##_template, \
320 .desc = &__event_desc___syscall_exit_##_name, \
323 /* Syscall exit table */
324 static const struct trace_syscall_entry sc_exit_table
[] = {
325 #include "instrumentation/syscalls/headers/syscalls_integers.h"
326 #include "instrumentation/syscalls/headers/syscalls_pointers.h"
329 #undef TRACE_SYSCALL_TABLE
330 #define TRACE_SYSCALL_TABLE(_template, _name, _nr, _nrargs) \
332 .func = __event_probe__compat_syscall_exit_##_template, \
333 .nrargs = (_nrargs), \
334 .fields = __event_fields___compat_syscall_exit_##_template, \
335 .desc = &__event_desc___compat_syscall_exit_##_name, \
338 /* Compat syscall exit table */
339 const struct trace_syscall_entry compat_sc_exit_table
[] = {
340 #include "instrumentation/syscalls/headers/compat_syscalls_integers.h"
341 #include "instrumentation/syscalls/headers/compat_syscalls_pointers.h"
346 #undef CREATE_SYSCALL_TABLE
348 struct lttng_syscall_filter
{
349 DECLARE_BITMAP(sc
, NR_syscalls
);
350 DECLARE_BITMAP(sc_compat
, NR_compat_syscalls
);
353 static void syscall_entry_unknown(struct lttng_event
*event
,
354 struct pt_regs
*regs
, unsigned int id
)
356 unsigned long args
[UNKNOWN_SYSCALL_NRARGS
];
358 syscall_get_arguments(current
, regs
, 0, UNKNOWN_SYSCALL_NRARGS
, args
);
359 if (unlikely(is_compat_task()))
360 __event_probe__compat_syscall_enter_unknown(event
, id
, args
);
362 __event_probe__syscall_enter_unknown(event
, id
, args
);
365 void syscall_entry_probe(void *__data
, struct pt_regs
*regs
, long id
)
367 struct lttng_channel
*chan
= __data
;
368 struct lttng_event
*event
, *unknown_event
;
369 const struct trace_syscall_entry
*table
, *entry
;
372 if (unlikely(is_compat_task())) {
373 struct lttng_syscall_filter
*filter
;
375 filter
= rcu_dereference(chan
->sc_filter
);
377 if (id
>= NR_compat_syscalls
378 || !test_bit(id
, filter
->sc_compat
)) {
379 /* System call filtered out. */
383 table
= compat_sc_table
;
384 table_len
= ARRAY_SIZE(compat_sc_table
);
385 unknown_event
= chan
->sc_compat_unknown
;
387 struct lttng_syscall_filter
*filter
;
389 filter
= rcu_dereference(chan
->sc_filter
);
391 if (id
>= NR_syscalls
392 || !test_bit(id
, filter
->sc
)) {
393 /* System call filtered out. */
398 table_len
= ARRAY_SIZE(sc_table
);
399 unknown_event
= chan
->sc_unknown
;
401 if (unlikely(id
>= table_len
)) {
402 syscall_entry_unknown(unknown_event
, regs
, id
);
405 if (unlikely(is_compat_task()))
406 event
= chan
->compat_sc_table
[id
];
408 event
= chan
->sc_table
[id
];
409 if (unlikely(!event
)) {
410 syscall_entry_unknown(unknown_event
, regs
, id
);
414 WARN_ON_ONCE(!entry
);
416 switch (entry
->nrargs
) {
419 void (*fptr
)(void *__data
) = entry
->func
;
426 void (*fptr
)(void *__data
, unsigned long arg0
) = entry
->func
;
427 unsigned long args
[1];
429 syscall_get_arguments(current
, regs
, 0, entry
->nrargs
, args
);
430 fptr(event
, args
[0]);
435 void (*fptr
)(void *__data
,
437 unsigned long arg1
) = entry
->func
;
438 unsigned long args
[2];
440 syscall_get_arguments(current
, regs
, 0, entry
->nrargs
, args
);
441 fptr(event
, args
[0], args
[1]);
446 void (*fptr
)(void *__data
,
449 unsigned long arg2
) = entry
->func
;
450 unsigned long args
[3];
452 syscall_get_arguments(current
, regs
, 0, entry
->nrargs
, args
);
453 fptr(event
, args
[0], args
[1], args
[2]);
458 void (*fptr
)(void *__data
,
462 unsigned long arg3
) = entry
->func
;
463 unsigned long args
[4];
465 syscall_get_arguments(current
, regs
, 0, entry
->nrargs
, args
);
466 fptr(event
, args
[0], args
[1], args
[2], args
[3]);
471 void (*fptr
)(void *__data
,
476 unsigned long arg4
) = entry
->func
;
477 unsigned long args
[5];
479 syscall_get_arguments(current
, regs
, 0, entry
->nrargs
, args
);
480 fptr(event
, args
[0], args
[1], args
[2], args
[3], args
[4]);
485 void (*fptr
)(void *__data
,
491 unsigned long arg5
) = entry
->func
;
492 unsigned long args
[6];
494 syscall_get_arguments(current
, regs
, 0, entry
->nrargs
, args
);
495 fptr(event
, args
[0], args
[1], args
[2],
496 args
[3], args
[4], args
[5]);
504 static void syscall_exit_unknown(struct lttng_event
*event
,
505 struct pt_regs
*regs
, unsigned int id
, long ret
)
507 unsigned long args
[UNKNOWN_SYSCALL_NRARGS
];
509 syscall_get_arguments(current
, regs
, 0, UNKNOWN_SYSCALL_NRARGS
, args
);
510 if (unlikely(is_compat_task()))
511 __event_probe__compat_syscall_exit_unknown(event
, id
, ret
,
514 __event_probe__syscall_exit_unknown(event
, id
, ret
, args
);
517 void syscall_exit_probe(void *__data
, struct pt_regs
*regs
, long ret
)
519 struct lttng_channel
*chan
= __data
;
520 struct lttng_event
*event
, *unknown_event
;
521 const struct trace_syscall_entry
*table
, *entry
;
525 id
= syscall_get_nr(current
, regs
);
526 if (unlikely(is_compat_task())) {
527 struct lttng_syscall_filter
*filter
;
529 filter
= rcu_dereference(chan
->sc_filter
);
531 if (id
>= NR_compat_syscalls
532 || !test_bit(id
, filter
->sc_compat
)) {
533 /* System call filtered out. */
537 table
= compat_sc_exit_table
;
538 table_len
= ARRAY_SIZE(compat_sc_exit_table
);
539 unknown_event
= chan
->compat_sc_exit_unknown
;
541 struct lttng_syscall_filter
*filter
;
543 filter
= rcu_dereference(chan
->sc_filter
);
545 if (id
>= NR_syscalls
546 || !test_bit(id
, filter
->sc
)) {
547 /* System call filtered out. */
551 table
= sc_exit_table
;
552 table_len
= ARRAY_SIZE(sc_exit_table
);
553 unknown_event
= chan
->sc_exit_unknown
;
555 if (unlikely(id
>= table_len
)) {
556 syscall_exit_unknown(unknown_event
, regs
, id
, ret
);
559 if (unlikely(is_compat_task()))
560 event
= chan
->compat_sc_exit_table
[id
];
562 event
= chan
->sc_exit_table
[id
];
563 if (unlikely(!event
)) {
564 syscall_exit_unknown(unknown_event
, regs
, id
, ret
);
568 WARN_ON_ONCE(!entry
);
570 switch (entry
->nrargs
) {
573 void (*fptr
)(void *__data
, long ret
) = entry
->func
;
580 void (*fptr
)(void *__data
,
582 unsigned long arg0
) = entry
->func
;
583 unsigned long args
[1];
585 syscall_get_arguments(current
, regs
, 0, entry
->nrargs
, args
);
586 fptr(event
, ret
, args
[0]);
591 void (*fptr
)(void *__data
,
594 unsigned long arg1
) = entry
->func
;
595 unsigned long args
[2];
597 syscall_get_arguments(current
, regs
, 0, entry
->nrargs
, args
);
598 fptr(event
, ret
, args
[0], args
[1]);
603 void (*fptr
)(void *__data
,
607 unsigned long arg2
) = entry
->func
;
608 unsigned long args
[3];
610 syscall_get_arguments(current
, regs
, 0, entry
->nrargs
, args
);
611 fptr(event
, ret
, args
[0], args
[1], args
[2]);
616 void (*fptr
)(void *__data
,
621 unsigned long arg3
) = entry
->func
;
622 unsigned long args
[4];
624 syscall_get_arguments(current
, regs
, 0, entry
->nrargs
, args
);
625 fptr(event
, ret
, args
[0], args
[1], args
[2], args
[3]);
630 void (*fptr
)(void *__data
,
636 unsigned long arg4
) = entry
->func
;
637 unsigned long args
[5];
639 syscall_get_arguments(current
, regs
, 0, entry
->nrargs
, args
);
640 fptr(event
, ret
, args
[0], args
[1], args
[2], args
[3], args
[4]);
645 void (*fptr
)(void *__data
,
652 unsigned long arg5
) = entry
->func
;
653 unsigned long args
[6];
655 syscall_get_arguments(current
, regs
, 0, entry
->nrargs
, args
);
656 fptr(event
, ret
, args
[0], args
[1], args
[2],
657 args
[3], args
[4], args
[5]);
665 /* noinline to diminish caller stack size */
667 int fill_table(const struct trace_syscall_entry
*table
, size_t table_len
,
668 struct lttng_event
**chan_table
, struct lttng_channel
*chan
,
669 void *filter
, enum sc_type type
)
671 const struct lttng_event_desc
*desc
;
674 /* Allocate events for each syscall, insert into table */
675 for (i
= 0; i
< table_len
; i
++) {
676 struct lttng_kernel_event ev
;
677 desc
= table
[i
].desc
;
680 /* Unknown syscall */
684 * Skip those already populated by previous failed
685 * register for this channel.
689 memset(&ev
, 0, sizeof(ev
));
692 strncpy(ev
.name
, SYSCALL_ENTRY_STR
,
693 LTTNG_KERNEL_SYM_NAME_LEN
);
696 strncpy(ev
.name
, SYSCALL_EXIT_STR
,
697 LTTNG_KERNEL_SYM_NAME_LEN
);
699 case SC_TYPE_COMPAT_ENTRY
:
700 strncpy(ev
.name
, COMPAT_SYSCALL_ENTRY_STR
,
701 LTTNG_KERNEL_SYM_NAME_LEN
);
703 case SC_TYPE_COMPAT_EXIT
:
704 strncpy(ev
.name
, COMPAT_SYSCALL_EXIT_STR
,
705 LTTNG_KERNEL_SYM_NAME_LEN
);
711 strncat(ev
.name
, desc
->name
,
712 LTTNG_KERNEL_SYM_NAME_LEN
- strlen(ev
.name
) - 1);
713 ev
.name
[LTTNG_KERNEL_SYM_NAME_LEN
- 1] = '\0';
714 ev
.instrumentation
= LTTNG_KERNEL_NOOP
;
715 chan_table
[i
] = lttng_event_create(chan
, &ev
, filter
,
717 WARN_ON_ONCE(!chan_table
[i
]);
718 if (IS_ERR(chan_table
[i
])) {
720 * If something goes wrong in event registration
721 * after the first one, we have no choice but to
722 * leave the previous events in there, until
723 * deleted by session teardown.
725 return PTR_ERR(chan_table
[i
]);
731 int lttng_syscalls_register(struct lttng_channel
*chan
, void *filter
)
733 struct lttng_kernel_event ev
;
736 wrapper_vmalloc_sync_all();
738 if (!chan
->sc_table
) {
739 /* create syscall table mapping syscall to events */
740 chan
->sc_table
= kzalloc(sizeof(struct lttng_event
*)
741 * ARRAY_SIZE(sc_table
), GFP_KERNEL
);
745 if (!chan
->sc_exit_table
) {
746 /* create syscall table mapping syscall to events */
747 chan
->sc_exit_table
= kzalloc(sizeof(struct lttng_event
*)
748 * ARRAY_SIZE(sc_exit_table
), GFP_KERNEL
);
749 if (!chan
->sc_exit_table
)
755 if (!chan
->compat_sc_table
) {
756 /* create syscall table mapping compat syscall to events */
757 chan
->compat_sc_table
= kzalloc(sizeof(struct lttng_event
*)
758 * ARRAY_SIZE(compat_sc_table
), GFP_KERNEL
);
759 if (!chan
->compat_sc_table
)
763 if (!chan
->compat_sc_exit_table
) {
764 /* create syscall table mapping compat syscall to events */
765 chan
->compat_sc_exit_table
= kzalloc(sizeof(struct lttng_event
*)
766 * ARRAY_SIZE(compat_sc_exit_table
), GFP_KERNEL
);
767 if (!chan
->compat_sc_exit_table
)
771 if (!chan
->sc_unknown
) {
772 const struct lttng_event_desc
*desc
=
773 &__event_desc___syscall_enter_unknown
;
775 memset(&ev
, 0, sizeof(ev
));
776 strncpy(ev
.name
, desc
->name
, LTTNG_KERNEL_SYM_NAME_LEN
);
777 ev
.name
[LTTNG_KERNEL_SYM_NAME_LEN
- 1] = '\0';
778 ev
.instrumentation
= LTTNG_KERNEL_NOOP
;
779 chan
->sc_unknown
= lttng_event_create(chan
, &ev
, filter
,
781 WARN_ON_ONCE(!chan
->sc_unknown
);
782 if (IS_ERR(chan
->sc_unknown
)) {
783 return PTR_ERR(chan
->sc_unknown
);
787 if (!chan
->sc_compat_unknown
) {
788 const struct lttng_event_desc
*desc
=
789 &__event_desc___compat_syscall_enter_unknown
;
791 memset(&ev
, 0, sizeof(ev
));
792 strncpy(ev
.name
, desc
->name
, LTTNG_KERNEL_SYM_NAME_LEN
);
793 ev
.name
[LTTNG_KERNEL_SYM_NAME_LEN
- 1] = '\0';
794 ev
.instrumentation
= LTTNG_KERNEL_NOOP
;
795 chan
->sc_compat_unknown
= lttng_event_create(chan
, &ev
, filter
,
797 WARN_ON_ONCE(!chan
->sc_unknown
);
798 if (IS_ERR(chan
->sc_compat_unknown
)) {
799 return PTR_ERR(chan
->sc_compat_unknown
);
803 if (!chan
->compat_sc_exit_unknown
) {
804 const struct lttng_event_desc
*desc
=
805 &__event_desc___compat_syscall_exit_unknown
;
807 memset(&ev
, 0, sizeof(ev
));
808 strncpy(ev
.name
, desc
->name
, LTTNG_KERNEL_SYM_NAME_LEN
);
809 ev
.name
[LTTNG_KERNEL_SYM_NAME_LEN
- 1] = '\0';
810 ev
.instrumentation
= LTTNG_KERNEL_NOOP
;
811 chan
->compat_sc_exit_unknown
= lttng_event_create(chan
, &ev
,
813 WARN_ON_ONCE(!chan
->compat_sc_exit_unknown
);
814 if (IS_ERR(chan
->compat_sc_exit_unknown
)) {
815 return PTR_ERR(chan
->compat_sc_exit_unknown
);
819 if (!chan
->sc_exit_unknown
) {
820 const struct lttng_event_desc
*desc
=
821 &__event_desc___syscall_exit_unknown
;
823 memset(&ev
, 0, sizeof(ev
));
824 strncpy(ev
.name
, desc
->name
, LTTNG_KERNEL_SYM_NAME_LEN
);
825 ev
.name
[LTTNG_KERNEL_SYM_NAME_LEN
- 1] = '\0';
826 ev
.instrumentation
= LTTNG_KERNEL_NOOP
;
827 chan
->sc_exit_unknown
= lttng_event_create(chan
, &ev
, filter
,
829 WARN_ON_ONCE(!chan
->sc_exit_unknown
);
830 if (IS_ERR(chan
->sc_exit_unknown
)) {
831 return PTR_ERR(chan
->sc_exit_unknown
);
835 ret
= fill_table(sc_table
, ARRAY_SIZE(sc_table
),
836 chan
->sc_table
, chan
, filter
, SC_TYPE_ENTRY
);
839 ret
= fill_table(sc_exit_table
, ARRAY_SIZE(sc_exit_table
),
840 chan
->sc_exit_table
, chan
, filter
, SC_TYPE_EXIT
);
845 ret
= fill_table(compat_sc_table
, ARRAY_SIZE(compat_sc_table
),
846 chan
->compat_sc_table
, chan
, filter
,
847 SC_TYPE_COMPAT_ENTRY
);
850 ret
= fill_table(compat_sc_exit_table
, ARRAY_SIZE(compat_sc_exit_table
),
851 chan
->compat_sc_exit_table
, chan
, filter
,
852 SC_TYPE_COMPAT_EXIT
);
856 if (!chan
->sys_enter_registered
) {
857 ret
= lttng_wrapper_tracepoint_probe_register("sys_enter",
858 (void *) syscall_entry_probe
, chan
);
861 chan
->sys_enter_registered
= 1;
864 * We change the name of sys_exit tracepoint due to namespace
865 * conflict with sys_exit syscall entry.
867 if (!chan
->sys_exit_registered
) {
868 ret
= lttng_wrapper_tracepoint_probe_register("sys_exit",
869 (void *) syscall_exit_probe
, chan
);
871 WARN_ON_ONCE(lttng_wrapper_tracepoint_probe_unregister("sys_enter",
872 (void *) syscall_entry_probe
, chan
));
875 chan
->sys_exit_registered
= 1;
881 * Only called at session destruction.
883 int lttng_syscalls_unregister(struct lttng_channel
*chan
)
889 if (chan
->sys_enter_registered
) {
890 ret
= lttng_wrapper_tracepoint_probe_unregister("sys_exit",
891 (void *) syscall_exit_probe
, chan
);
894 chan
->sys_enter_registered
= 0;
896 if (chan
->sys_exit_registered
) {
897 ret
= lttng_wrapper_tracepoint_probe_unregister("sys_enter",
898 (void *) syscall_entry_probe
, chan
);
901 chan
->sys_exit_registered
= 0;
903 /* lttng_event destroy will be performed by lttng_session_destroy() */
904 kfree(chan
->sc_table
);
905 kfree(chan
->sc_exit_table
);
907 kfree(chan
->compat_sc_table
);
908 kfree(chan
->compat_sc_exit_table
);
910 kfree(chan
->sc_filter
);
915 int get_syscall_nr(const char *syscall_name
)
920 for (i
= 0; i
< ARRAY_SIZE(sc_table
); i
++) {
921 const struct trace_syscall_entry
*entry
;
924 entry
= &sc_table
[i
];
927 it_name
= entry
->desc
->name
;
928 it_name
+= strlen(SYSCALL_ENTRY_STR
);
929 if (!strcmp(syscall_name
, it_name
)) {
938 int get_compat_syscall_nr(const char *syscall_name
)
943 for (i
= 0; i
< ARRAY_SIZE(compat_sc_table
); i
++) {
944 const struct trace_syscall_entry
*entry
;
947 entry
= &compat_sc_table
[i
];
950 it_name
= entry
->desc
->name
;
951 it_name
+= strlen(COMPAT_SYSCALL_ENTRY_STR
);
952 if (!strcmp(syscall_name
, it_name
)) {
960 int lttng_syscall_filter_enable(struct lttng_channel
*chan
,
963 int syscall_nr
, compat_syscall_nr
, ret
;
964 struct lttng_syscall_filter
*filter
;
966 WARN_ON_ONCE(!chan
->sc_table
);
969 /* Enable all system calls by removing filter */
970 if (chan
->sc_filter
) {
971 filter
= chan
->sc_filter
;
972 rcu_assign_pointer(chan
->sc_filter
, NULL
);
976 chan
->syscall_all
= 1;
980 if (!chan
->sc_filter
) {
981 if (chan
->syscall_all
) {
983 * All syscalls are already enabled.
987 filter
= kzalloc(sizeof(struct lttng_syscall_filter
),
992 filter
= chan
->sc_filter
;
994 syscall_nr
= get_syscall_nr(name
);
995 compat_syscall_nr
= get_compat_syscall_nr(name
);
996 if (syscall_nr
< 0 && compat_syscall_nr
< 0) {
1000 if (syscall_nr
>= 0) {
1001 if (test_bit(syscall_nr
, filter
->sc
)) {
1005 bitmap_set(filter
->sc
, syscall_nr
, 1);
1007 if (compat_syscall_nr
>= 0) {
1008 if (test_bit(compat_syscall_nr
, filter
->sc_compat
)) {
1012 bitmap_set(filter
->sc_compat
, compat_syscall_nr
, 1);
1014 if (!chan
->sc_filter
)
1015 rcu_assign_pointer(chan
->sc_filter
, filter
);
1019 if (!chan
->sc_filter
)
1024 int lttng_syscall_filter_disable(struct lttng_channel
*chan
,
1027 int syscall_nr
, compat_syscall_nr
, ret
;
1028 struct lttng_syscall_filter
*filter
;
1030 WARN_ON_ONCE(!chan
->sc_table
);
1032 if (!chan
->sc_filter
) {
1033 filter
= kzalloc(sizeof(struct lttng_syscall_filter
),
1037 /* Trace all system calls, then apply disable. */
1038 bitmap_set(filter
->sc
, 0, NR_syscalls
);
1039 bitmap_set(filter
->sc_compat
, 0, NR_compat_syscalls
);
1041 filter
= chan
->sc_filter
;
1044 syscall_nr
= get_syscall_nr(name
);
1045 compat_syscall_nr
= get_compat_syscall_nr(name
);
1046 if (syscall_nr
< 0 && compat_syscall_nr
< 0) {
1050 if (syscall_nr
>= 0) {
1051 if (!test_bit(syscall_nr
, chan
->sc_filter
->sc
)) {
1055 bitmap_clear(chan
->sc_filter
->sc
, syscall_nr
, 1);
1057 if (compat_syscall_nr
>= 0) {
1058 if (!test_bit(compat_syscall_nr
, chan
->sc_filter
->sc_compat
)) {
1062 bitmap_clear(chan
->sc_filter
->sc_compat
, compat_syscall_nr
, 1);
1064 if (!chan
->sc_filter
)
1065 rcu_assign_pointer(chan
->sc_filter
, filter
);
1066 chan
->syscall_all
= 0;
1070 if (!chan
->sc_filter
)