Refactoring: syscalls: use common match functions
[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 }
3b82c4e1 557 if (lttng_desc_match_enabler(desc,
1ae083ba 558 lttng_event_recorder_enabler_as_enabler(syscall_event_enabler)) <= 0)
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 */
d26015f6 754int lttng_syscalls_register_event(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
799 wrapper_vmalloc_sync_mappings();
800
0bb716a8 801 if (!syscall_table->sys_enter_registered) {
8a8ac9a8 802 ret = lttng_wrapper_tracepoint_probe_register("sys_enter",
0bb716a8 803 (void *) syscall_entry_event_probe, syscall_table);
8a8ac9a8
FD
804 if (ret)
805 return ret;
0bb716a8 806 syscall_table->sys_enter_registered = 1;
8a8ac9a8 807 }
0bb716a8 808 if (!syscall_table->sys_exit_registered) {
8a8ac9a8 809 ret = lttng_wrapper_tracepoint_probe_register("sys_exit",
0bb716a8 810 (void *) syscall_exit_event_probe, syscall_table);
8a8ac9a8
FD
811 if (ret) {
812 WARN_ON_ONCE(lttng_wrapper_tracepoint_probe_unregister("sys_enter",
0bb716a8 813 (void *) syscall_entry_event_probe, syscall_table));
8a8ac9a8
FD
814 return ret;
815 }
0bb716a8 816 syscall_table->sys_exit_registered = 1;
8a8ac9a8 817 }
0fab709d
MD
818
819 ret = lttng_syscalls_create_matching_event_notifiers(syscall_event_enabler);
820 if (ret)
821 return ret;
822
8a8ac9a8
FD
823 return ret;
824}
825
826static
827int create_unknown_event_notifier(
828 struct lttng_event_notifier_enabler *event_notifier_enabler,
829 enum sc_type type)
830{
0def9170 831 struct lttng_event_ht *events_ht = lttng_get_event_ht_from_enabler(&event_notifier_enabler->parent);
19bef247 832 struct lttng_kernel_event_common_private *event_priv;
83006ee0 833 struct lttng_kernel_event_common *event;
437d5aa5 834 const struct lttng_kernel_event_desc *desc;
8a8ac9a8 835 struct lttng_event_notifier_group *group = event_notifier_enabler->group;
0bb716a8 836 struct lttng_kernel_syscall_table *syscall_table = &group->syscall_table;
606828e4 837 struct lttng_kernel_abi_event_notifier event_notifier_param;
5b9817ae 838 uint64_t user_token = event_notifier_enabler->parent.user_token;
99f52fcc 839 uint64_t error_counter_index = event_notifier_enabler->error_counter_index;
8d554755 840 struct lttng_event_enabler_common *base_enabler = lttng_event_notifier_enabler_as_enabler(
8a8ac9a8
FD
841 event_notifier_enabler);
842 struct hlist_head *unknown_dispatch_list;
843 int ret = 0;
844 bool found = false;
606828e4
MD
845 enum lttng_kernel_abi_syscall_abi abi;
846 enum lttng_kernel_abi_syscall_entryexit entryexit;
8a8ac9a8
FD
847 struct hlist_head *head;
848
849 switch (type) {
850 case SC_TYPE_ENTRY:
851 desc = &__event_desc___syscall_entry_unknown;
0bb716a8 852 unknown_dispatch_list = &syscall_table->unknown_syscall_dispatch;
606828e4
MD
853 entryexit = LTTNG_KERNEL_ABI_SYSCALL_ENTRY;
854 abi = LTTNG_KERNEL_ABI_SYSCALL_ABI_NATIVE;
8a8ac9a8
FD
855 break;
856 case SC_TYPE_EXIT:
857 desc = &__event_desc___syscall_exit_unknown;
0bb716a8 858 unknown_dispatch_list = &syscall_table->unknown_syscall_exit_dispatch;
606828e4
MD
859 entryexit = LTTNG_KERNEL_ABI_SYSCALL_EXIT;
860 abi = LTTNG_KERNEL_ABI_SYSCALL_ABI_NATIVE;
8a8ac9a8
FD
861 break;
862 case SC_TYPE_COMPAT_ENTRY:
863 desc = &__event_desc___compat_syscall_entry_unknown;
0bb716a8 864 unknown_dispatch_list = &syscall_table->compat_unknown_syscall_dispatch;
606828e4
MD
865 entryexit = LTTNG_KERNEL_ABI_SYSCALL_ENTRY;
866 abi = LTTNG_KERNEL_ABI_SYSCALL_ABI_COMPAT;
8a8ac9a8
FD
867 break;
868 case SC_TYPE_COMPAT_EXIT:
869 desc = &__event_desc___compat_syscall_exit_unknown;
0bb716a8 870 unknown_dispatch_list = &syscall_table->compat_unknown_syscall_exit_dispatch;
606828e4
MD
871 entryexit = LTTNG_KERNEL_ABI_SYSCALL_EXIT;
872 abi = LTTNG_KERNEL_ABI_SYSCALL_ABI_COMPAT;
8a8ac9a8
FD
873 break;
874 default:
875 BUG_ON(1);
876 }
877
878 /*
879 * Check if already created.
880 */
0def9170 881 head = utils_borrow_hash_table_bucket(events_ht->table, LTTNG_EVENT_HT_SIZE, desc->event_name);
19bef247 882 lttng_hlist_for_each_entry(event_priv, head, hlist_node) {
adfdce76 883 if (lttng_event_enabler_desc_match_event(base_enabler, desc, event_priv->pub))
8a8ac9a8
FD
884 found = true;
885 }
886 if (found)
887 goto end;
888
889 memset(&event_notifier_param, 0, sizeof(event_notifier_param));
437d5aa5 890 strncat(event_notifier_param.event.name, desc->event_name,
606828e4 891 LTTNG_KERNEL_ABI_SYM_NAME_LEN - strlen(event_notifier_param.event.name) - 1);
8a8ac9a8 892
606828e4 893 event_notifier_param.event.name[LTTNG_KERNEL_ABI_SYM_NAME_LEN - 1] = '\0';
8a8ac9a8 894
606828e4 895 event_notifier_param.event.instrumentation = LTTNG_KERNEL_ABI_SYSCALL;
1bbb5b2d 896 event_notifier_param.event.token = user_token;
8a8ac9a8
FD
897 event_notifier_param.event.u.syscall.abi = abi;
898 event_notifier_param.event.u.syscall.entryexit = entryexit;
1bbb5b2d 899 event_notifier_param.error_counter_index = error_counter_index;
8a8ac9a8 900
1bbb5b2d
MD
901 event_notifier_enabler = lttng_event_notifier_enabler_create(LTTNG_ENABLER_FORMAT_NAME,
902 &event_notifier_param, group);
903 WARN_ON_ONCE(!event_notifier_enabler);
83006ee0 904 event = _lttng_kernel_event_create(&event_notifier_enabler->parent, desc);
1bbb5b2d 905 lttng_event_enabler_destroy(&event_notifier_enabler->parent);
83006ee0 906 if (IS_ERR(event)) {
8a8ac9a8 907 printk(KERN_INFO "Unable to create unknown notifier %s\n",
437d5aa5 908 desc->event_name);
8a8ac9a8
FD
909 ret = -ENOMEM;
910 goto end;
911 }
912
83006ee0 913 hlist_add_head_rcu(&event->priv->u.syscall.node, unknown_dispatch_list);
8a8ac9a8
FD
914
915end:
916 return ret;
917}
918
919static int create_matching_event_notifiers(
1bbb5b2d 920 struct lttng_event_notifier_enabler *syscall_event_notifier_enabler,
a67ba386 921 const struct trace_syscall_entry *table,
8a8ac9a8
FD
922 size_t table_len, enum sc_type type)
923{
0def9170 924 struct lttng_event_ht *events_ht = lttng_get_event_ht_from_enabler(&syscall_event_notifier_enabler->parent);
1bbb5b2d 925 struct lttng_event_notifier_group *group = syscall_event_notifier_enabler->group;
437d5aa5 926 const struct lttng_kernel_event_desc *desc;
1bbb5b2d
MD
927 uint64_t user_token = syscall_event_notifier_enabler->parent.user_token;
928 uint64_t error_counter_index = syscall_event_notifier_enabler->error_counter_index;
8a8ac9a8
FD
929 unsigned int i;
930 int ret = 0;
931
932 /* iterate over all syscall and create event_notifier that match */
933 for (i = 0; i < table_len; i++) {
1bbb5b2d 934 struct lttng_event_notifier_enabler *event_notifier_enabler;
19bef247 935 struct lttng_kernel_event_common_private *event_priv;
83006ee0 936 struct lttng_kernel_event_common *event;
606828e4 937 struct lttng_kernel_abi_event_notifier event_notifier_param;
8a8ac9a8
FD
938 struct hlist_head *head;
939 int found = 0;
940
941 desc = table[i].desc;
942 if (!desc) {
943 /* Unknown syscall */
944 continue;
945 }
946
947 if (!lttng_desc_match_enabler(desc,
1bbb5b2d 948 lttng_event_notifier_enabler_as_enabler(syscall_event_notifier_enabler)))
8a8ac9a8
FD
949 continue;
950
951 /*
952 * Check if already created.
953 */
0def9170 954 head = utils_borrow_hash_table_bucket(events_ht->table, LTTNG_EVENT_HT_SIZE, desc->event_name);
19bef247 955 lttng_hlist_for_each_entry(event_priv, head, hlist_node) {
adfdce76 956 if (lttng_event_enabler_desc_match_event(&syscall_event_notifier_enabler->parent, desc, event_priv->pub))
8a8ac9a8
FD
957 found = 1;
958 }
959 if (found)
960 continue;
961
962 memset(&event_notifier_param, 0, sizeof(event_notifier_param));
963 switch (type) {
964 case SC_TYPE_ENTRY:
606828e4
MD
965 event_notifier_param.event.u.syscall.entryexit = LTTNG_KERNEL_ABI_SYSCALL_ENTRY;
966 event_notifier_param.event.u.syscall.abi = LTTNG_KERNEL_ABI_SYSCALL_ABI_NATIVE;
8a8ac9a8
FD
967 break;
968 case SC_TYPE_EXIT:
606828e4
MD
969 event_notifier_param.event.u.syscall.entryexit = LTTNG_KERNEL_ABI_SYSCALL_EXIT;
970 event_notifier_param.event.u.syscall.abi = LTTNG_KERNEL_ABI_SYSCALL_ABI_NATIVE;
8a8ac9a8
FD
971 break;
972 case SC_TYPE_COMPAT_ENTRY:
606828e4
MD
973 event_notifier_param.event.u.syscall.entryexit = LTTNG_KERNEL_ABI_SYSCALL_ENTRY;
974 event_notifier_param.event.u.syscall.abi = LTTNG_KERNEL_ABI_SYSCALL_ABI_COMPAT;
8a8ac9a8
FD
975 break;
976 case SC_TYPE_COMPAT_EXIT:
606828e4
MD
977 event_notifier_param.event.u.syscall.entryexit = LTTNG_KERNEL_ABI_SYSCALL_EXIT;
978 event_notifier_param.event.u.syscall.abi = LTTNG_KERNEL_ABI_SYSCALL_ABI_COMPAT;
8a8ac9a8
FD
979 break;
980 }
437d5aa5 981 strncat(event_notifier_param.event.name, desc->event_name,
606828e4
MD
982 LTTNG_KERNEL_ABI_SYM_NAME_LEN - strlen(event_notifier_param.event.name) - 1);
983 event_notifier_param.event.name[LTTNG_KERNEL_ABI_SYM_NAME_LEN - 1] = '\0';
984 event_notifier_param.event.instrumentation = LTTNG_KERNEL_ABI_SYSCALL;
1bbb5b2d
MD
985 event_notifier_param.event.token = user_token;
986 event_notifier_param.error_counter_index = error_counter_index;
987
988 event_notifier_enabler = lttng_event_notifier_enabler_create(LTTNG_ENABLER_FORMAT_NAME,
989 &event_notifier_param, group);
990 WARN_ON_ONCE(!event_notifier_enabler);
83006ee0 991 event = _lttng_kernel_event_create(&event_notifier_enabler->parent, desc);
1bbb5b2d 992 lttng_event_enabler_destroy(&event_notifier_enabler->parent);
83006ee0 993 if (IS_ERR(event)) {
8a8ac9a8 994 printk(KERN_INFO "Unable to create event_notifier %s\n",
437d5aa5 995 desc->event_name);
8a8ac9a8
FD
996 ret = -ENOMEM;
997 goto end;
998 }
999
83006ee0 1000 event->priv->u.syscall.syscall_id = i;
8a8ac9a8
FD
1001 }
1002
1003end:
1004 return ret;
1005
1006}
1007
0fab709d
MD
1008static
1009int lttng_syscalls_create_matching_event_notifiers(struct lttng_event_enabler_common *event_enabler)
8a8ac9a8
FD
1010{
1011 int ret;
606828e4 1012 enum lttng_kernel_abi_syscall_entryexit entryexit =
0fab709d
MD
1013 event_enabler->event_param.u.syscall.entryexit;
1014 struct lttng_event_notifier_enabler *event_notifier_enabler;
1015
1016 if (event_enabler->enabler_type != LTTNG_EVENT_ENABLER_TYPE_NOTIFIER)
1017 return 0;
1018 event_notifier_enabler = container_of(event_enabler, struct lttng_event_notifier_enabler, parent);
8a8ac9a8 1019
606828e4 1020 if (entryexit == LTTNG_KERNEL_ABI_SYSCALL_ENTRY || entryexit == LTTNG_KERNEL_ABI_SYSCALL_ENTRYEXIT) {
8a8ac9a8 1021 ret = create_matching_event_notifiers(event_notifier_enabler,
ebcc64cd 1022 sc_table.table, sc_table.len, SC_TYPE_ENTRY);
8a8ac9a8
FD
1023 if (ret)
1024 goto end;
1025
1026 ret = create_matching_event_notifiers(event_notifier_enabler,
ebcc64cd 1027 compat_sc_table.table, compat_sc_table.len,
8a8ac9a8
FD
1028 SC_TYPE_COMPAT_ENTRY);
1029 if (ret)
1030 goto end;
1031
1032 ret = create_unknown_event_notifier(event_notifier_enabler,
1033 SC_TYPE_ENTRY);
1034 if (ret)
1035 goto end;
1036
1037 ret = create_unknown_event_notifier(event_notifier_enabler,
1038 SC_TYPE_COMPAT_ENTRY);
1039 if (ret)
1040 goto end;
1041 }
1042
606828e4 1043 if (entryexit == LTTNG_KERNEL_ABI_SYSCALL_EXIT || entryexit == LTTNG_KERNEL_ABI_SYSCALL_ENTRYEXIT) {
8a8ac9a8 1044 ret = create_matching_event_notifiers(event_notifier_enabler,
ebcc64cd 1045 sc_exit_table.table, sc_exit_table.len,
8a8ac9a8
FD
1046 SC_TYPE_EXIT);
1047 if (ret)
1048 goto end;
1049
1050 ret = create_unknown_event_notifier(event_notifier_enabler,
1051 SC_TYPE_EXIT);
1052 if (ret)
1053 goto end;
1054
1055 ret = create_matching_event_notifiers(event_notifier_enabler,
ebcc64cd 1056 compat_sc_exit_table.table, compat_sc_exit_table.len,
8a8ac9a8
FD
1057 SC_TYPE_COMPAT_EXIT);
1058 if (ret)
1059 goto end;
1060
1061 ret = create_unknown_event_notifier(event_notifier_enabler,
1062 SC_TYPE_COMPAT_EXIT);
1063 if (ret)
1064 goto end;
1065 }
1066
1067end:
1068 return ret;
1069}
1070
6053e75e 1071int lttng_syscalls_unregister_syscall_table(struct lttng_kernel_syscall_table *syscall_table)
259b6cb3
MD
1072{
1073 int ret;
1074
0bb716a8 1075 if (!syscall_table->syscall_dispatch)
259b6cb3 1076 return 0;
0bb716a8 1077 if (syscall_table->sys_enter_registered) {
2d9cd7f3 1078 ret = lttng_wrapper_tracepoint_probe_unregister("sys_enter",
0bb716a8 1079 (void *) syscall_entry_event_probe, syscall_table);
80f87dd2
MD
1080 if (ret)
1081 return ret;
0bb716a8 1082 syscall_table->sys_enter_registered = 0;
80f87dd2 1083 }
0bb716a8 1084 if (syscall_table->sys_exit_registered) {
2d9cd7f3 1085 ret = lttng_wrapper_tracepoint_probe_unregister("sys_exit",
0bb716a8 1086 (void *) syscall_exit_event_probe, syscall_table);
80f87dd2
MD
1087 if (ret)
1088 return ret;
0bb716a8 1089 syscall_table->sys_exit_registered = 0;
80f87dd2 1090 }
badfe9f5
MD
1091 return 0;
1092}
1093
6053e75e 1094int lttng_syscalls_destroy_syscall_table(struct lttng_kernel_syscall_table *syscall_table)
badfe9f5 1095{
0bb716a8
MD
1096 kfree(syscall_table->syscall_dispatch);
1097 kfree(syscall_table->syscall_exit_dispatch);
49c50022 1098#ifdef CONFIG_COMPAT
0bb716a8
MD
1099 kfree(syscall_table->compat_syscall_dispatch);
1100 kfree(syscall_table->compat_syscall_exit_dispatch);
49c50022 1101#endif
0bb716a8 1102 kfree(syscall_table->sc_filter);
80f87dd2
MD
1103 return 0;
1104}
1105
1106static
1107int get_syscall_nr(const char *syscall_name)
1108{
1109 int syscall_nr = -1;
1110 int i;
1111
ebcc64cd 1112 for (i = 0; i < sc_table.len; i++) {
80f87dd2 1113 const struct trace_syscall_entry *entry;
5b7ac358 1114 const char *it_name;
80f87dd2 1115
ebcc64cd 1116 entry = &sc_table.table[i];
80f87dd2
MD
1117 if (!entry->desc)
1118 continue;
437d5aa5 1119 it_name = entry->desc->event_name;
5b7ac358
MD
1120 it_name += strlen(SYSCALL_ENTRY_STR);
1121 if (!strcmp(syscall_name, it_name)) {
80f87dd2
MD
1122 syscall_nr = i;
1123 break;
1124 }
1125 }
1126 return syscall_nr;
1127}
1128
1129static
1130int get_compat_syscall_nr(const char *syscall_name)
1131{
1132 int syscall_nr = -1;
1133 int i;
1134
ebcc64cd 1135 for (i = 0; i < compat_sc_table.len; i++) {
80f87dd2 1136 const struct trace_syscall_entry *entry;
5b7ac358 1137 const char *it_name;
80f87dd2 1138
ebcc64cd 1139 entry = &compat_sc_table.table[i];
80f87dd2
MD
1140 if (!entry->desc)
1141 continue;
437d5aa5 1142 it_name = entry->desc->event_name;
5b7ac358
MD
1143 it_name += strlen(COMPAT_SYSCALL_ENTRY_STR);
1144 if (!strcmp(syscall_name, it_name)) {
80f87dd2
MD
1145 syscall_nr = i;
1146 break;
1147 }
1148 }
1149 return syscall_nr;
1150}
1151
12e579db
MD
1152static
1153uint32_t get_sc_tables_len(void)
1154{
ebcc64cd 1155 return sc_table.len + compat_sc_table.len;
12e579db
MD
1156}
1157
badfe9f5 1158static
ade8a729
FD
1159const char *get_syscall_name(const char *desc_name,
1160 enum lttng_syscall_abi abi,
1161 enum lttng_syscall_entryexit entryexit)
80f87dd2 1162{
badfe9f5 1163 size_t prefix_len = 0;
80f87dd2 1164
80f87dd2 1165
ade8a729 1166 switch (entryexit) {
badfe9f5 1167 case LTTNG_SYSCALL_ENTRY:
ade8a729 1168 switch (abi) {
badfe9f5
MD
1169 case LTTNG_SYSCALL_ABI_NATIVE:
1170 prefix_len = strlen(SYSCALL_ENTRY_STR);
1171 break;
1172 case LTTNG_SYSCALL_ABI_COMPAT:
1173 prefix_len = strlen(COMPAT_SYSCALL_ENTRY_STR);
1174 break;
80f87dd2 1175 }
badfe9f5
MD
1176 break;
1177 case LTTNG_SYSCALL_EXIT:
ade8a729 1178 switch (abi) {
badfe9f5
MD
1179 case LTTNG_SYSCALL_ABI_NATIVE:
1180 prefix_len = strlen(SYSCALL_EXIT_STR);
1181 break;
1182 case LTTNG_SYSCALL_ABI_COMPAT:
1183 prefix_len = strlen(COMPAT_SYSCALL_EXIT_STR);
1184 break;
80f87dd2 1185 }
badfe9f5 1186 break;
80f87dd2 1187 }
badfe9f5 1188 WARN_ON_ONCE(prefix_len == 0);
ade8a729 1189 return desc_name + prefix_len;
badfe9f5
MD
1190}
1191
ade8a729
FD
1192static
1193int lttng_syscall_filter_enable(
1194 struct lttng_syscall_filter *filter,
1195 const char *desc_name, enum lttng_syscall_abi abi,
1196 enum lttng_syscall_entryexit entryexit)
badfe9f5 1197{
badfe9f5
MD
1198 const char *syscall_name;
1199 unsigned long *bitmap;
1200 int syscall_nr;
1201
ade8a729 1202 syscall_name = get_syscall_name(desc_name, abi, entryexit);
badfe9f5 1203
ade8a729 1204 switch (abi) {
badfe9f5
MD
1205 case LTTNG_SYSCALL_ABI_NATIVE:
1206 syscall_nr = get_syscall_nr(syscall_name);
1207 break;
1208 case LTTNG_SYSCALL_ABI_COMPAT:
1209 syscall_nr = get_compat_syscall_nr(syscall_name);
1210 break;
1211 default:
1212 return -EINVAL;
80f87dd2 1213 }
badfe9f5
MD
1214 if (syscall_nr < 0)
1215 return -ENOENT;
1216
ade8a729 1217 switch (entryexit) {
badfe9f5 1218 case LTTNG_SYSCALL_ENTRY:
ade8a729 1219 switch (abi) {
badfe9f5
MD
1220 case LTTNG_SYSCALL_ABI_NATIVE:
1221 bitmap = filter->sc_entry;
1222 break;
1223 case LTTNG_SYSCALL_ABI_COMPAT:
1224 bitmap = filter->sc_compat_entry;
1225 break;
6d9694d8
MD
1226 default:
1227 return -EINVAL;
80f87dd2 1228 }
badfe9f5
MD
1229 break;
1230 case LTTNG_SYSCALL_EXIT:
ade8a729 1231 switch (abi) {
badfe9f5
MD
1232 case LTTNG_SYSCALL_ABI_NATIVE:
1233 bitmap = filter->sc_exit;
1234 break;
1235 case LTTNG_SYSCALL_ABI_COMPAT:
1236 bitmap = filter->sc_compat_exit;
1237 break;
6d9694d8
MD
1238 default:
1239 return -EINVAL;
80f87dd2 1240 }
badfe9f5
MD
1241 break;
1242 default:
1243 return -EINVAL;
80f87dd2 1244 }
badfe9f5
MD
1245 if (test_bit(syscall_nr, bitmap))
1246 return -EEXIST;
1247 bitmap_set(bitmap, syscall_nr, 1);
80f87dd2 1248 return 0;
80f87dd2
MD
1249}
1250
9b2f1c54 1251int lttng_syscall_filter_enable_event(struct lttng_kernel_event_common *event)
8a8ac9a8 1252{
9b2f1c54
MD
1253 struct lttng_kernel_syscall_table *syscall_table = get_syscall_table_from_event(event);
1254 int ret;
8a8ac9a8 1255
9b2f1c54 1256 WARN_ON_ONCE(event->priv->instrumentation != LTTNG_KERNEL_ABI_SYSCALL);
8a8ac9a8 1257
0bb716a8 1258 ret = lttng_syscall_filter_enable(syscall_table->sc_filter,
9b2f1c54
MD
1259 event->priv->desc->event_name, event->priv->u.syscall.abi,
1260 event->priv->u.syscall.entryexit);
1261 if (ret)
1262 return ret;
8a8ac9a8 1263
9b2f1c54
MD
1264 switch (event->type) {
1265 case LTTNG_KERNEL_EVENT_TYPE_RECORDER:
8a8ac9a8 1266 break;
9b2f1c54
MD
1267 case LTTNG_KERNEL_EVENT_TYPE_NOTIFIER:
1268 {
1269 unsigned int syscall_id = event->priv->u.syscall.syscall_id;
1270 struct hlist_head *dispatch_list;
1271
1272 switch (event->priv->u.syscall.entryexit) {
1273 case LTTNG_SYSCALL_ENTRY:
1274 switch (event->priv->u.syscall.abi) {
1275 case LTTNG_SYSCALL_ABI_NATIVE:
1276 dispatch_list = &syscall_table->syscall_dispatch[syscall_id];
1277 break;
1278 case LTTNG_SYSCALL_ABI_COMPAT:
1279 dispatch_list = &syscall_table->compat_syscall_dispatch[syscall_id];
1280 break;
1281 default:
1282 ret = -EINVAL;
1283 goto end;
1284 }
8a8ac9a8 1285 break;
9b2f1c54
MD
1286 case LTTNG_SYSCALL_EXIT:
1287 switch (event->priv->u.syscall.abi) {
1288 case LTTNG_SYSCALL_ABI_NATIVE:
1289 dispatch_list = &syscall_table->syscall_exit_dispatch[syscall_id];
1290 break;
1291 case LTTNG_SYSCALL_ABI_COMPAT:
1292 dispatch_list = &syscall_table->compat_syscall_exit_dispatch[syscall_id];
1293 break;
1294 default:
1295 ret = -EINVAL;
1296 goto end;
1297 }
8a8ac9a8 1298 break;
6866b1c7
MJ
1299 default:
1300 ret = -EINVAL;
1301 goto end;
8a8ac9a8 1302 }
9b2f1c54
MD
1303
1304 hlist_add_head_rcu(&event->priv->u.syscall.node, dispatch_list);
8a8ac9a8 1305 break;
9b2f1c54 1306 }
6866b1c7 1307 default:
9b2f1c54
MD
1308 WARN_ON_ONCE(1);
1309 return -ENOSYS;
8a8ac9a8 1310 }
8a8ac9a8 1311end:
9b2f1c54 1312 return ret;
ade8a729
FD
1313}
1314
1315static
f2db8be3 1316int lttng_syscall_filter_disable(struct lttng_syscall_filter *filter,
ade8a729
FD
1317 const char *desc_name, enum lttng_syscall_abi abi,
1318 enum lttng_syscall_entryexit entryexit)
1319{
badfe9f5
MD
1320 const char *syscall_name;
1321 unsigned long *bitmap;
1322 int syscall_nr;
80f87dd2 1323
ade8a729 1324 syscall_name = get_syscall_name(desc_name, abi, entryexit);
80f87dd2 1325
ade8a729 1326 switch (abi) {
badfe9f5
MD
1327 case LTTNG_SYSCALL_ABI_NATIVE:
1328 syscall_nr = get_syscall_nr(syscall_name);
1329 break;
1330 case LTTNG_SYSCALL_ABI_COMPAT:
1331 syscall_nr = get_compat_syscall_nr(syscall_name);
1332 break;
1333 default:
1334 return -EINVAL;
80f87dd2 1335 }
badfe9f5
MD
1336 if (syscall_nr < 0)
1337 return -ENOENT;
80f87dd2 1338
ade8a729 1339 switch (entryexit) {
badfe9f5 1340 case LTTNG_SYSCALL_ENTRY:
ade8a729 1341 switch (abi) {
badfe9f5
MD
1342 case LTTNG_SYSCALL_ABI_NATIVE:
1343 bitmap = filter->sc_entry;
1344 break;
1345 case LTTNG_SYSCALL_ABI_COMPAT:
1346 bitmap = filter->sc_compat_entry;
1347 break;
6d9694d8
MD
1348 default:
1349 return -EINVAL;
80f87dd2 1350 }
badfe9f5
MD
1351 break;
1352 case LTTNG_SYSCALL_EXIT:
ade8a729 1353 switch (abi) {
badfe9f5
MD
1354 case LTTNG_SYSCALL_ABI_NATIVE:
1355 bitmap = filter->sc_exit;
1356 break;
1357 case LTTNG_SYSCALL_ABI_COMPAT:
1358 bitmap = filter->sc_compat_exit;
1359 break;
6d9694d8
MD
1360 default:
1361 return -EINVAL;
80f87dd2 1362 }
badfe9f5
MD
1363 break;
1364 default:
1365 return -EINVAL;
80f87dd2 1366 }
badfe9f5
MD
1367 if (!test_bit(syscall_nr, bitmap))
1368 return -EEXIST;
1369 bitmap_clear(bitmap, syscall_nr, 1);
80f87dd2 1370
badfe9f5 1371 return 0;
259b6cb3 1372}
2d2464bd 1373
9b2f1c54 1374int lttng_syscall_filter_disable_event(struct lttng_kernel_event_common *event)
8a8ac9a8 1375{
9b2f1c54 1376 struct lttng_kernel_syscall_table *syscall_table = get_syscall_table_from_event(event);
8a8ac9a8
FD
1377 int ret;
1378
0bb716a8 1379 ret = lttng_syscall_filter_disable(syscall_table->sc_filter,
9b2f1c54
MD
1380 event->priv->desc->event_name, event->priv->u.syscall.abi,
1381 event->priv->u.syscall.entryexit);
1382 if (ret)
1383 return ret;
8a8ac9a8 1384
9b2f1c54
MD
1385 switch (event->type) {
1386 case LTTNG_KERNEL_EVENT_TYPE_RECORDER:
1387 break;
1388 case LTTNG_KERNEL_EVENT_TYPE_NOTIFIER:
1389 {
1390 hlist_del_rcu(&event->priv->u.syscall.node);
1391 break;
1392 }
1393 default:
1394 WARN_ON_ONCE(1);
1395 return -ENOSYS;
1396 }
8a8ac9a8
FD
1397 return 0;
1398}
1399
2d2464bd
MD
1400static
1401const struct trace_syscall_entry *syscall_list_get_entry(loff_t *pos)
1402{
1403 const struct trace_syscall_entry *entry;
1404 int iter = 0;
1405
ebcc64cd
FD
1406 for (entry = sc_table.table;
1407 entry < sc_table.table + sc_table.len;
2d2464bd
MD
1408 entry++) {
1409 if (iter++ >= *pos)
1410 return entry;
1411 }
ebcc64cd
FD
1412 for (entry = compat_sc_table.table;
1413 entry < compat_sc_table.table + compat_sc_table.len;
2d2464bd
MD
1414 entry++) {
1415 if (iter++ >= *pos)
1416 return entry;
1417 }
1418 /* End of list */
1419 return NULL;
1420}
1421
1422static
1423void *syscall_list_start(struct seq_file *m, loff_t *pos)
1424{
1425 return (void *) syscall_list_get_entry(pos);
1426}
1427
1428static
1429void *syscall_list_next(struct seq_file *m, void *p, loff_t *ppos)
1430{
1431 (*ppos)++;
1432 return (void *) syscall_list_get_entry(ppos);
1433}
1434
1435static
1436void syscall_list_stop(struct seq_file *m, void *p)
1437{
1438}
1439
12e579db
MD
1440static
1441int get_sc_table(const struct trace_syscall_entry *entry,
1442 const struct trace_syscall_entry **table,
1443 unsigned int *bitness)
1444{
ebcc64cd 1445 if (entry >= sc_table.table && entry < sc_table.table + sc_table.len) {
12e579db
MD
1446 if (bitness)
1447 *bitness = BITS_PER_LONG;
1448 if (table)
ebcc64cd 1449 *table = sc_table.table;
12e579db
MD
1450 return 0;
1451 }
ebcc64cd
FD
1452 if (!(entry >= compat_sc_table.table
1453 && entry < compat_sc_table.table + compat_sc_table.len)) {
12e579db
MD
1454 return -EINVAL;
1455 }
1456 if (bitness)
1457 *bitness = 32;
1458 if (table)
ebcc64cd 1459 *table = compat_sc_table.table;
12e579db
MD
1460 return 0;
1461}
1462
2d2464bd
MD
1463static
1464int syscall_list_show(struct seq_file *m, void *p)
1465{
1466 const struct trace_syscall_entry *table, *entry = p;
1467 unsigned int bitness;
d4291869 1468 unsigned long index;
12e579db 1469 int ret;
d4291869 1470 const char *name;
2d2464bd 1471
12e579db
MD
1472 ret = get_sc_table(entry, &table, &bitness);
1473 if (ret)
1474 return ret;
f4855b46
MD
1475 if (!entry->desc)
1476 return 0;
ebcc64cd 1477 if (table == sc_table.table) {
d4291869 1478 index = entry - table;
437d5aa5 1479 name = &entry->desc->event_name[strlen(SYSCALL_ENTRY_STR)];
d4291869 1480 } else {
ebcc64cd 1481 index = (entry - table) + sc_table.len;
437d5aa5 1482 name = &entry->desc->event_name[strlen(COMPAT_SYSCALL_ENTRY_STR)];
d4291869 1483 }
12e579db 1484 seq_printf(m, "syscall { index = %lu; name = %s; bitness = %u; };\n",
d4291869 1485 index, name, bitness);
2d2464bd
MD
1486 return 0;
1487}
1488
1489static
1490const struct seq_operations lttng_syscall_list_seq_ops = {
1491 .start = syscall_list_start,
1492 .next = syscall_list_next,
1493 .stop = syscall_list_stop,
1494 .show = syscall_list_show,
1495};
1496
1497static
1498int lttng_syscall_list_open(struct inode *inode, struct file *file)
1499{
1500 return seq_open(file, &lttng_syscall_list_seq_ops);
1501}
1502
1503const struct file_operations lttng_syscall_list_fops = {
1504 .owner = THIS_MODULE,
1505 .open = lttng_syscall_list_open,
1506 .read = seq_read,
1507 .llseek = seq_lseek,
1508 .release = seq_release,
1509};
12e579db 1510
badfe9f5
MD
1511/*
1512 * A syscall is enabled if it is traced for either entry or exit.
1513 */
c970b655 1514long lttng_syscall_table_get_active_mask(struct lttng_kernel_syscall_table *syscall_table,
606828e4 1515 struct lttng_kernel_abi_syscall_mask __user *usyscall_mask)
12e579db
MD
1516{
1517 uint32_t len, sc_tables_len, bitmask_len;
1518 int ret = 0, bit;
1519 char *tmp_mask;
1520 struct lttng_syscall_filter *filter;
1521
1522 ret = get_user(len, &usyscall_mask->len);
1523 if (ret)
1524 return ret;
1525 sc_tables_len = get_sc_tables_len();
1526 bitmask_len = ALIGN(sc_tables_len, 8) >> 3;
1527 if (len < sc_tables_len) {
1528 return put_user(sc_tables_len, &usyscall_mask->len);
1529 }
1530 /* Array is large enough, we can copy array to user-space. */
1531 tmp_mask = kzalloc(bitmask_len, GFP_KERNEL);
1532 if (!tmp_mask)
1533 return -ENOMEM;
0bb716a8 1534 filter = syscall_table->sc_filter;
12e579db 1535
ebcc64cd 1536 for (bit = 0; bit < sc_table.len; bit++) {
e2129868 1537 char state;
2f25059d 1538
0bb716a8
MD
1539 if (syscall_table->syscall_dispatch) {
1540 if (!(READ_ONCE(syscall_table->syscall_all_entry)
1541 || READ_ONCE(syscall_table->syscall_all_exit)) && filter)
badfe9f5
MD
1542 state = test_bit(bit, filter->sc_entry)
1543 || test_bit(bit, filter->sc_exit);
2f25059d
MD
1544 else
1545 state = 1;
1546 } else {
1547 state = 0;
1548 }
1549 bt_bitfield_write_be(tmp_mask, char, bit, 1, state);
12e579db
MD
1550 }
1551 for (; bit < sc_tables_len; bit++) {
e2129868 1552 char state;
2f25059d 1553
0bb716a8
MD
1554 if (syscall_table->compat_syscall_dispatch) {
1555 if (!(READ_ONCE(syscall_table->syscall_all_entry)
1556 || READ_ONCE(syscall_table->syscall_all_exit)) && filter)
ebcc64cd 1557 state = test_bit(bit - sc_table.len,
badfe9f5 1558 filter->sc_compat_entry)
ebcc64cd 1559 || test_bit(bit - sc_table.len,
badfe9f5 1560 filter->sc_compat_exit);
2f25059d
MD
1561 else
1562 state = 1;
1563 } else {
1564 state = 0;
1565 }
1566 bt_bitfield_write_be(tmp_mask, char, bit, 1, state);
12e579db
MD
1567 }
1568 if (copy_to_user(usyscall_mask->mask, tmp_mask, bitmask_len))
1569 ret = -EFAULT;
1570 kfree(tmp_mask);
1571 return ret;
1572}
082d4946
MD
1573
1574int lttng_abi_syscall_list(void)
1575{
1576 struct file *syscall_list_file;
1577 int file_fd, ret;
1578
4ac10b76 1579 file_fd = lttng_get_unused_fd();
082d4946
MD
1580 if (file_fd < 0) {
1581 ret = file_fd;
1582 goto fd_error;
1583 }
1584
1585 syscall_list_file = anon_inode_getfile("[lttng_syscall_list]",
1586 &lttng_syscall_list_fops,
1587 NULL, O_RDWR);
1588 if (IS_ERR(syscall_list_file)) {
1589 ret = PTR_ERR(syscall_list_file);
1590 goto file_error;
1591 }
1592 ret = lttng_syscall_list_fops.open(NULL, syscall_list_file);
1593 if (ret < 0)
1594 goto open_error;
1595 fd_install(file_fd, syscall_list_file);
082d4946
MD
1596 return file_fd;
1597
1598open_error:
1599 fput(syscall_list_file);
1600file_error:
1601 put_unused_fd(file_fd);
1602fd_error:
1603 return ret;
1604}
This page took 0.144185 seconds and 4 git commands to generate.