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