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