Refactoring: syscall: combine syscall filter enable/disable recorder/notifier
[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
3b82c4e1 135static void syscall_entry_event_unknown(struct hlist_head *unknown_action_list_head,
8a8ac9a8 136 struct pt_regs *regs, long id)
f405cfce 137{
1b7b9c65 138 unsigned long args[LTTNG_SYSCALL_NR_ARGS];
a67ba386 139 struct lttng_kernel_event_common_private *event_priv;
f405cfce 140
1b7b9c65 141 lttng_syscall_get_arguments(current, regs, args);
a67ba386 142 lttng_hlist_for_each_entry_rcu(event_priv, unknown_action_list_head, u.syscall.node) {
8a8ac9a8 143 if (unlikely(in_compat_syscall()))
e2d5dbc7 144 __event_probe__compat_syscall_entry_unknown(event_priv->pub, id, args);
8a8ac9a8 145 else
e2d5dbc7 146 __event_probe__syscall_entry_unknown(event_priv->pub, id, args);
8a8ac9a8
FD
147 }
148}
149
63aa9160 150static __always_inline
e2d5dbc7 151void syscall_entry_event_call_func(struct hlist_head *action_list,
3b82c4e1 152 void *func, unsigned int nrargs,
63aa9160 153 struct pt_regs *regs)
259b6cb3 154{
a67ba386 155 struct lttng_kernel_event_common_private *event_priv;
3b82c4e1 156
63aa9160 157 switch (nrargs) {
259b6cb3
MD
158 case 0:
159 {
63aa9160 160 void (*fptr)(void *__data) = func;
259b6cb3 161
e2d5dbc7
MD
162 lttng_hlist_for_each_entry_rcu(event_priv, action_list, u.syscall.node)
163 fptr(event_priv->pub);
259b6cb3
MD
164 break;
165 }
166 case 1:
167 {
63aa9160 168 void (*fptr)(void *__data, unsigned long arg0) = func;
1b7b9c65 169 unsigned long args[LTTNG_SYSCALL_NR_ARGS];
259b6cb3 170
1b7b9c65 171 lttng_syscall_get_arguments(current, regs, args);
e2d5dbc7
MD
172 lttng_hlist_for_each_entry_rcu(event_priv, action_list, u.syscall.node)
173 fptr(event_priv->pub, args[0]);
259b6cb3
MD
174 break;
175 }
176 case 2:
177 {
178 void (*fptr)(void *__data,
179 unsigned long arg0,
63aa9160 180 unsigned long arg1) = func;
1b7b9c65 181 unsigned long args[LTTNG_SYSCALL_NR_ARGS];
259b6cb3 182
1b7b9c65 183 lttng_syscall_get_arguments(current, regs, args);
e2d5dbc7
MD
184 lttng_hlist_for_each_entry_rcu(event_priv, action_list, u.syscall.node)
185 fptr(event_priv->pub, args[0], args[1]);
259b6cb3
MD
186 break;
187 }
188 case 3:
189 {
190 void (*fptr)(void *__data,
191 unsigned long arg0,
192 unsigned long arg1,
63aa9160 193 unsigned long arg2) = func;
1b7b9c65 194 unsigned long args[LTTNG_SYSCALL_NR_ARGS];
259b6cb3 195
1b7b9c65 196 lttng_syscall_get_arguments(current, regs, args);
e2d5dbc7
MD
197 lttng_hlist_for_each_entry_rcu(event_priv, action_list, u.syscall.node)
198 fptr(event_priv->pub, args[0], args[1], args[2]);
259b6cb3
MD
199 break;
200 }
201 case 4:
202 {
203 void (*fptr)(void *__data,
204 unsigned long arg0,
205 unsigned long arg1,
206 unsigned long arg2,
63aa9160 207 unsigned long arg3) = func;
1b7b9c65 208 unsigned long args[LTTNG_SYSCALL_NR_ARGS];
259b6cb3 209
1b7b9c65 210 lttng_syscall_get_arguments(current, regs, args);
e2d5dbc7
MD
211 lttng_hlist_for_each_entry_rcu(event_priv, action_list, u.syscall.node)
212 fptr(event_priv->pub, args[0], args[1], args[2], args[3]);
259b6cb3
MD
213 break;
214 }
215 case 5:
216 {
217 void (*fptr)(void *__data,
218 unsigned long arg0,
219 unsigned long arg1,
220 unsigned long arg2,
221 unsigned long arg3,
63aa9160 222 unsigned long arg4) = func;
1b7b9c65 223 unsigned long args[LTTNG_SYSCALL_NR_ARGS];
259b6cb3 224
1b7b9c65 225 lttng_syscall_get_arguments(current, regs, args);
e2d5dbc7
MD
226 lttng_hlist_for_each_entry_rcu(event_priv, action_list, u.syscall.node)
227 fptr(event_priv->pub, args[0], args[1], args[2], args[3], args[4]);
259b6cb3
MD
228 break;
229 }
230 case 6:
231 {
232 void (*fptr)(void *__data,
233 unsigned long arg0,
234 unsigned long arg1,
235 unsigned long arg2,
236 unsigned long arg3,
237 unsigned long arg4,
63aa9160 238 unsigned long arg5) = func;
1b7b9c65 239 unsigned long args[LTTNG_SYSCALL_NR_ARGS];
259b6cb3 240
1b7b9c65 241 lttng_syscall_get_arguments(current, regs, args);
e2d5dbc7
MD
242 lttng_hlist_for_each_entry_rcu(event_priv, action_list, u.syscall.node)
243 fptr(event_priv->pub, args[0], args[1], args[2],
3b82c4e1 244 args[3], args[4], args[5]);
8a8ac9a8
FD
245 break;
246 }
247 default:
248 break;
249 }
250}
251
63aa9160
FD
252void syscall_entry_event_probe(void *__data, struct pt_regs *regs, long id)
253{
0bb716a8 254 struct lttng_kernel_syscall_table *syscall_table = __data;
3b82c4e1 255 struct hlist_head *action_list, *unknown_action_list;
63aa9160
FD
256 const struct trace_syscall_entry *table, *entry;
257 size_t table_len;
258
259 if (unlikely(in_compat_syscall())) {
0bb716a8 260 struct lttng_syscall_filter *filter = syscall_table->sc_filter;
63aa9160
FD
261
262 if (id < 0 || id >= NR_compat_syscalls
0bb716a8 263 || (!READ_ONCE(syscall_table->syscall_all_entry) && !test_bit(id, filter->sc_compat_entry))) {
63aa9160
FD
264 /* System call filtered out. */
265 return;
266 }
ebcc64cd
FD
267 table = compat_sc_table.table;
268 table_len = compat_sc_table.len;
0bb716a8 269 unknown_action_list = &syscall_table->compat_unknown_syscall_dispatch;
63aa9160 270 } else {
0bb716a8 271 struct lttng_syscall_filter *filter = syscall_table->sc_filter;
63aa9160
FD
272
273 if (id < 0 || id >= NR_syscalls
0bb716a8 274 || (!READ_ONCE(syscall_table->syscall_all_entry) && !test_bit(id, filter->sc_entry))) {
63aa9160
FD
275 /* System call filtered out. */
276 return;
277 }
ebcc64cd
FD
278 table = sc_table.table;
279 table_len = sc_table.len;
0bb716a8 280 unknown_action_list = &syscall_table->unknown_syscall_dispatch;
63aa9160
FD
281 }
282 if (unlikely(id < 0 || id >= table_len)) {
3b82c4e1 283 syscall_entry_event_unknown(unknown_action_list, regs, id);
63aa9160
FD
284 return;
285 }
3b82c4e1
MD
286
287 entry = &table[id];
288 if (!entry->event_func) {
289 syscall_entry_event_unknown(unknown_action_list, regs, id);
63aa9160
FD
290 return;
291 }
3b82c4e1
MD
292
293 if (unlikely(in_compat_syscall())) {
0bb716a8 294 action_list = &syscall_table->compat_syscall_dispatch[id];
3b82c4e1 295 } else {
0bb716a8 296 action_list = &syscall_table->syscall_dispatch[id];
3b82c4e1
MD
297 }
298 if (unlikely(hlist_empty(action_list)))
299 return;
300
e2d5dbc7 301 syscall_entry_event_call_func(action_list, entry->event_func, entry->nrargs, regs);
63aa9160
FD
302}
303
3b82c4e1 304static void syscall_exit_event_unknown(struct hlist_head *unknown_action_list_head,
8a8ac9a8 305 struct pt_regs *regs, long id, long ret)
5b7ac358 306{
1b7b9c65 307 unsigned long args[LTTNG_SYSCALL_NR_ARGS];
a67ba386 308 struct lttng_kernel_event_common_private *event_priv;
5b7ac358 309
1b7b9c65 310 lttng_syscall_get_arguments(current, regs, args);
a67ba386 311 lttng_hlist_for_each_entry_rcu(event_priv, unknown_action_list_head, u.syscall.node) {
3b82c4e1 312 if (unlikely(in_compat_syscall()))
e2d5dbc7 313 __event_probe__compat_syscall_exit_unknown(event_priv->pub, id, ret,
3b82c4e1
MD
314 args);
315 else
e2d5dbc7 316 __event_probe__syscall_exit_unknown(event_priv->pub, id, ret, args);
3b82c4e1 317 }
5b7ac358
MD
318}
319
3b82c4e1 320static __always_inline
e2d5dbc7 321void syscall_exit_event_call_func(struct hlist_head *action_list,
3b82c4e1
MD
322 void *func, unsigned int nrargs,
323 struct pt_regs *regs, long ret)
5b7ac358 324{
a67ba386 325 struct lttng_kernel_event_common_private *event_priv;
badfe9f5 326
3b82c4e1 327 switch (nrargs) {
5b7ac358
MD
328 case 0:
329 {
3b82c4e1 330 void (*fptr)(void *__data, long ret) = func;
5b7ac358 331
e2d5dbc7
MD
332 lttng_hlist_for_each_entry_rcu(event_priv, action_list, u.syscall.node)
333 fptr(event_priv->pub, ret);
5b7ac358
MD
334 break;
335 }
336 case 1:
337 {
338 void (*fptr)(void *__data,
fc4f7161 339 long ret,
3b82c4e1 340 unsigned long arg0) = func;
1b7b9c65 341 unsigned long args[LTTNG_SYSCALL_NR_ARGS];
5b7ac358 342
1b7b9c65 343 lttng_syscall_get_arguments(current, regs, args);
e2d5dbc7
MD
344 lttng_hlist_for_each_entry_rcu(event_priv, action_list, u.syscall.node)
345 fptr(event_priv->pub, ret, args[0]);
5b7ac358
MD
346 break;
347 }
348 case 2:
349 {
350 void (*fptr)(void *__data,
fc4f7161 351 long ret,
5b7ac358 352 unsigned long arg0,
3b82c4e1 353 unsigned long arg1) = func;
1b7b9c65 354 unsigned long args[LTTNG_SYSCALL_NR_ARGS];
5b7ac358 355
1b7b9c65 356 lttng_syscall_get_arguments(current, regs, args);
e2d5dbc7
MD
357 lttng_hlist_for_each_entry_rcu(event_priv, action_list, u.syscall.node)
358 fptr(event_priv->pub, ret, args[0], args[1]);
5b7ac358
MD
359 break;
360 }
361 case 3:
362 {
363 void (*fptr)(void *__data,
fc4f7161 364 long ret,
5b7ac358
MD
365 unsigned long arg0,
366 unsigned long arg1,
3b82c4e1 367 unsigned long arg2) = func;
1b7b9c65 368 unsigned long args[LTTNG_SYSCALL_NR_ARGS];
5b7ac358 369
1b7b9c65 370 lttng_syscall_get_arguments(current, regs, args);
e2d5dbc7
MD
371 lttng_hlist_for_each_entry_rcu(event_priv, action_list, u.syscall.node)
372 fptr(event_priv->pub, ret, args[0], args[1], args[2]);
5b7ac358
MD
373 break;
374 }
375 case 4:
376 {
377 void (*fptr)(void *__data,
fc4f7161 378 long ret,
5b7ac358
MD
379 unsigned long arg0,
380 unsigned long arg1,
381 unsigned long arg2,
3b82c4e1 382 unsigned long arg3) = func;
1b7b9c65 383 unsigned long args[LTTNG_SYSCALL_NR_ARGS];
5b7ac358 384
1b7b9c65 385 lttng_syscall_get_arguments(current, regs, args);
e2d5dbc7
MD
386 lttng_hlist_for_each_entry_rcu(event_priv, action_list, u.syscall.node)
387 fptr(event_priv->pub, ret, args[0], args[1], args[2], args[3]);
5b7ac358
MD
388 break;
389 }
390 case 5:
391 {
392 void (*fptr)(void *__data,
fc4f7161 393 long ret,
5b7ac358
MD
394 unsigned long arg0,
395 unsigned long arg1,
396 unsigned long arg2,
397 unsigned long arg3,
3b82c4e1 398 unsigned long arg4) = func;
1b7b9c65 399 unsigned long args[LTTNG_SYSCALL_NR_ARGS];
5b7ac358 400
1b7b9c65 401 lttng_syscall_get_arguments(current, regs, args);
e2d5dbc7
MD
402 lttng_hlist_for_each_entry_rcu(event_priv, action_list, u.syscall.node)
403 fptr(event_priv->pub, ret, args[0], args[1], args[2], args[3], args[4]);
5b7ac358
MD
404 break;
405 }
406 case 6:
407 {
408 void (*fptr)(void *__data,
fc4f7161 409 long ret,
5b7ac358
MD
410 unsigned long arg0,
411 unsigned long arg1,
412 unsigned long arg2,
413 unsigned long arg3,
414 unsigned long arg4,
3b82c4e1 415 unsigned long arg5) = func;
1b7b9c65 416 unsigned long args[LTTNG_SYSCALL_NR_ARGS];
5b7ac358 417
1b7b9c65 418 lttng_syscall_get_arguments(current, regs, args);
e2d5dbc7
MD
419 lttng_hlist_for_each_entry_rcu(event_priv, action_list, u.syscall.node)
420 fptr(event_priv->pub, ret, args[0], args[1], args[2],
3b82c4e1 421 args[3], args[4], args[5]);
5b7ac358
MD
422 break;
423 }
424 default:
425 break;
426 }
427}
428
3b82c4e1
MD
429void syscall_exit_event_probe(void *__data, struct pt_regs *regs, long ret)
430{
0bb716a8 431 struct lttng_kernel_syscall_table *syscall_table = __data;
3b82c4e1
MD
432 struct hlist_head *action_list, *unknown_action_list;
433 const struct trace_syscall_entry *table, *entry;
434 size_t table_len;
435 long id;
436
437 id = syscall_get_nr(current, regs);
438
439 if (unlikely(in_compat_syscall())) {
0bb716a8 440 struct lttng_syscall_filter *filter = syscall_table->sc_filter;
3b82c4e1
MD
441
442 if (id < 0 || id >= NR_compat_syscalls
0bb716a8 443 || (!READ_ONCE(syscall_table->syscall_all_exit) && !test_bit(id, filter->sc_compat_exit))) {
3b82c4e1
MD
444 /* System call filtered out. */
445 return;
446 }
ebcc64cd
FD
447 table = compat_sc_exit_table.table;
448 table_len = compat_sc_exit_table.len;
0bb716a8 449 unknown_action_list = &syscall_table->compat_unknown_syscall_exit_dispatch;
3b82c4e1 450 } else {
0bb716a8 451 struct lttng_syscall_filter *filter = syscall_table->sc_filter;
3b82c4e1
MD
452
453 if (id < 0 || id >= NR_syscalls
0bb716a8 454 || (!READ_ONCE(syscall_table->syscall_all_exit) && !test_bit(id, filter->sc_exit))) {
3b82c4e1
MD
455 /* System call filtered out. */
456 return;
457 }
ebcc64cd
FD
458 table = sc_exit_table.table;
459 table_len = sc_exit_table.len;
0bb716a8 460 unknown_action_list = &syscall_table->unknown_syscall_exit_dispatch;
3b82c4e1
MD
461 }
462 if (unlikely(id < 0 || id >= table_len)) {
463 syscall_exit_event_unknown(unknown_action_list, regs, id, ret);
464 return;
465 }
466
467 entry = &table[id];
468 if (!entry->event_func) {
469 syscall_exit_event_unknown(unknown_action_list, regs, id, ret);
470 return;
471 }
472
473 if (unlikely(in_compat_syscall())) {
0bb716a8 474 action_list = &syscall_table->compat_syscall_exit_dispatch[id];
3b82c4e1 475 } else {
0bb716a8 476 action_list = &syscall_table->syscall_exit_dispatch[id];
3b82c4e1
MD
477 }
478 if (unlikely(hlist_empty(action_list)))
479 return;
480
e2d5dbc7 481 syscall_exit_event_call_func(action_list, entry->event_func, entry->nrargs,
3b82c4e1
MD
482 regs, ret);
483}
484
0bb716a8
MD
485static
486struct lttng_kernel_syscall_table *get_syscall_table_from_enabler(struct lttng_event_enabler_common *event_enabler)
8a8ac9a8 487{
0bb716a8
MD
488 switch (event_enabler->enabler_type) {
489 case LTTNG_EVENT_ENABLER_TYPE_RECORDER:
490 {
1ae083ba
MD
491 struct lttng_event_recorder_enabler *event_recorder_enabler =
492 container_of(event_enabler, struct lttng_event_recorder_enabler, parent);
0bb716a8 493 return &event_recorder_enabler->chan->priv->parent.syscall_table;
8a8ac9a8 494 }
0bb716a8
MD
495 case LTTNG_EVENT_ENABLER_TYPE_NOTIFIER:
496 {
497 struct lttng_event_notifier_enabler *event_notifier_enabler =
498 container_of(event_enabler, struct lttng_event_notifier_enabler, parent);
499 return &event_notifier_enabler->group->syscall_table;
8a8ac9a8 500 }
0bb716a8
MD
501 default:
502 return NULL;
8a8ac9a8 503 }
0bb716a8 504}
8a8ac9a8 505
0bb716a8
MD
506static
507struct lttng_kernel_syscall_table *get_syscall_table_from_event(struct lttng_kernel_event_common *event)
508{
509 switch (event->type) {
510 case LTTNG_KERNEL_EVENT_TYPE_RECORDER:
511 {
512 struct lttng_kernel_event_recorder *event_recorder =
513 container_of(event, struct lttng_kernel_event_recorder, parent);
514 return &event_recorder->chan->priv->parent.syscall_table;
515 }
516 case LTTNG_KERNEL_EVENT_TYPE_NOTIFIER:
517 {
518 struct lttng_kernel_event_notifier *event_notifier =
519 container_of(event, struct lttng_kernel_event_notifier, parent);
520 return &event_notifier->priv->group->syscall_table;
521 }
522 default:
523 return NULL;
8a8ac9a8 524 }
8a8ac9a8 525}
0bb716a8 526
33a39a3c
MD
527/*
528 * noinline to diminish caller stack size.
529 * Should be called with sessions lock held.
530 */
49c50022 531static
3b82c4e1 532int lttng_create_syscall_event_if_missing(const struct trace_syscall_entry *table, size_t table_len,
1ae083ba 533 struct hlist_head *chan_table, struct lttng_event_recorder_enabler *syscall_event_enabler,
a67ba386 534 enum sc_type type)
259b6cb3 535{
0bb716a8 536 struct lttng_kernel_syscall_table *syscall_table = get_syscall_table_from_enabler(&syscall_event_enabler->parent);
def1e304 537 struct lttng_kernel_channel_buffer *chan = syscall_event_enabler->chan;
f7d06400 538 struct lttng_kernel_session *session = chan->parent.session;
259b6cb3 539 unsigned int i;
49c50022 540
3b82c4e1 541 /* Allocate events for each syscall matching enabler, insert into table */
49c50022 542 for (i = 0; i < table_len; i++) {
437d5aa5 543 const struct lttng_kernel_event_desc *desc = table[i].desc;
1ae083ba 544 struct lttng_event_recorder_enabler *event_enabler;
606828e4 545 struct lttng_kernel_abi_event ev;
a67ba386
MD
546 struct lttng_kernel_event_recorder_private *event_recorder_priv;
547 struct lttng_kernel_event_recorder *event_recorder;
3b82c4e1
MD
548 struct hlist_head *head;
549 bool found = false;
49c50022
MD
550
551 if (!desc) {
552 /* Unknown syscall */
553 continue;
554 }
3b82c4e1 555 if (lttng_desc_match_enabler(desc,
1ae083ba 556 lttng_event_recorder_enabler_as_enabler(syscall_event_enabler)) <= 0)
3b82c4e1 557 continue;
49c50022 558 /*
3b82c4e1 559 * Check if already created.
49c50022 560 */
3b82c4e1 561 head = utils_borrow_hash_table_bucket(
8cdc1a81 562 session->priv->events_ht.table, LTTNG_EVENT_HT_SIZE,
437d5aa5 563 desc->event_name);
a67ba386
MD
564 lttng_hlist_for_each_entry(event_recorder_priv, head, hlist) {
565 if (event_recorder_priv->parent.desc == desc
0bb716a8 566 && get_syscall_table_from_event(event_recorder_priv->parent.pub) == syscall_table)
3b82c4e1
MD
567 found = true;
568 }
569 if (found)
49c50022 570 continue;
3b82c4e1
MD
571
572 /* We need to create an event for this syscall/enabler. */
49c50022 573 memset(&ev, 0, sizeof(ev));
5b7ac358
MD
574 switch (type) {
575 case SC_TYPE_ENTRY:
606828e4
MD
576 ev.u.syscall.entryexit = LTTNG_KERNEL_ABI_SYSCALL_ENTRY;
577 ev.u.syscall.abi = LTTNG_KERNEL_ABI_SYSCALL_ABI_NATIVE;
5b7ac358
MD
578 break;
579 case SC_TYPE_EXIT:
606828e4
MD
580 ev.u.syscall.entryexit = LTTNG_KERNEL_ABI_SYSCALL_EXIT;
581 ev.u.syscall.abi = LTTNG_KERNEL_ABI_SYSCALL_ABI_NATIVE;
5b7ac358
MD
582 break;
583 case SC_TYPE_COMPAT_ENTRY:
606828e4
MD
584 ev.u.syscall.entryexit = LTTNG_KERNEL_ABI_SYSCALL_ENTRY;
585 ev.u.syscall.abi = LTTNG_KERNEL_ABI_SYSCALL_ABI_COMPAT;
5b7ac358
MD
586 break;
587 case SC_TYPE_COMPAT_EXIT:
606828e4
MD
588 ev.u.syscall.entryexit = LTTNG_KERNEL_ABI_SYSCALL_EXIT;
589 ev.u.syscall.abi = LTTNG_KERNEL_ABI_SYSCALL_ABI_COMPAT;
5b7ac358
MD
590 break;
591 }
606828e4
MD
592 strncpy(ev.name, desc->event_name, LTTNG_KERNEL_ABI_SYM_NAME_LEN - 1);
593 ev.name[LTTNG_KERNEL_ABI_SYM_NAME_LEN - 1] = '\0';
594 ev.instrumentation = LTTNG_KERNEL_ABI_SYSCALL;
1ae083ba 595 event_enabler = lttng_event_recorder_enabler_create(LTTNG_ENABLER_FORMAT_NAME, &ev, chan);
def1e304
MD
596 if (!event_enabler) {
597 return -ENOMEM;
598 }
599 event_recorder = _lttng_kernel_event_recorder_create(event_enabler, desc);
a67ba386 600 WARN_ON_ONCE(!event_recorder);
44b1abdc 601 lttng_event_enabler_destroy(&event_enabler->parent);
a67ba386 602 if (IS_ERR(event_recorder)) {
49c50022
MD
603 /*
604 * If something goes wrong in event registration
605 * after the first one, we have no choice but to
606 * leave the previous events in there, until
607 * deleted by session teardown.
608 */
a67ba386 609 return PTR_ERR(event_recorder);
49c50022 610 }
a67ba386 611 hlist_add_head(&event_recorder->priv->parent.u.syscall.node, &chan_table[i]);
49c50022
MD
612 }
613 return 0;
614}
615
33a39a3c
MD
616/*
617 * Should be called with sessions lock held.
618 */
3c6beb8d 619int lttng_syscalls_register_event_recorder(struct lttng_event_recorder_enabler *syscall_event_enabler)
49c50022 620{
0bb716a8 621 struct lttng_kernel_syscall_table *syscall_table = get_syscall_table_from_enabler(&syscall_event_enabler->parent);
606828e4 622 struct lttng_kernel_abi_event ev;
259b6cb3
MD
623 int ret;
624
263b6c88 625 wrapper_vmalloc_sync_mappings();
259b6cb3 626
0bb716a8 627 if (!syscall_table->syscall_dispatch) {
259b6cb3 628 /* create syscall table mapping syscall to events */
0bb716a8
MD
629 syscall_table->syscall_dispatch = kzalloc(sizeof(struct hlist_head) * sc_table.len, GFP_KERNEL);
630 if (!syscall_table->syscall_dispatch)
259b6cb3
MD
631 return -ENOMEM;
632 }
0bb716a8 633 if (!syscall_table->syscall_exit_dispatch) {
5b7ac358 634 /* create syscall table mapping syscall to events */
0bb716a8
MD
635 syscall_table->syscall_exit_dispatch = kzalloc(sizeof(struct hlist_head) * sc_exit_table.len, GFP_KERNEL);
636 if (!syscall_table->syscall_exit_dispatch)
5b7ac358
MD
637 return -ENOMEM;
638 }
639
259b6cb3 640
49c50022 641#ifdef CONFIG_COMPAT
0bb716a8 642 if (!syscall_table->compat_syscall_dispatch) {
49c50022 643 /* create syscall table mapping compat syscall to events */
0bb716a8
MD
644 syscall_table->compat_syscall_dispatch = kzalloc(sizeof(struct hlist_head) * compat_sc_table.len, GFP_KERNEL);
645 if (!syscall_table->compat_syscall_dispatch)
49c50022
MD
646 return -ENOMEM;
647 }
5b7ac358 648
0bb716a8 649 if (!syscall_table->compat_syscall_exit_dispatch) {
5b7ac358 650 /* create syscall table mapping compat syscall to events */
0bb716a8
MD
651 syscall_table->compat_syscall_exit_dispatch = kzalloc(sizeof(struct hlist_head) * compat_sc_exit_table.len, GFP_KERNEL);
652 if (!syscall_table->compat_syscall_exit_dispatch)
5b7ac358
MD
653 return -ENOMEM;
654 }
49c50022 655#endif
0bb716a8 656 if (hlist_empty(&syscall_table->unknown_syscall_dispatch)) {
437d5aa5 657 const struct lttng_kernel_event_desc *desc =
d4291869 658 &__event_desc___syscall_entry_unknown;
a67ba386 659 struct lttng_kernel_event_recorder *event_recorder;
1ae083ba 660 struct lttng_event_recorder_enabler *event_enabler;
2f804c0a 661
f405cfce 662 memset(&ev, 0, sizeof(ev));
606828e4
MD
663 strncpy(ev.name, desc->event_name, LTTNG_KERNEL_ABI_SYM_NAME_LEN);
664 ev.name[LTTNG_KERNEL_ABI_SYM_NAME_LEN - 1] = '\0';
665 ev.instrumentation = LTTNG_KERNEL_ABI_SYSCALL;
666 ev.u.syscall.entryexit = LTTNG_KERNEL_ABI_SYSCALL_ENTRY;
667 ev.u.syscall.abi = LTTNG_KERNEL_ABI_SYSCALL_ABI_NATIVE;
1ae083ba 668 event_enabler = lttng_event_recorder_enabler_create(LTTNG_ENABLER_FORMAT_NAME, &ev, syscall_event_enabler->chan);
def1e304
MD
669 if (!event_enabler) {
670 return -ENOMEM;
671 }
672 event_recorder = _lttng_kernel_event_recorder_create(event_enabler, desc);
44b1abdc 673 lttng_event_enabler_destroy(&event_enabler->parent);
a67ba386
MD
674 WARN_ON_ONCE(!event_recorder);
675 if (IS_ERR(event_recorder)) {
676 return PTR_ERR(event_recorder);
f405cfce 677 }
0bb716a8 678 hlist_add_head(&event_recorder->priv->parent.u.syscall.node, &syscall_table->unknown_syscall_dispatch);
f405cfce
MD
679 }
680
0bb716a8 681 if (hlist_empty(&syscall_table->compat_unknown_syscall_dispatch)) {
437d5aa5 682 const struct lttng_kernel_event_desc *desc =
d4291869 683 &__event_desc___compat_syscall_entry_unknown;
a67ba386 684 struct lttng_kernel_event_recorder *event_recorder;
1ae083ba 685 struct lttng_event_recorder_enabler *event_enabler;
b76dc1a0
MD
686
687 memset(&ev, 0, sizeof(ev));
606828e4
MD
688 strncpy(ev.name, desc->event_name, LTTNG_KERNEL_ABI_SYM_NAME_LEN);
689 ev.name[LTTNG_KERNEL_ABI_SYM_NAME_LEN - 1] = '\0';
690 ev.instrumentation = LTTNG_KERNEL_ABI_SYSCALL;
691 ev.u.syscall.entryexit = LTTNG_KERNEL_ABI_SYSCALL_ENTRY;
692 ev.u.syscall.abi = LTTNG_KERNEL_ABI_SYSCALL_ABI_COMPAT;
1ae083ba 693 event_enabler = lttng_event_recorder_enabler_create(LTTNG_ENABLER_FORMAT_NAME, &ev, syscall_event_enabler->chan);
def1e304
MD
694 if (!event_enabler) {
695 return -ENOMEM;
696 }
697 event_recorder = _lttng_kernel_event_recorder_create(event_enabler, desc);
a67ba386 698 WARN_ON_ONCE(!event_recorder);
44b1abdc 699 lttng_event_enabler_destroy(&event_enabler->parent);
a67ba386
MD
700 if (IS_ERR(event_recorder)) {
701 return PTR_ERR(event_recorder);
b76dc1a0 702 }
0bb716a8 703 hlist_add_head(&event_recorder->priv->parent.u.syscall.node, &syscall_table->compat_unknown_syscall_dispatch);
b76dc1a0
MD
704 }
705
0bb716a8 706 if (hlist_empty(&syscall_table->compat_unknown_syscall_exit_dispatch)) {
437d5aa5 707 const struct lttng_kernel_event_desc *desc =
5b7ac358 708 &__event_desc___compat_syscall_exit_unknown;
a67ba386 709 struct lttng_kernel_event_recorder *event_recorder;
1ae083ba 710 struct lttng_event_recorder_enabler *event_enabler;
2f804c0a
MD
711
712 memset(&ev, 0, sizeof(ev));
606828e4
MD
713 strncpy(ev.name, desc->event_name, LTTNG_KERNEL_ABI_SYM_NAME_LEN);
714 ev.name[LTTNG_KERNEL_ABI_SYM_NAME_LEN - 1] = '\0';
715 ev.instrumentation = LTTNG_KERNEL_ABI_SYSCALL;
716 ev.u.syscall.entryexit = LTTNG_KERNEL_ABI_SYSCALL_EXIT;
717 ev.u.syscall.abi = LTTNG_KERNEL_ABI_SYSCALL_ABI_COMPAT;
1ae083ba 718 event_enabler = lttng_event_recorder_enabler_create(LTTNG_ENABLER_FORMAT_NAME, &ev, syscall_event_enabler->chan);
def1e304
MD
719 if (!event_enabler) {
720 return -ENOMEM;
721 }
722 event_recorder = _lttng_kernel_event_recorder_create(event_enabler, desc);
a67ba386 723 WARN_ON_ONCE(!event_recorder);
44b1abdc 724 lttng_event_enabler_destroy(&event_enabler->parent);
a67ba386
MD
725 if (IS_ERR(event_recorder)) {
726 return PTR_ERR(event_recorder);
5b7ac358 727 }
0bb716a8 728 hlist_add_head(&event_recorder->priv->parent.u.syscall.node, &syscall_table->compat_unknown_syscall_exit_dispatch);
5b7ac358
MD
729 }
730
0bb716a8 731 if (hlist_empty(&syscall_table->unknown_syscall_exit_dispatch)) {
437d5aa5 732 const struct lttng_kernel_event_desc *desc =
5b7ac358 733 &__event_desc___syscall_exit_unknown;
a67ba386 734 struct lttng_kernel_event_recorder *event_recorder;
1ae083ba 735 struct lttng_event_recorder_enabler *event_enabler;
5b7ac358
MD
736
737 memset(&ev, 0, sizeof(ev));
606828e4
MD
738 strncpy(ev.name, desc->event_name, LTTNG_KERNEL_ABI_SYM_NAME_LEN);
739 ev.name[LTTNG_KERNEL_ABI_SYM_NAME_LEN - 1] = '\0';
740 ev.instrumentation = LTTNG_KERNEL_ABI_SYSCALL;
741 ev.u.syscall.entryexit = LTTNG_KERNEL_ABI_SYSCALL_EXIT;
742 ev.u.syscall.abi = LTTNG_KERNEL_ABI_SYSCALL_ABI_NATIVE;
1ae083ba 743 event_enabler = lttng_event_recorder_enabler_create(LTTNG_ENABLER_FORMAT_NAME, &ev, syscall_event_enabler->chan);
def1e304
MD
744 if (!event_enabler) {
745 return -ENOMEM;
746 }
747 event_recorder = _lttng_kernel_event_recorder_create(event_enabler, desc);
a67ba386 748 WARN_ON_ONCE(!event_recorder);
44b1abdc 749 lttng_event_enabler_destroy(&event_enabler->parent);
a67ba386
MD
750 if (IS_ERR(event_recorder)) {
751 return PTR_ERR(event_recorder);
2f804c0a 752 }
0bb716a8 753 hlist_add_head(&event_recorder->priv->parent.u.syscall.node, &syscall_table->unknown_syscall_exit_dispatch);
2f804c0a
MD
754 }
755
ebcc64cd 756 ret = lttng_create_syscall_event_if_missing(sc_table.table, sc_table.len,
0bb716a8 757 syscall_table->syscall_dispatch, syscall_event_enabler, SC_TYPE_ENTRY);
5b7ac358
MD
758 if (ret)
759 return ret;
ebcc64cd 760 ret = lttng_create_syscall_event_if_missing(sc_exit_table.table, sc_exit_table.len,
0bb716a8 761 syscall_table->syscall_exit_dispatch, syscall_event_enabler, SC_TYPE_EXIT);
49c50022
MD
762 if (ret)
763 return ret;
5b7ac358 764
49c50022 765#ifdef CONFIG_COMPAT
ebcc64cd 766 ret = lttng_create_syscall_event_if_missing(compat_sc_table.table, compat_sc_table.len,
0bb716a8 767 syscall_table->compat_syscall_dispatch, syscall_event_enabler, SC_TYPE_COMPAT_ENTRY);
5b7ac358
MD
768 if (ret)
769 return ret;
ebcc64cd 770 ret = lttng_create_syscall_event_if_missing(compat_sc_exit_table.table, compat_sc_exit_table.len,
0bb716a8 771 syscall_table->compat_syscall_exit_dispatch, syscall_event_enabler, SC_TYPE_COMPAT_EXIT);
49c50022
MD
772 if (ret)
773 return ret;
774#endif
badfe9f5 775
0bb716a8
MD
776 if (!syscall_table->sc_filter) {
777 syscall_table->sc_filter = kzalloc(sizeof(struct lttng_syscall_filter),
badfe9f5 778 GFP_KERNEL);
0bb716a8 779 if (!syscall_table->sc_filter)
badfe9f5
MD
780 return -ENOMEM;
781 }
782
0bb716a8 783 if (!syscall_table->sys_enter_registered) {
80f87dd2 784 ret = lttng_wrapper_tracepoint_probe_register("sys_enter",
0bb716a8 785 (void *) syscall_entry_event_probe, syscall_table);
80f87dd2
MD
786 if (ret)
787 return ret;
0bb716a8 788 syscall_table->sys_enter_registered = 1;
80f87dd2 789 }
63728b02
MD
790 /*
791 * We change the name of sys_exit tracepoint due to namespace
792 * conflict with sys_exit syscall entry.
793 */
0bb716a8 794 if (!syscall_table->sys_exit_registered) {
80f87dd2 795 ret = lttng_wrapper_tracepoint_probe_register("sys_exit",
0bb716a8 796 (void *) syscall_exit_event_probe, syscall_table);
80f87dd2
MD
797 if (ret) {
798 WARN_ON_ONCE(lttng_wrapper_tracepoint_probe_unregister("sys_enter",
0bb716a8 799 (void *) syscall_entry_event_probe, syscall_table));
80f87dd2
MD
800 return ret;
801 }
0bb716a8 802 syscall_table->sys_exit_registered = 1;
63728b02 803 }
259b6cb3
MD
804 return ret;
805}
806
807/*
8a8ac9a8
FD
808 * Should be called with sessions lock held.
809 */
810int lttng_syscalls_register_event_notifier(
a67ba386 811 struct lttng_event_notifier_enabler *event_notifier_enabler)
8a8ac9a8
FD
812{
813 struct lttng_event_notifier_group *group = event_notifier_enabler->group;
0bb716a8 814 struct lttng_kernel_syscall_table *syscall_table = &group->syscall_table;
8a8ac9a8
FD
815 int ret = 0;
816
817 wrapper_vmalloc_sync_mappings();
818
0bb716a8
MD
819 if (!syscall_table->syscall_dispatch) {
820 syscall_table->syscall_dispatch = kzalloc(sizeof(struct hlist_head) * sc_table.len, GFP_KERNEL);
821 if (!syscall_table->syscall_dispatch)
8a8ac9a8 822 return -ENOMEM;
8a8ac9a8
FD
823 }
824
0bb716a8
MD
825 if (!syscall_table->syscall_exit_dispatch) {
826 syscall_table->syscall_exit_dispatch = kzalloc(sizeof(struct hlist_head) * sc_table.len, GFP_KERNEL);
827 if (!syscall_table->syscall_exit_dispatch)
8a8ac9a8 828 return -ENOMEM;
8a8ac9a8
FD
829 }
830
831#ifdef CONFIG_COMPAT
0bb716a8
MD
832 if (!syscall_table->compat_syscall_dispatch) {
833 syscall_table->compat_syscall_dispatch = kzalloc(sizeof(struct hlist_head) * compat_sc_table.len, GFP_KERNEL);
834 if (!syscall_table->compat_syscall_dispatch)
8a8ac9a8 835 return -ENOMEM;
8a8ac9a8
FD
836 }
837
0bb716a8
MD
838 if (!syscall_table->compat_syscall_exit_dispatch) {
839 syscall_table->compat_syscall_exit_dispatch =
ebcc64cd 840 kzalloc(sizeof(struct hlist_head) * compat_sc_exit_table.len,
8a8ac9a8 841 GFP_KERNEL);
0bb716a8 842 if (!syscall_table->compat_syscall_exit_dispatch)
8a8ac9a8 843 return -ENOMEM;
8a8ac9a8
FD
844 }
845#endif
846
0bb716a8
MD
847 if (!syscall_table->sc_filter) {
848 syscall_table->sc_filter = kzalloc(sizeof(struct lttng_syscall_filter),
8a8ac9a8 849 GFP_KERNEL);
0bb716a8 850 if (!syscall_table->sc_filter)
8a8ac9a8
FD
851 return -ENOMEM;
852 }
853
0bb716a8 854 if (!syscall_table->sys_enter_registered) {
8a8ac9a8 855 ret = lttng_wrapper_tracepoint_probe_register("sys_enter",
0bb716a8 856 (void *) syscall_entry_event_probe, syscall_table);
8a8ac9a8
FD
857 if (ret)
858 return ret;
0bb716a8 859 syscall_table->sys_enter_registered = 1;
8a8ac9a8
FD
860 }
861
0bb716a8 862 if (!syscall_table->sys_exit_registered) {
8a8ac9a8 863 ret = lttng_wrapper_tracepoint_probe_register("sys_exit",
0bb716a8 864 (void *) syscall_exit_event_probe, syscall_table);
8a8ac9a8
FD
865 if (ret) {
866 WARN_ON_ONCE(lttng_wrapper_tracepoint_probe_unregister("sys_enter",
0bb716a8 867 (void *) syscall_entry_event_probe, syscall_table));
8a8ac9a8
FD
868 return ret;
869 }
0bb716a8 870 syscall_table->sys_exit_registered = 1;
8a8ac9a8
FD
871 }
872
873 return ret;
874}
875
876static
877int create_unknown_event_notifier(
878 struct lttng_event_notifier_enabler *event_notifier_enabler,
879 enum sc_type type)
880{
a67ba386
MD
881 struct lttng_kernel_event_notifier_private *event_notifier_priv;
882 struct lttng_kernel_event_notifier *event_notifier;
437d5aa5 883 const struct lttng_kernel_event_desc *desc;
8a8ac9a8 884 struct lttng_event_notifier_group *group = event_notifier_enabler->group;
0bb716a8 885 struct lttng_kernel_syscall_table *syscall_table = &group->syscall_table;
606828e4 886 struct lttng_kernel_abi_event_notifier event_notifier_param;
5b9817ae 887 uint64_t user_token = event_notifier_enabler->parent.user_token;
99f52fcc 888 uint64_t error_counter_index = event_notifier_enabler->error_counter_index;
8d554755 889 struct lttng_event_enabler_common *base_enabler = lttng_event_notifier_enabler_as_enabler(
8a8ac9a8
FD
890 event_notifier_enabler);
891 struct hlist_head *unknown_dispatch_list;
892 int ret = 0;
893 bool found = false;
606828e4
MD
894 enum lttng_kernel_abi_syscall_abi abi;
895 enum lttng_kernel_abi_syscall_entryexit entryexit;
8a8ac9a8
FD
896 struct hlist_head *head;
897
898 switch (type) {
899 case SC_TYPE_ENTRY:
900 desc = &__event_desc___syscall_entry_unknown;
0bb716a8 901 unknown_dispatch_list = &syscall_table->unknown_syscall_dispatch;
606828e4
MD
902 entryexit = LTTNG_KERNEL_ABI_SYSCALL_ENTRY;
903 abi = LTTNG_KERNEL_ABI_SYSCALL_ABI_NATIVE;
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;
606828e4
MD
908 entryexit = LTTNG_KERNEL_ABI_SYSCALL_EXIT;
909 abi = LTTNG_KERNEL_ABI_SYSCALL_ABI_NATIVE;
8a8ac9a8
FD
910 break;
911 case SC_TYPE_COMPAT_ENTRY:
912 desc = &__event_desc___compat_syscall_entry_unknown;
0bb716a8 913 unknown_dispatch_list = &syscall_table->compat_unknown_syscall_dispatch;
606828e4
MD
914 entryexit = LTTNG_KERNEL_ABI_SYSCALL_ENTRY;
915 abi = LTTNG_KERNEL_ABI_SYSCALL_ABI_COMPAT;
8a8ac9a8
FD
916 break;
917 case SC_TYPE_COMPAT_EXIT:
918 desc = &__event_desc___compat_syscall_exit_unknown;
0bb716a8 919 unknown_dispatch_list = &syscall_table->compat_unknown_syscall_exit_dispatch;
606828e4
MD
920 entryexit = LTTNG_KERNEL_ABI_SYSCALL_EXIT;
921 abi = LTTNG_KERNEL_ABI_SYSCALL_ABI_COMPAT;
8a8ac9a8
FD
922 break;
923 default:
924 BUG_ON(1);
925 }
926
927 /*
928 * Check if already created.
929 */
930 head = utils_borrow_hash_table_bucket(group->event_notifiers_ht.table,
437d5aa5 931 LTTNG_EVENT_NOTIFIER_HT_SIZE, desc->event_name);
a67ba386
MD
932 lttng_hlist_for_each_entry(event_notifier_priv, head, hlist) {
933 if (event_notifier_priv->parent.desc == desc &&
934 event_notifier_priv->parent.user_token == base_enabler->user_token)
8a8ac9a8
FD
935 found = true;
936 }
937 if (found)
938 goto end;
939
940 memset(&event_notifier_param, 0, sizeof(event_notifier_param));
437d5aa5 941 strncat(event_notifier_param.event.name, desc->event_name,
606828e4 942 LTTNG_KERNEL_ABI_SYM_NAME_LEN - strlen(event_notifier_param.event.name) - 1);
8a8ac9a8 943
606828e4 944 event_notifier_param.event.name[LTTNG_KERNEL_ABI_SYM_NAME_LEN - 1] = '\0';
8a8ac9a8 945
606828e4 946 event_notifier_param.event.instrumentation = LTTNG_KERNEL_ABI_SYSCALL;
8a8ac9a8
FD
947 event_notifier_param.event.u.syscall.abi = abi;
948 event_notifier_param.event.u.syscall.entryexit = entryexit;
949
a67ba386
MD
950 event_notifier = _lttng_event_notifier_create(desc, user_token,
951 error_counter_index, group, &event_notifier_param,
8a8ac9a8 952 event_notifier_param.event.instrumentation);
a67ba386 953 if (IS_ERR(event_notifier)) {
8a8ac9a8 954 printk(KERN_INFO "Unable to create unknown notifier %s\n",
437d5aa5 955 desc->event_name);
8a8ac9a8
FD
956 ret = -ENOMEM;
957 goto end;
958 }
959
a67ba386 960 hlist_add_head_rcu(&event_notifier->priv->parent.u.syscall.node, unknown_dispatch_list);
8a8ac9a8
FD
961
962end:
963 return ret;
964}
965
966static int create_matching_event_notifiers(
967 struct lttng_event_notifier_enabler *event_notifier_enabler,
a67ba386 968 const struct trace_syscall_entry *table,
8a8ac9a8
FD
969 size_t table_len, enum sc_type type)
970{
971 struct lttng_event_notifier_group *group = event_notifier_enabler->group;
437d5aa5 972 const struct lttng_kernel_event_desc *desc;
5b9817ae 973 uint64_t user_token = event_notifier_enabler->parent.user_token;
99f52fcc 974 uint64_t error_counter_index = event_notifier_enabler->error_counter_index;
8a8ac9a8
FD
975 unsigned int i;
976 int ret = 0;
977
978 /* iterate over all syscall and create event_notifier that match */
979 for (i = 0; i < table_len; i++) {
a67ba386
MD
980 struct lttng_kernel_event_notifier_private *event_notifier_priv;
981 struct lttng_kernel_event_notifier *event_notifier;
606828e4 982 struct lttng_kernel_abi_event_notifier event_notifier_param;
8a8ac9a8
FD
983 struct hlist_head *head;
984 int found = 0;
985
986 desc = table[i].desc;
987 if (!desc) {
988 /* Unknown syscall */
989 continue;
990 }
991
992 if (!lttng_desc_match_enabler(desc,
993 lttng_event_notifier_enabler_as_enabler(event_notifier_enabler)))
994 continue;
995
996 /*
997 * Check if already created.
998 */
999 head = utils_borrow_hash_table_bucket(group->event_notifiers_ht.table,
437d5aa5 1000 LTTNG_EVENT_NOTIFIER_HT_SIZE, desc->event_name);
a67ba386
MD
1001 lttng_hlist_for_each_entry(event_notifier_priv, head, hlist) {
1002 if (event_notifier_priv->parent.desc == desc
5b9817ae 1003 && event_notifier_priv->parent.user_token == event_notifier_enabler->parent.user_token)
8a8ac9a8
FD
1004 found = 1;
1005 }
1006 if (found)
1007 continue;
1008
1009 memset(&event_notifier_param, 0, sizeof(event_notifier_param));
1010 switch (type) {
1011 case SC_TYPE_ENTRY:
606828e4
MD
1012 event_notifier_param.event.u.syscall.entryexit = LTTNG_KERNEL_ABI_SYSCALL_ENTRY;
1013 event_notifier_param.event.u.syscall.abi = LTTNG_KERNEL_ABI_SYSCALL_ABI_NATIVE;
8a8ac9a8
FD
1014 break;
1015 case SC_TYPE_EXIT:
606828e4
MD
1016 event_notifier_param.event.u.syscall.entryexit = LTTNG_KERNEL_ABI_SYSCALL_EXIT;
1017 event_notifier_param.event.u.syscall.abi = LTTNG_KERNEL_ABI_SYSCALL_ABI_NATIVE;
8a8ac9a8
FD
1018 break;
1019 case SC_TYPE_COMPAT_ENTRY:
606828e4
MD
1020 event_notifier_param.event.u.syscall.entryexit = LTTNG_KERNEL_ABI_SYSCALL_ENTRY;
1021 event_notifier_param.event.u.syscall.abi = LTTNG_KERNEL_ABI_SYSCALL_ABI_COMPAT;
8a8ac9a8
FD
1022 break;
1023 case SC_TYPE_COMPAT_EXIT:
606828e4
MD
1024 event_notifier_param.event.u.syscall.entryexit = LTTNG_KERNEL_ABI_SYSCALL_EXIT;
1025 event_notifier_param.event.u.syscall.abi = LTTNG_KERNEL_ABI_SYSCALL_ABI_COMPAT;
8a8ac9a8
FD
1026 break;
1027 }
437d5aa5 1028 strncat(event_notifier_param.event.name, desc->event_name,
606828e4
MD
1029 LTTNG_KERNEL_ABI_SYM_NAME_LEN - strlen(event_notifier_param.event.name) - 1);
1030 event_notifier_param.event.name[LTTNG_KERNEL_ABI_SYM_NAME_LEN - 1] = '\0';
1031 event_notifier_param.event.instrumentation = LTTNG_KERNEL_ABI_SYSCALL;
8a8ac9a8 1032
99f52fcc
FD
1033 event_notifier = _lttng_event_notifier_create(desc, user_token,
1034 error_counter_index, group, &event_notifier_param,
a67ba386 1035 event_notifier_param.event.instrumentation);
8a8ac9a8
FD
1036 if (IS_ERR(event_notifier)) {
1037 printk(KERN_INFO "Unable to create event_notifier %s\n",
437d5aa5 1038 desc->event_name);
8a8ac9a8
FD
1039 ret = -ENOMEM;
1040 goto end;
1041 }
1042
a67ba386 1043 event_notifier->priv->parent.u.syscall.syscall_id = i;
8a8ac9a8
FD
1044 }
1045
1046end:
1047 return ret;
1048
1049}
1050
a67ba386
MD
1051int lttng_syscalls_create_matching_event_notifiers(
1052 struct lttng_event_notifier_enabler *event_notifier_enabler)
8a8ac9a8
FD
1053{
1054 int ret;
8d554755 1055 struct lttng_event_enabler_common *base_enabler =
8a8ac9a8 1056 lttng_event_notifier_enabler_as_enabler(event_notifier_enabler);
606828e4 1057 enum lttng_kernel_abi_syscall_entryexit entryexit =
8a8ac9a8
FD
1058 base_enabler->event_param.u.syscall.entryexit;
1059
606828e4 1060 if (entryexit == LTTNG_KERNEL_ABI_SYSCALL_ENTRY || entryexit == LTTNG_KERNEL_ABI_SYSCALL_ENTRYEXIT) {
8a8ac9a8 1061 ret = create_matching_event_notifiers(event_notifier_enabler,
ebcc64cd 1062 sc_table.table, sc_table.len, SC_TYPE_ENTRY);
8a8ac9a8
FD
1063 if (ret)
1064 goto end;
1065
1066 ret = create_matching_event_notifiers(event_notifier_enabler,
ebcc64cd 1067 compat_sc_table.table, compat_sc_table.len,
8a8ac9a8
FD
1068 SC_TYPE_COMPAT_ENTRY);
1069 if (ret)
1070 goto end;
1071
1072 ret = create_unknown_event_notifier(event_notifier_enabler,
1073 SC_TYPE_ENTRY);
1074 if (ret)
1075 goto end;
1076
1077 ret = create_unknown_event_notifier(event_notifier_enabler,
1078 SC_TYPE_COMPAT_ENTRY);
1079 if (ret)
1080 goto end;
1081 }
1082
606828e4 1083 if (entryexit == LTTNG_KERNEL_ABI_SYSCALL_EXIT || entryexit == LTTNG_KERNEL_ABI_SYSCALL_ENTRYEXIT) {
8a8ac9a8 1084 ret = create_matching_event_notifiers(event_notifier_enabler,
ebcc64cd 1085 sc_exit_table.table, sc_exit_table.len,
8a8ac9a8
FD
1086 SC_TYPE_EXIT);
1087 if (ret)
1088 goto end;
1089
1090 ret = create_unknown_event_notifier(event_notifier_enabler,
1091 SC_TYPE_EXIT);
1092 if (ret)
1093 goto end;
1094
1095 ret = create_matching_event_notifiers(event_notifier_enabler,
ebcc64cd 1096 compat_sc_exit_table.table, compat_sc_exit_table.len,
8a8ac9a8
FD
1097 SC_TYPE_COMPAT_EXIT);
1098 if (ret)
1099 goto end;
1100
1101 ret = create_unknown_event_notifier(event_notifier_enabler,
1102 SC_TYPE_COMPAT_EXIT);
1103 if (ret)
1104 goto end;
1105 }
1106
1107end:
1108 return ret;
1109}
1110
6053e75e 1111int lttng_syscalls_unregister_syscall_table(struct lttng_kernel_syscall_table *syscall_table)
259b6cb3
MD
1112{
1113 int ret;
1114
0bb716a8 1115 if (!syscall_table->syscall_dispatch)
259b6cb3 1116 return 0;
0bb716a8 1117 if (syscall_table->sys_enter_registered) {
2d9cd7f3 1118 ret = lttng_wrapper_tracepoint_probe_unregister("sys_enter",
0bb716a8 1119 (void *) syscall_entry_event_probe, syscall_table);
80f87dd2
MD
1120 if (ret)
1121 return ret;
0bb716a8 1122 syscall_table->sys_enter_registered = 0;
80f87dd2 1123 }
0bb716a8 1124 if (syscall_table->sys_exit_registered) {
2d9cd7f3 1125 ret = lttng_wrapper_tracepoint_probe_unregister("sys_exit",
0bb716a8 1126 (void *) syscall_exit_event_probe, syscall_table);
80f87dd2
MD
1127 if (ret)
1128 return ret;
0bb716a8 1129 syscall_table->sys_exit_registered = 0;
80f87dd2 1130 }
badfe9f5
MD
1131 return 0;
1132}
1133
6053e75e 1134int lttng_syscalls_destroy_syscall_table(struct lttng_kernel_syscall_table *syscall_table)
badfe9f5 1135{
0bb716a8
MD
1136 kfree(syscall_table->syscall_dispatch);
1137 kfree(syscall_table->syscall_exit_dispatch);
49c50022 1138#ifdef CONFIG_COMPAT
0bb716a8
MD
1139 kfree(syscall_table->compat_syscall_dispatch);
1140 kfree(syscall_table->compat_syscall_exit_dispatch);
49c50022 1141#endif
0bb716a8 1142 kfree(syscall_table->sc_filter);
80f87dd2
MD
1143 return 0;
1144}
1145
1146static
1147int get_syscall_nr(const char *syscall_name)
1148{
1149 int syscall_nr = -1;
1150 int i;
1151
ebcc64cd 1152 for (i = 0; i < sc_table.len; i++) {
80f87dd2 1153 const struct trace_syscall_entry *entry;
5b7ac358 1154 const char *it_name;
80f87dd2 1155
ebcc64cd 1156 entry = &sc_table.table[i];
80f87dd2
MD
1157 if (!entry->desc)
1158 continue;
437d5aa5 1159 it_name = entry->desc->event_name;
5b7ac358
MD
1160 it_name += strlen(SYSCALL_ENTRY_STR);
1161 if (!strcmp(syscall_name, it_name)) {
80f87dd2
MD
1162 syscall_nr = i;
1163 break;
1164 }
1165 }
1166 return syscall_nr;
1167}
1168
1169static
1170int get_compat_syscall_nr(const char *syscall_name)
1171{
1172 int syscall_nr = -1;
1173 int i;
1174
ebcc64cd 1175 for (i = 0; i < compat_sc_table.len; i++) {
80f87dd2 1176 const struct trace_syscall_entry *entry;
5b7ac358 1177 const char *it_name;
80f87dd2 1178
ebcc64cd 1179 entry = &compat_sc_table.table[i];
80f87dd2
MD
1180 if (!entry->desc)
1181 continue;
437d5aa5 1182 it_name = entry->desc->event_name;
5b7ac358
MD
1183 it_name += strlen(COMPAT_SYSCALL_ENTRY_STR);
1184 if (!strcmp(syscall_name, it_name)) {
80f87dd2
MD
1185 syscall_nr = i;
1186 break;
1187 }
1188 }
1189 return syscall_nr;
1190}
1191
12e579db
MD
1192static
1193uint32_t get_sc_tables_len(void)
1194{
ebcc64cd 1195 return sc_table.len + compat_sc_table.len;
12e579db
MD
1196}
1197
badfe9f5 1198static
ade8a729
FD
1199const char *get_syscall_name(const char *desc_name,
1200 enum lttng_syscall_abi abi,
1201 enum lttng_syscall_entryexit entryexit)
80f87dd2 1202{
badfe9f5 1203 size_t prefix_len = 0;
80f87dd2 1204
80f87dd2 1205
ade8a729 1206 switch (entryexit) {
badfe9f5 1207 case LTTNG_SYSCALL_ENTRY:
ade8a729 1208 switch (abi) {
badfe9f5
MD
1209 case LTTNG_SYSCALL_ABI_NATIVE:
1210 prefix_len = strlen(SYSCALL_ENTRY_STR);
1211 break;
1212 case LTTNG_SYSCALL_ABI_COMPAT:
1213 prefix_len = strlen(COMPAT_SYSCALL_ENTRY_STR);
1214 break;
80f87dd2 1215 }
badfe9f5
MD
1216 break;
1217 case LTTNG_SYSCALL_EXIT:
ade8a729 1218 switch (abi) {
badfe9f5
MD
1219 case LTTNG_SYSCALL_ABI_NATIVE:
1220 prefix_len = strlen(SYSCALL_EXIT_STR);
1221 break;
1222 case LTTNG_SYSCALL_ABI_COMPAT:
1223 prefix_len = strlen(COMPAT_SYSCALL_EXIT_STR);
1224 break;
80f87dd2 1225 }
badfe9f5 1226 break;
80f87dd2 1227 }
badfe9f5 1228 WARN_ON_ONCE(prefix_len == 0);
ade8a729 1229 return desc_name + prefix_len;
badfe9f5
MD
1230}
1231
ade8a729
FD
1232static
1233int lttng_syscall_filter_enable(
1234 struct lttng_syscall_filter *filter,
1235 const char *desc_name, enum lttng_syscall_abi abi,
1236 enum lttng_syscall_entryexit entryexit)
badfe9f5 1237{
badfe9f5
MD
1238 const char *syscall_name;
1239 unsigned long *bitmap;
1240 int syscall_nr;
1241
ade8a729 1242 syscall_name = get_syscall_name(desc_name, abi, entryexit);
badfe9f5 1243
ade8a729 1244 switch (abi) {
badfe9f5
MD
1245 case LTTNG_SYSCALL_ABI_NATIVE:
1246 syscall_nr = get_syscall_nr(syscall_name);
1247 break;
1248 case LTTNG_SYSCALL_ABI_COMPAT:
1249 syscall_nr = get_compat_syscall_nr(syscall_name);
1250 break;
1251 default:
1252 return -EINVAL;
80f87dd2 1253 }
badfe9f5
MD
1254 if (syscall_nr < 0)
1255 return -ENOENT;
1256
ade8a729 1257 switch (entryexit) {
badfe9f5 1258 case LTTNG_SYSCALL_ENTRY:
ade8a729 1259 switch (abi) {
badfe9f5
MD
1260 case LTTNG_SYSCALL_ABI_NATIVE:
1261 bitmap = filter->sc_entry;
1262 break;
1263 case LTTNG_SYSCALL_ABI_COMPAT:
1264 bitmap = filter->sc_compat_entry;
1265 break;
6d9694d8
MD
1266 default:
1267 return -EINVAL;
80f87dd2 1268 }
badfe9f5
MD
1269 break;
1270 case LTTNG_SYSCALL_EXIT:
ade8a729 1271 switch (abi) {
badfe9f5
MD
1272 case LTTNG_SYSCALL_ABI_NATIVE:
1273 bitmap = filter->sc_exit;
1274 break;
1275 case LTTNG_SYSCALL_ABI_COMPAT:
1276 bitmap = filter->sc_compat_exit;
1277 break;
6d9694d8
MD
1278 default:
1279 return -EINVAL;
80f87dd2 1280 }
badfe9f5
MD
1281 break;
1282 default:
1283 return -EINVAL;
80f87dd2 1284 }
badfe9f5
MD
1285 if (test_bit(syscall_nr, bitmap))
1286 return -EEXIST;
1287 bitmap_set(bitmap, syscall_nr, 1);
80f87dd2 1288 return 0;
80f87dd2
MD
1289}
1290
9b2f1c54 1291int lttng_syscall_filter_enable_event(struct lttng_kernel_event_common *event)
8a8ac9a8 1292{
9b2f1c54
MD
1293 struct lttng_kernel_syscall_table *syscall_table = get_syscall_table_from_event(event);
1294 int ret;
8a8ac9a8 1295
9b2f1c54 1296 WARN_ON_ONCE(event->priv->instrumentation != LTTNG_KERNEL_ABI_SYSCALL);
8a8ac9a8 1297
0bb716a8 1298 ret = lttng_syscall_filter_enable(syscall_table->sc_filter,
9b2f1c54
MD
1299 event->priv->desc->event_name, event->priv->u.syscall.abi,
1300 event->priv->u.syscall.entryexit);
1301 if (ret)
1302 return ret;
8a8ac9a8 1303
9b2f1c54
MD
1304 switch (event->type) {
1305 case LTTNG_KERNEL_EVENT_TYPE_RECORDER:
8a8ac9a8 1306 break;
9b2f1c54
MD
1307 case LTTNG_KERNEL_EVENT_TYPE_NOTIFIER:
1308 {
1309 unsigned int syscall_id = event->priv->u.syscall.syscall_id;
1310 struct hlist_head *dispatch_list;
1311
1312 switch (event->priv->u.syscall.entryexit) {
1313 case LTTNG_SYSCALL_ENTRY:
1314 switch (event->priv->u.syscall.abi) {
1315 case LTTNG_SYSCALL_ABI_NATIVE:
1316 dispatch_list = &syscall_table->syscall_dispatch[syscall_id];
1317 break;
1318 case LTTNG_SYSCALL_ABI_COMPAT:
1319 dispatch_list = &syscall_table->compat_syscall_dispatch[syscall_id];
1320 break;
1321 default:
1322 ret = -EINVAL;
1323 goto end;
1324 }
8a8ac9a8 1325 break;
9b2f1c54
MD
1326 case LTTNG_SYSCALL_EXIT:
1327 switch (event->priv->u.syscall.abi) {
1328 case LTTNG_SYSCALL_ABI_NATIVE:
1329 dispatch_list = &syscall_table->syscall_exit_dispatch[syscall_id];
1330 break;
1331 case LTTNG_SYSCALL_ABI_COMPAT:
1332 dispatch_list = &syscall_table->compat_syscall_exit_dispatch[syscall_id];
1333 break;
1334 default:
1335 ret = -EINVAL;
1336 goto end;
1337 }
8a8ac9a8 1338 break;
6866b1c7
MJ
1339 default:
1340 ret = -EINVAL;
1341 goto end;
8a8ac9a8 1342 }
9b2f1c54
MD
1343
1344 hlist_add_head_rcu(&event->priv->u.syscall.node, dispatch_list);
8a8ac9a8 1345 break;
9b2f1c54 1346 }
6866b1c7 1347 default:
9b2f1c54
MD
1348 WARN_ON_ONCE(1);
1349 return -ENOSYS;
8a8ac9a8 1350 }
8a8ac9a8 1351end:
9b2f1c54 1352 return ret;
ade8a729
FD
1353}
1354
1355static
f2db8be3 1356int lttng_syscall_filter_disable(struct lttng_syscall_filter *filter,
ade8a729
FD
1357 const char *desc_name, enum lttng_syscall_abi abi,
1358 enum lttng_syscall_entryexit entryexit)
1359{
badfe9f5
MD
1360 const char *syscall_name;
1361 unsigned long *bitmap;
1362 int syscall_nr;
80f87dd2 1363
ade8a729 1364 syscall_name = get_syscall_name(desc_name, abi, entryexit);
80f87dd2 1365
ade8a729 1366 switch (abi) {
badfe9f5
MD
1367 case LTTNG_SYSCALL_ABI_NATIVE:
1368 syscall_nr = get_syscall_nr(syscall_name);
1369 break;
1370 case LTTNG_SYSCALL_ABI_COMPAT:
1371 syscall_nr = get_compat_syscall_nr(syscall_name);
1372 break;
1373 default:
1374 return -EINVAL;
80f87dd2 1375 }
badfe9f5
MD
1376 if (syscall_nr < 0)
1377 return -ENOENT;
80f87dd2 1378
ade8a729 1379 switch (entryexit) {
badfe9f5 1380 case LTTNG_SYSCALL_ENTRY:
ade8a729 1381 switch (abi) {
badfe9f5
MD
1382 case LTTNG_SYSCALL_ABI_NATIVE:
1383 bitmap = filter->sc_entry;
1384 break;
1385 case LTTNG_SYSCALL_ABI_COMPAT:
1386 bitmap = filter->sc_compat_entry;
1387 break;
6d9694d8
MD
1388 default:
1389 return -EINVAL;
80f87dd2 1390 }
badfe9f5
MD
1391 break;
1392 case LTTNG_SYSCALL_EXIT:
ade8a729 1393 switch (abi) {
badfe9f5
MD
1394 case LTTNG_SYSCALL_ABI_NATIVE:
1395 bitmap = filter->sc_exit;
1396 break;
1397 case LTTNG_SYSCALL_ABI_COMPAT:
1398 bitmap = filter->sc_compat_exit;
1399 break;
6d9694d8
MD
1400 default:
1401 return -EINVAL;
80f87dd2 1402 }
badfe9f5
MD
1403 break;
1404 default:
1405 return -EINVAL;
80f87dd2 1406 }
badfe9f5
MD
1407 if (!test_bit(syscall_nr, bitmap))
1408 return -EEXIST;
1409 bitmap_clear(bitmap, syscall_nr, 1);
80f87dd2 1410
badfe9f5 1411 return 0;
259b6cb3 1412}
2d2464bd 1413
9b2f1c54 1414int lttng_syscall_filter_disable_event(struct lttng_kernel_event_common *event)
8a8ac9a8 1415{
9b2f1c54 1416 struct lttng_kernel_syscall_table *syscall_table = get_syscall_table_from_event(event);
8a8ac9a8
FD
1417 int ret;
1418
0bb716a8 1419 ret = lttng_syscall_filter_disable(syscall_table->sc_filter,
9b2f1c54
MD
1420 event->priv->desc->event_name, event->priv->u.syscall.abi,
1421 event->priv->u.syscall.entryexit);
1422 if (ret)
1423 return ret;
8a8ac9a8 1424
9b2f1c54
MD
1425 switch (event->type) {
1426 case LTTNG_KERNEL_EVENT_TYPE_RECORDER:
1427 break;
1428 case LTTNG_KERNEL_EVENT_TYPE_NOTIFIER:
1429 {
1430 hlist_del_rcu(&event->priv->u.syscall.node);
1431 break;
1432 }
1433 default:
1434 WARN_ON_ONCE(1);
1435 return -ENOSYS;
1436 }
8a8ac9a8
FD
1437 return 0;
1438}
1439
2d2464bd
MD
1440static
1441const struct trace_syscall_entry *syscall_list_get_entry(loff_t *pos)
1442{
1443 const struct trace_syscall_entry *entry;
1444 int iter = 0;
1445
ebcc64cd
FD
1446 for (entry = sc_table.table;
1447 entry < sc_table.table + sc_table.len;
2d2464bd
MD
1448 entry++) {
1449 if (iter++ >= *pos)
1450 return entry;
1451 }
ebcc64cd
FD
1452 for (entry = compat_sc_table.table;
1453 entry < compat_sc_table.table + compat_sc_table.len;
2d2464bd
MD
1454 entry++) {
1455 if (iter++ >= *pos)
1456 return entry;
1457 }
1458 /* End of list */
1459 return NULL;
1460}
1461
1462static
1463void *syscall_list_start(struct seq_file *m, loff_t *pos)
1464{
1465 return (void *) syscall_list_get_entry(pos);
1466}
1467
1468static
1469void *syscall_list_next(struct seq_file *m, void *p, loff_t *ppos)
1470{
1471 (*ppos)++;
1472 return (void *) syscall_list_get_entry(ppos);
1473}
1474
1475static
1476void syscall_list_stop(struct seq_file *m, void *p)
1477{
1478}
1479
12e579db
MD
1480static
1481int get_sc_table(const struct trace_syscall_entry *entry,
1482 const struct trace_syscall_entry **table,
1483 unsigned int *bitness)
1484{
ebcc64cd 1485 if (entry >= sc_table.table && entry < sc_table.table + sc_table.len) {
12e579db
MD
1486 if (bitness)
1487 *bitness = BITS_PER_LONG;
1488 if (table)
ebcc64cd 1489 *table = sc_table.table;
12e579db
MD
1490 return 0;
1491 }
ebcc64cd
FD
1492 if (!(entry >= compat_sc_table.table
1493 && entry < compat_sc_table.table + compat_sc_table.len)) {
12e579db
MD
1494 return -EINVAL;
1495 }
1496 if (bitness)
1497 *bitness = 32;
1498 if (table)
ebcc64cd 1499 *table = compat_sc_table.table;
12e579db
MD
1500 return 0;
1501}
1502
2d2464bd
MD
1503static
1504int syscall_list_show(struct seq_file *m, void *p)
1505{
1506 const struct trace_syscall_entry *table, *entry = p;
1507 unsigned int bitness;
d4291869 1508 unsigned long index;
12e579db 1509 int ret;
d4291869 1510 const char *name;
2d2464bd 1511
12e579db
MD
1512 ret = get_sc_table(entry, &table, &bitness);
1513 if (ret)
1514 return ret;
f4855b46
MD
1515 if (!entry->desc)
1516 return 0;
ebcc64cd 1517 if (table == sc_table.table) {
d4291869 1518 index = entry - table;
437d5aa5 1519 name = &entry->desc->event_name[strlen(SYSCALL_ENTRY_STR)];
d4291869 1520 } else {
ebcc64cd 1521 index = (entry - table) + sc_table.len;
437d5aa5 1522 name = &entry->desc->event_name[strlen(COMPAT_SYSCALL_ENTRY_STR)];
d4291869 1523 }
12e579db 1524 seq_printf(m, "syscall { index = %lu; name = %s; bitness = %u; };\n",
d4291869 1525 index, name, bitness);
2d2464bd
MD
1526 return 0;
1527}
1528
1529static
1530const struct seq_operations lttng_syscall_list_seq_ops = {
1531 .start = syscall_list_start,
1532 .next = syscall_list_next,
1533 .stop = syscall_list_stop,
1534 .show = syscall_list_show,
1535};
1536
1537static
1538int lttng_syscall_list_open(struct inode *inode, struct file *file)
1539{
1540 return seq_open(file, &lttng_syscall_list_seq_ops);
1541}
1542
1543const struct file_operations lttng_syscall_list_fops = {
1544 .owner = THIS_MODULE,
1545 .open = lttng_syscall_list_open,
1546 .read = seq_read,
1547 .llseek = seq_lseek,
1548 .release = seq_release,
1549};
12e579db 1550
badfe9f5
MD
1551/*
1552 * A syscall is enabled if it is traced for either entry or exit.
1553 */
f7d06400 1554long lttng_channel_syscall_mask(struct lttng_kernel_channel_buffer *channel,
606828e4 1555 struct lttng_kernel_abi_syscall_mask __user *usyscall_mask)
12e579db 1556{
0bb716a8 1557 struct lttng_kernel_syscall_table *syscall_table = &channel->priv->parent.syscall_table;
12e579db
MD
1558 uint32_t len, sc_tables_len, bitmask_len;
1559 int ret = 0, bit;
1560 char *tmp_mask;
1561 struct lttng_syscall_filter *filter;
1562
1563 ret = get_user(len, &usyscall_mask->len);
1564 if (ret)
1565 return ret;
1566 sc_tables_len = get_sc_tables_len();
1567 bitmask_len = ALIGN(sc_tables_len, 8) >> 3;
1568 if (len < sc_tables_len) {
1569 return put_user(sc_tables_len, &usyscall_mask->len);
1570 }
1571 /* Array is large enough, we can copy array to user-space. */
1572 tmp_mask = kzalloc(bitmask_len, GFP_KERNEL);
1573 if (!tmp_mask)
1574 return -ENOMEM;
0bb716a8 1575 filter = syscall_table->sc_filter;
12e579db 1576
ebcc64cd 1577 for (bit = 0; bit < sc_table.len; bit++) {
e2129868 1578 char state;
2f25059d 1579
0bb716a8
MD
1580 if (syscall_table->syscall_dispatch) {
1581 if (!(READ_ONCE(syscall_table->syscall_all_entry)
1582 || READ_ONCE(syscall_table->syscall_all_exit)) && filter)
badfe9f5
MD
1583 state = test_bit(bit, filter->sc_entry)
1584 || test_bit(bit, filter->sc_exit);
2f25059d
MD
1585 else
1586 state = 1;
1587 } else {
1588 state = 0;
1589 }
1590 bt_bitfield_write_be(tmp_mask, char, bit, 1, state);
12e579db
MD
1591 }
1592 for (; bit < sc_tables_len; bit++) {
e2129868 1593 char state;
2f25059d 1594
0bb716a8
MD
1595 if (syscall_table->compat_syscall_dispatch) {
1596 if (!(READ_ONCE(syscall_table->syscall_all_entry)
1597 || READ_ONCE(syscall_table->syscall_all_exit)) && filter)
ebcc64cd 1598 state = test_bit(bit - sc_table.len,
badfe9f5 1599 filter->sc_compat_entry)
ebcc64cd 1600 || test_bit(bit - sc_table.len,
badfe9f5 1601 filter->sc_compat_exit);
2f25059d
MD
1602 else
1603 state = 1;
1604 } else {
1605 state = 0;
1606 }
1607 bt_bitfield_write_be(tmp_mask, char, bit, 1, state);
12e579db
MD
1608 }
1609 if (copy_to_user(usyscall_mask->mask, tmp_mask, bitmask_len))
1610 ret = -EFAULT;
1611 kfree(tmp_mask);
1612 return ret;
1613}
082d4946
MD
1614
1615int lttng_abi_syscall_list(void)
1616{
1617 struct file *syscall_list_file;
1618 int file_fd, ret;
1619
4ac10b76 1620 file_fd = lttng_get_unused_fd();
082d4946
MD
1621 if (file_fd < 0) {
1622 ret = file_fd;
1623 goto fd_error;
1624 }
1625
1626 syscall_list_file = anon_inode_getfile("[lttng_syscall_list]",
1627 &lttng_syscall_list_fops,
1628 NULL, O_RDWR);
1629 if (IS_ERR(syscall_list_file)) {
1630 ret = PTR_ERR(syscall_list_file);
1631 goto file_error;
1632 }
1633 ret = lttng_syscall_list_fops.open(NULL, syscall_list_file);
1634 if (ret < 0)
1635 goto open_error;
1636 fd_install(file_fd, syscall_list_file);
082d4946
MD
1637 return file_fd;
1638
1639open_error:
1640 fput(syscall_list_file);
1641file_error:
1642 put_unused_fd(file_fd);
1643fd_error:
1644 return ret;
1645}
This page took 0.143647 seconds and 4 git commands to generate.