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