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