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