SoW-2019-0002: Dynamic Snapshot
[deliverable/lttng-modules.git] / lttng-syscalls.c
1 /* SPDX-License-Identifier: (GPL-2.0 or LGPL-2.1)
2 *
3 * lttng-syscalls.c
4 *
5 * LTTng syscall probes.
6 *
7 * Copyright (C) 2010-2012 Mathieu Desnoyers <mathieu.desnoyers@efficios.com>
8 */
9
10 #include <linux/module.h>
11 #include <linux/slab.h>
12 #include <linux/compat.h>
13 #include <linux/err.h>
14 #include <linux/bitmap.h>
15 #include <linux/in.h>
16 #include <linux/in6.h>
17 #include <linux/seq_file.h>
18 #include <linux/stringify.h>
19 #include <linux/file.h>
20 #include <linux/anon_inodes.h>
21 #include <asm/ptrace.h>
22 #include <asm/syscall.h>
23
24 #include <lib/bitfield.h>
25 #include <wrapper/tracepoint.h>
26 #include <wrapper/file.h>
27 #include <wrapper/rcu.h>
28 #include <wrapper/syscall.h>
29 #include <lttng-events.h>
30 #include <lttng-utils.h>
31
32 #ifndef CONFIG_COMPAT
33 # ifndef is_compat_task
34 # define is_compat_task() (0)
35 # endif
36 #endif
37
38 /* in_compat_syscall appears in kernel 4.6. */
39 #ifndef in_compat_syscall
40 #define in_compat_syscall() is_compat_task()
41 #endif
42
43 enum sc_type {
44 SC_TYPE_ENTRY,
45 SC_TYPE_EXIT,
46 SC_TYPE_COMPAT_ENTRY,
47 SC_TYPE_COMPAT_EXIT,
48 };
49
50 #define SYSCALL_ENTRY_TOK syscall_entry_
51 #define COMPAT_SYSCALL_ENTRY_TOK compat_syscall_entry_
52 #define SYSCALL_EXIT_TOK syscall_exit_
53 #define COMPAT_SYSCALL_EXIT_TOK compat_syscall_exit_
54
55 #define SYSCALL_ENTRY_STR __stringify(SYSCALL_ENTRY_TOK)
56 #define COMPAT_SYSCALL_ENTRY_STR __stringify(COMPAT_SYSCALL_ENTRY_TOK)
57 #define SYSCALL_EXIT_STR __stringify(SYSCALL_EXIT_TOK)
58 #define COMPAT_SYSCALL_EXIT_STR __stringify(COMPAT_SYSCALL_EXIT_TOK)
59
60 static
61 void syscall_entry_event_probe(void *__data, struct pt_regs *regs, long id);
62 static
63 void syscall_exit_event_probe(void *__data, struct pt_regs *regs, long ret);
64
65 /*
66 * Forward declarations for old kernels.
67 */
68 struct mmsghdr;
69 struct rlimit64;
70 struct oldold_utsname;
71 struct old_utsname;
72 struct sel_arg_struct;
73 struct mmap_arg_struct;
74 struct file_handle;
75 struct user_msghdr;
76
77 #ifdef IA32_NR_syscalls
78 #define NR_compat_syscalls IA32_NR_syscalls
79 #else
80 #define NR_compat_syscalls NR_syscalls
81 #endif
82
83 /*
84 * Create LTTng tracepoint probes.
85 */
86 #define LTTNG_PACKAGE_BUILD
87 #define CREATE_TRACE_POINTS
88 #define TP_MODULE_NOINIT
89 #define TRACE_INCLUDE_PATH instrumentation/syscalls/headers
90
91 #define PARAMS(args...) args
92
93 /* Handle unknown syscalls */
94 #undef TRACE_SYSTEM
95 #define TRACE_SYSTEM syscalls_unknown
96 #include <instrumentation/syscalls/headers/syscalls_unknown.h>
97 #undef TRACE_SYSTEM
98
99 #define SC_ENTER
100
101 #undef sc_exit
102 #define sc_exit(...)
103 #undef sc_in
104 #define sc_in(...) __VA_ARGS__
105 #undef sc_out
106 #define sc_out(...)
107 #undef sc_inout
108 #define sc_inout(...) __VA_ARGS__
109
110 /* Hijack probe callback for system call enter */
111 #undef TP_PROBE_CB
112 #define TP_PROBE_CB(_template) &syscall_entry_event_probe
113 #define SC_LTTNG_TRACEPOINT_EVENT(_name, _proto, _args, _fields) \
114 LTTNG_TRACEPOINT_EVENT(syscall_entry_##_name, PARAMS(_proto), PARAMS(_args), \
115 PARAMS(_fields))
116 #define SC_LTTNG_TRACEPOINT_EVENT_CODE(_name, _proto, _args, _locvar, _code_pre, _fields, _code_post) \
117 LTTNG_TRACEPOINT_EVENT_CODE(syscall_entry_##_name, PARAMS(_proto), PARAMS(_args), \
118 PARAMS(_locvar), PARAMS(_code_pre), \
119 PARAMS(_fields), PARAMS(_code_post))
120 #define SC_LTTNG_TRACEPOINT_EVENT_CLASS_NOARGS(_name, _fields) \
121 LTTNG_TRACEPOINT_EVENT_CLASS_NOARGS(syscall_entry_##_name, PARAMS(_fields))
122 #define SC_LTTNG_TRACEPOINT_EVENT_INSTANCE_NOARGS(_template, _name) \
123 LTTNG_TRACEPOINT_EVENT_INSTANCE_NOARGS(syscall_entry_##_template, syscall_entry_##_name)
124 /* Enumerations only defined at first inclusion. */
125 #define SC_LTTNG_TRACEPOINT_ENUM(_name, _values) \
126 LTTNG_TRACEPOINT_ENUM(_name, PARAMS(_values))
127 #undef TRACE_SYSTEM
128 #define TRACE_SYSTEM syscall_entry_integers
129 #define TRACE_INCLUDE_FILE syscalls_integers
130 #include <instrumentation/syscalls/headers/syscalls_integers.h>
131 #undef TRACE_INCLUDE_FILE
132 #undef TRACE_SYSTEM
133 #define TRACE_SYSTEM syscall_entry_pointers
134 #define TRACE_INCLUDE_FILE syscalls_pointers
135 #include <instrumentation/syscalls/headers/syscalls_pointers.h>
136 #undef TRACE_INCLUDE_FILE
137 #undef TRACE_SYSTEM
138 #undef SC_LTTNG_TRACEPOINT_ENUM
139 #undef SC_LTTNG_TRACEPOINT_EVENT_CODE
140 #undef SC_LTTNG_TRACEPOINT_EVENT
141 #undef SC_LTTNG_TRACEPOINT_EVENT_CLASS_NOARGS
142 #undef SC_LTTNG_TRACEPOINT_EVENT_INSTANCE_NOARGS
143 #undef TP_PROBE_CB
144 #undef _TRACE_SYSCALLS_INTEGERS_H
145 #undef _TRACE_SYSCALLS_POINTERS_H
146
147 /* Hijack probe callback for compat system call enter */
148 #define TP_PROBE_CB(_template) &syscall_entry_event_probe
149 #define LTTNG_SC_COMPAT
150 #define SC_LTTNG_TRACEPOINT_EVENT(_name, _proto, _args, _fields) \
151 LTTNG_TRACEPOINT_EVENT(compat_syscall_entry_##_name, PARAMS(_proto), PARAMS(_args), \
152 PARAMS(_fields))
153 #define SC_LTTNG_TRACEPOINT_EVENT_CODE(_name, _proto, _args, _locvar, _code_pre, _fields, _code_post) \
154 LTTNG_TRACEPOINT_EVENT_CODE(compat_syscall_entry_##_name, PARAMS(_proto), PARAMS(_args), \
155 PARAMS(_locvar), PARAMS(_code_pre), PARAMS(_fields), PARAMS(_code_post))
156 #define SC_LTTNG_TRACEPOINT_EVENT_CLASS_NOARGS(_name, _fields) \
157 LTTNG_TRACEPOINT_EVENT_CLASS_NOARGS(compat_syscall_entry_##_name, PARAMS(_fields))
158 #define SC_LTTNG_TRACEPOINT_EVENT_INSTANCE_NOARGS(_template, _name) \
159 LTTNG_TRACEPOINT_EVENT_INSTANCE_NOARGS(compat_syscall_entry_##_template, \
160 compat_syscall_entry_##_name)
161 /* Enumerations only defined at inital inclusion (not here). */
162 #define SC_LTTNG_TRACEPOINT_ENUM(_name, _values)
163 #define TRACE_SYSTEM compat_syscall_entry_integers
164 #define TRACE_INCLUDE_FILE compat_syscalls_integers
165 #include <instrumentation/syscalls/headers/compat_syscalls_integers.h>
166 #undef TRACE_INCLUDE_FILE
167 #undef TRACE_SYSTEM
168 #define TRACE_SYSTEM compat_syscall_entry_pointers
169 #define TRACE_INCLUDE_FILE compat_syscalls_pointers
170 #include <instrumentation/syscalls/headers/compat_syscalls_pointers.h>
171 #undef TRACE_INCLUDE_FILE
172 #undef TRACE_SYSTEM
173 #undef SC_LTTNG_TRACEPOINT_ENUM
174 #undef SC_LTTNG_TRACEPOINT_EVENT_CODE
175 #undef SC_LTTNG_TRACEPOINT_EVENT
176 #undef SC_LTTNG_TRACEPOINT_EVENT_CLASS_NOARGS
177 #undef SC_LTTNG_TRACEPOINT_EVENT_INSTANCE_NOARGS
178 #undef TP_PROBE_CB
179 #undef _TRACE_SYSCALLS_INTEGERS_H
180 #undef _TRACE_SYSCALLS_POINTERS_H
181 #undef LTTNG_SC_COMPAT
182
183 #undef SC_ENTER
184
185 #define SC_EXIT
186
187 #undef sc_exit
188 #define sc_exit(...) __VA_ARGS__
189 #undef sc_in
190 #define sc_in(...)
191 #undef sc_out
192 #define sc_out(...) __VA_ARGS__
193 #undef sc_inout
194 #define sc_inout(...) __VA_ARGS__
195
196 /* Hijack probe callback for system call exit */
197 #define TP_PROBE_CB(_template) &syscall_exit_event_probe
198 #define SC_LTTNG_TRACEPOINT_EVENT(_name, _proto, _args, _fields) \
199 LTTNG_TRACEPOINT_EVENT(syscall_exit_##_name, PARAMS(_proto), PARAMS(_args), \
200 PARAMS(_fields))
201 #define SC_LTTNG_TRACEPOINT_EVENT_CODE(_name, _proto, _args, _locvar, _code_pre, _fields, _code_post) \
202 LTTNG_TRACEPOINT_EVENT_CODE(syscall_exit_##_name, PARAMS(_proto), PARAMS(_args), \
203 PARAMS(_locvar), PARAMS(_code_pre), PARAMS(_fields), PARAMS(_code_post))
204 #define SC_LTTNG_TRACEPOINT_EVENT_CLASS_NOARGS(_name, _fields) \
205 LTTNG_TRACEPOINT_EVENT_CLASS_NOARGS(syscall_exit_##_name, PARAMS(_fields))
206 #define SC_LTTNG_TRACEPOINT_EVENT_INSTANCE_NOARGS(_template, _name) \
207 LTTNG_TRACEPOINT_EVENT_INSTANCE_NOARGS(syscall_exit_##_template, \
208 syscall_exit_##_name)
209 /* Enumerations only defined at inital inclusion (not here). */
210 #define SC_LTTNG_TRACEPOINT_ENUM(_name, _values)
211 #define TRACE_SYSTEM syscall_exit_integers
212 #define TRACE_INCLUDE_FILE syscalls_integers
213 #include <instrumentation/syscalls/headers/syscalls_integers.h>
214 #undef TRACE_INCLUDE_FILE
215 #undef TRACE_SYSTEM
216 #define TRACE_SYSTEM syscall_exit_pointers
217 #define TRACE_INCLUDE_FILE syscalls_pointers
218 #include <instrumentation/syscalls/headers/syscalls_pointers.h>
219 #undef TRACE_INCLUDE_FILE
220 #undef TRACE_SYSTEM
221 #undef SC_LTTNG_TRACEPOINT_ENUM
222 #undef SC_LTTNG_TRACEPOINT_EVENT_CODE
223 #undef SC_LTTNG_TRACEPOINT_EVENT
224 #undef SC_LTTNG_TRACEPOINT_EVENT_CLASS_NOARGS
225 #undef SC_LTTNG_TRACEPOINT_EVENT_INSTANCE_NOARGS
226 #undef TP_PROBE_CB
227 #undef _TRACE_SYSCALLS_INTEGERS_H
228 #undef _TRACE_SYSCALLS_POINTERS_H
229
230
231 /* Hijack probe callback for compat system call exit */
232 #define TP_PROBE_CB(_template) &syscall_exit_event_probe
233 #define LTTNG_SC_COMPAT
234 #define SC_LTTNG_TRACEPOINT_EVENT(_name, _proto, _args, _fields) \
235 LTTNG_TRACEPOINT_EVENT(compat_syscall_exit_##_name, PARAMS(_proto), PARAMS(_args), \
236 PARAMS(_fields))
237 #define SC_LTTNG_TRACEPOINT_EVENT_CODE(_name, _proto, _args, _locvar, _code_pre, _fields, _code_post) \
238 LTTNG_TRACEPOINT_EVENT_CODE(compat_syscall_exit_##_name, PARAMS(_proto), PARAMS(_args), \
239 PARAMS(_locvar), PARAMS(_code_pre), PARAMS(_fields), PARAMS(_code_post))
240 #define SC_LTTNG_TRACEPOINT_EVENT_CLASS_NOARGS(_name, _fields) \
241 LTTNG_TRACEPOINT_EVENT_CLASS_NOARGS(compat_syscall_exit_##_name, PARAMS(_fields))
242 #define SC_LTTNG_TRACEPOINT_EVENT_INSTANCE_NOARGS(_template, _name) \
243 LTTNG_TRACEPOINT_EVENT_INSTANCE_NOARGS(compat_syscall_exit_##_template, \
244 compat_syscall_exit_##_name)
245 /* Enumerations only defined at inital inclusion (not here). */
246 #define SC_LTTNG_TRACEPOINT_ENUM(_name, _values)
247 #define TRACE_SYSTEM compat_syscall_exit_integers
248 #define TRACE_INCLUDE_FILE compat_syscalls_integers
249 #include <instrumentation/syscalls/headers/compat_syscalls_integers.h>
250 #undef TRACE_INCLUDE_FILE
251 #undef TRACE_SYSTEM
252 #define TRACE_SYSTEM compat_syscall_exit_pointers
253 #define TRACE_INCLUDE_FILE compat_syscalls_pointers
254 #include <instrumentation/syscalls/headers/compat_syscalls_pointers.h>
255 #undef TRACE_INCLUDE_FILE
256 #undef TRACE_SYSTEM
257 #undef SC_LTTNG_TRACEPOINT_ENUM
258 #undef SC_LTTNG_TRACEPOINT_EVENT_CODE
259 #undef SC_LTTNG_TRACEPOINT_EVENT
260 #undef SC_LTTNG_TRACEPOINT_EVENT_CLASS_NOARGS
261 #undef SC_LTTNG_TRACEPOINT_EVENT_INSTANCE_NOARGS
262 #undef TP_PROBE_CB
263 #undef _TRACE_SYSCALLS_INTEGERS_H
264 #undef _TRACE_SYSCALLS_POINTERS_H
265 #undef LTTNG_SC_COMPAT
266
267 #undef SC_EXIT
268
269 #undef TP_MODULE_NOINIT
270 #undef LTTNG_PACKAGE_BUILD
271 #undef CREATE_TRACE_POINTS
272
273 struct trace_syscall_entry {
274 void *event_func;
275 void *trigger_func;
276 const struct lttng_event_desc *desc;
277 const struct lttng_event_field *fields;
278 unsigned int nrargs;
279 };
280
281 #define CREATE_SYSCALL_TABLE
282
283 #define SC_ENTER
284
285 #undef sc_exit
286 #define sc_exit(...)
287
288 #undef TRACE_SYSCALL_TABLE
289 #define TRACE_SYSCALL_TABLE(_template, _name, _nr, _nrargs) \
290 [ _nr ] = { \
291 .event_func = __event_probe__syscall_entry_##_template, \
292 .trigger_func = __trigger_probe__syscall_entry_##_template, \
293 .nrargs = (_nrargs), \
294 .fields = __event_fields___syscall_entry_##_template, \
295 .desc = &__event_desc___syscall_entry_##_name, \
296 },
297
298 /* Event syscall enter tracing table */
299 static const struct trace_syscall_entry sc_table[] = {
300 #include <instrumentation/syscalls/headers/syscalls_integers.h>
301 #include <instrumentation/syscalls/headers/syscalls_pointers.h>
302 };
303
304 #undef TRACE_SYSCALL_TABLE
305 #define TRACE_SYSCALL_TABLE(_template, _name, _nr, _nrargs) \
306 [ _nr ] = { \
307 .event_func = __event_probe__compat_syscall_entry_##_template, \
308 .trigger_func = __trigger_probe__compat_syscall_entry_##_template, \
309 .nrargs = (_nrargs), \
310 .fields = __event_fields___compat_syscall_entry_##_template, \
311 .desc = &__event_desc___compat_syscall_entry_##_name, \
312 },
313
314 /* Event compat syscall enter table */
315 const struct trace_syscall_entry compat_sc_table[] = {
316 #include <instrumentation/syscalls/headers/compat_syscalls_integers.h>
317 #include <instrumentation/syscalls/headers/compat_syscalls_pointers.h>
318 };
319
320 #undef SC_ENTER
321
322 #define SC_EXIT
323
324 #undef sc_exit
325 #define sc_exit(...) __VA_ARGS__
326
327 #undef TRACE_SYSCALL_TABLE
328 #define TRACE_SYSCALL_TABLE(_template, _name, _nr, _nrargs) \
329 [ _nr ] = { \
330 .event_func = __event_probe__syscall_exit_##_template, \
331 .trigger_func = __trigger_probe__syscall_exit_##_template, \
332 .nrargs = (_nrargs), \
333 .fields = __event_fields___syscall_exit_##_template, \
334 .desc = &__event_desc___syscall_exit_##_name, \
335 },
336
337 /* Event syscall exit table */
338 static const struct trace_syscall_entry sc_exit_table[] = {
339 #include <instrumentation/syscalls/headers/syscalls_integers.h>
340 #include <instrumentation/syscalls/headers/syscalls_pointers.h>
341 };
342
343 #undef TRACE_SYSCALL_TABLE
344 #define TRACE_SYSCALL_TABLE(_template, _name, _nr, _nrargs) \
345 [ _nr ] = { \
346 .event_func = __event_probe__compat_syscall_exit_##_template, \
347 .trigger_func = __trigger_probe__compat_syscall_exit_##_template, \
348 .nrargs = (_nrargs), \
349 .fields = __event_fields___compat_syscall_exit_##_template, \
350 .desc = &__event_desc___compat_syscall_exit_##_name, \
351 },
352
353 /* Event compat syscall exit table */
354 const struct trace_syscall_entry compat_sc_exit_table[] = {
355 #include <instrumentation/syscalls/headers/compat_syscalls_integers.h>
356 #include <instrumentation/syscalls/headers/compat_syscalls_pointers.h>
357 };
358
359 #undef SC_EXIT
360
361 #undef CREATE_SYSCALL_TABLE
362
363 struct lttng_syscall_filter {
364 DECLARE_BITMAP(sc, NR_syscalls);
365 DECLARE_BITMAP(sc_compat, NR_compat_syscalls);
366 };
367
368 static void syscall_entry_event_unknown(struct lttng_event *event,
369 struct pt_regs *regs, unsigned int id)
370 {
371 unsigned long args[LTTNG_SYSCALL_NR_ARGS];
372
373 lttng_syscall_get_arguments(current, regs, args);
374 if (unlikely(in_compat_syscall()))
375 __event_probe__compat_syscall_entry_unknown(event, id, args);
376 else
377 __event_probe__syscall_entry_unknown(event, id, args);
378 }
379
380 static __always_inline
381 void syscall_entry_call_func(void *func, unsigned int nrargs, void *data,
382 struct pt_regs *regs)
383 {
384 switch (nrargs) {
385 case 0:
386 {
387 void (*fptr)(void *__data) = func;
388
389 fptr(data);
390 break;
391 }
392 case 1:
393 {
394 void (*fptr)(void *__data, unsigned long arg0) = func;
395 unsigned long args[LTTNG_SYSCALL_NR_ARGS];
396
397 lttng_syscall_get_arguments(current, regs, args);
398 fptr(data, args[0]);
399 break;
400 }
401 case 2:
402 {
403 void (*fptr)(void *__data,
404 unsigned long arg0,
405 unsigned long arg1) = func;
406 unsigned long args[LTTNG_SYSCALL_NR_ARGS];
407
408 lttng_syscall_get_arguments(current, regs, args);
409 fptr(data, args[0], args[1]);
410 break;
411 }
412 case 3:
413 {
414 void (*fptr)(void *__data,
415 unsigned long arg0,
416 unsigned long arg1,
417 unsigned long arg2) = func;
418 unsigned long args[LTTNG_SYSCALL_NR_ARGS];
419
420 lttng_syscall_get_arguments(current, regs, args);
421 fptr(data, args[0], args[1], args[2]);
422 break;
423 }
424 case 4:
425 {
426 void (*fptr)(void *__data,
427 unsigned long arg0,
428 unsigned long arg1,
429 unsigned long arg2,
430 unsigned long arg3) = func;
431 unsigned long args[LTTNG_SYSCALL_NR_ARGS];
432
433 lttng_syscall_get_arguments(current, regs, args);
434 fptr(data, args[0], args[1], args[2], args[3]);
435 break;
436 }
437 case 5:
438 {
439 void (*fptr)(void *__data,
440 unsigned long arg0,
441 unsigned long arg1,
442 unsigned long arg2,
443 unsigned long arg3,
444 unsigned long arg4) = func;
445 unsigned long args[LTTNG_SYSCALL_NR_ARGS];
446
447 lttng_syscall_get_arguments(current, regs, args);
448 fptr(data, args[0], args[1], args[2], args[3], args[4]);
449 break;
450 }
451 case 6:
452 {
453 void (*fptr)(void *__data,
454 unsigned long arg0,
455 unsigned long arg1,
456 unsigned long arg2,
457 unsigned long arg3,
458 unsigned long arg4,
459 unsigned long arg5) = func;
460 unsigned long args[LTTNG_SYSCALL_NR_ARGS];
461
462 lttng_syscall_get_arguments(current, regs, args);
463 fptr(data, args[0], args[1], args[2],
464 args[3], args[4], args[5]);
465 break;
466 }
467 default:
468 break;
469 }
470 }
471
472 void syscall_entry_event_probe(void *__data, struct pt_regs *regs, long id)
473 {
474 struct lttng_channel *chan = __data;
475 struct lttng_syscall_filter *filter;
476 struct lttng_event *event, *unknown_event;
477 const struct trace_syscall_entry *table, *entry;
478 size_t table_len;
479
480 filter = lttng_rcu_dereference(chan->sc_filter);
481
482 if (unlikely(in_compat_syscall())) {
483 if (filter) {
484 if (id < 0 || id >= NR_compat_syscalls
485 || !test_bit(id, filter->sc_compat)) {
486 /* System call filtered out. */
487 return;
488 }
489 }
490 table = compat_sc_table;
491 table_len = ARRAY_SIZE(compat_sc_table);
492 unknown_event = chan->sc_compat_unknown;
493 } else {
494 if (filter) {
495 if (id < 0 || id >= NR_syscalls
496 || !test_bit(id, filter->sc)) {
497 /* System call filtered out. */
498 return;
499 }
500 }
501 table = sc_table;
502 table_len = ARRAY_SIZE(sc_table);
503 unknown_event = chan->sc_unknown;
504 }
505 if (unlikely(id < 0 || id >= table_len)) {
506 syscall_entry_event_unknown(unknown_event, regs, id);
507 return;
508 }
509 if (unlikely(in_compat_syscall()))
510 event = chan->compat_sc_table[id];
511 else
512 event = chan->sc_table[id];
513 if (unlikely(!event)) {
514 syscall_entry_event_unknown(unknown_event, regs, id);
515 return;
516 }
517 entry = &table[id];
518 WARN_ON_ONCE(!entry);
519
520 syscall_entry_call_func(entry->event_func, entry->nrargs, event, regs);
521 }
522
523 void syscall_entry_trigger_probe(void *__data, struct pt_regs *regs, long id)
524 {
525 struct lttng_trigger_group *trigger_group = __data;
526 const struct trace_syscall_entry *entry;
527 struct list_head *dispatch_list;
528 struct lttng_trigger *iter;
529 size_t table_len;
530
531
532 if (unlikely(in_compat_syscall())) {
533 table_len = ARRAY_SIZE(compat_sc_table);
534 if (unlikely(id < 0 || id >= table_len)) {
535 return;
536 }
537 entry = &compat_sc_table[id];
538 dispatch_list = &trigger_group->trigger_compat_syscall_dispatch[id];
539 } else {
540 table_len = ARRAY_SIZE(sc_table);
541 if (unlikely(id < 0 || id >= table_len)) {
542 return;
543 }
544 entry = &sc_table[id];
545 dispatch_list = &trigger_group->trigger_syscall_dispatch[id];
546 }
547
548 /* TODO handle unknown syscall */
549
550 list_for_each_entry_rcu(iter, dispatch_list, u.syscall.node) {
551 BUG_ON(iter->u.syscall.syscall_id != id);
552 syscall_entry_call_func(entry->trigger_func, entry->nrargs, iter, regs);
553 }
554 }
555
556 static void syscall_exit_event_unknown(struct lttng_event *event,
557 struct pt_regs *regs, int id, long ret)
558 {
559 unsigned long args[LTTNG_SYSCALL_NR_ARGS];
560
561 lttng_syscall_get_arguments(current, regs, args);
562 if (unlikely(in_compat_syscall()))
563 __event_probe__compat_syscall_exit_unknown(event, id, ret,
564 args);
565 else
566 __event_probe__syscall_exit_unknown(event, id, ret, args);
567 }
568
569 void syscall_exit_event_probe(void *__data, struct pt_regs *regs, long ret)
570 {
571 struct lttng_channel *chan = __data;
572 struct lttng_syscall_filter *filter;
573 struct lttng_event *event, *unknown_event;
574 const struct trace_syscall_entry *table, *entry;
575 size_t table_len;
576 long id;
577
578 filter = lttng_rcu_dereference(chan->sc_filter);
579
580 id = syscall_get_nr(current, regs);
581 if (unlikely(in_compat_syscall())) {
582 if (filter) {
583 if (id < 0 || id >= NR_compat_syscalls
584 || !test_bit(id, filter->sc_compat)) {
585 /* System call filtered out. */
586 return;
587 }
588 }
589 table = compat_sc_exit_table;
590 table_len = ARRAY_SIZE(compat_sc_exit_table);
591 unknown_event = chan->compat_sc_exit_unknown;
592 } else {
593 if (filter) {
594 if (id < 0 || id >= NR_syscalls
595 || !test_bit(id, filter->sc)) {
596 /* System call filtered out. */
597 return;
598 }
599 }
600 table = sc_exit_table;
601 table_len = ARRAY_SIZE(sc_exit_table);
602 unknown_event = chan->sc_exit_unknown;
603 }
604 if (unlikely(id < 0 || id >= table_len)) {
605 syscall_exit_event_unknown(unknown_event, regs, id, ret);
606 return;
607 }
608 if (unlikely(in_compat_syscall()))
609 event = chan->compat_sc_exit_table[id];
610 else
611 event = chan->sc_exit_table[id];
612 if (unlikely(!event)) {
613 syscall_exit_event_unknown(unknown_event, regs, id, ret);
614 return;
615 }
616 entry = &table[id];
617 WARN_ON_ONCE(!entry);
618
619 switch (entry->nrargs) {
620 case 0:
621 {
622 void (*fptr)(void *__data, long ret) = entry->event_func;
623
624 fptr(event, ret);
625 break;
626 }
627 case 1:
628 {
629 void (*fptr)(void *__data,
630 long ret,
631 unsigned long arg0) = entry->event_func;
632 unsigned long args[LTTNG_SYSCALL_NR_ARGS];
633
634 lttng_syscall_get_arguments(current, regs, args);
635 fptr(event, ret, args[0]);
636 break;
637 }
638 case 2:
639 {
640 void (*fptr)(void *__data,
641 long ret,
642 unsigned long arg0,
643 unsigned long arg1) = entry->event_func;
644 unsigned long args[LTTNG_SYSCALL_NR_ARGS];
645
646 lttng_syscall_get_arguments(current, regs, args);
647 fptr(event, ret, args[0], args[1]);
648 break;
649 }
650 case 3:
651 {
652 void (*fptr)(void *__data,
653 long ret,
654 unsigned long arg0,
655 unsigned long arg1,
656 unsigned long arg2) = entry->event_func;
657 unsigned long args[LTTNG_SYSCALL_NR_ARGS];
658
659 lttng_syscall_get_arguments(current, regs, args);
660 fptr(event, ret, args[0], args[1], args[2]);
661 break;
662 }
663 case 4:
664 {
665 void (*fptr)(void *__data,
666 long ret,
667 unsigned long arg0,
668 unsigned long arg1,
669 unsigned long arg2,
670 unsigned long arg3) = entry->event_func;
671 unsigned long args[LTTNG_SYSCALL_NR_ARGS];
672
673 lttng_syscall_get_arguments(current, regs, args);
674 fptr(event, ret, args[0], args[1], args[2], args[3]);
675 break;
676 }
677 case 5:
678 {
679 void (*fptr)(void *__data,
680 long ret,
681 unsigned long arg0,
682 unsigned long arg1,
683 unsigned long arg2,
684 unsigned long arg3,
685 unsigned long arg4) = entry->event_func;
686 unsigned long args[LTTNG_SYSCALL_NR_ARGS];
687
688 lttng_syscall_get_arguments(current, regs, args);
689 fptr(event, ret, args[0], args[1], args[2], args[3], args[4]);
690 break;
691 }
692 case 6:
693 {
694 void (*fptr)(void *__data,
695 long ret,
696 unsigned long arg0,
697 unsigned long arg1,
698 unsigned long arg2,
699 unsigned long arg3,
700 unsigned long arg4,
701 unsigned long arg5) = entry->event_func;
702 unsigned long args[LTTNG_SYSCALL_NR_ARGS];
703
704 lttng_syscall_get_arguments(current, regs, args);
705 fptr(event, ret, args[0], args[1], args[2],
706 args[3], args[4], args[5]);
707 break;
708 }
709 default:
710 break;
711 }
712 }
713
714 /*
715 * noinline to diminish caller stack size.
716 * Should be called with sessions lock held.
717 */
718 static
719 int fill_event_table(const struct trace_syscall_entry *table, size_t table_len,
720 struct lttng_event **chan_table, struct lttng_channel *chan,
721 void *filter, enum sc_type type)
722 {
723 const struct lttng_event_desc *desc;
724 unsigned int i;
725
726 /* Allocate events for each syscall, insert into table */
727 for (i = 0; i < table_len; i++) {
728 struct lttng_kernel_event ev;
729 desc = table[i].desc;
730
731 if (!desc) {
732 /* Unknown syscall */
733 continue;
734 }
735 /*
736 * Skip those already populated by previous failed
737 * register for this channel.
738 */
739 if (chan_table[i])
740 continue;
741 memset(&ev, 0, sizeof(ev));
742 switch (type) {
743 case SC_TYPE_ENTRY:
744 strncpy(ev.name, SYSCALL_ENTRY_STR,
745 LTTNG_KERNEL_SYM_NAME_LEN);
746 break;
747 case SC_TYPE_EXIT:
748 strncpy(ev.name, SYSCALL_EXIT_STR,
749 LTTNG_KERNEL_SYM_NAME_LEN);
750 break;
751 case SC_TYPE_COMPAT_ENTRY:
752 strncpy(ev.name, COMPAT_SYSCALL_ENTRY_STR,
753 LTTNG_KERNEL_SYM_NAME_LEN);
754 break;
755 case SC_TYPE_COMPAT_EXIT:
756 strncpy(ev.name, COMPAT_SYSCALL_EXIT_STR,
757 LTTNG_KERNEL_SYM_NAME_LEN);
758 break;
759 default:
760 BUG_ON(1);
761 break;
762 }
763 strncat(ev.name, desc->name,
764 LTTNG_KERNEL_SYM_NAME_LEN - strlen(ev.name) - 1);
765 ev.name[LTTNG_KERNEL_SYM_NAME_LEN - 1] = '\0';
766 ev.instrumentation = LTTNG_KERNEL_SYSCALL;
767 chan_table[i] = _lttng_event_create(chan, &ev, filter,
768 desc, ev.instrumentation);
769 WARN_ON_ONCE(!chan_table[i]);
770 if (IS_ERR(chan_table[i])) {
771 /*
772 * If something goes wrong in event registration
773 * after the first one, we have no choice but to
774 * leave the previous events in there, until
775 * deleted by session teardown.
776 */
777 return PTR_ERR(chan_table[i]);
778 }
779 }
780 return 0;
781 }
782
783 /*
784 * Should be called with sessions lock held.
785 */
786 int lttng_syscalls_register_event(struct lttng_channel *chan, void *filter)
787 {
788 struct lttng_kernel_event ev;
789 int ret;
790
791 wrapper_vmalloc_sync_all();
792
793 if (!chan->sc_table) {
794 /* create syscall table mapping syscall to events */
795 chan->sc_table = kzalloc(sizeof(struct lttng_event *)
796 * ARRAY_SIZE(sc_table), GFP_KERNEL);
797 if (!chan->sc_table)
798 return -ENOMEM;
799 }
800 if (!chan->sc_exit_table) {
801 /* create syscall table mapping syscall to events */
802 chan->sc_exit_table = kzalloc(sizeof(struct lttng_event *)
803 * ARRAY_SIZE(sc_exit_table), GFP_KERNEL);
804 if (!chan->sc_exit_table)
805 return -ENOMEM;
806 }
807
808
809 #ifdef CONFIG_COMPAT
810 if (!chan->compat_sc_table) {
811 /* create syscall table mapping compat syscall to events */
812 chan->compat_sc_table = kzalloc(sizeof(struct lttng_event *)
813 * ARRAY_SIZE(compat_sc_table), GFP_KERNEL);
814 if (!chan->compat_sc_table)
815 return -ENOMEM;
816 }
817
818 if (!chan->compat_sc_exit_table) {
819 /* create syscall table mapping compat syscall to events */
820 chan->compat_sc_exit_table = kzalloc(sizeof(struct lttng_event *)
821 * ARRAY_SIZE(compat_sc_exit_table), GFP_KERNEL);
822 if (!chan->compat_sc_exit_table)
823 return -ENOMEM;
824 }
825 #endif
826 if (!chan->sc_unknown) {
827 const struct lttng_event_desc *desc =
828 &__event_desc___syscall_entry_unknown;
829
830 memset(&ev, 0, sizeof(ev));
831 strncpy(ev.name, desc->name, LTTNG_KERNEL_SYM_NAME_LEN);
832 ev.name[LTTNG_KERNEL_SYM_NAME_LEN - 1] = '\0';
833 ev.instrumentation = LTTNG_KERNEL_SYSCALL;
834 chan->sc_unknown = _lttng_event_create(chan, &ev, filter,
835 desc,
836 ev.instrumentation);
837 WARN_ON_ONCE(!chan->sc_unknown);
838 if (IS_ERR(chan->sc_unknown)) {
839 return PTR_ERR(chan->sc_unknown);
840 }
841 }
842
843 if (!chan->sc_compat_unknown) {
844 const struct lttng_event_desc *desc =
845 &__event_desc___compat_syscall_entry_unknown;
846
847 memset(&ev, 0, sizeof(ev));
848 strncpy(ev.name, desc->name, LTTNG_KERNEL_SYM_NAME_LEN);
849 ev.name[LTTNG_KERNEL_SYM_NAME_LEN - 1] = '\0';
850 ev.instrumentation = LTTNG_KERNEL_SYSCALL;
851 chan->sc_compat_unknown = _lttng_event_create(chan, &ev, filter,
852 desc,
853 ev.instrumentation);
854 WARN_ON_ONCE(!chan->sc_unknown);
855 if (IS_ERR(chan->sc_compat_unknown)) {
856 return PTR_ERR(chan->sc_compat_unknown);
857 }
858 }
859
860 if (!chan->compat_sc_exit_unknown) {
861 const struct lttng_event_desc *desc =
862 &__event_desc___compat_syscall_exit_unknown;
863
864 memset(&ev, 0, sizeof(ev));
865 strncpy(ev.name, desc->name, LTTNG_KERNEL_SYM_NAME_LEN);
866 ev.name[LTTNG_KERNEL_SYM_NAME_LEN - 1] = '\0';
867 ev.instrumentation = LTTNG_KERNEL_SYSCALL;
868 chan->compat_sc_exit_unknown = _lttng_event_create(chan, &ev,
869 filter, desc,
870 ev.instrumentation);
871 WARN_ON_ONCE(!chan->compat_sc_exit_unknown);
872 if (IS_ERR(chan->compat_sc_exit_unknown)) {
873 return PTR_ERR(chan->compat_sc_exit_unknown);
874 }
875 }
876
877 if (!chan->sc_exit_unknown) {
878 const struct lttng_event_desc *desc =
879 &__event_desc___syscall_exit_unknown;
880
881 memset(&ev, 0, sizeof(ev));
882 strncpy(ev.name, desc->name, LTTNG_KERNEL_SYM_NAME_LEN);
883 ev.name[LTTNG_KERNEL_SYM_NAME_LEN - 1] = '\0';
884 ev.instrumentation = LTTNG_KERNEL_SYSCALL;
885 chan->sc_exit_unknown = _lttng_event_create(chan, &ev, filter,
886 desc, ev.instrumentation);
887 WARN_ON_ONCE(!chan->sc_exit_unknown);
888 if (IS_ERR(chan->sc_exit_unknown)) {
889 return PTR_ERR(chan->sc_exit_unknown);
890 }
891 }
892
893 ret = fill_event_table(sc_table, ARRAY_SIZE(sc_table),
894 chan->sc_table, chan, filter, SC_TYPE_ENTRY);
895 if (ret)
896 return ret;
897 ret = fill_event_table(sc_exit_table, ARRAY_SIZE(sc_exit_table),
898 chan->sc_exit_table, chan, filter, SC_TYPE_EXIT);
899 if (ret)
900 return ret;
901
902 #ifdef CONFIG_COMPAT
903 ret = fill_event_table(compat_sc_table, ARRAY_SIZE(compat_sc_table),
904 chan->compat_sc_table, chan, filter,
905 SC_TYPE_COMPAT_ENTRY);
906 if (ret)
907 return ret;
908 ret = fill_event_table(compat_sc_exit_table, ARRAY_SIZE(compat_sc_exit_table),
909 chan->compat_sc_exit_table, chan, filter,
910 SC_TYPE_COMPAT_EXIT);
911 if (ret)
912 return ret;
913 #endif
914 if (!chan->sys_enter_registered) {
915 ret = lttng_wrapper_tracepoint_probe_register("sys_enter",
916 (void *) syscall_entry_event_probe, chan);
917 if (ret)
918 return ret;
919 chan->sys_enter_registered = 1;
920 }
921 /*
922 * We change the name of sys_exit tracepoint due to namespace
923 * conflict with sys_exit syscall entry.
924 */
925 if (!chan->sys_exit_registered) {
926 ret = lttng_wrapper_tracepoint_probe_register("sys_exit",
927 (void *) syscall_exit_event_probe, chan);
928 if (ret) {
929 WARN_ON_ONCE(lttng_wrapper_tracepoint_probe_unregister("sys_enter",
930 (void *) syscall_entry_event_probe, chan));
931 return ret;
932 }
933 chan->sys_exit_registered = 1;
934 }
935 return ret;
936 }
937
938 /*
939 * Should be called with sessions lock held.
940 */
941 int lttng_syscalls_register_trigger(struct lttng_trigger_enabler *trigger_enabler, void *filter)
942 {
943 struct lttng_trigger_group *group = trigger_enabler->group;
944 unsigned int i;
945 int ret = 0;
946
947 wrapper_vmalloc_sync_all();
948
949 if (!group->trigger_syscall_dispatch) {
950 group->trigger_syscall_dispatch = kzalloc(sizeof(struct list_head)
951 * ARRAY_SIZE(sc_table), GFP_KERNEL);
952 if (!group->trigger_syscall_dispatch)
953 return -ENOMEM;
954
955 /* Initialize all list_head */
956 for (i = 0; i < ARRAY_SIZE(sc_table); i++)
957 INIT_LIST_HEAD(&group->trigger_syscall_dispatch[i]);
958 }
959
960 #ifdef CONFIG_COMPAT
961 if (!group->trigger_compat_syscall_dispatch) {
962 group->trigger_compat_syscall_dispatch = kzalloc(sizeof(struct list_head)
963 * ARRAY_SIZE(compat_sc_table), GFP_KERNEL);
964 if (!group->trigger_syscall_dispatch)
965 return -ENOMEM;
966
967 /* Initialize all list_head */
968 for (i = 0; i < ARRAY_SIZE(compat_sc_table); i++)
969 INIT_LIST_HEAD(&group->trigger_compat_syscall_dispatch[i]);
970 }
971 #endif
972
973 if (!group->sys_enter_registered) {
974 ret = lttng_wrapper_tracepoint_probe_register("sys_enter",
975 (void *) syscall_entry_trigger_probe, group);
976 if (ret)
977 return ret;
978 group->sys_enter_registered = 1;
979 }
980
981 return ret;
982 }
983
984 static int create_matching_triggers(struct lttng_trigger_enabler *trigger_enabler,
985 void *filter, const struct trace_syscall_entry *table,
986 size_t table_len, bool is_compat)
987 {
988 struct lttng_trigger_group *group = trigger_enabler->group;
989 const struct lttng_event_desc *desc;
990 uint64_t id = trigger_enabler->id;
991 unsigned int i;
992 int ret = 0;
993
994 /* iterate over all syscall and create trigger that match */
995 for (i = 0; i < table_len; i++) {
996 struct lttng_trigger *trigger;
997 struct lttng_kernel_trigger trigger_param;
998 struct hlist_head *head;
999 int found = 0;
1000
1001 desc = table[i].desc;
1002 if (!desc) {
1003 /* Unknown syscall */
1004 continue;
1005 }
1006
1007 if (!lttng_desc_match_enabler(desc,
1008 lttng_trigger_enabler_as_enabler(trigger_enabler)))
1009 continue;
1010
1011 /*
1012 * Check if already created.
1013 */
1014 head = utils_borrow_hash_table_bucket(group->triggers_ht.table,
1015 LTTNG_TRIGGER_HT_SIZE, desc->name);
1016 lttng_hlist_for_each_entry(trigger, head, hlist) {
1017 if (trigger->desc == desc
1018 && trigger->id == trigger_enabler->id)
1019 found = 1;
1020 }
1021 if (found)
1022 continue;
1023
1024 memset(&trigger_param, 0, sizeof(trigger_param));
1025 strncat(trigger_param.name, desc->name,
1026 LTTNG_KERNEL_SYM_NAME_LEN - strlen(trigger_param.name) - 1);
1027 trigger_param.name[LTTNG_KERNEL_SYM_NAME_LEN - 1] = '\0';
1028 trigger_param.instrumentation = LTTNG_KERNEL_SYSCALL;
1029
1030 trigger = _lttng_trigger_create(desc, id, group,
1031 &trigger_param, filter, trigger_param.instrumentation);
1032 if (IS_ERR(trigger)) {
1033 printk(KERN_INFO "Unable to create trigger %s\n",
1034 desc->name);
1035 ret = -ENOMEM;
1036 goto end;
1037 }
1038
1039 trigger->u.syscall.syscall_id = i;
1040 trigger->u.syscall.is_compat = is_compat;
1041 }
1042 end:
1043 return ret;
1044
1045 }
1046
1047 int lttng_syscals_create_matching_triggers(struct lttng_trigger_enabler *trigger_enabler, void *filter)
1048 {
1049 int ret;
1050
1051 ret = create_matching_triggers(trigger_enabler, filter, sc_table,
1052 ARRAY_SIZE(sc_table), false);
1053 if (ret)
1054 goto end;
1055
1056 ret = create_matching_triggers(trigger_enabler, filter, compat_sc_table,
1057 ARRAY_SIZE(compat_sc_table), true);
1058 end:
1059 return ret;
1060 }
1061
1062 /*
1063 * TODO
1064 */
1065 int lttng_syscalls_unregister_trigger(struct lttng_trigger_group *trigger_group)
1066 {
1067 int ret;
1068
1069 if (trigger_group->sys_enter_registered) {
1070 ret = lttng_wrapper_tracepoint_probe_unregister("sys_enter",
1071 (void *) syscall_entry_trigger_probe, trigger_group);
1072 if (ret)
1073 return ret;
1074 trigger_group->sys_enter_registered = 0;
1075 }
1076
1077 kfree(trigger_group->trigger_syscall_dispatch);
1078 #ifdef CONFIG_COMPAT
1079 kfree(trigger_group->trigger_compat_syscall_dispatch);
1080 #endif
1081 return 0;
1082 }
1083
1084 int lttng_syscalls_unregister_event(struct lttng_channel *chan)
1085 {
1086 int ret;
1087
1088 if (!chan->sc_table)
1089 return 0;
1090 if (chan->sys_enter_registered) {
1091 ret = lttng_wrapper_tracepoint_probe_unregister("sys_enter",
1092 (void *) syscall_entry_event_probe, chan);
1093 if (ret)
1094 return ret;
1095 chan->sys_enter_registered = 0;
1096 }
1097 if (chan->sys_exit_registered) {
1098 ret = lttng_wrapper_tracepoint_probe_unregister("sys_exit",
1099 (void *) syscall_exit_event_probe, chan);
1100 if (ret)
1101 return ret;
1102 chan->sys_exit_registered = 0;
1103 }
1104 /* lttng_event destroy will be performed by lttng_session_destroy() */
1105 kfree(chan->sc_table);
1106 kfree(chan->sc_exit_table);
1107 #ifdef CONFIG_COMPAT
1108 kfree(chan->compat_sc_table);
1109 kfree(chan->compat_sc_exit_table);
1110 #endif
1111 kfree(chan->sc_filter);
1112 return 0;
1113 }
1114
1115 static
1116 int get_syscall_nr(const char *syscall_name)
1117 {
1118 int syscall_nr = -1;
1119 int i;
1120
1121 for (i = 0; i < ARRAY_SIZE(sc_table); i++) {
1122 const struct trace_syscall_entry *entry;
1123
1124 entry = &sc_table[i];
1125 if (!entry->desc)
1126 continue;
1127
1128 if (!strcmp(syscall_name, entry->desc->name)) {
1129 syscall_nr = i;
1130 break;
1131 }
1132 }
1133 return syscall_nr;
1134 }
1135
1136 static
1137 int get_compat_syscall_nr(const char *syscall_name)
1138 {
1139 int syscall_nr = -1;
1140 int i;
1141
1142 for (i = 0; i < ARRAY_SIZE(compat_sc_table); i++) {
1143 const struct trace_syscall_entry *entry;
1144
1145 entry = &compat_sc_table[i];
1146 if (!entry->desc)
1147 continue;
1148
1149 if (!strcmp(syscall_name, entry->desc->name)) {
1150 syscall_nr = i;
1151 break;
1152 }
1153 }
1154 return syscall_nr;
1155 }
1156
1157 static
1158 uint32_t get_sc_tables_len(void)
1159 {
1160 return ARRAY_SIZE(sc_table) + ARRAY_SIZE(compat_sc_table);
1161 }
1162
1163 int lttng_syscall_filter_enable_event(struct lttng_channel *chan,
1164 const char *name)
1165 {
1166 int syscall_nr, compat_syscall_nr, ret;
1167 struct lttng_syscall_filter *filter;
1168
1169 WARN_ON_ONCE(!chan->sc_table);
1170
1171 if (!name) {
1172 /* Enable all system calls by removing filter */
1173 if (chan->sc_filter) {
1174 filter = chan->sc_filter;
1175 rcu_assign_pointer(chan->sc_filter, NULL);
1176 synchronize_trace();
1177 kfree(filter);
1178 }
1179 chan->syscall_all = 1;
1180 return 0;
1181 }
1182
1183 if (!chan->sc_filter) {
1184 if (chan->syscall_all) {
1185 /*
1186 * All syscalls are already enabled.
1187 */
1188 return -EEXIST;
1189 }
1190 filter = kzalloc(sizeof(struct lttng_syscall_filter),
1191 GFP_KERNEL);
1192 if (!filter)
1193 return -ENOMEM;
1194 } else {
1195 filter = chan->sc_filter;
1196 }
1197 syscall_nr = get_syscall_nr(name);
1198 compat_syscall_nr = get_compat_syscall_nr(name);
1199 if (syscall_nr < 0 && compat_syscall_nr < 0) {
1200 ret = -ENOENT;
1201 goto error;
1202 }
1203 if (syscall_nr >= 0) {
1204 if (test_bit(syscall_nr, filter->sc)) {
1205 ret = -EEXIST;
1206 goto error;
1207 }
1208 bitmap_set(filter->sc, syscall_nr, 1);
1209 }
1210 if (compat_syscall_nr >= 0) {
1211 if (test_bit(compat_syscall_nr, filter->sc_compat)) {
1212 ret = -EEXIST;
1213 goto error;
1214 }
1215 bitmap_set(filter->sc_compat, compat_syscall_nr, 1);
1216 }
1217 if (!chan->sc_filter)
1218 rcu_assign_pointer(chan->sc_filter, filter);
1219 return 0;
1220
1221 error:
1222 if (!chan->sc_filter)
1223 kfree(filter);
1224 return ret;
1225 }
1226
1227 int lttng_syscall_filter_enable_trigger(struct lttng_trigger *trigger)
1228 {
1229 struct lttng_trigger_group *group = trigger->group;
1230 unsigned int syscall_id = trigger->u.syscall.syscall_id;
1231 struct list_head *dispatch_list;
1232
1233 if (trigger->u.syscall.is_compat)
1234 dispatch_list = &group->trigger_compat_syscall_dispatch[syscall_id];
1235 else
1236 dispatch_list = &group->trigger_syscall_dispatch[syscall_id];
1237
1238 list_add_rcu(&trigger->u.syscall.node, dispatch_list);
1239
1240 return 0;
1241 }
1242
1243 int lttng_syscall_filter_disable_event(struct lttng_channel *chan,
1244 const char *name)
1245 {
1246 int syscall_nr, compat_syscall_nr, ret;
1247 struct lttng_syscall_filter *filter;
1248
1249 WARN_ON_ONCE(!chan->sc_table);
1250
1251 if (!chan->sc_filter) {
1252 if (!chan->syscall_all)
1253 return -EEXIST;
1254 filter = kzalloc(sizeof(struct lttng_syscall_filter),
1255 GFP_KERNEL);
1256 if (!filter)
1257 return -ENOMEM;
1258 /* Trace all system calls, then apply disable. */
1259 bitmap_set(filter->sc, 0, NR_syscalls);
1260 bitmap_set(filter->sc_compat, 0, NR_compat_syscalls);
1261 } else {
1262 filter = chan->sc_filter;
1263 }
1264
1265 if (!name) {
1266 /* Fail if all syscalls are already disabled. */
1267 if (bitmap_empty(filter->sc, NR_syscalls)
1268 && bitmap_empty(filter->sc_compat,
1269 NR_compat_syscalls)) {
1270 ret = -EEXIST;
1271 goto error;
1272 }
1273
1274 /* Disable all system calls */
1275 bitmap_clear(filter->sc, 0, NR_syscalls);
1276 bitmap_clear(filter->sc_compat, 0, NR_compat_syscalls);
1277 goto apply_filter;
1278 }
1279 syscall_nr = get_syscall_nr(name);
1280 compat_syscall_nr = get_compat_syscall_nr(name);
1281 if (syscall_nr < 0 && compat_syscall_nr < 0) {
1282 ret = -ENOENT;
1283 goto error;
1284 }
1285 if (syscall_nr >= 0) {
1286 if (!test_bit(syscall_nr, filter->sc)) {
1287 ret = -EEXIST;
1288 goto error;
1289 }
1290 bitmap_clear(filter->sc, syscall_nr, 1);
1291 }
1292 if (compat_syscall_nr >= 0) {
1293 if (!test_bit(compat_syscall_nr, filter->sc_compat)) {
1294 ret = -EEXIST;
1295 goto error;
1296 }
1297 bitmap_clear(filter->sc_compat, compat_syscall_nr, 1);
1298 }
1299 apply_filter:
1300 if (!chan->sc_filter)
1301 rcu_assign_pointer(chan->sc_filter, filter);
1302 chan->syscall_all = 0;
1303 return 0;
1304
1305 error:
1306 if (!chan->sc_filter)
1307 kfree(filter);
1308 return ret;
1309 }
1310
1311 int lttng_syscall_filter_disable_trigger(struct lttng_trigger *trigger)
1312 {
1313 list_del_rcu(&trigger->u.syscall.node);
1314 return 0;
1315 }
1316
1317 static
1318 const struct trace_syscall_entry *syscall_list_get_entry(loff_t *pos)
1319 {
1320 const struct trace_syscall_entry *entry;
1321 int iter = 0;
1322
1323 for (entry = sc_table;
1324 entry < sc_table + ARRAY_SIZE(sc_table);
1325 entry++) {
1326 if (iter++ >= *pos)
1327 return entry;
1328 }
1329 for (entry = compat_sc_table;
1330 entry < compat_sc_table + ARRAY_SIZE(compat_sc_table);
1331 entry++) {
1332 if (iter++ >= *pos)
1333 return entry;
1334 }
1335 /* End of list */
1336 return NULL;
1337 }
1338
1339 static
1340 void *syscall_list_start(struct seq_file *m, loff_t *pos)
1341 {
1342 return (void *) syscall_list_get_entry(pos);
1343 }
1344
1345 static
1346 void *syscall_list_next(struct seq_file *m, void *p, loff_t *ppos)
1347 {
1348 (*ppos)++;
1349 return (void *) syscall_list_get_entry(ppos);
1350 }
1351
1352 static
1353 void syscall_list_stop(struct seq_file *m, void *p)
1354 {
1355 }
1356
1357 static
1358 int get_sc_table(const struct trace_syscall_entry *entry,
1359 const struct trace_syscall_entry **table,
1360 unsigned int *bitness)
1361 {
1362 if (entry >= sc_table && entry < sc_table + ARRAY_SIZE(sc_table)) {
1363 if (bitness)
1364 *bitness = BITS_PER_LONG;
1365 if (table)
1366 *table = sc_table;
1367 return 0;
1368 }
1369 if (!(entry >= compat_sc_table
1370 && entry < compat_sc_table + ARRAY_SIZE(compat_sc_table))) {
1371 return -EINVAL;
1372 }
1373 if (bitness)
1374 *bitness = 32;
1375 if (table)
1376 *table = compat_sc_table;
1377 return 0;
1378 }
1379
1380 static
1381 int syscall_list_show(struct seq_file *m, void *p)
1382 {
1383 const struct trace_syscall_entry *table, *entry = p;
1384 unsigned int bitness;
1385 unsigned long index;
1386 int ret;
1387 const char *name;
1388
1389 ret = get_sc_table(entry, &table, &bitness);
1390 if (ret)
1391 return ret;
1392 if (!entry->desc)
1393 return 0;
1394 if (table == sc_table) {
1395 index = entry - table;
1396 name = &entry->desc->name[strlen(SYSCALL_ENTRY_STR)];
1397 } else {
1398 index = (entry - table) + ARRAY_SIZE(sc_table);
1399 name = &entry->desc->name[strlen(COMPAT_SYSCALL_ENTRY_STR)];
1400 }
1401 seq_printf(m, "syscall { index = %lu; name = %s; bitness = %u; };\n",
1402 index, name, bitness);
1403 return 0;
1404 }
1405
1406 static
1407 const struct seq_operations lttng_syscall_list_seq_ops = {
1408 .start = syscall_list_start,
1409 .next = syscall_list_next,
1410 .stop = syscall_list_stop,
1411 .show = syscall_list_show,
1412 };
1413
1414 static
1415 int lttng_syscall_list_open(struct inode *inode, struct file *file)
1416 {
1417 return seq_open(file, &lttng_syscall_list_seq_ops);
1418 }
1419
1420 const struct file_operations lttng_syscall_list_fops = {
1421 .owner = THIS_MODULE,
1422 .open = lttng_syscall_list_open,
1423 .read = seq_read,
1424 .llseek = seq_lseek,
1425 .release = seq_release,
1426 };
1427
1428 long lttng_channel_syscall_mask(struct lttng_channel *channel,
1429 struct lttng_kernel_syscall_mask __user *usyscall_mask)
1430 {
1431 uint32_t len, sc_tables_len, bitmask_len;
1432 int ret = 0, bit;
1433 char *tmp_mask;
1434 struct lttng_syscall_filter *filter;
1435
1436 ret = get_user(len, &usyscall_mask->len);
1437 if (ret)
1438 return ret;
1439 sc_tables_len = get_sc_tables_len();
1440 bitmask_len = ALIGN(sc_tables_len, 8) >> 3;
1441 if (len < sc_tables_len) {
1442 return put_user(sc_tables_len, &usyscall_mask->len);
1443 }
1444 /* Array is large enough, we can copy array to user-space. */
1445 tmp_mask = kzalloc(bitmask_len, GFP_KERNEL);
1446 if (!tmp_mask)
1447 return -ENOMEM;
1448 filter = channel->sc_filter;
1449
1450 for (bit = 0; bit < ARRAY_SIZE(sc_table); bit++) {
1451 char state;
1452
1453 if (channel->sc_table) {
1454 if (filter)
1455 state = test_bit(bit, filter->sc);
1456 else
1457 state = 1;
1458 } else {
1459 state = 0;
1460 }
1461 bt_bitfield_write_be(tmp_mask, char, bit, 1, state);
1462 }
1463 for (; bit < sc_tables_len; bit++) {
1464 char state;
1465
1466 if (channel->compat_sc_table) {
1467 if (filter)
1468 state = test_bit(bit - ARRAY_SIZE(sc_table),
1469 filter->sc_compat);
1470 else
1471 state = 1;
1472 } else {
1473 state = 0;
1474 }
1475 bt_bitfield_write_be(tmp_mask, char, bit, 1, state);
1476 }
1477 if (copy_to_user(usyscall_mask->mask, tmp_mask, bitmask_len))
1478 ret = -EFAULT;
1479 kfree(tmp_mask);
1480 return ret;
1481 }
1482
1483 int lttng_abi_syscall_list(void)
1484 {
1485 struct file *syscall_list_file;
1486 int file_fd, ret;
1487
1488 file_fd = lttng_get_unused_fd();
1489 if (file_fd < 0) {
1490 ret = file_fd;
1491 goto fd_error;
1492 }
1493
1494 syscall_list_file = anon_inode_getfile("[lttng_syscall_list]",
1495 &lttng_syscall_list_fops,
1496 NULL, O_RDWR);
1497 if (IS_ERR(syscall_list_file)) {
1498 ret = PTR_ERR(syscall_list_file);
1499 goto file_error;
1500 }
1501 ret = lttng_syscall_list_fops.open(NULL, syscall_list_file);
1502 if (ret < 0)
1503 goto open_error;
1504 fd_install(file_fd, syscall_list_file);
1505 return file_fd;
1506
1507 open_error:
1508 fput(syscall_list_file);
1509 file_error:
1510 put_unused_fd(file_fd);
1511 fd_error:
1512 return ret;
1513 }
This page took 0.103893 seconds and 5 git commands to generate.