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