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