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