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