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 * Create LTTng tracepoint probes.
78 #define LTTNG_PACKAGE_BUILD
79 #define CREATE_TRACE_POINTS
80 #define TP_MODULE_NOINIT
81 #define TRACE_INCLUDE_PATH ../instrumentation/syscalls/headers
83 #define PARAMS(args...) args
85 /* Handle unknown syscalls */
86 #define TRACE_SYSTEM syscalls_unknown
87 #include "instrumentation/syscalls/headers/syscalls_unknown.h"
95 #define sc_in(...) __VA_ARGS__
99 #define sc_inout(...) __VA_ARGS__
101 /* Hijack probe callback for system call enter */
103 #define TP_PROBE_CB(_template) &syscall_entry_probe
104 #define SC_LTTNG_TRACEPOINT_EVENT(_name, _proto, _args, _struct, _assign, _printk) \
105 LTTNG_TRACEPOINT_EVENT(syscall_enter_##_name, PARAMS(_proto), PARAMS(_args), \
106 PARAMS(_struct), PARAMS(_assign), PARAMS(_printk))
107 #define SC_LTTNG_TRACEPOINT_EVENT_CODE(_name, _proto, _args, _locvar, _code, _struct, _assign, _printk) \
108 LTTNG_TRACEPOINT_EVENT_CODE(syscall_enter_##_name, PARAMS(_proto), PARAMS(_args), \
109 PARAMS(_locvar), PARAMS(_code), \
110 PARAMS(_struct), PARAMS(_assign), PARAMS(_printk))
111 #define SC_LTTNG_TRACEPOINT_EVENT_CLASS_NOARGS(_name, _struct, _assign, _printk) \
112 LTTNG_TRACEPOINT_EVENT_CLASS_NOARGS(syscall_enter_##_name, PARAMS(_struct), PARAMS(_assign), \
114 #define SC_LTTNG_TRACEPOINT_EVENT_INSTANCE_NOARGS(_template, _name) \
115 LTTNG_TRACEPOINT_EVENT_INSTANCE_NOARGS(syscall_enter_##_template, syscall_enter_##_name)
117 #define TRACE_SYSTEM syscall_enter_integers
118 #define TRACE_INCLUDE_FILE syscalls_integers
119 #include "instrumentation/syscalls/headers/syscalls_integers.h"
120 #undef TRACE_INCLUDE_FILE
122 #define TRACE_SYSTEM syscall_enter_pointers
123 #define TRACE_INCLUDE_FILE syscalls_pointers
124 #include "instrumentation/syscalls/headers/syscalls_pointers.h"
125 #undef TRACE_INCLUDE_FILE
127 #undef SC_LTTNG_TRACEPOINT_EVENT_CODE
128 #undef SC_LTTNG_TRACEPOINT_EVENT
129 #undef SC_LTTNG_TRACEPOINT_EVENT_CLASS_NOARGS
130 #undef SC_LTTNG_TRACEPOINT_EVENT_INSTANCE_NOARGS
132 #undef _TRACE_SYSCALLS_INTEGERS_H
133 #undef _TRACE_SYSCALLS_POINTERS_H
135 /* Hijack probe callback for compat system call enter */
136 #define TP_PROBE_CB(_template) &syscall_entry_probe
137 #define SC_LTTNG_TRACEPOINT_EVENT(_name, _proto, _args, _struct, _assign, _printk) \
138 LTTNG_TRACEPOINT_EVENT(compat_syscall_enter_##_name, PARAMS(_proto), PARAMS(_args), \
139 PARAMS(_struct), PARAMS(_assign), \
141 #define SC_LTTNG_TRACEPOINT_EVENT_CODE(_name, _proto, _args, _locvar, _code, _struct, _assign, _printk) \
142 LTTNG_TRACEPOINT_EVENT_CODE(compat_syscall_enter_##_name, PARAMS(_proto), PARAMS(_args), \
143 PARAMS(_locvar), PARAMS(_code), \
144 PARAMS(_struct), PARAMS(_assign), PARAMS(_printk))
145 #define SC_LTTNG_TRACEPOINT_EVENT_CLASS_NOARGS(_name, _struct, _assign, _printk) \
146 LTTNG_TRACEPOINT_EVENT_CLASS_NOARGS(compat_syscall_enter_##_name, PARAMS(_struct), \
147 PARAMS(_assign), PARAMS(_printk))
148 #define SC_LTTNG_TRACEPOINT_EVENT_INSTANCE_NOARGS(_template, _name) \
149 LTTNG_TRACEPOINT_EVENT_INSTANCE_NOARGS(compat_syscall_enter_##_template, \
150 compat_syscall_enter_##_name)
151 #define TRACE_SYSTEM compat_syscall_enter_integers
152 #define TRACE_INCLUDE_FILE compat_syscalls_integers
153 #include "instrumentation/syscalls/headers/compat_syscalls_integers.h"
154 #undef TRACE_INCLUDE_FILE
156 #define TRACE_SYSTEM compat_syscall_enter_pointers
157 #define TRACE_INCLUDE_FILE compat_syscalls_pointers
158 #include "instrumentation/syscalls/headers/compat_syscalls_pointers.h"
159 #undef TRACE_INCLUDE_FILE
161 #undef SC_LTTNG_TRACEPOINT_EVENT_CODE
162 #undef SC_LTTNG_TRACEPOINT_EVENT
163 #undef SC_LTTNG_TRACEPOINT_EVENT_CLASS_NOARGS
164 #undef SC_LTTNG_TRACEPOINT_EVENT_INSTANCE_NOARGS
166 #undef _TRACE_SYSCALLS_INTEGERS_H
167 #undef _TRACE_SYSCALLS_POINTERS_H
174 #define sc_exit(...) __VA_ARGS__
178 #define sc_out(...) __VA_ARGS__
180 #define sc_inout(...) __VA_ARGS__
182 /* Hijack probe callback for system call exit */
183 #define TP_PROBE_CB(_template) &syscall_exit_probe
184 #define SC_LTTNG_TRACEPOINT_EVENT(_name, _proto, _args, _struct, _assign, _printk) \
185 LTTNG_TRACEPOINT_EVENT(syscall_exit_##_name, PARAMS(_proto), PARAMS(_args), \
186 PARAMS(_struct), PARAMS(_assign), PARAMS(_printk))
187 #define SC_LTTNG_TRACEPOINT_EVENT_CODE(_name, _proto, _args, _locvar, _code, _struct, _assign, _printk) \
188 LTTNG_TRACEPOINT_EVENT_CODE(syscall_exit_##_name, PARAMS(_proto), PARAMS(_args), \
189 PARAMS(_locvar), PARAMS(_code), \
190 PARAMS(_struct), PARAMS(_assign), PARAMS(_printk))
191 #define SC_LTTNG_TRACEPOINT_EVENT_CLASS_NOARGS(_name, _struct, _assign, _printk) \
192 LTTNG_TRACEPOINT_EVENT_CLASS_NOARGS(syscall_exit_##_name, PARAMS(_struct), \
193 PARAMS(_assign), PARAMS(_printk))
194 #define SC_LTTNG_TRACEPOINT_EVENT_INSTANCE_NOARGS(_template, _name) \
195 LTTNG_TRACEPOINT_EVENT_INSTANCE_NOARGS(syscall_exit_##_template, \
196 syscall_exit_##_name)
197 #define TRACE_SYSTEM syscall_exit_integers
198 #define TRACE_INCLUDE_FILE syscalls_integers
199 #include "instrumentation/syscalls/headers/syscalls_integers.h"
200 #undef TRACE_INCLUDE_FILE
202 #define TRACE_SYSTEM syscall_exit_pointers
203 #define TRACE_INCLUDE_FILE syscalls_pointers
204 #include "instrumentation/syscalls/headers/syscalls_pointers.h"
205 #undef TRACE_INCLUDE_FILE
207 #undef SC_LTTNG_TRACEPOINT_EVENT_CODE
208 #undef SC_LTTNG_TRACEPOINT_EVENT
209 #undef SC_LTTNG_TRACEPOINT_EVENT_CLASS_NOARGS
210 #undef SC_LTTNG_TRACEPOINT_EVENT_INSTANCE_NOARGS
212 #undef _TRACE_SYSCALLS_INTEGERS_H
213 #undef _TRACE_SYSCALLS_POINTERS_H
216 /* Hijack probe callback for compat system call exit */
217 #define TP_PROBE_CB(_template) &syscall_exit_probe
218 #define SC_LTTNG_TRACEPOINT_EVENT(_name, _proto, _args, _struct, _assign, _printk) \
219 LTTNG_TRACEPOINT_EVENT(compat_syscall_exit_##_name, PARAMS(_proto), PARAMS(_args), \
220 PARAMS(_struct), PARAMS(_assign), PARAMS(_printk))
221 #define SC_LTTNG_TRACEPOINT_EVENT_CODE(_name, _proto, _args, _locvar, _code, _struct, _assign, _printk) \
222 LTTNG_TRACEPOINT_EVENT_CODE(compat_syscall_exit_##_name, PARAMS(_proto), PARAMS(_args), \
223 PARAMS(_locvar), PARAMS(_code), \
224 PARAMS(_struct), PARAMS(_assign), PARAMS(_printk))
225 #define SC_LTTNG_TRACEPOINT_EVENT_CLASS_NOARGS(_name, _struct, _assign, _printk) \
226 LTTNG_TRACEPOINT_EVENT_CLASS_NOARGS(compat_syscall_exit_##_name, PARAMS(_struct), \
227 PARAMS(_assign), PARAMS(_printk))
228 #define SC_LTTNG_TRACEPOINT_EVENT_INSTANCE_NOARGS(_template, _name) \
229 LTTNG_TRACEPOINT_EVENT_INSTANCE_NOARGS(compat_syscall_exit_##_template, \
230 compat_syscall_exit_##_name)
231 #define TRACE_SYSTEM compat_syscall_exit_integers
232 #define TRACE_INCLUDE_FILE compat_syscalls_integers
233 #include "instrumentation/syscalls/headers/compat_syscalls_integers.h"
234 #undef TRACE_INCLUDE_FILE
236 #define TRACE_SYSTEM compat_syscall_exit_pointers
237 #define TRACE_INCLUDE_FILE compat_syscalls_pointers
238 #include "instrumentation/syscalls/headers/compat_syscalls_pointers.h"
239 #undef TRACE_INCLUDE_FILE
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
251 #undef TP_MODULE_NOINIT
252 #undef LTTNG_PACKAGE_BUILD
253 #undef CREATE_TRACE_POINTS
255 struct trace_syscall_entry
{
257 const struct lttng_event_desc
*desc
;
258 const struct lttng_event_field
*fields
;
262 #define CREATE_SYSCALL_TABLE
269 #undef TRACE_SYSCALL_TABLE
270 #define TRACE_SYSCALL_TABLE(_template, _name, _nr, _nrargs) \
272 .func = __event_probe__syscall_enter_##_template, \
273 .nrargs = (_nrargs), \
274 .fields = __event_fields___syscall_enter_##_template, \
275 .desc = &__event_desc___syscall_enter_##_name, \
278 /* Syscall enter tracing table */
279 static const struct trace_syscall_entry sc_table
[] = {
280 #include "instrumentation/syscalls/headers/syscalls_integers.h"
281 #include "instrumentation/syscalls/headers/syscalls_pointers.h"
284 #undef TRACE_SYSCALL_TABLE
285 #define TRACE_SYSCALL_TABLE(_template, _name, _nr, _nrargs) \
287 .func = __event_probe__compat_syscall_enter_##_template, \
288 .nrargs = (_nrargs), \
289 .fields = __event_fields___compat_syscall_enter_##_template, \
290 .desc = &__event_desc___compat_syscall_enter_##_name, \
293 /* Compat syscall enter table */
294 const struct trace_syscall_entry compat_sc_table
[] = {
295 #include "instrumentation/syscalls/headers/compat_syscalls_integers.h"
296 #include "instrumentation/syscalls/headers/compat_syscalls_pointers.h"
304 #define sc_exit(...) __VA_ARGS__
306 #undef TRACE_SYSCALL_TABLE
307 #define TRACE_SYSCALL_TABLE(_template, _name, _nr, _nrargs) \
309 .func = __event_probe__syscall_exit_##_template, \
310 .nrargs = (_nrargs), \
311 .fields = __event_fields___syscall_exit_##_template, \
312 .desc = &__event_desc___syscall_exit_##_name, \
315 /* Syscall exit table */
316 static const struct trace_syscall_entry sc_exit_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_exit_##_template, \
325 .nrargs = (_nrargs), \
326 .fields = __event_fields___compat_syscall_exit_##_template, \
327 .desc = &__event_desc___compat_syscall_exit_##_name, \
330 /* Compat syscall exit table */
331 const struct trace_syscall_entry compat_sc_exit_table
[] = {
332 #include "instrumentation/syscalls/headers/compat_syscalls_integers.h"
333 #include "instrumentation/syscalls/headers/compat_syscalls_pointers.h"
338 #undef CREATE_SYSCALL_TABLE
340 struct lttng_syscall_filter
{
341 DECLARE_BITMAP(sc
, NR_syscalls
);
342 DECLARE_BITMAP(sc_compat
, NR_compat_syscalls
);
345 static void syscall_entry_unknown(struct lttng_event
*event
,
346 struct pt_regs
*regs
, unsigned int id
)
348 unsigned long args
[UNKNOWN_SYSCALL_NRARGS
];
350 syscall_get_arguments(current
, regs
, 0, UNKNOWN_SYSCALL_NRARGS
, args
);
351 if (unlikely(is_compat_task()))
352 __event_probe__compat_syscall_enter_unknown(event
, id
, args
);
354 __event_probe__syscall_enter_unknown(event
, id
, args
);
357 void syscall_entry_probe(void *__data
, struct pt_regs
*regs
, long id
)
359 struct lttng_channel
*chan
= __data
;
360 struct lttng_event
*event
, *unknown_event
;
361 const struct trace_syscall_entry
*table
, *entry
;
364 if (unlikely(is_compat_task())) {
365 struct lttng_syscall_filter
*filter
;
367 filter
= rcu_dereference(chan
->sc_filter
);
369 if (id
>= NR_compat_syscalls
370 || !test_bit(id
, filter
->sc_compat
)) {
371 /* System call filtered out. */
375 table
= compat_sc_table
;
376 table_len
= ARRAY_SIZE(compat_sc_table
);
377 unknown_event
= chan
->sc_compat_unknown
;
379 struct lttng_syscall_filter
*filter
;
381 filter
= rcu_dereference(chan
->sc_filter
);
383 if (id
>= NR_syscalls
384 || !test_bit(id
, filter
->sc
)) {
385 /* System call filtered out. */
390 table_len
= ARRAY_SIZE(sc_table
);
391 unknown_event
= chan
->sc_unknown
;
393 if (unlikely(id
>= table_len
)) {
394 syscall_entry_unknown(unknown_event
, regs
, id
);
397 if (unlikely(is_compat_task()))
398 event
= chan
->compat_sc_table
[id
];
400 event
= chan
->sc_table
[id
];
401 if (unlikely(!event
)) {
402 syscall_entry_unknown(unknown_event
, regs
, id
);
406 WARN_ON_ONCE(!entry
);
408 switch (entry
->nrargs
) {
411 void (*fptr
)(void *__data
) = entry
->func
;
418 void (*fptr
)(void *__data
, unsigned long arg0
) = entry
->func
;
419 unsigned long args
[1];
421 syscall_get_arguments(current
, regs
, 0, entry
->nrargs
, args
);
422 fptr(event
, args
[0]);
427 void (*fptr
)(void *__data
,
429 unsigned long arg1
) = entry
->func
;
430 unsigned long args
[2];
432 syscall_get_arguments(current
, regs
, 0, entry
->nrargs
, args
);
433 fptr(event
, args
[0], args
[1]);
438 void (*fptr
)(void *__data
,
441 unsigned long arg2
) = entry
->func
;
442 unsigned long args
[3];
444 syscall_get_arguments(current
, regs
, 0, entry
->nrargs
, args
);
445 fptr(event
, args
[0], args
[1], args
[2]);
450 void (*fptr
)(void *__data
,
454 unsigned long arg3
) = entry
->func
;
455 unsigned long args
[4];
457 syscall_get_arguments(current
, regs
, 0, entry
->nrargs
, args
);
458 fptr(event
, args
[0], args
[1], args
[2], args
[3]);
463 void (*fptr
)(void *__data
,
468 unsigned long arg4
) = entry
->func
;
469 unsigned long args
[5];
471 syscall_get_arguments(current
, regs
, 0, entry
->nrargs
, args
);
472 fptr(event
, args
[0], args
[1], args
[2], args
[3], args
[4]);
477 void (*fptr
)(void *__data
,
483 unsigned long arg5
) = entry
->func
;
484 unsigned long args
[6];
486 syscall_get_arguments(current
, regs
, 0, entry
->nrargs
, args
);
487 fptr(event
, args
[0], args
[1], args
[2],
488 args
[3], args
[4], args
[5]);
496 static void syscall_exit_unknown(struct lttng_event
*event
,
497 struct pt_regs
*regs
, unsigned int id
, long ret
)
499 unsigned long args
[UNKNOWN_SYSCALL_NRARGS
];
501 syscall_get_arguments(current
, regs
, 0, UNKNOWN_SYSCALL_NRARGS
, args
);
502 if (unlikely(is_compat_task()))
503 __event_probe__compat_syscall_exit_unknown(event
, id
, ret
,
506 __event_probe__syscall_exit_unknown(event
, id
, ret
, args
);
509 void syscall_exit_probe(void *__data
, struct pt_regs
*regs
, long ret
)
511 struct lttng_channel
*chan
= __data
;
512 struct lttng_event
*event
, *unknown_event
;
513 const struct trace_syscall_entry
*table
, *entry
;
517 id
= syscall_get_nr(current
, regs
);
518 if (unlikely(is_compat_task())) {
519 struct lttng_syscall_filter
*filter
;
521 filter
= rcu_dereference(chan
->sc_filter
);
523 if (id
>= NR_compat_syscalls
524 || !test_bit(id
, filter
->sc_compat
)) {
525 /* System call filtered out. */
529 table
= compat_sc_exit_table
;
530 table_len
= ARRAY_SIZE(compat_sc_exit_table
);
531 unknown_event
= chan
->compat_sc_exit_unknown
;
533 struct lttng_syscall_filter
*filter
;
535 filter
= rcu_dereference(chan
->sc_filter
);
537 if (id
>= NR_syscalls
538 || !test_bit(id
, filter
->sc
)) {
539 /* System call filtered out. */
543 table
= sc_exit_table
;
544 table_len
= ARRAY_SIZE(sc_exit_table
);
545 unknown_event
= chan
->sc_exit_unknown
;
547 if (unlikely(id
>= table_len
)) {
548 syscall_exit_unknown(unknown_event
, regs
, id
, ret
);
551 if (unlikely(is_compat_task()))
552 event
= chan
->compat_sc_exit_table
[id
];
554 event
= chan
->sc_exit_table
[id
];
555 if (unlikely(!event
)) {
556 syscall_exit_unknown(unknown_event
, regs
, id
, ret
);
560 WARN_ON_ONCE(!entry
);
562 switch (entry
->nrargs
) {
565 void (*fptr
)(void *__data
, long ret
) = entry
->func
;
572 void (*fptr
)(void *__data
,
574 unsigned long arg0
) = entry
->func
;
575 unsigned long args
[1];
577 syscall_get_arguments(current
, regs
, 0, entry
->nrargs
, args
);
578 fptr(event
, ret
, args
[0]);
583 void (*fptr
)(void *__data
,
586 unsigned long arg1
) = entry
->func
;
587 unsigned long args
[2];
589 syscall_get_arguments(current
, regs
, 0, entry
->nrargs
, args
);
590 fptr(event
, ret
, args
[0], args
[1]);
595 void (*fptr
)(void *__data
,
599 unsigned long arg2
) = entry
->func
;
600 unsigned long args
[3];
602 syscall_get_arguments(current
, regs
, 0, entry
->nrargs
, args
);
603 fptr(event
, ret
, args
[0], args
[1], args
[2]);
608 void (*fptr
)(void *__data
,
613 unsigned long arg3
) = entry
->func
;
614 unsigned long args
[4];
616 syscall_get_arguments(current
, regs
, 0, entry
->nrargs
, args
);
617 fptr(event
, ret
, args
[0], args
[1], args
[2], args
[3]);
622 void (*fptr
)(void *__data
,
628 unsigned long arg4
) = entry
->func
;
629 unsigned long args
[5];
631 syscall_get_arguments(current
, regs
, 0, entry
->nrargs
, args
);
632 fptr(event
, ret
, args
[0], args
[1], args
[2], args
[3], args
[4]);
637 void (*fptr
)(void *__data
,
644 unsigned long arg5
) = entry
->func
;
645 unsigned long args
[6];
647 syscall_get_arguments(current
, regs
, 0, entry
->nrargs
, args
);
648 fptr(event
, ret
, args
[0], args
[1], args
[2],
649 args
[3], args
[4], args
[5]);
657 /* noinline to diminish caller stack size */
659 int fill_table(const struct trace_syscall_entry
*table
, size_t table_len
,
660 struct lttng_event
**chan_table
, struct lttng_channel
*chan
,
661 void *filter
, enum sc_type type
)
663 const struct lttng_event_desc
*desc
;
666 /* Allocate events for each syscall, insert into table */
667 for (i
= 0; i
< table_len
; i
++) {
668 struct lttng_kernel_event ev
;
669 desc
= table
[i
].desc
;
672 /* Unknown syscall */
676 * Skip those already populated by previous failed
677 * register for this channel.
681 memset(&ev
, 0, sizeof(ev
));
684 strncpy(ev
.name
, SYSCALL_ENTRY_STR
,
685 LTTNG_KERNEL_SYM_NAME_LEN
);
688 strncpy(ev
.name
, SYSCALL_EXIT_STR
,
689 LTTNG_KERNEL_SYM_NAME_LEN
);
691 case SC_TYPE_COMPAT_ENTRY
:
692 strncpy(ev
.name
, COMPAT_SYSCALL_ENTRY_STR
,
693 LTTNG_KERNEL_SYM_NAME_LEN
);
695 case SC_TYPE_COMPAT_EXIT
:
696 strncpy(ev
.name
, COMPAT_SYSCALL_EXIT_STR
,
697 LTTNG_KERNEL_SYM_NAME_LEN
);
703 strncat(ev
.name
, desc
->name
,
704 LTTNG_KERNEL_SYM_NAME_LEN
- strlen(ev
.name
) - 1);
705 ev
.name
[LTTNG_KERNEL_SYM_NAME_LEN
- 1] = '\0';
706 ev
.instrumentation
= LTTNG_KERNEL_NOOP
;
707 chan_table
[i
] = lttng_event_create(chan
, &ev
, filter
,
709 WARN_ON_ONCE(!chan_table
[i
]);
710 if (IS_ERR(chan_table
[i
])) {
712 * If something goes wrong in event registration
713 * after the first one, we have no choice but to
714 * leave the previous events in there, until
715 * deleted by session teardown.
717 return PTR_ERR(chan_table
[i
]);
723 int lttng_syscalls_register(struct lttng_channel
*chan
, void *filter
)
725 struct lttng_kernel_event ev
;
728 wrapper_vmalloc_sync_all();
730 if (!chan
->sc_table
) {
731 /* create syscall table mapping syscall to events */
732 chan
->sc_table
= kzalloc(sizeof(struct lttng_event
*)
733 * ARRAY_SIZE(sc_table
), GFP_KERNEL
);
737 if (!chan
->sc_exit_table
) {
738 /* create syscall table mapping syscall to events */
739 chan
->sc_exit_table
= kzalloc(sizeof(struct lttng_event
*)
740 * ARRAY_SIZE(sc_exit_table
), GFP_KERNEL
);
741 if (!chan
->sc_exit_table
)
747 if (!chan
->compat_sc_table
) {
748 /* create syscall table mapping compat syscall to events */
749 chan
->compat_sc_table
= kzalloc(sizeof(struct lttng_event
*)
750 * ARRAY_SIZE(compat_sc_table
), GFP_KERNEL
);
751 if (!chan
->compat_sc_table
)
755 if (!chan
->compat_sc_exit_table
) {
756 /* create syscall table mapping compat syscall to events */
757 chan
->compat_sc_exit_table
= kzalloc(sizeof(struct lttng_event
*)
758 * ARRAY_SIZE(compat_sc_exit_table
), GFP_KERNEL
);
759 if (!chan
->compat_sc_exit_table
)
763 if (!chan
->sc_unknown
) {
764 const struct lttng_event_desc
*desc
=
765 &__event_desc___syscall_enter_unknown
;
767 memset(&ev
, 0, sizeof(ev
));
768 strncpy(ev
.name
, desc
->name
, LTTNG_KERNEL_SYM_NAME_LEN
);
769 ev
.name
[LTTNG_KERNEL_SYM_NAME_LEN
- 1] = '\0';
770 ev
.instrumentation
= LTTNG_KERNEL_NOOP
;
771 chan
->sc_unknown
= lttng_event_create(chan
, &ev
, filter
,
773 WARN_ON_ONCE(!chan
->sc_unknown
);
774 if (IS_ERR(chan
->sc_unknown
)) {
775 return PTR_ERR(chan
->sc_unknown
);
779 if (!chan
->sc_compat_unknown
) {
780 const struct lttng_event_desc
*desc
=
781 &__event_desc___compat_syscall_enter_unknown
;
783 memset(&ev
, 0, sizeof(ev
));
784 strncpy(ev
.name
, desc
->name
, LTTNG_KERNEL_SYM_NAME_LEN
);
785 ev
.name
[LTTNG_KERNEL_SYM_NAME_LEN
- 1] = '\0';
786 ev
.instrumentation
= LTTNG_KERNEL_NOOP
;
787 chan
->sc_compat_unknown
= lttng_event_create(chan
, &ev
, filter
,
789 WARN_ON_ONCE(!chan
->sc_unknown
);
790 if (IS_ERR(chan
->sc_compat_unknown
)) {
791 return PTR_ERR(chan
->sc_compat_unknown
);
795 if (!chan
->compat_sc_exit_unknown
) {
796 const struct lttng_event_desc
*desc
=
797 &__event_desc___compat_syscall_exit_unknown
;
799 memset(&ev
, 0, sizeof(ev
));
800 strncpy(ev
.name
, desc
->name
, LTTNG_KERNEL_SYM_NAME_LEN
);
801 ev
.name
[LTTNG_KERNEL_SYM_NAME_LEN
- 1] = '\0';
802 ev
.instrumentation
= LTTNG_KERNEL_NOOP
;
803 chan
->compat_sc_exit_unknown
= lttng_event_create(chan
, &ev
,
805 WARN_ON_ONCE(!chan
->compat_sc_exit_unknown
);
806 if (IS_ERR(chan
->compat_sc_exit_unknown
)) {
807 return PTR_ERR(chan
->compat_sc_exit_unknown
);
811 if (!chan
->sc_exit_unknown
) {
812 const struct lttng_event_desc
*desc
=
813 &__event_desc___syscall_exit_unknown
;
815 memset(&ev
, 0, sizeof(ev
));
816 strncpy(ev
.name
, desc
->name
, LTTNG_KERNEL_SYM_NAME_LEN
);
817 ev
.name
[LTTNG_KERNEL_SYM_NAME_LEN
- 1] = '\0';
818 ev
.instrumentation
= LTTNG_KERNEL_NOOP
;
819 chan
->sc_exit_unknown
= lttng_event_create(chan
, &ev
, filter
,
821 WARN_ON_ONCE(!chan
->sc_exit_unknown
);
822 if (IS_ERR(chan
->sc_exit_unknown
)) {
823 return PTR_ERR(chan
->sc_exit_unknown
);
827 ret
= fill_table(sc_table
, ARRAY_SIZE(sc_table
),
828 chan
->sc_table
, chan
, filter
, SC_TYPE_ENTRY
);
831 ret
= fill_table(sc_exit_table
, ARRAY_SIZE(sc_exit_table
),
832 chan
->sc_exit_table
, chan
, filter
, SC_TYPE_EXIT
);
837 ret
= fill_table(compat_sc_table
, ARRAY_SIZE(compat_sc_table
),
838 chan
->compat_sc_table
, chan
, filter
,
839 SC_TYPE_COMPAT_ENTRY
);
842 ret
= fill_table(compat_sc_exit_table
, ARRAY_SIZE(compat_sc_exit_table
),
843 chan
->compat_sc_exit_table
, chan
, filter
,
844 SC_TYPE_COMPAT_EXIT
);
848 if (!chan
->sys_enter_registered
) {
849 ret
= lttng_wrapper_tracepoint_probe_register("sys_enter",
850 (void *) syscall_entry_probe
, chan
);
853 chan
->sys_enter_registered
= 1;
856 * We change the name of sys_exit tracepoint due to namespace
857 * conflict with sys_exit syscall entry.
859 if (!chan
->sys_exit_registered
) {
860 ret
= lttng_wrapper_tracepoint_probe_register("sys_exit",
861 (void *) syscall_exit_probe
, chan
);
863 WARN_ON_ONCE(lttng_wrapper_tracepoint_probe_unregister("sys_enter",
864 (void *) syscall_entry_probe
, chan
));
867 chan
->sys_exit_registered
= 1;
873 * Only called at session destruction.
875 int lttng_syscalls_unregister(struct lttng_channel
*chan
)
881 if (chan
->sys_enter_registered
) {
882 ret
= lttng_wrapper_tracepoint_probe_unregister("sys_exit",
883 (void *) syscall_exit_probe
, chan
);
886 chan
->sys_enter_registered
= 0;
888 if (chan
->sys_exit_registered
) {
889 ret
= lttng_wrapper_tracepoint_probe_unregister("sys_enter",
890 (void *) syscall_entry_probe
, chan
);
893 chan
->sys_exit_registered
= 0;
895 /* lttng_event destroy will be performed by lttng_session_destroy() */
896 kfree(chan
->sc_table
);
897 kfree(chan
->sc_exit_table
);
899 kfree(chan
->compat_sc_table
);
900 kfree(chan
->compat_sc_exit_table
);
902 kfree(chan
->sc_filter
);
907 int get_syscall_nr(const char *syscall_name
)
912 for (i
= 0; i
< ARRAY_SIZE(sc_table
); i
++) {
913 const struct trace_syscall_entry
*entry
;
916 entry
= &sc_table
[i
];
919 it_name
= entry
->desc
->name
;
920 it_name
+= strlen(SYSCALL_ENTRY_STR
);
921 if (!strcmp(syscall_name
, it_name
)) {
930 int get_compat_syscall_nr(const char *syscall_name
)
935 for (i
= 0; i
< ARRAY_SIZE(compat_sc_table
); i
++) {
936 const struct trace_syscall_entry
*entry
;
939 entry
= &compat_sc_table
[i
];
942 it_name
= entry
->desc
->name
;
943 it_name
+= strlen(COMPAT_SYSCALL_ENTRY_STR
);
944 if (!strcmp(syscall_name
, it_name
)) {
952 int lttng_syscall_filter_enable(struct lttng_channel
*chan
,
955 int syscall_nr
, compat_syscall_nr
, ret
;
956 struct lttng_syscall_filter
*filter
;
958 WARN_ON_ONCE(!chan
->sc_table
);
961 /* Enable all system calls by removing filter */
962 if (chan
->sc_filter
) {
963 filter
= chan
->sc_filter
;
964 rcu_assign_pointer(chan
->sc_filter
, NULL
);
968 chan
->syscall_all
= 1;
972 if (!chan
->sc_filter
) {
973 if (chan
->syscall_all
) {
975 * All syscalls are already enabled.
979 filter
= kzalloc(sizeof(struct lttng_syscall_filter
),
984 filter
= chan
->sc_filter
;
986 syscall_nr
= get_syscall_nr(name
);
987 compat_syscall_nr
= get_compat_syscall_nr(name
);
988 if (syscall_nr
< 0 && compat_syscall_nr
< 0) {
992 if (syscall_nr
>= 0) {
993 if (test_bit(syscall_nr
, filter
->sc
)) {
997 bitmap_set(filter
->sc
, syscall_nr
, 1);
999 if (compat_syscall_nr
>= 0) {
1000 if (test_bit(compat_syscall_nr
, filter
->sc_compat
)) {
1004 bitmap_set(filter
->sc_compat
, compat_syscall_nr
, 1);
1006 if (!chan
->sc_filter
)
1007 rcu_assign_pointer(chan
->sc_filter
, filter
);
1011 if (!chan
->sc_filter
)
1016 int lttng_syscall_filter_disable(struct lttng_channel
*chan
,
1019 int syscall_nr
, compat_syscall_nr
, ret
;
1020 struct lttng_syscall_filter
*filter
;
1022 WARN_ON_ONCE(!chan
->sc_table
);
1024 if (!chan
->sc_filter
) {
1025 filter
= kzalloc(sizeof(struct lttng_syscall_filter
),
1029 /* Trace all system calls, then apply disable. */
1030 bitmap_set(filter
->sc
, 0, NR_syscalls
);
1031 bitmap_set(filter
->sc_compat
, 0, NR_compat_syscalls
);
1033 filter
= chan
->sc_filter
;
1037 /* Disable all system calls */
1038 bitmap_clear(filter
->sc
, 0, NR_syscalls
);
1039 bitmap_clear(filter
->sc_compat
, 0, NR_compat_syscalls
);
1042 syscall_nr
= get_syscall_nr(name
);
1043 compat_syscall_nr
= get_compat_syscall_nr(name
);
1044 if (syscall_nr
< 0 && compat_syscall_nr
< 0) {
1048 if (syscall_nr
>= 0) {
1049 if (!test_bit(syscall_nr
, chan
->sc_filter
->sc
)) {
1053 bitmap_clear(chan
->sc_filter
->sc
, syscall_nr
, 1);
1055 if (compat_syscall_nr
>= 0) {
1056 if (!test_bit(compat_syscall_nr
, chan
->sc_filter
->sc_compat
)) {
1060 bitmap_clear(chan
->sc_filter
->sc_compat
, compat_syscall_nr
, 1);
1063 if (!chan
->sc_filter
)
1064 rcu_assign_pointer(chan
->sc_filter
, filter
);
1065 chan
->syscall_all
= 0;
1069 if (!chan
->sc_filter
)