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