Refactoring: event notifier create: use enablers
[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{
0bb716a8 539 struct lttng_kernel_syscall_table *syscall_table = get_syscall_table_from_enabler(&syscall_event_enabler->parent);
def1e304 540 struct lttng_kernel_channel_buffer *chan = syscall_event_enabler->chan;
f7d06400 541 struct lttng_kernel_session *session = chan->parent.session;
259b6cb3 542 unsigned int i;
49c50022 543
3b82c4e1 544 /* Allocate events for each syscall matching enabler, insert into table */
49c50022 545 for (i = 0; i < table_len; i++) {
437d5aa5 546 const struct lttng_kernel_event_desc *desc = table[i].desc;
1ae083ba 547 struct lttng_event_recorder_enabler *event_enabler;
606828e4 548 struct lttng_kernel_abi_event ev;
a67ba386
MD
549 struct lttng_kernel_event_recorder_private *event_recorder_priv;
550 struct lttng_kernel_event_recorder *event_recorder;
3b82c4e1
MD
551 struct hlist_head *head;
552 bool found = false;
49c50022
MD
553
554 if (!desc) {
555 /* Unknown syscall */
556 continue;
557 }
3b82c4e1 558 if (lttng_desc_match_enabler(desc,
1ae083ba 559 lttng_event_recorder_enabler_as_enabler(syscall_event_enabler)) <= 0)
3b82c4e1 560 continue;
49c50022 561 /*
3b82c4e1 562 * Check if already created.
49c50022 563 */
3b82c4e1 564 head = utils_borrow_hash_table_bucket(
8cdc1a81 565 session->priv->events_ht.table, LTTNG_EVENT_HT_SIZE,
437d5aa5 566 desc->event_name);
a67ba386
MD
567 lttng_hlist_for_each_entry(event_recorder_priv, head, hlist) {
568 if (event_recorder_priv->parent.desc == desc
0bb716a8 569 && get_syscall_table_from_event(event_recorder_priv->parent.pub) == syscall_table)
3b82c4e1
MD
570 found = true;
571 }
572 if (found)
49c50022 573 continue;
3b82c4e1
MD
574
575 /* We need to create an event for this syscall/enabler. */
49c50022 576 memset(&ev, 0, sizeof(ev));
5b7ac358
MD
577 switch (type) {
578 case SC_TYPE_ENTRY:
606828e4
MD
579 ev.u.syscall.entryexit = LTTNG_KERNEL_ABI_SYSCALL_ENTRY;
580 ev.u.syscall.abi = LTTNG_KERNEL_ABI_SYSCALL_ABI_NATIVE;
5b7ac358
MD
581 break;
582 case SC_TYPE_EXIT:
606828e4
MD
583 ev.u.syscall.entryexit = LTTNG_KERNEL_ABI_SYSCALL_EXIT;
584 ev.u.syscall.abi = LTTNG_KERNEL_ABI_SYSCALL_ABI_NATIVE;
5b7ac358
MD
585 break;
586 case SC_TYPE_COMPAT_ENTRY:
606828e4
MD
587 ev.u.syscall.entryexit = LTTNG_KERNEL_ABI_SYSCALL_ENTRY;
588 ev.u.syscall.abi = LTTNG_KERNEL_ABI_SYSCALL_ABI_COMPAT;
5b7ac358
MD
589 break;
590 case SC_TYPE_COMPAT_EXIT:
606828e4
MD
591 ev.u.syscall.entryexit = LTTNG_KERNEL_ABI_SYSCALL_EXIT;
592 ev.u.syscall.abi = LTTNG_KERNEL_ABI_SYSCALL_ABI_COMPAT;
5b7ac358
MD
593 break;
594 }
606828e4
MD
595 strncpy(ev.name, desc->event_name, LTTNG_KERNEL_ABI_SYM_NAME_LEN - 1);
596 ev.name[LTTNG_KERNEL_ABI_SYM_NAME_LEN - 1] = '\0';
597 ev.instrumentation = LTTNG_KERNEL_ABI_SYSCALL;
1ae083ba 598 event_enabler = lttng_event_recorder_enabler_create(LTTNG_ENABLER_FORMAT_NAME, &ev, chan);
def1e304
MD
599 if (!event_enabler) {
600 return -ENOMEM;
601 }
602 event_recorder = _lttng_kernel_event_recorder_create(event_enabler, desc);
a67ba386 603 WARN_ON_ONCE(!event_recorder);
44b1abdc 604 lttng_event_enabler_destroy(&event_enabler->parent);
a67ba386 605 if (IS_ERR(event_recorder)) {
49c50022
MD
606 /*
607 * If something goes wrong in event registration
608 * after the first one, we have no choice but to
609 * leave the previous events in there, until
610 * deleted by session teardown.
611 */
a67ba386 612 return PTR_ERR(event_recorder);
49c50022 613 }
a67ba386 614 hlist_add_head(&event_recorder->priv->parent.u.syscall.node, &chan_table[i]);
49c50022
MD
615 }
616 return 0;
617}
618
d26015f6
MD
619static
620int lttng_syscalls_populate_events(struct lttng_event_enabler_common *syscall_event_enabler)
49c50022 621{
d26015f6
MD
622 struct lttng_kernel_syscall_table *syscall_table = get_syscall_table_from_enabler(syscall_event_enabler);
623 struct lttng_event_recorder_enabler *event_recorder_enabler;
624 struct lttng_kernel_channel_buffer *chan;
606828e4 625 struct lttng_kernel_abi_event ev;
259b6cb3
MD
626 int ret;
627
d26015f6
MD
628 if (syscall_event_enabler->enabler_type != LTTNG_EVENT_ENABLER_TYPE_RECORDER)
629 return 0;
630 event_recorder_enabler = container_of(syscall_event_enabler, struct lttng_event_recorder_enabler, parent);
631 chan = event_recorder_enabler->chan;
259b6cb3 632
0bb716a8 633 if (hlist_empty(&syscall_table->unknown_syscall_dispatch)) {
437d5aa5 634 const struct lttng_kernel_event_desc *desc =
d4291869 635 &__event_desc___syscall_entry_unknown;
a67ba386 636 struct lttng_kernel_event_recorder *event_recorder;
1ae083ba 637 struct lttng_event_recorder_enabler *event_enabler;
2f804c0a 638
f405cfce 639 memset(&ev, 0, sizeof(ev));
606828e4
MD
640 strncpy(ev.name, desc->event_name, LTTNG_KERNEL_ABI_SYM_NAME_LEN);
641 ev.name[LTTNG_KERNEL_ABI_SYM_NAME_LEN - 1] = '\0';
642 ev.instrumentation = LTTNG_KERNEL_ABI_SYSCALL;
643 ev.u.syscall.entryexit = LTTNG_KERNEL_ABI_SYSCALL_ENTRY;
644 ev.u.syscall.abi = LTTNG_KERNEL_ABI_SYSCALL_ABI_NATIVE;
d26015f6 645 event_enabler = lttng_event_recorder_enabler_create(LTTNG_ENABLER_FORMAT_NAME, &ev, chan);
def1e304
MD
646 if (!event_enabler) {
647 return -ENOMEM;
648 }
649 event_recorder = _lttng_kernel_event_recorder_create(event_enabler, desc);
44b1abdc 650 lttng_event_enabler_destroy(&event_enabler->parent);
a67ba386
MD
651 WARN_ON_ONCE(!event_recorder);
652 if (IS_ERR(event_recorder)) {
653 return PTR_ERR(event_recorder);
f405cfce 654 }
0bb716a8 655 hlist_add_head(&event_recorder->priv->parent.u.syscall.node, &syscall_table->unknown_syscall_dispatch);
f405cfce
MD
656 }
657
0bb716a8 658 if (hlist_empty(&syscall_table->compat_unknown_syscall_dispatch)) {
437d5aa5 659 const struct lttng_kernel_event_desc *desc =
d4291869 660 &__event_desc___compat_syscall_entry_unknown;
a67ba386 661 struct lttng_kernel_event_recorder *event_recorder;
1ae083ba 662 struct lttng_event_recorder_enabler *event_enabler;
b76dc1a0
MD
663
664 memset(&ev, 0, sizeof(ev));
606828e4
MD
665 strncpy(ev.name, desc->event_name, LTTNG_KERNEL_ABI_SYM_NAME_LEN);
666 ev.name[LTTNG_KERNEL_ABI_SYM_NAME_LEN - 1] = '\0';
667 ev.instrumentation = LTTNG_KERNEL_ABI_SYSCALL;
668 ev.u.syscall.entryexit = LTTNG_KERNEL_ABI_SYSCALL_ENTRY;
669 ev.u.syscall.abi = LTTNG_KERNEL_ABI_SYSCALL_ABI_COMPAT;
d26015f6 670 event_enabler = lttng_event_recorder_enabler_create(LTTNG_ENABLER_FORMAT_NAME, &ev, chan);
def1e304
MD
671 if (!event_enabler) {
672 return -ENOMEM;
673 }
674 event_recorder = _lttng_kernel_event_recorder_create(event_enabler, desc);
a67ba386 675 WARN_ON_ONCE(!event_recorder);
44b1abdc 676 lttng_event_enabler_destroy(&event_enabler->parent);
a67ba386
MD
677 if (IS_ERR(event_recorder)) {
678 return PTR_ERR(event_recorder);
b76dc1a0 679 }
0bb716a8 680 hlist_add_head(&event_recorder->priv->parent.u.syscall.node, &syscall_table->compat_unknown_syscall_dispatch);
b76dc1a0
MD
681 }
682
0bb716a8 683 if (hlist_empty(&syscall_table->compat_unknown_syscall_exit_dispatch)) {
437d5aa5 684 const struct lttng_kernel_event_desc *desc =
5b7ac358 685 &__event_desc___compat_syscall_exit_unknown;
a67ba386 686 struct lttng_kernel_event_recorder *event_recorder;
1ae083ba 687 struct lttng_event_recorder_enabler *event_enabler;
2f804c0a
MD
688
689 memset(&ev, 0, sizeof(ev));
606828e4
MD
690 strncpy(ev.name, desc->event_name, LTTNG_KERNEL_ABI_SYM_NAME_LEN);
691 ev.name[LTTNG_KERNEL_ABI_SYM_NAME_LEN - 1] = '\0';
692 ev.instrumentation = LTTNG_KERNEL_ABI_SYSCALL;
693 ev.u.syscall.entryexit = LTTNG_KERNEL_ABI_SYSCALL_EXIT;
694 ev.u.syscall.abi = LTTNG_KERNEL_ABI_SYSCALL_ABI_COMPAT;
d26015f6 695 event_enabler = lttng_event_recorder_enabler_create(LTTNG_ENABLER_FORMAT_NAME, &ev, chan);
def1e304
MD
696 if (!event_enabler) {
697 return -ENOMEM;
698 }
699 event_recorder = _lttng_kernel_event_recorder_create(event_enabler, desc);
a67ba386 700 WARN_ON_ONCE(!event_recorder);
44b1abdc 701 lttng_event_enabler_destroy(&event_enabler->parent);
a67ba386
MD
702 if (IS_ERR(event_recorder)) {
703 return PTR_ERR(event_recorder);
5b7ac358 704 }
0bb716a8 705 hlist_add_head(&event_recorder->priv->parent.u.syscall.node, &syscall_table->compat_unknown_syscall_exit_dispatch);
5b7ac358
MD
706 }
707
0bb716a8 708 if (hlist_empty(&syscall_table->unknown_syscall_exit_dispatch)) {
437d5aa5 709 const struct lttng_kernel_event_desc *desc =
5b7ac358 710 &__event_desc___syscall_exit_unknown;
a67ba386 711 struct lttng_kernel_event_recorder *event_recorder;
1ae083ba 712 struct lttng_event_recorder_enabler *event_enabler;
5b7ac358
MD
713
714 memset(&ev, 0, sizeof(ev));
606828e4
MD
715 strncpy(ev.name, desc->event_name, LTTNG_KERNEL_ABI_SYM_NAME_LEN);
716 ev.name[LTTNG_KERNEL_ABI_SYM_NAME_LEN - 1] = '\0';
717 ev.instrumentation = LTTNG_KERNEL_ABI_SYSCALL;
718 ev.u.syscall.entryexit = LTTNG_KERNEL_ABI_SYSCALL_EXIT;
719 ev.u.syscall.abi = LTTNG_KERNEL_ABI_SYSCALL_ABI_NATIVE;
d26015f6 720 event_enabler = lttng_event_recorder_enabler_create(LTTNG_ENABLER_FORMAT_NAME, &ev, chan);
def1e304
MD
721 if (!event_enabler) {
722 return -ENOMEM;
723 }
724 event_recorder = _lttng_kernel_event_recorder_create(event_enabler, desc);
a67ba386 725 WARN_ON_ONCE(!event_recorder);
44b1abdc 726 lttng_event_enabler_destroy(&event_enabler->parent);
a67ba386
MD
727 if (IS_ERR(event_recorder)) {
728 return PTR_ERR(event_recorder);
2f804c0a 729 }
0bb716a8 730 hlist_add_head(&event_recorder->priv->parent.u.syscall.node, &syscall_table->unknown_syscall_exit_dispatch);
2f804c0a
MD
731 }
732
ebcc64cd 733 ret = lttng_create_syscall_event_if_missing(sc_table.table, sc_table.len,
d26015f6 734 syscall_table->syscall_dispatch, event_recorder_enabler, SC_TYPE_ENTRY);
5b7ac358
MD
735 if (ret)
736 return ret;
ebcc64cd 737 ret = lttng_create_syscall_event_if_missing(sc_exit_table.table, sc_exit_table.len,
d26015f6 738 syscall_table->syscall_exit_dispatch, event_recorder_enabler, SC_TYPE_EXIT);
49c50022
MD
739 if (ret)
740 return ret;
5b7ac358 741
49c50022 742#ifdef CONFIG_COMPAT
ebcc64cd 743 ret = lttng_create_syscall_event_if_missing(compat_sc_table.table, compat_sc_table.len,
d26015f6 744 syscall_table->compat_syscall_dispatch, event_recorder_enabler, SC_TYPE_COMPAT_ENTRY);
5b7ac358
MD
745 if (ret)
746 return ret;
ebcc64cd 747 ret = lttng_create_syscall_event_if_missing(compat_sc_exit_table.table, compat_sc_exit_table.len,
d26015f6 748 syscall_table->compat_syscall_exit_dispatch, event_recorder_enabler, SC_TYPE_COMPAT_EXIT);
49c50022
MD
749 if (ret)
750 return ret;
751#endif
259b6cb3
MD
752 return ret;
753}
754
755/*
8a8ac9a8
FD
756 * Should be called with sessions lock held.
757 */
d26015f6 758int lttng_syscalls_register_event(struct lttng_event_enabler_common *syscall_event_enabler)
8a8ac9a8 759{
d26015f6
MD
760 struct lttng_kernel_syscall_table *syscall_table = get_syscall_table_from_enabler(syscall_event_enabler);
761 int ret;
8a8ac9a8 762
0bb716a8 763 if (!syscall_table->syscall_dispatch) {
d26015f6 764 /* create syscall table mapping syscall to events */
0bb716a8
MD
765 syscall_table->syscall_dispatch = kzalloc(sizeof(struct hlist_head) * sc_table.len, GFP_KERNEL);
766 if (!syscall_table->syscall_dispatch)
8a8ac9a8 767 return -ENOMEM;
8a8ac9a8 768 }
0bb716a8 769 if (!syscall_table->syscall_exit_dispatch) {
d26015f6
MD
770 /* create syscall table mapping syscall to events */
771 syscall_table->syscall_exit_dispatch = kzalloc(sizeof(struct hlist_head) * sc_exit_table.len, GFP_KERNEL);
0bb716a8 772 if (!syscall_table->syscall_exit_dispatch)
8a8ac9a8 773 return -ENOMEM;
8a8ac9a8
FD
774 }
775
d26015f6 776
8a8ac9a8 777#ifdef CONFIG_COMPAT
0bb716a8 778 if (!syscall_table->compat_syscall_dispatch) {
d26015f6 779 /* create syscall table mapping compat syscall to events */
0bb716a8
MD
780 syscall_table->compat_syscall_dispatch = kzalloc(sizeof(struct hlist_head) * compat_sc_table.len, GFP_KERNEL);
781 if (!syscall_table->compat_syscall_dispatch)
8a8ac9a8 782 return -ENOMEM;
8a8ac9a8
FD
783 }
784
0bb716a8 785 if (!syscall_table->compat_syscall_exit_dispatch) {
d26015f6
MD
786 /* create syscall table mapping compat syscall to events */
787 syscall_table->compat_syscall_exit_dispatch = kzalloc(sizeof(struct hlist_head) * compat_sc_exit_table.len, GFP_KERNEL);
0bb716a8 788 if (!syscall_table->compat_syscall_exit_dispatch)
8a8ac9a8 789 return -ENOMEM;
8a8ac9a8
FD
790 }
791#endif
0bb716a8
MD
792 if (!syscall_table->sc_filter) {
793 syscall_table->sc_filter = kzalloc(sizeof(struct lttng_syscall_filter),
8a8ac9a8 794 GFP_KERNEL);
0bb716a8 795 if (!syscall_table->sc_filter)
8a8ac9a8
FD
796 return -ENOMEM;
797 }
798
d26015f6
MD
799 ret = lttng_syscalls_populate_events(syscall_event_enabler);
800 if (ret)
801 return ret;
802
803 wrapper_vmalloc_sync_mappings();
804
0bb716a8 805 if (!syscall_table->sys_enter_registered) {
8a8ac9a8 806 ret = lttng_wrapper_tracepoint_probe_register("sys_enter",
0bb716a8 807 (void *) syscall_entry_event_probe, syscall_table);
8a8ac9a8
FD
808 if (ret)
809 return ret;
0bb716a8 810 syscall_table->sys_enter_registered = 1;
8a8ac9a8 811 }
0bb716a8 812 if (!syscall_table->sys_exit_registered) {
8a8ac9a8 813 ret = lttng_wrapper_tracepoint_probe_register("sys_exit",
0bb716a8 814 (void *) syscall_exit_event_probe, syscall_table);
8a8ac9a8
FD
815 if (ret) {
816 WARN_ON_ONCE(lttng_wrapper_tracepoint_probe_unregister("sys_enter",
0bb716a8 817 (void *) syscall_entry_event_probe, syscall_table));
8a8ac9a8
FD
818 return ret;
819 }
0bb716a8 820 syscall_table->sys_exit_registered = 1;
8a8ac9a8 821 }
0fab709d
MD
822
823 ret = lttng_syscalls_create_matching_event_notifiers(syscall_event_enabler);
824 if (ret)
825 return ret;
826
8a8ac9a8
FD
827 return ret;
828}
829
830static
831int create_unknown_event_notifier(
832 struct lttng_event_notifier_enabler *event_notifier_enabler,
833 enum sc_type type)
834{
a67ba386
MD
835 struct lttng_kernel_event_notifier_private *event_notifier_priv;
836 struct lttng_kernel_event_notifier *event_notifier;
437d5aa5 837 const struct lttng_kernel_event_desc *desc;
8a8ac9a8 838 struct lttng_event_notifier_group *group = event_notifier_enabler->group;
0bb716a8 839 struct lttng_kernel_syscall_table *syscall_table = &group->syscall_table;
606828e4 840 struct lttng_kernel_abi_event_notifier event_notifier_param;
5b9817ae 841 uint64_t user_token = event_notifier_enabler->parent.user_token;
99f52fcc 842 uint64_t error_counter_index = event_notifier_enabler->error_counter_index;
8d554755 843 struct lttng_event_enabler_common *base_enabler = lttng_event_notifier_enabler_as_enabler(
8a8ac9a8
FD
844 event_notifier_enabler);
845 struct hlist_head *unknown_dispatch_list;
846 int ret = 0;
847 bool found = false;
606828e4
MD
848 enum lttng_kernel_abi_syscall_abi abi;
849 enum lttng_kernel_abi_syscall_entryexit entryexit;
8a8ac9a8
FD
850 struct hlist_head *head;
851
852 switch (type) {
853 case SC_TYPE_ENTRY:
854 desc = &__event_desc___syscall_entry_unknown;
0bb716a8 855 unknown_dispatch_list = &syscall_table->unknown_syscall_dispatch;
606828e4
MD
856 entryexit = LTTNG_KERNEL_ABI_SYSCALL_ENTRY;
857 abi = LTTNG_KERNEL_ABI_SYSCALL_ABI_NATIVE;
8a8ac9a8
FD
858 break;
859 case SC_TYPE_EXIT:
860 desc = &__event_desc___syscall_exit_unknown;
0bb716a8 861 unknown_dispatch_list = &syscall_table->unknown_syscall_exit_dispatch;
606828e4
MD
862 entryexit = LTTNG_KERNEL_ABI_SYSCALL_EXIT;
863 abi = LTTNG_KERNEL_ABI_SYSCALL_ABI_NATIVE;
8a8ac9a8
FD
864 break;
865 case SC_TYPE_COMPAT_ENTRY:
866 desc = &__event_desc___compat_syscall_entry_unknown;
0bb716a8 867 unknown_dispatch_list = &syscall_table->compat_unknown_syscall_dispatch;
606828e4
MD
868 entryexit = LTTNG_KERNEL_ABI_SYSCALL_ENTRY;
869 abi = LTTNG_KERNEL_ABI_SYSCALL_ABI_COMPAT;
8a8ac9a8
FD
870 break;
871 case SC_TYPE_COMPAT_EXIT:
872 desc = &__event_desc___compat_syscall_exit_unknown;
0bb716a8 873 unknown_dispatch_list = &syscall_table->compat_unknown_syscall_exit_dispatch;
606828e4
MD
874 entryexit = LTTNG_KERNEL_ABI_SYSCALL_EXIT;
875 abi = LTTNG_KERNEL_ABI_SYSCALL_ABI_COMPAT;
8a8ac9a8
FD
876 break;
877 default:
878 BUG_ON(1);
879 }
880
881 /*
882 * Check if already created.
883 */
33af697f
MD
884 head = utils_borrow_hash_table_bucket(group->events_ht.table,
885 LTTNG_EVENT_HT_SIZE, desc->event_name);
a67ba386
MD
886 lttng_hlist_for_each_entry(event_notifier_priv, head, hlist) {
887 if (event_notifier_priv->parent.desc == desc &&
888 event_notifier_priv->parent.user_token == base_enabler->user_token)
8a8ac9a8
FD
889 found = true;
890 }
891 if (found)
892 goto end;
893
894 memset(&event_notifier_param, 0, sizeof(event_notifier_param));
437d5aa5 895 strncat(event_notifier_param.event.name, desc->event_name,
606828e4 896 LTTNG_KERNEL_ABI_SYM_NAME_LEN - strlen(event_notifier_param.event.name) - 1);
8a8ac9a8 897
606828e4 898 event_notifier_param.event.name[LTTNG_KERNEL_ABI_SYM_NAME_LEN - 1] = '\0';
8a8ac9a8 899
606828e4 900 event_notifier_param.event.instrumentation = LTTNG_KERNEL_ABI_SYSCALL;
1bbb5b2d 901 event_notifier_param.event.token = user_token;
8a8ac9a8
FD
902 event_notifier_param.event.u.syscall.abi = abi;
903 event_notifier_param.event.u.syscall.entryexit = entryexit;
1bbb5b2d 904 event_notifier_param.error_counter_index = error_counter_index;
8a8ac9a8 905
1bbb5b2d
MD
906 event_notifier_enabler = lttng_event_notifier_enabler_create(LTTNG_ENABLER_FORMAT_NAME,
907 &event_notifier_param, group);
908 WARN_ON_ONCE(!event_notifier_enabler);
909 event_notifier = _lttng_event_notifier_create(event_notifier_enabler, desc);
910 lttng_event_enabler_destroy(&event_notifier_enabler->parent);
a67ba386 911 if (IS_ERR(event_notifier)) {
8a8ac9a8 912 printk(KERN_INFO "Unable to create unknown notifier %s\n",
437d5aa5 913 desc->event_name);
8a8ac9a8
FD
914 ret = -ENOMEM;
915 goto end;
916 }
917
a67ba386 918 hlist_add_head_rcu(&event_notifier->priv->parent.u.syscall.node, unknown_dispatch_list);
8a8ac9a8
FD
919
920end:
921 return ret;
922}
923
924static int create_matching_event_notifiers(
1bbb5b2d 925 struct lttng_event_notifier_enabler *syscall_event_notifier_enabler,
a67ba386 926 const struct trace_syscall_entry *table,
8a8ac9a8
FD
927 size_t table_len, enum sc_type type)
928{
1bbb5b2d 929 struct lttng_event_notifier_group *group = syscall_event_notifier_enabler->group;
437d5aa5 930 const struct lttng_kernel_event_desc *desc;
1bbb5b2d
MD
931 uint64_t user_token = syscall_event_notifier_enabler->parent.user_token;
932 uint64_t error_counter_index = syscall_event_notifier_enabler->error_counter_index;
8a8ac9a8
FD
933 unsigned int i;
934 int ret = 0;
935
936 /* iterate over all syscall and create event_notifier that match */
937 for (i = 0; i < table_len; i++) {
1bbb5b2d 938 struct lttng_event_notifier_enabler *event_notifier_enabler;
a67ba386
MD
939 struct lttng_kernel_event_notifier_private *event_notifier_priv;
940 struct lttng_kernel_event_notifier *event_notifier;
606828e4 941 struct lttng_kernel_abi_event_notifier event_notifier_param;
8a8ac9a8
FD
942 struct hlist_head *head;
943 int found = 0;
944
945 desc = table[i].desc;
946 if (!desc) {
947 /* Unknown syscall */
948 continue;
949 }
950
951 if (!lttng_desc_match_enabler(desc,
1bbb5b2d 952 lttng_event_notifier_enabler_as_enabler(syscall_event_notifier_enabler)))
8a8ac9a8
FD
953 continue;
954
955 /*
956 * Check if already created.
957 */
33af697f
MD
958 head = utils_borrow_hash_table_bucket(group->events_ht.table,
959 LTTNG_EVENT_HT_SIZE, desc->event_name);
a67ba386
MD
960 lttng_hlist_for_each_entry(event_notifier_priv, head, hlist) {
961 if (event_notifier_priv->parent.desc == desc
1bbb5b2d 962 && event_notifier_priv->parent.user_token == syscall_event_notifier_enabler->parent.user_token)
8a8ac9a8
FD
963 found = 1;
964 }
965 if (found)
966 continue;
967
968 memset(&event_notifier_param, 0, sizeof(event_notifier_param));
969 switch (type) {
970 case SC_TYPE_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_NATIVE;
8a8ac9a8
FD
973 break;
974 case SC_TYPE_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_NATIVE;
8a8ac9a8
FD
977 break;
978 case SC_TYPE_COMPAT_ENTRY:
606828e4
MD
979 event_notifier_param.event.u.syscall.entryexit = LTTNG_KERNEL_ABI_SYSCALL_ENTRY;
980 event_notifier_param.event.u.syscall.abi = LTTNG_KERNEL_ABI_SYSCALL_ABI_COMPAT;
8a8ac9a8
FD
981 break;
982 case SC_TYPE_COMPAT_EXIT:
606828e4
MD
983 event_notifier_param.event.u.syscall.entryexit = LTTNG_KERNEL_ABI_SYSCALL_EXIT;
984 event_notifier_param.event.u.syscall.abi = LTTNG_KERNEL_ABI_SYSCALL_ABI_COMPAT;
8a8ac9a8
FD
985 break;
986 }
437d5aa5 987 strncat(event_notifier_param.event.name, desc->event_name,
606828e4
MD
988 LTTNG_KERNEL_ABI_SYM_NAME_LEN - strlen(event_notifier_param.event.name) - 1);
989 event_notifier_param.event.name[LTTNG_KERNEL_ABI_SYM_NAME_LEN - 1] = '\0';
990 event_notifier_param.event.instrumentation = LTTNG_KERNEL_ABI_SYSCALL;
1bbb5b2d
MD
991 event_notifier_param.event.token = user_token;
992 event_notifier_param.error_counter_index = error_counter_index;
993
994 event_notifier_enabler = lttng_event_notifier_enabler_create(LTTNG_ENABLER_FORMAT_NAME,
995 &event_notifier_param, group);
996 WARN_ON_ONCE(!event_notifier_enabler);
997 event_notifier = _lttng_event_notifier_create(event_notifier_enabler, desc);
998 lttng_event_enabler_destroy(&event_notifier_enabler->parent);
8a8ac9a8
FD
999 if (IS_ERR(event_notifier)) {
1000 printk(KERN_INFO "Unable to create event_notifier %s\n",
437d5aa5 1001 desc->event_name);
8a8ac9a8
FD
1002 ret = -ENOMEM;
1003 goto end;
1004 }
1005
a67ba386 1006 event_notifier->priv->parent.u.syscall.syscall_id = i;
8a8ac9a8
FD
1007 }
1008
1009end:
1010 return ret;
1011
1012}
1013
0fab709d
MD
1014static
1015int lttng_syscalls_create_matching_event_notifiers(struct lttng_event_enabler_common *event_enabler)
8a8ac9a8
FD
1016{
1017 int ret;
606828e4 1018 enum lttng_kernel_abi_syscall_entryexit entryexit =
0fab709d
MD
1019 event_enabler->event_param.u.syscall.entryexit;
1020 struct lttng_event_notifier_enabler *event_notifier_enabler;
1021
1022 if (event_enabler->enabler_type != LTTNG_EVENT_ENABLER_TYPE_NOTIFIER)
1023 return 0;
1024 event_notifier_enabler = container_of(event_enabler, struct lttng_event_notifier_enabler, parent);
8a8ac9a8 1025
606828e4 1026 if (entryexit == LTTNG_KERNEL_ABI_SYSCALL_ENTRY || entryexit == LTTNG_KERNEL_ABI_SYSCALL_ENTRYEXIT) {
8a8ac9a8 1027 ret = create_matching_event_notifiers(event_notifier_enabler,
ebcc64cd 1028 sc_table.table, sc_table.len, SC_TYPE_ENTRY);
8a8ac9a8
FD
1029 if (ret)
1030 goto end;
1031
1032 ret = create_matching_event_notifiers(event_notifier_enabler,
ebcc64cd 1033 compat_sc_table.table, compat_sc_table.len,
8a8ac9a8
FD
1034 SC_TYPE_COMPAT_ENTRY);
1035 if (ret)
1036 goto end;
1037
1038 ret = create_unknown_event_notifier(event_notifier_enabler,
1039 SC_TYPE_ENTRY);
1040 if (ret)
1041 goto end;
1042
1043 ret = create_unknown_event_notifier(event_notifier_enabler,
1044 SC_TYPE_COMPAT_ENTRY);
1045 if (ret)
1046 goto end;
1047 }
1048
606828e4 1049 if (entryexit == LTTNG_KERNEL_ABI_SYSCALL_EXIT || entryexit == LTTNG_KERNEL_ABI_SYSCALL_ENTRYEXIT) {
8a8ac9a8 1050 ret = create_matching_event_notifiers(event_notifier_enabler,
ebcc64cd 1051 sc_exit_table.table, sc_exit_table.len,
8a8ac9a8
FD
1052 SC_TYPE_EXIT);
1053 if (ret)
1054 goto end;
1055
1056 ret = create_unknown_event_notifier(event_notifier_enabler,
1057 SC_TYPE_EXIT);
1058 if (ret)
1059 goto end;
1060
1061 ret = create_matching_event_notifiers(event_notifier_enabler,
ebcc64cd 1062 compat_sc_exit_table.table, compat_sc_exit_table.len,
8a8ac9a8
FD
1063 SC_TYPE_COMPAT_EXIT);
1064 if (ret)
1065 goto end;
1066
1067 ret = create_unknown_event_notifier(event_notifier_enabler,
1068 SC_TYPE_COMPAT_EXIT);
1069 if (ret)
1070 goto end;
1071 }
1072
1073end:
1074 return ret;
1075}
1076
6053e75e 1077int lttng_syscalls_unregister_syscall_table(struct lttng_kernel_syscall_table *syscall_table)
259b6cb3
MD
1078{
1079 int ret;
1080
0bb716a8 1081 if (!syscall_table->syscall_dispatch)
259b6cb3 1082 return 0;
0bb716a8 1083 if (syscall_table->sys_enter_registered) {
2d9cd7f3 1084 ret = lttng_wrapper_tracepoint_probe_unregister("sys_enter",
0bb716a8 1085 (void *) syscall_entry_event_probe, syscall_table);
80f87dd2
MD
1086 if (ret)
1087 return ret;
0bb716a8 1088 syscall_table->sys_enter_registered = 0;
80f87dd2 1089 }
0bb716a8 1090 if (syscall_table->sys_exit_registered) {
2d9cd7f3 1091 ret = lttng_wrapper_tracepoint_probe_unregister("sys_exit",
0bb716a8 1092 (void *) syscall_exit_event_probe, syscall_table);
80f87dd2
MD
1093 if (ret)
1094 return ret;
0bb716a8 1095 syscall_table->sys_exit_registered = 0;
80f87dd2 1096 }
badfe9f5
MD
1097 return 0;
1098}
1099
6053e75e 1100int lttng_syscalls_destroy_syscall_table(struct lttng_kernel_syscall_table *syscall_table)
badfe9f5 1101{
0bb716a8
MD
1102 kfree(syscall_table->syscall_dispatch);
1103 kfree(syscall_table->syscall_exit_dispatch);
49c50022 1104#ifdef CONFIG_COMPAT
0bb716a8
MD
1105 kfree(syscall_table->compat_syscall_dispatch);
1106 kfree(syscall_table->compat_syscall_exit_dispatch);
49c50022 1107#endif
0bb716a8 1108 kfree(syscall_table->sc_filter);
80f87dd2
MD
1109 return 0;
1110}
1111
1112static
1113int get_syscall_nr(const char *syscall_name)
1114{
1115 int syscall_nr = -1;
1116 int i;
1117
ebcc64cd 1118 for (i = 0; i < sc_table.len; i++) {
80f87dd2 1119 const struct trace_syscall_entry *entry;
5b7ac358 1120 const char *it_name;
80f87dd2 1121
ebcc64cd 1122 entry = &sc_table.table[i];
80f87dd2
MD
1123 if (!entry->desc)
1124 continue;
437d5aa5 1125 it_name = entry->desc->event_name;
5b7ac358
MD
1126 it_name += strlen(SYSCALL_ENTRY_STR);
1127 if (!strcmp(syscall_name, it_name)) {
80f87dd2
MD
1128 syscall_nr = i;
1129 break;
1130 }
1131 }
1132 return syscall_nr;
1133}
1134
1135static
1136int get_compat_syscall_nr(const char *syscall_name)
1137{
1138 int syscall_nr = -1;
1139 int i;
1140
ebcc64cd 1141 for (i = 0; i < compat_sc_table.len; i++) {
80f87dd2 1142 const struct trace_syscall_entry *entry;
5b7ac358 1143 const char *it_name;
80f87dd2 1144
ebcc64cd 1145 entry = &compat_sc_table.table[i];
80f87dd2
MD
1146 if (!entry->desc)
1147 continue;
437d5aa5 1148 it_name = entry->desc->event_name;
5b7ac358
MD
1149 it_name += strlen(COMPAT_SYSCALL_ENTRY_STR);
1150 if (!strcmp(syscall_name, it_name)) {
80f87dd2
MD
1151 syscall_nr = i;
1152 break;
1153 }
1154 }
1155 return syscall_nr;
1156}
1157
12e579db
MD
1158static
1159uint32_t get_sc_tables_len(void)
1160{
ebcc64cd 1161 return sc_table.len + compat_sc_table.len;
12e579db
MD
1162}
1163
badfe9f5 1164static
ade8a729
FD
1165const char *get_syscall_name(const char *desc_name,
1166 enum lttng_syscall_abi abi,
1167 enum lttng_syscall_entryexit entryexit)
80f87dd2 1168{
badfe9f5 1169 size_t prefix_len = 0;
80f87dd2 1170
80f87dd2 1171
ade8a729 1172 switch (entryexit) {
badfe9f5 1173 case LTTNG_SYSCALL_ENTRY:
ade8a729 1174 switch (abi) {
badfe9f5
MD
1175 case LTTNG_SYSCALL_ABI_NATIVE:
1176 prefix_len = strlen(SYSCALL_ENTRY_STR);
1177 break;
1178 case LTTNG_SYSCALL_ABI_COMPAT:
1179 prefix_len = strlen(COMPAT_SYSCALL_ENTRY_STR);
1180 break;
80f87dd2 1181 }
badfe9f5
MD
1182 break;
1183 case LTTNG_SYSCALL_EXIT:
ade8a729 1184 switch (abi) {
badfe9f5
MD
1185 case LTTNG_SYSCALL_ABI_NATIVE:
1186 prefix_len = strlen(SYSCALL_EXIT_STR);
1187 break;
1188 case LTTNG_SYSCALL_ABI_COMPAT:
1189 prefix_len = strlen(COMPAT_SYSCALL_EXIT_STR);
1190 break;
80f87dd2 1191 }
badfe9f5 1192 break;
80f87dd2 1193 }
badfe9f5 1194 WARN_ON_ONCE(prefix_len == 0);
ade8a729 1195 return desc_name + prefix_len;
badfe9f5
MD
1196}
1197
ade8a729
FD
1198static
1199int lttng_syscall_filter_enable(
1200 struct lttng_syscall_filter *filter,
1201 const char *desc_name, enum lttng_syscall_abi abi,
1202 enum lttng_syscall_entryexit entryexit)
badfe9f5 1203{
badfe9f5
MD
1204 const char *syscall_name;
1205 unsigned long *bitmap;
1206 int syscall_nr;
1207
ade8a729 1208 syscall_name = get_syscall_name(desc_name, abi, entryexit);
badfe9f5 1209
ade8a729 1210 switch (abi) {
badfe9f5
MD
1211 case LTTNG_SYSCALL_ABI_NATIVE:
1212 syscall_nr = get_syscall_nr(syscall_name);
1213 break;
1214 case LTTNG_SYSCALL_ABI_COMPAT:
1215 syscall_nr = get_compat_syscall_nr(syscall_name);
1216 break;
1217 default:
1218 return -EINVAL;
80f87dd2 1219 }
badfe9f5
MD
1220 if (syscall_nr < 0)
1221 return -ENOENT;
1222
ade8a729 1223 switch (entryexit) {
badfe9f5 1224 case LTTNG_SYSCALL_ENTRY:
ade8a729 1225 switch (abi) {
badfe9f5
MD
1226 case LTTNG_SYSCALL_ABI_NATIVE:
1227 bitmap = filter->sc_entry;
1228 break;
1229 case LTTNG_SYSCALL_ABI_COMPAT:
1230 bitmap = filter->sc_compat_entry;
1231 break;
6d9694d8
MD
1232 default:
1233 return -EINVAL;
80f87dd2 1234 }
badfe9f5
MD
1235 break;
1236 case LTTNG_SYSCALL_EXIT:
ade8a729 1237 switch (abi) {
badfe9f5
MD
1238 case LTTNG_SYSCALL_ABI_NATIVE:
1239 bitmap = filter->sc_exit;
1240 break;
1241 case LTTNG_SYSCALL_ABI_COMPAT:
1242 bitmap = filter->sc_compat_exit;
1243 break;
6d9694d8
MD
1244 default:
1245 return -EINVAL;
80f87dd2 1246 }
badfe9f5
MD
1247 break;
1248 default:
1249 return -EINVAL;
80f87dd2 1250 }
badfe9f5
MD
1251 if (test_bit(syscall_nr, bitmap))
1252 return -EEXIST;
1253 bitmap_set(bitmap, syscall_nr, 1);
80f87dd2 1254 return 0;
80f87dd2
MD
1255}
1256
9b2f1c54 1257int lttng_syscall_filter_enable_event(struct lttng_kernel_event_common *event)
8a8ac9a8 1258{
9b2f1c54
MD
1259 struct lttng_kernel_syscall_table *syscall_table = get_syscall_table_from_event(event);
1260 int ret;
8a8ac9a8 1261
9b2f1c54 1262 WARN_ON_ONCE(event->priv->instrumentation != LTTNG_KERNEL_ABI_SYSCALL);
8a8ac9a8 1263
0bb716a8 1264 ret = lttng_syscall_filter_enable(syscall_table->sc_filter,
9b2f1c54
MD
1265 event->priv->desc->event_name, event->priv->u.syscall.abi,
1266 event->priv->u.syscall.entryexit);
1267 if (ret)
1268 return ret;
8a8ac9a8 1269
9b2f1c54
MD
1270 switch (event->type) {
1271 case LTTNG_KERNEL_EVENT_TYPE_RECORDER:
8a8ac9a8 1272 break;
9b2f1c54
MD
1273 case LTTNG_KERNEL_EVENT_TYPE_NOTIFIER:
1274 {
1275 unsigned int syscall_id = event->priv->u.syscall.syscall_id;
1276 struct hlist_head *dispatch_list;
1277
1278 switch (event->priv->u.syscall.entryexit) {
1279 case LTTNG_SYSCALL_ENTRY:
1280 switch (event->priv->u.syscall.abi) {
1281 case LTTNG_SYSCALL_ABI_NATIVE:
1282 dispatch_list = &syscall_table->syscall_dispatch[syscall_id];
1283 break;
1284 case LTTNG_SYSCALL_ABI_COMPAT:
1285 dispatch_list = &syscall_table->compat_syscall_dispatch[syscall_id];
1286 break;
1287 default:
1288 ret = -EINVAL;
1289 goto end;
1290 }
8a8ac9a8 1291 break;
9b2f1c54
MD
1292 case LTTNG_SYSCALL_EXIT:
1293 switch (event->priv->u.syscall.abi) {
1294 case LTTNG_SYSCALL_ABI_NATIVE:
1295 dispatch_list = &syscall_table->syscall_exit_dispatch[syscall_id];
1296 break;
1297 case LTTNG_SYSCALL_ABI_COMPAT:
1298 dispatch_list = &syscall_table->compat_syscall_exit_dispatch[syscall_id];
1299 break;
1300 default:
1301 ret = -EINVAL;
1302 goto end;
1303 }
8a8ac9a8 1304 break;
6866b1c7
MJ
1305 default:
1306 ret = -EINVAL;
1307 goto end;
8a8ac9a8 1308 }
9b2f1c54
MD
1309
1310 hlist_add_head_rcu(&event->priv->u.syscall.node, dispatch_list);
8a8ac9a8 1311 break;
9b2f1c54 1312 }
6866b1c7 1313 default:
9b2f1c54
MD
1314 WARN_ON_ONCE(1);
1315 return -ENOSYS;
8a8ac9a8 1316 }
8a8ac9a8 1317end:
9b2f1c54 1318 return ret;
ade8a729
FD
1319}
1320
1321static
f2db8be3 1322int lttng_syscall_filter_disable(struct lttng_syscall_filter *filter,
ade8a729
FD
1323 const char *desc_name, enum lttng_syscall_abi abi,
1324 enum lttng_syscall_entryexit entryexit)
1325{
badfe9f5
MD
1326 const char *syscall_name;
1327 unsigned long *bitmap;
1328 int syscall_nr;
80f87dd2 1329
ade8a729 1330 syscall_name = get_syscall_name(desc_name, abi, entryexit);
80f87dd2 1331
ade8a729 1332 switch (abi) {
badfe9f5
MD
1333 case LTTNG_SYSCALL_ABI_NATIVE:
1334 syscall_nr = get_syscall_nr(syscall_name);
1335 break;
1336 case LTTNG_SYSCALL_ABI_COMPAT:
1337 syscall_nr = get_compat_syscall_nr(syscall_name);
1338 break;
1339 default:
1340 return -EINVAL;
80f87dd2 1341 }
badfe9f5
MD
1342 if (syscall_nr < 0)
1343 return -ENOENT;
80f87dd2 1344
ade8a729 1345 switch (entryexit) {
badfe9f5 1346 case LTTNG_SYSCALL_ENTRY:
ade8a729 1347 switch (abi) {
badfe9f5
MD
1348 case LTTNG_SYSCALL_ABI_NATIVE:
1349 bitmap = filter->sc_entry;
1350 break;
1351 case LTTNG_SYSCALL_ABI_COMPAT:
1352 bitmap = filter->sc_compat_entry;
1353 break;
6d9694d8
MD
1354 default:
1355 return -EINVAL;
80f87dd2 1356 }
badfe9f5
MD
1357 break;
1358 case LTTNG_SYSCALL_EXIT:
ade8a729 1359 switch (abi) {
badfe9f5
MD
1360 case LTTNG_SYSCALL_ABI_NATIVE:
1361 bitmap = filter->sc_exit;
1362 break;
1363 case LTTNG_SYSCALL_ABI_COMPAT:
1364 bitmap = filter->sc_compat_exit;
1365 break;
6d9694d8
MD
1366 default:
1367 return -EINVAL;
80f87dd2 1368 }
badfe9f5
MD
1369 break;
1370 default:
1371 return -EINVAL;
80f87dd2 1372 }
badfe9f5
MD
1373 if (!test_bit(syscall_nr, bitmap))
1374 return -EEXIST;
1375 bitmap_clear(bitmap, syscall_nr, 1);
80f87dd2 1376
badfe9f5 1377 return 0;
259b6cb3 1378}
2d2464bd 1379
9b2f1c54 1380int lttng_syscall_filter_disable_event(struct lttng_kernel_event_common *event)
8a8ac9a8 1381{
9b2f1c54 1382 struct lttng_kernel_syscall_table *syscall_table = get_syscall_table_from_event(event);
8a8ac9a8
FD
1383 int ret;
1384
0bb716a8 1385 ret = lttng_syscall_filter_disable(syscall_table->sc_filter,
9b2f1c54
MD
1386 event->priv->desc->event_name, event->priv->u.syscall.abi,
1387 event->priv->u.syscall.entryexit);
1388 if (ret)
1389 return ret;
8a8ac9a8 1390
9b2f1c54
MD
1391 switch (event->type) {
1392 case LTTNG_KERNEL_EVENT_TYPE_RECORDER:
1393 break;
1394 case LTTNG_KERNEL_EVENT_TYPE_NOTIFIER:
1395 {
1396 hlist_del_rcu(&event->priv->u.syscall.node);
1397 break;
1398 }
1399 default:
1400 WARN_ON_ONCE(1);
1401 return -ENOSYS;
1402 }
8a8ac9a8
FD
1403 return 0;
1404}
1405
2d2464bd
MD
1406static
1407const struct trace_syscall_entry *syscall_list_get_entry(loff_t *pos)
1408{
1409 const struct trace_syscall_entry *entry;
1410 int iter = 0;
1411
ebcc64cd
FD
1412 for (entry = sc_table.table;
1413 entry < sc_table.table + sc_table.len;
2d2464bd
MD
1414 entry++) {
1415 if (iter++ >= *pos)
1416 return entry;
1417 }
ebcc64cd
FD
1418 for (entry = compat_sc_table.table;
1419 entry < compat_sc_table.table + compat_sc_table.len;
2d2464bd
MD
1420 entry++) {
1421 if (iter++ >= *pos)
1422 return entry;
1423 }
1424 /* End of list */
1425 return NULL;
1426}
1427
1428static
1429void *syscall_list_start(struct seq_file *m, loff_t *pos)
1430{
1431 return (void *) syscall_list_get_entry(pos);
1432}
1433
1434static
1435void *syscall_list_next(struct seq_file *m, void *p, loff_t *ppos)
1436{
1437 (*ppos)++;
1438 return (void *) syscall_list_get_entry(ppos);
1439}
1440
1441static
1442void syscall_list_stop(struct seq_file *m, void *p)
1443{
1444}
1445
12e579db
MD
1446static
1447int get_sc_table(const struct trace_syscall_entry *entry,
1448 const struct trace_syscall_entry **table,
1449 unsigned int *bitness)
1450{
ebcc64cd 1451 if (entry >= sc_table.table && entry < sc_table.table + sc_table.len) {
12e579db
MD
1452 if (bitness)
1453 *bitness = BITS_PER_LONG;
1454 if (table)
ebcc64cd 1455 *table = sc_table.table;
12e579db
MD
1456 return 0;
1457 }
ebcc64cd
FD
1458 if (!(entry >= compat_sc_table.table
1459 && entry < compat_sc_table.table + compat_sc_table.len)) {
12e579db
MD
1460 return -EINVAL;
1461 }
1462 if (bitness)
1463 *bitness = 32;
1464 if (table)
ebcc64cd 1465 *table = compat_sc_table.table;
12e579db
MD
1466 return 0;
1467}
1468
2d2464bd
MD
1469static
1470int syscall_list_show(struct seq_file *m, void *p)
1471{
1472 const struct trace_syscall_entry *table, *entry = p;
1473 unsigned int bitness;
d4291869 1474 unsigned long index;
12e579db 1475 int ret;
d4291869 1476 const char *name;
2d2464bd 1477
12e579db
MD
1478 ret = get_sc_table(entry, &table, &bitness);
1479 if (ret)
1480 return ret;
f4855b46
MD
1481 if (!entry->desc)
1482 return 0;
ebcc64cd 1483 if (table == sc_table.table) {
d4291869 1484 index = entry - table;
437d5aa5 1485 name = &entry->desc->event_name[strlen(SYSCALL_ENTRY_STR)];
d4291869 1486 } else {
ebcc64cd 1487 index = (entry - table) + sc_table.len;
437d5aa5 1488 name = &entry->desc->event_name[strlen(COMPAT_SYSCALL_ENTRY_STR)];
d4291869 1489 }
12e579db 1490 seq_printf(m, "syscall { index = %lu; name = %s; bitness = %u; };\n",
d4291869 1491 index, name, bitness);
2d2464bd
MD
1492 return 0;
1493}
1494
1495static
1496const struct seq_operations lttng_syscall_list_seq_ops = {
1497 .start = syscall_list_start,
1498 .next = syscall_list_next,
1499 .stop = syscall_list_stop,
1500 .show = syscall_list_show,
1501};
1502
1503static
1504int lttng_syscall_list_open(struct inode *inode, struct file *file)
1505{
1506 return seq_open(file, &lttng_syscall_list_seq_ops);
1507}
1508
1509const struct file_operations lttng_syscall_list_fops = {
1510 .owner = THIS_MODULE,
1511 .open = lttng_syscall_list_open,
1512 .read = seq_read,
1513 .llseek = seq_lseek,
1514 .release = seq_release,
1515};
12e579db 1516
badfe9f5
MD
1517/*
1518 * A syscall is enabled if it is traced for either entry or exit.
1519 */
c970b655 1520long lttng_syscall_table_get_active_mask(struct lttng_kernel_syscall_table *syscall_table,
606828e4 1521 struct lttng_kernel_abi_syscall_mask __user *usyscall_mask)
12e579db
MD
1522{
1523 uint32_t len, sc_tables_len, bitmask_len;
1524 int ret = 0, bit;
1525 char *tmp_mask;
1526 struct lttng_syscall_filter *filter;
1527
1528 ret = get_user(len, &usyscall_mask->len);
1529 if (ret)
1530 return ret;
1531 sc_tables_len = get_sc_tables_len();
1532 bitmask_len = ALIGN(sc_tables_len, 8) >> 3;
1533 if (len < sc_tables_len) {
1534 return put_user(sc_tables_len, &usyscall_mask->len);
1535 }
1536 /* Array is large enough, we can copy array to user-space. */
1537 tmp_mask = kzalloc(bitmask_len, GFP_KERNEL);
1538 if (!tmp_mask)
1539 return -ENOMEM;
0bb716a8 1540 filter = syscall_table->sc_filter;
12e579db 1541
ebcc64cd 1542 for (bit = 0; bit < sc_table.len; bit++) {
e2129868 1543 char state;
2f25059d 1544
0bb716a8
MD
1545 if (syscall_table->syscall_dispatch) {
1546 if (!(READ_ONCE(syscall_table->syscall_all_entry)
1547 || READ_ONCE(syscall_table->syscall_all_exit)) && filter)
badfe9f5
MD
1548 state = test_bit(bit, filter->sc_entry)
1549 || test_bit(bit, filter->sc_exit);
2f25059d
MD
1550 else
1551 state = 1;
1552 } else {
1553 state = 0;
1554 }
1555 bt_bitfield_write_be(tmp_mask, char, bit, 1, state);
12e579db
MD
1556 }
1557 for (; bit < sc_tables_len; bit++) {
e2129868 1558 char state;
2f25059d 1559
0bb716a8
MD
1560 if (syscall_table->compat_syscall_dispatch) {
1561 if (!(READ_ONCE(syscall_table->syscall_all_entry)
1562 || READ_ONCE(syscall_table->syscall_all_exit)) && filter)
ebcc64cd 1563 state = test_bit(bit - sc_table.len,
badfe9f5 1564 filter->sc_compat_entry)
ebcc64cd 1565 || test_bit(bit - sc_table.len,
badfe9f5 1566 filter->sc_compat_exit);
2f25059d
MD
1567 else
1568 state = 1;
1569 } else {
1570 state = 0;
1571 }
1572 bt_bitfield_write_be(tmp_mask, char, bit, 1, state);
12e579db
MD
1573 }
1574 if (copy_to_user(usyscall_mask->mask, tmp_mask, bitmask_len))
1575 ret = -EFAULT;
1576 kfree(tmp_mask);
1577 return ret;
1578}
082d4946
MD
1579
1580int lttng_abi_syscall_list(void)
1581{
1582 struct file *syscall_list_file;
1583 int file_fd, ret;
1584
4ac10b76 1585 file_fd = lttng_get_unused_fd();
082d4946
MD
1586 if (file_fd < 0) {
1587 ret = file_fd;
1588 goto fd_error;
1589 }
1590
1591 syscall_list_file = anon_inode_getfile("[lttng_syscall_list]",
1592 &lttng_syscall_list_fops,
1593 NULL, O_RDWR);
1594 if (IS_ERR(syscall_list_file)) {
1595 ret = PTR_ERR(syscall_list_file);
1596 goto file_error;
1597 }
1598 ret = lttng_syscall_list_fops.open(NULL, syscall_list_file);
1599 if (ret < 0)
1600 goto open_error;
1601 fd_install(file_fd, syscall_list_file);
082d4946
MD
1602 return file_fd;
1603
1604open_error:
1605 fput(syscall_list_file);
1606file_error:
1607 put_unused_fd(file_fd);
1608fd_error:
1609 return ret;
1610}
This page took 0.143085 seconds and 4 git commands to generate.