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