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