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