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