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