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