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