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