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