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 <linux/seq_file.h>
31 #include <asm/ptrace.h>
32 #include <asm/syscall.h>
34 #include "lib/bitfield.h"
35 #include "wrapper/tracepoint.h"
36 #include "lttng-events.h"
39 # ifndef is_compat_task
40 # define is_compat_task() (0)
51 #define SYSCALL_ENTRY_STR "syscall_entry_"
52 #define COMPAT_SYSCALL_ENTRY_STR "compat_syscall_entry_"
53 #define SYSCALL_EXIT_STR "syscall_exit_"
54 #define COMPAT_SYSCALL_EXIT_STR "compat_syscall_exit_"
57 void syscall_entry_probe(void *__data
, struct pt_regs
*regs
, long id
);
59 void syscall_exit_probe(void *__data
, struct pt_regs
*regs
, long ret
);
62 * Forward declarations for old kernels.
66 struct oldold_utsname
;
68 struct sel_arg_struct
;
69 struct mmap_arg_struct
;
71 #ifdef IA32_NR_syscalls
72 #define NR_compat_syscalls IA32_NR_syscalls
74 #define NR_compat_syscalls NR_syscalls
78 * Create LTTng tracepoint probes.
80 #define LTTNG_PACKAGE_BUILD
81 #define CREATE_TRACE_POINTS
82 #define TP_MODULE_NOINIT
83 #define TRACE_INCLUDE_PATH ../instrumentation/syscalls/headers
85 #define PARAMS(args...) args
87 /* Handle unknown syscalls */
88 #define TRACE_SYSTEM syscalls_unknown
89 #include "instrumentation/syscalls/headers/syscalls_unknown.h"
97 #define sc_in(...) __VA_ARGS__
101 #define sc_inout(...) __VA_ARGS__
103 /* Hijack probe callback for system call enter */
105 #define TP_PROBE_CB(_template) &syscall_entry_probe
106 #define SC_LTTNG_TRACEPOINT_EVENT(_name, _proto, _args, _struct, _assign, _printk) \
107 LTTNG_TRACEPOINT_EVENT(syscall_enter_##_name, PARAMS(_proto), PARAMS(_args), \
108 PARAMS(_struct), PARAMS(_assign), PARAMS(_printk))
109 #define SC_LTTNG_TRACEPOINT_EVENT_CODE(_name, _proto, _args, _locvar, _code, _struct, _assign, _printk) \
110 LTTNG_TRACEPOINT_EVENT_CODE(syscall_enter_##_name, PARAMS(_proto), PARAMS(_args), \
111 PARAMS(_locvar), PARAMS(_code), \
112 PARAMS(_struct), PARAMS(_assign), PARAMS(_printk))
113 #define SC_LTTNG_TRACEPOINT_EVENT_CLASS_NOARGS(_name, _struct, _assign, _printk) \
114 LTTNG_TRACEPOINT_EVENT_CLASS_NOARGS(syscall_enter_##_name, PARAMS(_struct), PARAMS(_assign), \
116 #define SC_LTTNG_TRACEPOINT_EVENT_INSTANCE_NOARGS(_template, _name) \
117 LTTNG_TRACEPOINT_EVENT_INSTANCE_NOARGS(syscall_enter_##_template, syscall_enter_##_name)
119 #define TRACE_SYSTEM syscall_enter_integers
120 #define TRACE_INCLUDE_FILE syscalls_integers
121 #include "instrumentation/syscalls/headers/syscalls_integers.h"
122 #undef TRACE_INCLUDE_FILE
124 #define TRACE_SYSTEM syscall_enter_pointers
125 #define TRACE_INCLUDE_FILE syscalls_pointers
126 #include "instrumentation/syscalls/headers/syscalls_pointers.h"
127 #undef TRACE_INCLUDE_FILE
129 #undef SC_LTTNG_TRACEPOINT_EVENT_CODE
130 #undef SC_LTTNG_TRACEPOINT_EVENT
131 #undef SC_LTTNG_TRACEPOINT_EVENT_CLASS_NOARGS
132 #undef SC_LTTNG_TRACEPOINT_EVENT_INSTANCE_NOARGS
134 #undef _TRACE_SYSCALLS_INTEGERS_H
135 #undef _TRACE_SYSCALLS_POINTERS_H
137 /* Hijack probe callback for compat system call enter */
138 #define TP_PROBE_CB(_template) &syscall_entry_probe
139 #define SC_LTTNG_TRACEPOINT_EVENT(_name, _proto, _args, _struct, _assign, _printk) \
140 LTTNG_TRACEPOINT_EVENT(compat_syscall_enter_##_name, PARAMS(_proto), PARAMS(_args), \
141 PARAMS(_struct), PARAMS(_assign), \
143 #define SC_LTTNG_TRACEPOINT_EVENT_CODE(_name, _proto, _args, _locvar, _code, _struct, _assign, _printk) \
144 LTTNG_TRACEPOINT_EVENT_CODE(compat_syscall_enter_##_name, PARAMS(_proto), PARAMS(_args), \
145 PARAMS(_locvar), PARAMS(_code), \
146 PARAMS(_struct), PARAMS(_assign), PARAMS(_printk))
147 #define SC_LTTNG_TRACEPOINT_EVENT_CLASS_NOARGS(_name, _struct, _assign, _printk) \
148 LTTNG_TRACEPOINT_EVENT_CLASS_NOARGS(compat_syscall_enter_##_name, PARAMS(_struct), \
149 PARAMS(_assign), PARAMS(_printk))
150 #define SC_LTTNG_TRACEPOINT_EVENT_INSTANCE_NOARGS(_template, _name) \
151 LTTNG_TRACEPOINT_EVENT_INSTANCE_NOARGS(compat_syscall_enter_##_template, \
152 compat_syscall_enter_##_name)
153 #define TRACE_SYSTEM compat_syscall_enter_integers
154 #define TRACE_INCLUDE_FILE compat_syscalls_integers
155 #include "instrumentation/syscalls/headers/compat_syscalls_integers.h"
156 #undef TRACE_INCLUDE_FILE
158 #define TRACE_SYSTEM compat_syscall_enter_pointers
159 #define TRACE_INCLUDE_FILE compat_syscalls_pointers
160 #include "instrumentation/syscalls/headers/compat_syscalls_pointers.h"
161 #undef TRACE_INCLUDE_FILE
163 #undef SC_LTTNG_TRACEPOINT_EVENT_CODE
164 #undef SC_LTTNG_TRACEPOINT_EVENT
165 #undef SC_LTTNG_TRACEPOINT_EVENT_CLASS_NOARGS
166 #undef SC_LTTNG_TRACEPOINT_EVENT_INSTANCE_NOARGS
168 #undef _TRACE_SYSCALLS_INTEGERS_H
169 #undef _TRACE_SYSCALLS_POINTERS_H
176 #define sc_exit(...) __VA_ARGS__
180 #define sc_out(...) __VA_ARGS__
182 #define sc_inout(...) __VA_ARGS__
184 /* Hijack probe callback for system call exit */
185 #define TP_PROBE_CB(_template) &syscall_exit_probe
186 #define SC_LTTNG_TRACEPOINT_EVENT(_name, _proto, _args, _struct, _assign, _printk) \
187 LTTNG_TRACEPOINT_EVENT(syscall_exit_##_name, PARAMS(_proto), PARAMS(_args), \
188 PARAMS(_struct), PARAMS(_assign), PARAMS(_printk))
189 #define SC_LTTNG_TRACEPOINT_EVENT_CODE(_name, _proto, _args, _locvar, _code, _struct, _assign, _printk) \
190 LTTNG_TRACEPOINT_EVENT_CODE(syscall_exit_##_name, PARAMS(_proto), PARAMS(_args), \
191 PARAMS(_locvar), PARAMS(_code), \
192 PARAMS(_struct), PARAMS(_assign), PARAMS(_printk))
193 #define SC_LTTNG_TRACEPOINT_EVENT_CLASS_NOARGS(_name, _struct, _assign, _printk) \
194 LTTNG_TRACEPOINT_EVENT_CLASS_NOARGS(syscall_exit_##_name, PARAMS(_struct), \
195 PARAMS(_assign), PARAMS(_printk))
196 #define SC_LTTNG_TRACEPOINT_EVENT_INSTANCE_NOARGS(_template, _name) \
197 LTTNG_TRACEPOINT_EVENT_INSTANCE_NOARGS(syscall_exit_##_template, \
198 syscall_exit_##_name)
199 #define TRACE_SYSTEM syscall_exit_integers
200 #define TRACE_INCLUDE_FILE syscalls_integers
201 #include "instrumentation/syscalls/headers/syscalls_integers.h"
202 #undef TRACE_INCLUDE_FILE
204 #define TRACE_SYSTEM syscall_exit_pointers
205 #define TRACE_INCLUDE_FILE syscalls_pointers
206 #include "instrumentation/syscalls/headers/syscalls_pointers.h"
207 #undef TRACE_INCLUDE_FILE
209 #undef SC_LTTNG_TRACEPOINT_EVENT_CODE
210 #undef SC_LTTNG_TRACEPOINT_EVENT
211 #undef SC_LTTNG_TRACEPOINT_EVENT_CLASS_NOARGS
212 #undef SC_LTTNG_TRACEPOINT_EVENT_INSTANCE_NOARGS
214 #undef _TRACE_SYSCALLS_INTEGERS_H
215 #undef _TRACE_SYSCALLS_POINTERS_H
218 /* Hijack probe callback for compat system call exit */
219 #define TP_PROBE_CB(_template) &syscall_exit_probe
220 #define SC_LTTNG_TRACEPOINT_EVENT(_name, _proto, _args, _struct, _assign, _printk) \
221 LTTNG_TRACEPOINT_EVENT(compat_syscall_exit_##_name, PARAMS(_proto), PARAMS(_args), \
222 PARAMS(_struct), PARAMS(_assign), PARAMS(_printk))
223 #define SC_LTTNG_TRACEPOINT_EVENT_CODE(_name, _proto, _args, _locvar, _code, _struct, _assign, _printk) \
224 LTTNG_TRACEPOINT_EVENT_CODE(compat_syscall_exit_##_name, PARAMS(_proto), PARAMS(_args), \
225 PARAMS(_locvar), PARAMS(_code), \
226 PARAMS(_struct), PARAMS(_assign), PARAMS(_printk))
227 #define SC_LTTNG_TRACEPOINT_EVENT_CLASS_NOARGS(_name, _struct, _assign, _printk) \
228 LTTNG_TRACEPOINT_EVENT_CLASS_NOARGS(compat_syscall_exit_##_name, PARAMS(_struct), \
229 PARAMS(_assign), PARAMS(_printk))
230 #define SC_LTTNG_TRACEPOINT_EVENT_INSTANCE_NOARGS(_template, _name) \
231 LTTNG_TRACEPOINT_EVENT_INSTANCE_NOARGS(compat_syscall_exit_##_template, \
232 compat_syscall_exit_##_name)
233 #define TRACE_SYSTEM compat_syscall_exit_integers
234 #define TRACE_INCLUDE_FILE compat_syscalls_integers
235 #include "instrumentation/syscalls/headers/compat_syscalls_integers.h"
236 #undef TRACE_INCLUDE_FILE
238 #define TRACE_SYSTEM compat_syscall_exit_pointers
239 #define TRACE_INCLUDE_FILE compat_syscalls_pointers
240 #include "instrumentation/syscalls/headers/compat_syscalls_pointers.h"
241 #undef TRACE_INCLUDE_FILE
243 #undef SC_LTTNG_TRACEPOINT_EVENT_CODE
244 #undef SC_LTTNG_TRACEPOINT_EVENT
245 #undef SC_LTTNG_TRACEPOINT_EVENT_CLASS_NOARGS
246 #undef SC_LTTNG_TRACEPOINT_EVENT_INSTANCE_NOARGS
248 #undef _TRACE_SYSCALLS_INTEGERS_H
249 #undef _TRACE_SYSCALLS_POINTERS_H
253 #undef TP_MODULE_NOINIT
254 #undef LTTNG_PACKAGE_BUILD
255 #undef CREATE_TRACE_POINTS
257 struct trace_syscall_entry
{
259 const struct lttng_event_desc
*desc
;
260 const struct lttng_event_field
*fields
;
264 #define CREATE_SYSCALL_TABLE
271 #undef TRACE_SYSCALL_TABLE
272 #define TRACE_SYSCALL_TABLE(_template, _name, _nr, _nrargs) \
274 .func = __event_probe__syscall_enter_##_template, \
275 .nrargs = (_nrargs), \
276 .fields = __event_fields___syscall_enter_##_template, \
277 .desc = &__event_desc___syscall_enter_##_name, \
280 /* Syscall enter tracing table */
281 static const struct trace_syscall_entry sc_table
[] = {
282 #include "instrumentation/syscalls/headers/syscalls_integers.h"
283 #include "instrumentation/syscalls/headers/syscalls_pointers.h"
286 #undef TRACE_SYSCALL_TABLE
287 #define TRACE_SYSCALL_TABLE(_template, _name, _nr, _nrargs) \
289 .func = __event_probe__compat_syscall_enter_##_template, \
290 .nrargs = (_nrargs), \
291 .fields = __event_fields___compat_syscall_enter_##_template, \
292 .desc = &__event_desc___compat_syscall_enter_##_name, \
295 /* Compat syscall enter table */
296 const struct trace_syscall_entry compat_sc_table
[] = {
297 #include "instrumentation/syscalls/headers/compat_syscalls_integers.h"
298 #include "instrumentation/syscalls/headers/compat_syscalls_pointers.h"
306 #define sc_exit(...) __VA_ARGS__
308 #undef TRACE_SYSCALL_TABLE
309 #define TRACE_SYSCALL_TABLE(_template, _name, _nr, _nrargs) \
311 .func = __event_probe__syscall_exit_##_template, \
312 .nrargs = (_nrargs), \
313 .fields = __event_fields___syscall_exit_##_template, \
314 .desc = &__event_desc___syscall_exit_##_name, \
317 /* Syscall exit table */
318 static const struct trace_syscall_entry sc_exit_table
[] = {
319 #include "instrumentation/syscalls/headers/syscalls_integers.h"
320 #include "instrumentation/syscalls/headers/syscalls_pointers.h"
323 #undef TRACE_SYSCALL_TABLE
324 #define TRACE_SYSCALL_TABLE(_template, _name, _nr, _nrargs) \
326 .func = __event_probe__compat_syscall_exit_##_template, \
327 .nrargs = (_nrargs), \
328 .fields = __event_fields___compat_syscall_exit_##_template, \
329 .desc = &__event_desc___compat_syscall_exit_##_name, \
332 /* Compat syscall exit table */
333 const struct trace_syscall_entry compat_sc_exit_table
[] = {
334 #include "instrumentation/syscalls/headers/compat_syscalls_integers.h"
335 #include "instrumentation/syscalls/headers/compat_syscalls_pointers.h"
340 #undef CREATE_SYSCALL_TABLE
342 struct lttng_syscall_filter
{
343 DECLARE_BITMAP(sc
, NR_syscalls
);
344 DECLARE_BITMAP(sc_compat
, NR_compat_syscalls
);
347 static void syscall_entry_unknown(struct lttng_event
*event
,
348 struct pt_regs
*regs
, unsigned int id
)
350 unsigned long args
[UNKNOWN_SYSCALL_NRARGS
];
352 syscall_get_arguments(current
, regs
, 0, UNKNOWN_SYSCALL_NRARGS
, args
);
353 if (unlikely(is_compat_task()))
354 __event_probe__compat_syscall_enter_unknown(event
, id
, args
);
356 __event_probe__syscall_enter_unknown(event
, id
, args
);
359 void syscall_entry_probe(void *__data
, struct pt_regs
*regs
, long id
)
361 struct lttng_channel
*chan
= __data
;
362 struct lttng_event
*event
, *unknown_event
;
363 const struct trace_syscall_entry
*table
, *entry
;
366 if (unlikely(is_compat_task())) {
367 struct lttng_syscall_filter
*filter
;
369 filter
= rcu_dereference(chan
->sc_filter
);
371 if (id
>= NR_compat_syscalls
372 || !test_bit(id
, filter
->sc_compat
)) {
373 /* System call filtered out. */
377 table
= compat_sc_table
;
378 table_len
= ARRAY_SIZE(compat_sc_table
);
379 unknown_event
= chan
->sc_compat_unknown
;
381 struct lttng_syscall_filter
*filter
;
383 filter
= rcu_dereference(chan
->sc_filter
);
385 if (id
>= NR_syscalls
386 || !test_bit(id
, filter
->sc
)) {
387 /* System call filtered out. */
392 table_len
= ARRAY_SIZE(sc_table
);
393 unknown_event
= chan
->sc_unknown
;
395 if (unlikely(id
>= table_len
)) {
396 syscall_entry_unknown(unknown_event
, regs
, id
);
399 if (unlikely(is_compat_task()))
400 event
= chan
->compat_sc_table
[id
];
402 event
= chan
->sc_table
[id
];
403 if (unlikely(!event
)) {
404 syscall_entry_unknown(unknown_event
, regs
, id
);
408 WARN_ON_ONCE(!entry
);
410 switch (entry
->nrargs
) {
413 void (*fptr
)(void *__data
) = entry
->func
;
420 void (*fptr
)(void *__data
, unsigned long arg0
) = entry
->func
;
421 unsigned long args
[1];
423 syscall_get_arguments(current
, regs
, 0, entry
->nrargs
, args
);
424 fptr(event
, args
[0]);
429 void (*fptr
)(void *__data
,
431 unsigned long arg1
) = entry
->func
;
432 unsigned long args
[2];
434 syscall_get_arguments(current
, regs
, 0, entry
->nrargs
, args
);
435 fptr(event
, args
[0], args
[1]);
440 void (*fptr
)(void *__data
,
443 unsigned long arg2
) = entry
->func
;
444 unsigned long args
[3];
446 syscall_get_arguments(current
, regs
, 0, entry
->nrargs
, args
);
447 fptr(event
, args
[0], args
[1], args
[2]);
452 void (*fptr
)(void *__data
,
456 unsigned long arg3
) = entry
->func
;
457 unsigned long args
[4];
459 syscall_get_arguments(current
, regs
, 0, entry
->nrargs
, args
);
460 fptr(event
, args
[0], args
[1], args
[2], args
[3]);
465 void (*fptr
)(void *__data
,
470 unsigned long arg4
) = entry
->func
;
471 unsigned long args
[5];
473 syscall_get_arguments(current
, regs
, 0, entry
->nrargs
, args
);
474 fptr(event
, args
[0], args
[1], args
[2], args
[3], args
[4]);
479 void (*fptr
)(void *__data
,
485 unsigned long arg5
) = entry
->func
;
486 unsigned long args
[6];
488 syscall_get_arguments(current
, regs
, 0, entry
->nrargs
, args
);
489 fptr(event
, args
[0], args
[1], args
[2],
490 args
[3], args
[4], args
[5]);
498 static void syscall_exit_unknown(struct lttng_event
*event
,
499 struct pt_regs
*regs
, unsigned int id
, long ret
)
501 unsigned long args
[UNKNOWN_SYSCALL_NRARGS
];
503 syscall_get_arguments(current
, regs
, 0, UNKNOWN_SYSCALL_NRARGS
, args
);
504 if (unlikely(is_compat_task()))
505 __event_probe__compat_syscall_exit_unknown(event
, id
, ret
,
508 __event_probe__syscall_exit_unknown(event
, id
, ret
, args
);
511 void syscall_exit_probe(void *__data
, struct pt_regs
*regs
, long ret
)
513 struct lttng_channel
*chan
= __data
;
514 struct lttng_event
*event
, *unknown_event
;
515 const struct trace_syscall_entry
*table
, *entry
;
519 id
= syscall_get_nr(current
, regs
);
520 if (unlikely(is_compat_task())) {
521 struct lttng_syscall_filter
*filter
;
523 filter
= rcu_dereference(chan
->sc_filter
);
525 if (id
>= NR_compat_syscalls
526 || !test_bit(id
, filter
->sc_compat
)) {
527 /* System call filtered out. */
531 table
= compat_sc_exit_table
;
532 table_len
= ARRAY_SIZE(compat_sc_exit_table
);
533 unknown_event
= chan
->compat_sc_exit_unknown
;
535 struct lttng_syscall_filter
*filter
;
537 filter
= rcu_dereference(chan
->sc_filter
);
539 if (id
>= NR_syscalls
540 || !test_bit(id
, filter
->sc
)) {
541 /* System call filtered out. */
545 table
= sc_exit_table
;
546 table_len
= ARRAY_SIZE(sc_exit_table
);
547 unknown_event
= chan
->sc_exit_unknown
;
549 if (unlikely(id
>= table_len
)) {
550 syscall_exit_unknown(unknown_event
, regs
, id
, ret
);
553 if (unlikely(is_compat_task()))
554 event
= chan
->compat_sc_exit_table
[id
];
556 event
= chan
->sc_exit_table
[id
];
557 if (unlikely(!event
)) {
558 syscall_exit_unknown(unknown_event
, regs
, id
, ret
);
562 WARN_ON_ONCE(!entry
);
564 switch (entry
->nrargs
) {
567 void (*fptr
)(void *__data
, long ret
) = entry
->func
;
574 void (*fptr
)(void *__data
,
576 unsigned long arg0
) = entry
->func
;
577 unsigned long args
[1];
579 syscall_get_arguments(current
, regs
, 0, entry
->nrargs
, args
);
580 fptr(event
, ret
, args
[0]);
585 void (*fptr
)(void *__data
,
588 unsigned long arg1
) = entry
->func
;
589 unsigned long args
[2];
591 syscall_get_arguments(current
, regs
, 0, entry
->nrargs
, args
);
592 fptr(event
, ret
, args
[0], args
[1]);
597 void (*fptr
)(void *__data
,
601 unsigned long arg2
) = entry
->func
;
602 unsigned long args
[3];
604 syscall_get_arguments(current
, regs
, 0, entry
->nrargs
, args
);
605 fptr(event
, ret
, args
[0], args
[1], args
[2]);
610 void (*fptr
)(void *__data
,
615 unsigned long arg3
) = entry
->func
;
616 unsigned long args
[4];
618 syscall_get_arguments(current
, regs
, 0, entry
->nrargs
, args
);
619 fptr(event
, ret
, args
[0], args
[1], args
[2], args
[3]);
624 void (*fptr
)(void *__data
,
630 unsigned long arg4
) = entry
->func
;
631 unsigned long args
[5];
633 syscall_get_arguments(current
, regs
, 0, entry
->nrargs
, args
);
634 fptr(event
, ret
, args
[0], args
[1], args
[2], args
[3], args
[4]);
639 void (*fptr
)(void *__data
,
646 unsigned long arg5
) = entry
->func
;
647 unsigned long args
[6];
649 syscall_get_arguments(current
, regs
, 0, entry
->nrargs
, args
);
650 fptr(event
, ret
, args
[0], args
[1], args
[2],
651 args
[3], args
[4], args
[5]);
659 /* noinline to diminish caller stack size */
661 int fill_table(const struct trace_syscall_entry
*table
, size_t table_len
,
662 struct lttng_event
**chan_table
, struct lttng_channel
*chan
,
663 void *filter
, enum sc_type type
)
665 const struct lttng_event_desc
*desc
;
668 /* Allocate events for each syscall, insert into table */
669 for (i
= 0; i
< table_len
; i
++) {
670 struct lttng_kernel_event ev
;
671 desc
= table
[i
].desc
;
674 /* Unknown syscall */
678 * Skip those already populated by previous failed
679 * register for this channel.
683 memset(&ev
, 0, sizeof(ev
));
686 strncpy(ev
.name
, SYSCALL_ENTRY_STR
,
687 LTTNG_KERNEL_SYM_NAME_LEN
);
690 strncpy(ev
.name
, SYSCALL_EXIT_STR
,
691 LTTNG_KERNEL_SYM_NAME_LEN
);
693 case SC_TYPE_COMPAT_ENTRY
:
694 strncpy(ev
.name
, COMPAT_SYSCALL_ENTRY_STR
,
695 LTTNG_KERNEL_SYM_NAME_LEN
);
697 case SC_TYPE_COMPAT_EXIT
:
698 strncpy(ev
.name
, COMPAT_SYSCALL_EXIT_STR
,
699 LTTNG_KERNEL_SYM_NAME_LEN
);
705 strncat(ev
.name
, desc
->name
,
706 LTTNG_KERNEL_SYM_NAME_LEN
- strlen(ev
.name
) - 1);
707 ev
.name
[LTTNG_KERNEL_SYM_NAME_LEN
- 1] = '\0';
708 ev
.instrumentation
= LTTNG_KERNEL_NOOP
;
709 chan_table
[i
] = lttng_event_create(chan
, &ev
, filter
,
711 WARN_ON_ONCE(!chan_table
[i
]);
712 if (IS_ERR(chan_table
[i
])) {
714 * If something goes wrong in event registration
715 * after the first one, we have no choice but to
716 * leave the previous events in there, until
717 * deleted by session teardown.
719 return PTR_ERR(chan_table
[i
]);
725 int lttng_syscalls_register(struct lttng_channel
*chan
, void *filter
)
727 struct lttng_kernel_event ev
;
730 wrapper_vmalloc_sync_all();
732 if (!chan
->sc_table
) {
733 /* create syscall table mapping syscall to events */
734 chan
->sc_table
= kzalloc(sizeof(struct lttng_event
*)
735 * ARRAY_SIZE(sc_table
), GFP_KERNEL
);
739 if (!chan
->sc_exit_table
) {
740 /* create syscall table mapping syscall to events */
741 chan
->sc_exit_table
= kzalloc(sizeof(struct lttng_event
*)
742 * ARRAY_SIZE(sc_exit_table
), GFP_KERNEL
);
743 if (!chan
->sc_exit_table
)
749 if (!chan
->compat_sc_table
) {
750 /* create syscall table mapping compat syscall to events */
751 chan
->compat_sc_table
= kzalloc(sizeof(struct lttng_event
*)
752 * ARRAY_SIZE(compat_sc_table
), GFP_KERNEL
);
753 if (!chan
->compat_sc_table
)
757 if (!chan
->compat_sc_exit_table
) {
758 /* create syscall table mapping compat syscall to events */
759 chan
->compat_sc_exit_table
= kzalloc(sizeof(struct lttng_event
*)
760 * ARRAY_SIZE(compat_sc_exit_table
), GFP_KERNEL
);
761 if (!chan
->compat_sc_exit_table
)
765 if (!chan
->sc_unknown
) {
766 const struct lttng_event_desc
*desc
=
767 &__event_desc___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_unknown
= lttng_event_create(chan
, &ev
, filter
,
775 WARN_ON_ONCE(!chan
->sc_unknown
);
776 if (IS_ERR(chan
->sc_unknown
)) {
777 return PTR_ERR(chan
->sc_unknown
);
781 if (!chan
->sc_compat_unknown
) {
782 const struct lttng_event_desc
*desc
=
783 &__event_desc___compat_syscall_enter_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
->sc_compat_unknown
= lttng_event_create(chan
, &ev
, filter
,
791 WARN_ON_ONCE(!chan
->sc_unknown
);
792 if (IS_ERR(chan
->sc_compat_unknown
)) {
793 return PTR_ERR(chan
->sc_compat_unknown
);
797 if (!chan
->compat_sc_exit_unknown
) {
798 const struct lttng_event_desc
*desc
=
799 &__event_desc___compat_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
->compat_sc_exit_unknown
= lttng_event_create(chan
, &ev
,
807 WARN_ON_ONCE(!chan
->compat_sc_exit_unknown
);
808 if (IS_ERR(chan
->compat_sc_exit_unknown
)) {
809 return PTR_ERR(chan
->compat_sc_exit_unknown
);
813 if (!chan
->sc_exit_unknown
) {
814 const struct lttng_event_desc
*desc
=
815 &__event_desc___syscall_exit_unknown
;
817 memset(&ev
, 0, sizeof(ev
));
818 strncpy(ev
.name
, desc
->name
, LTTNG_KERNEL_SYM_NAME_LEN
);
819 ev
.name
[LTTNG_KERNEL_SYM_NAME_LEN
- 1] = '\0';
820 ev
.instrumentation
= LTTNG_KERNEL_NOOP
;
821 chan
->sc_exit_unknown
= lttng_event_create(chan
, &ev
, filter
,
823 WARN_ON_ONCE(!chan
->sc_exit_unknown
);
824 if (IS_ERR(chan
->sc_exit_unknown
)) {
825 return PTR_ERR(chan
->sc_exit_unknown
);
829 ret
= fill_table(sc_table
, ARRAY_SIZE(sc_table
),
830 chan
->sc_table
, chan
, filter
, SC_TYPE_ENTRY
);
833 ret
= fill_table(sc_exit_table
, ARRAY_SIZE(sc_exit_table
),
834 chan
->sc_exit_table
, chan
, filter
, SC_TYPE_EXIT
);
839 ret
= fill_table(compat_sc_table
, ARRAY_SIZE(compat_sc_table
),
840 chan
->compat_sc_table
, chan
, filter
,
841 SC_TYPE_COMPAT_ENTRY
);
844 ret
= fill_table(compat_sc_exit_table
, ARRAY_SIZE(compat_sc_exit_table
),
845 chan
->compat_sc_exit_table
, chan
, filter
,
846 SC_TYPE_COMPAT_EXIT
);
850 if (!chan
->sys_enter_registered
) {
851 ret
= lttng_wrapper_tracepoint_probe_register("sys_enter",
852 (void *) syscall_entry_probe
, chan
);
855 chan
->sys_enter_registered
= 1;
858 * We change the name of sys_exit tracepoint due to namespace
859 * conflict with sys_exit syscall entry.
861 if (!chan
->sys_exit_registered
) {
862 ret
= lttng_wrapper_tracepoint_probe_register("sys_exit",
863 (void *) syscall_exit_probe
, chan
);
865 WARN_ON_ONCE(lttng_wrapper_tracepoint_probe_unregister("sys_enter",
866 (void *) syscall_entry_probe
, chan
));
869 chan
->sys_exit_registered
= 1;
875 * Only called at session destruction.
877 int lttng_syscalls_unregister(struct lttng_channel
*chan
)
883 if (chan
->sys_enter_registered
) {
884 ret
= lttng_wrapper_tracepoint_probe_unregister("sys_exit",
885 (void *) syscall_exit_probe
, chan
);
888 chan
->sys_enter_registered
= 0;
890 if (chan
->sys_exit_registered
) {
891 ret
= lttng_wrapper_tracepoint_probe_unregister("sys_enter",
892 (void *) syscall_entry_probe
, chan
);
895 chan
->sys_exit_registered
= 0;
897 /* lttng_event destroy will be performed by lttng_session_destroy() */
898 kfree(chan
->sc_table
);
899 kfree(chan
->sc_exit_table
);
901 kfree(chan
->compat_sc_table
);
902 kfree(chan
->compat_sc_exit_table
);
904 kfree(chan
->sc_filter
);
909 int get_syscall_nr(const char *syscall_name
)
914 for (i
= 0; i
< ARRAY_SIZE(sc_table
); i
++) {
915 const struct trace_syscall_entry
*entry
;
918 entry
= &sc_table
[i
];
921 it_name
= entry
->desc
->name
;
922 it_name
+= strlen(SYSCALL_ENTRY_STR
);
923 if (!strcmp(syscall_name
, it_name
)) {
932 int get_compat_syscall_nr(const char *syscall_name
)
937 for (i
= 0; i
< ARRAY_SIZE(compat_sc_table
); i
++) {
938 const struct trace_syscall_entry
*entry
;
941 entry
= &compat_sc_table
[i
];
944 it_name
= entry
->desc
->name
;
945 it_name
+= strlen(COMPAT_SYSCALL_ENTRY_STR
);
946 if (!strcmp(syscall_name
, it_name
)) {
955 uint32_t get_sc_tables_len(void)
957 return ARRAY_SIZE(sc_table
) + ARRAY_SIZE(compat_sc_table
);
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
;
1045 /* Disable all system calls */
1046 bitmap_clear(filter
->sc
, 0, NR_syscalls
);
1047 bitmap_clear(filter
->sc_compat
, 0, NR_compat_syscalls
);
1050 syscall_nr
= get_syscall_nr(name
);
1051 compat_syscall_nr
= get_compat_syscall_nr(name
);
1052 if (syscall_nr
< 0 && compat_syscall_nr
< 0) {
1056 if (syscall_nr
>= 0) {
1057 if (!test_bit(syscall_nr
, chan
->sc_filter
->sc
)) {
1061 bitmap_clear(chan
->sc_filter
->sc
, syscall_nr
, 1);
1063 if (compat_syscall_nr
>= 0) {
1064 if (!test_bit(compat_syscall_nr
, chan
->sc_filter
->sc_compat
)) {
1068 bitmap_clear(chan
->sc_filter
->sc_compat
, compat_syscall_nr
, 1);
1071 if (!chan
->sc_filter
)
1072 rcu_assign_pointer(chan
->sc_filter
, filter
);
1073 chan
->syscall_all
= 0;
1077 if (!chan
->sc_filter
)
1083 const struct trace_syscall_entry
*syscall_list_get_entry(loff_t
*pos
)
1085 const struct trace_syscall_entry
*entry
;
1088 for (entry
= sc_table
;
1089 entry
< sc_table
+ ARRAY_SIZE(sc_table
);
1094 for (entry
= compat_sc_table
;
1095 entry
< compat_sc_table
+ ARRAY_SIZE(compat_sc_table
);
1105 void *syscall_list_start(struct seq_file
*m
, loff_t
*pos
)
1107 return (void *) syscall_list_get_entry(pos
);
1111 void *syscall_list_next(struct seq_file
*m
, void *p
, loff_t
*ppos
)
1114 return (void *) syscall_list_get_entry(ppos
);
1118 void syscall_list_stop(struct seq_file
*m
, void *p
)
1123 int get_sc_table(const struct trace_syscall_entry
*entry
,
1124 const struct trace_syscall_entry
**table
,
1125 unsigned int *bitness
)
1127 if (entry
>= sc_table
&& entry
< sc_table
+ ARRAY_SIZE(sc_table
)) {
1129 *bitness
= BITS_PER_LONG
;
1134 if (!(entry
>= compat_sc_table
1135 && entry
< compat_sc_table
+ ARRAY_SIZE(compat_sc_table
))) {
1141 *table
= compat_sc_table
;
1146 int syscall_list_show(struct seq_file
*m
, void *p
)
1148 const struct trace_syscall_entry
*table
, *entry
= p
;
1149 unsigned int bitness
;
1152 ret
= get_sc_table(entry
, &table
, &bitness
);
1155 seq_printf(m
, "syscall { index = %lu; name = %s; bitness = %u; };\n",
1163 const struct seq_operations lttng_syscall_list_seq_ops
= {
1164 .start
= syscall_list_start
,
1165 .next
= syscall_list_next
,
1166 .stop
= syscall_list_stop
,
1167 .show
= syscall_list_show
,
1171 int lttng_syscall_list_open(struct inode
*inode
, struct file
*file
)
1173 return seq_open(file
, <tng_syscall_list_seq_ops
);
1176 const struct file_operations lttng_syscall_list_fops
= {
1177 .owner
= THIS_MODULE
,
1178 .open
= lttng_syscall_list_open
,
1180 .llseek
= seq_lseek
,
1181 .release
= seq_release
,
1184 long lttng_channel_syscall_mask(struct lttng_channel
*channel
,
1185 struct lttng_kernel_syscall_mask __user
*usyscall_mask
)
1187 uint32_t len
, sc_tables_len
, bitmask_len
;
1190 struct lttng_syscall_filter
*filter
;
1192 ret
= get_user(len
, &usyscall_mask
->len
);
1195 sc_tables_len
= get_sc_tables_len();
1196 bitmask_len
= ALIGN(sc_tables_len
, 8) >> 3;
1197 if (len
< sc_tables_len
) {
1198 return put_user(sc_tables_len
, &usyscall_mask
->len
);
1200 /* Array is large enough, we can copy array to user-space. */
1201 tmp_mask
= kzalloc(bitmask_len
, GFP_KERNEL
);
1204 filter
= channel
->sc_filter
;
1206 for (bit
= 0; bit
< ARRAY_SIZE(sc_table
); bit
++) {
1207 bt_bitfield_write_be(tmp_mask
, char, bit
, 1,
1208 test_bit(bit
, filter
->sc
));
1210 for (; bit
< sc_tables_len
; bit
++) {
1211 bt_bitfield_write_be(tmp_mask
, char, bit
, 1,
1212 test_bit(bit
- ARRAY_SIZE(sc_table
),
1213 filter
->sc_compat
));
1215 if (copy_to_user(usyscall_mask
->mask
, tmp_mask
, bitmask_len
))