Fix: syscall tracing: missing trigger actions
[lttng-modules.git] / src / lttng-syscalls.c
CommitLineData
b7cdc182 1/* SPDX-License-Identifier: (GPL-2.0-only or LGPL-2.1-only)
9f36eaed 2 *
259b6cb3
MD
3 * lttng-syscalls.c
4 *
2faf7d1b 5 * LTTng syscall probes.
259b6cb3 6 *
886d51a3 7 * Copyright (C) 2010-2012 Mathieu Desnoyers <mathieu.desnoyers@efficios.com>
259b6cb3
MD
8 */
9
10#include <linux/module.h>
11#include <linux/slab.h>
6333ace3 12#include <linux/compat.h>
abc0446a 13#include <linux/err.h>
80f87dd2 14#include <linux/bitmap.h>
7ca580f8
MD
15#include <linux/in.h>
16#include <linux/in6.h>
2d2464bd 17#include <linux/seq_file.h>
d4291869 18#include <linux/stringify.h>
082d4946
MD
19#include <linux/file.h>
20#include <linux/anon_inodes.h>
c8dfb724 21#include <linux/fcntl.h>
3cf55950 22#include <linux/mman.h>
259b6cb3
MD
23#include <asm/ptrace.h>
24#include <asm/syscall.h>
25
a071f25d 26#include <lttng/bitfield.h>
241ae9a8
MD
27#include <wrapper/tracepoint.h>
28#include <wrapper/file.h>
29#include <wrapper/rcu.h>
1b7b9c65 30#include <wrapper/syscall.h>
2df37e95 31#include <lttng/events.h>
1ea8aa0a 32#include <lttng/events-internal.h>
8a8ac9a8 33#include <lttng/utils.h>
259b6cb3 34
f385fc5f
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
8a8ac9a8
FD
68void syscall_entry_event_notifier_probe(void *__data, struct pt_regs *regs,
69 long id);
8a8ac9a8
FD
70void syscall_exit_event_notifier_probe(void *__data, struct pt_regs *regs,
71 long ret);
72
3a523f5b
MD
73/*
74 * Forward declarations for old kernels.
75 */
76struct mmsghdr;
77struct rlimit64;
78struct oldold_utsname;
79struct old_utsname;
80struct sel_arg_struct;
81struct mmap_arg_struct;
c0b71117 82struct file_handle;
a292e6f1 83struct user_msghdr;
3a523f5b 84
9eb15e8b
MJ
85/*
86 * Forward declaration for kernels >= 5.6
87 */
88struct timex;
edfdcb68
MJ
89struct timeval;
90struct itimerval;
91struct itimerspec;
92
5f4c791e 93#if (LTTNG_LINUX_VERSION_CODE >= LTTNG_KERNEL_VERSION(5,6,0))
edfdcb68
MJ
94typedef __kernel_old_time_t time_t;
95#endif
9eb15e8b 96
80f87dd2
MD
97#ifdef IA32_NR_syscalls
98#define NR_compat_syscalls IA32_NR_syscalls
99#else
100#define NR_compat_syscalls NR_syscalls
101#endif
102
259b6cb3
MD
103/*
104 * Create LTTng tracepoint probes.
105 */
106#define LTTNG_PACKAGE_BUILD
107#define CREATE_TRACE_POINTS
2655f9ad 108#define TP_MODULE_NOINIT
c075712b 109#define TRACE_INCLUDE_PATH instrumentation/syscalls/headers
259b6cb3 110
a93244f8
MD
111#define PARAMS(args...) args
112
5b7ac358 113/* Handle unknown syscalls */
72a52753 114#undef TRACE_SYSTEM
5b7ac358 115#define TRACE_SYSTEM syscalls_unknown
241ae9a8 116#include <instrumentation/syscalls/headers/syscalls_unknown.h>
5b7ac358
MD
117#undef TRACE_SYSTEM
118
5b7ac358 119#undef TP_PROBE_CB
fc4f7161 120
5bcf4dbd
FD
121extern const struct trace_syscall_table sc_table;
122extern const struct trace_syscall_table compat_sc_table;
5b7ac358 123
2d6d88c6 124/* Event syscall exit table */
5bcf4dbd
FD
125extern const struct trace_syscall_table sc_exit_table;
126extern const struct trace_syscall_table compat_sc_exit_table;
f385fc5f
FD
127
128
fc4f7161
MD
129#undef SC_EXIT
130
a93244f8 131#undef CREATE_SYSCALL_TABLE
2faf7d1b 132
80f87dd2 133struct lttng_syscall_filter {
badfe9f5
MD
134 DECLARE_BITMAP(sc_entry, NR_syscalls);
135 DECLARE_BITMAP(sc_exit, NR_syscalls);
136 DECLARE_BITMAP(sc_compat_entry, NR_compat_syscalls);
137 DECLARE_BITMAP(sc_compat_exit, NR_compat_syscalls);
4fabf854
MD
138
139 /*
140 * Reference counters keeping track of number of events enabled
141 * for each bit.
142 */
143 u32 sc_entry_refcount_map[NR_syscalls];
144 u32 sc_exit_refcount_map[NR_syscalls];
145 u32 sc_compat_entry_refcount_map[NR_compat_syscalls];
146 u32 sc_compat_exit_refcount_map[NR_compat_syscalls];
80f87dd2
MD
147};
148
3b82c4e1 149static void syscall_entry_event_unknown(struct hlist_head *unknown_action_list_head,
8a8ac9a8 150 struct pt_regs *regs, long id)
f405cfce 151{
1b7b9c65 152 unsigned long args[LTTNG_SYSCALL_NR_ARGS];
a67ba386 153 struct lttng_kernel_event_common_private *event_priv;
f405cfce 154
1b7b9c65 155 lttng_syscall_get_arguments(current, regs, args);
a67ba386 156 lttng_hlist_for_each_entry_rcu(event_priv, unknown_action_list_head, u.syscall.node) {
8a8ac9a8 157 if (unlikely(in_compat_syscall()))
e2d5dbc7 158 __event_probe__compat_syscall_entry_unknown(event_priv->pub, id, args);
8a8ac9a8 159 else
e2d5dbc7 160 __event_probe__syscall_entry_unknown(event_priv->pub, id, args);
8a8ac9a8
FD
161 }
162}
163
63aa9160 164static __always_inline
e2d5dbc7 165void syscall_entry_event_call_func(struct hlist_head *action_list,
3b82c4e1 166 void *func, unsigned int nrargs,
63aa9160 167 struct pt_regs *regs)
259b6cb3 168{
a67ba386 169 struct lttng_kernel_event_common_private *event_priv;
3b82c4e1 170
63aa9160 171 switch (nrargs) {
259b6cb3
MD
172 case 0:
173 {
63aa9160 174 void (*fptr)(void *__data) = func;
259b6cb3 175
e2d5dbc7
MD
176 lttng_hlist_for_each_entry_rcu(event_priv, action_list, u.syscall.node)
177 fptr(event_priv->pub);
259b6cb3
MD
178 break;
179 }
180 case 1:
181 {
63aa9160 182 void (*fptr)(void *__data, unsigned long arg0) = func;
1b7b9c65 183 unsigned long args[LTTNG_SYSCALL_NR_ARGS];
259b6cb3 184
1b7b9c65 185 lttng_syscall_get_arguments(current, regs, args);
e2d5dbc7
MD
186 lttng_hlist_for_each_entry_rcu(event_priv, action_list, u.syscall.node)
187 fptr(event_priv->pub, args[0]);
259b6cb3
MD
188 break;
189 }
190 case 2:
191 {
192 void (*fptr)(void *__data,
193 unsigned long arg0,
63aa9160 194 unsigned long arg1) = func;
1b7b9c65 195 unsigned long args[LTTNG_SYSCALL_NR_ARGS];
259b6cb3 196
1b7b9c65 197 lttng_syscall_get_arguments(current, regs, args);
e2d5dbc7
MD
198 lttng_hlist_for_each_entry_rcu(event_priv, action_list, u.syscall.node)
199 fptr(event_priv->pub, args[0], args[1]);
259b6cb3
MD
200 break;
201 }
202 case 3:
203 {
204 void (*fptr)(void *__data,
205 unsigned long arg0,
206 unsigned long arg1,
63aa9160 207 unsigned long arg2) = func;
1b7b9c65 208 unsigned long args[LTTNG_SYSCALL_NR_ARGS];
259b6cb3 209
1b7b9c65 210 lttng_syscall_get_arguments(current, regs, args);
e2d5dbc7
MD
211 lttng_hlist_for_each_entry_rcu(event_priv, action_list, u.syscall.node)
212 fptr(event_priv->pub, args[0], args[1], args[2]);
259b6cb3
MD
213 break;
214 }
215 case 4:
216 {
217 void (*fptr)(void *__data,
218 unsigned long arg0,
219 unsigned long arg1,
220 unsigned long arg2,
63aa9160 221 unsigned long arg3) = func;
1b7b9c65 222 unsigned long args[LTTNG_SYSCALL_NR_ARGS];
259b6cb3 223
1b7b9c65 224 lttng_syscall_get_arguments(current, regs, args);
e2d5dbc7
MD
225 lttng_hlist_for_each_entry_rcu(event_priv, action_list, u.syscall.node)
226 fptr(event_priv->pub, args[0], args[1], args[2], args[3]);
259b6cb3
MD
227 break;
228 }
229 case 5:
230 {
231 void (*fptr)(void *__data,
232 unsigned long arg0,
233 unsigned long arg1,
234 unsigned long arg2,
235 unsigned long arg3,
63aa9160 236 unsigned long arg4) = func;
1b7b9c65 237 unsigned long args[LTTNG_SYSCALL_NR_ARGS];
259b6cb3 238
1b7b9c65 239 lttng_syscall_get_arguments(current, regs, args);
e2d5dbc7
MD
240 lttng_hlist_for_each_entry_rcu(event_priv, action_list, u.syscall.node)
241 fptr(event_priv->pub, args[0], args[1], args[2], args[3], args[4]);
259b6cb3
MD
242 break;
243 }
244 case 6:
245 {
246 void (*fptr)(void *__data,
247 unsigned long arg0,
248 unsigned long arg1,
249 unsigned long arg2,
250 unsigned long arg3,
251 unsigned long arg4,
63aa9160 252 unsigned long arg5) = func;
1b7b9c65 253 unsigned long args[LTTNG_SYSCALL_NR_ARGS];
259b6cb3 254
1b7b9c65 255 lttng_syscall_get_arguments(current, regs, args);
e2d5dbc7
MD
256 lttng_hlist_for_each_entry_rcu(event_priv, action_list, u.syscall.node)
257 fptr(event_priv->pub, args[0], args[1], args[2],
3b82c4e1 258 args[3], args[4], args[5]);
8a8ac9a8
FD
259 break;
260 }
261 default:
262 break;
263 }
264}
265
63aa9160
FD
266void syscall_entry_event_probe(void *__data, struct pt_regs *regs, long id)
267{
ac847066 268 struct lttng_kernel_channel_buffer *chan = __data;
3b82c4e1 269 struct hlist_head *action_list, *unknown_action_list;
63aa9160
FD
270 const struct trace_syscall_entry *table, *entry;
271 size_t table_len;
272
273 if (unlikely(in_compat_syscall())) {
ac847066 274 struct lttng_syscall_filter *filter = chan->priv->parent.sc_filter;
63aa9160
FD
275
276 if (id < 0 || id >= NR_compat_syscalls
ac847066 277 || (!READ_ONCE(chan->priv->parent.syscall_all_entry) && !test_bit(id, filter->sc_compat_entry))) {
63aa9160
FD
278 /* System call filtered out. */
279 return;
280 }
f385fc5f
FD
281 table = compat_sc_table.table;
282 table_len = compat_sc_table.len;
ac847066 283 unknown_action_list = &chan->priv->parent.sc_compat_unknown;
63aa9160 284 } else {
ac847066 285 struct lttng_syscall_filter *filter = chan->priv->parent.sc_filter;
63aa9160
FD
286
287 if (id < 0 || id >= NR_syscalls
ac847066 288 || (!READ_ONCE(chan->priv->parent.syscall_all_entry) && !test_bit(id, filter->sc_entry))) {
63aa9160
FD
289 /* System call filtered out. */
290 return;
291 }
f385fc5f
FD
292 table = sc_table.table;
293 table_len = sc_table.len;
ac847066 294 unknown_action_list = &chan->priv->parent.sc_unknown;
63aa9160
FD
295 }
296 if (unlikely(id < 0 || id >= table_len)) {
3b82c4e1 297 syscall_entry_event_unknown(unknown_action_list, regs, id);
63aa9160
FD
298 return;
299 }
3b82c4e1
MD
300
301 entry = &table[id];
302 if (!entry->event_func) {
303 syscall_entry_event_unknown(unknown_action_list, regs, id);
63aa9160
FD
304 return;
305 }
3b82c4e1
MD
306
307 if (unlikely(in_compat_syscall())) {
ac847066 308 action_list = &chan->priv->parent.compat_sc_table[id];
3b82c4e1 309 } else {
ac847066 310 action_list = &chan->priv->parent.sc_table[id];
3b82c4e1
MD
311 }
312 if (unlikely(hlist_empty(action_list)))
313 return;
314
e2d5dbc7 315 syscall_entry_event_call_func(action_list, entry->event_func, entry->nrargs, regs);
63aa9160
FD
316}
317
8a8ac9a8
FD
318void syscall_entry_event_notifier_probe(void *__data, struct pt_regs *regs,
319 long id)
320{
321 struct lttng_event_notifier_group *group = __data;
322 const struct trace_syscall_entry *table, *entry;
323 struct hlist_head *dispatch_list, *unknown_dispatch_list;
324 size_t table_len;
325
326 if (unlikely(in_compat_syscall())) {
327 struct lttng_syscall_filter *filter = group->sc_filter;
328
329 if (id < 0 || id >= NR_compat_syscalls
330 || (!READ_ONCE(group->syscall_all_entry) &&
331 !test_bit(id, filter->sc_compat_entry))) {
332 /* System call filtered out. */
333 return;
334 }
f385fc5f
FD
335 table = compat_sc_table.table;
336 table_len = compat_sc_table.len;
8a8ac9a8
FD
337 unknown_dispatch_list = &group->event_notifier_compat_unknown_syscall_dispatch;
338 } else {
339 struct lttng_syscall_filter *filter = group->sc_filter;
340
341 if (id < 0 || id >= NR_syscalls
342 || (!READ_ONCE(group->syscall_all_entry) &&
343 !test_bit(id, filter->sc_entry))) {
344 /* System call filtered out. */
345 return;
346 }
f385fc5f
FD
347 table = sc_table.table;
348 table_len = sc_table.len;
8a8ac9a8
FD
349 unknown_dispatch_list = &group->event_notifier_unknown_syscall_dispatch;
350 }
351 /* Check if the syscall id is out of bound. */
352 if (unlikely(id < 0 || id >= table_len)) {
e2d5dbc7 353 syscall_entry_event_unknown(unknown_dispatch_list,
8a8ac9a8
FD
354 regs, id);
355 return;
356 }
357
358 entry = &table[id];
e2d5dbc7
MD
359 if (!entry->event_func) {
360 syscall_entry_event_unknown(unknown_dispatch_list,
8a8ac9a8
FD
361 regs, id);
362 return;
363 }
364
365 if (unlikely(in_compat_syscall())) {
366 dispatch_list = &group->event_notifier_compat_syscall_dispatch[id];
367 } else {
368 dispatch_list = &group->event_notifier_syscall_dispatch[id];
369 }
370 if (unlikely(hlist_empty(dispatch_list)))
371 return;
372
e2d5dbc7
MD
373 syscall_entry_event_call_func(dispatch_list,
374 entry->event_func, entry->nrargs, regs);
8a8ac9a8
FD
375}
376
3b82c4e1 377static void syscall_exit_event_unknown(struct hlist_head *unknown_action_list_head,
8a8ac9a8 378 struct pt_regs *regs, long id, long ret)
5b7ac358 379{
1b7b9c65 380 unsigned long args[LTTNG_SYSCALL_NR_ARGS];
a67ba386 381 struct lttng_kernel_event_common_private *event_priv;
5b7ac358 382
1b7b9c65 383 lttng_syscall_get_arguments(current, regs, args);
a67ba386 384 lttng_hlist_for_each_entry_rcu(event_priv, unknown_action_list_head, u.syscall.node) {
3b82c4e1 385 if (unlikely(in_compat_syscall()))
e2d5dbc7 386 __event_probe__compat_syscall_exit_unknown(event_priv->pub, id, ret,
3b82c4e1
MD
387 args);
388 else
e2d5dbc7 389 __event_probe__syscall_exit_unknown(event_priv->pub, id, ret, args);
3b82c4e1 390 }
5b7ac358
MD
391}
392
3b82c4e1 393static __always_inline
e2d5dbc7 394void syscall_exit_event_call_func(struct hlist_head *action_list,
3b82c4e1
MD
395 void *func, unsigned int nrargs,
396 struct pt_regs *regs, long ret)
5b7ac358 397{
a67ba386 398 struct lttng_kernel_event_common_private *event_priv;
badfe9f5 399
3b82c4e1 400 switch (nrargs) {
5b7ac358
MD
401 case 0:
402 {
3b82c4e1 403 void (*fptr)(void *__data, long ret) = func;
5b7ac358 404
e2d5dbc7
MD
405 lttng_hlist_for_each_entry_rcu(event_priv, action_list, u.syscall.node)
406 fptr(event_priv->pub, ret);
5b7ac358
MD
407 break;
408 }
409 case 1:
410 {
411 void (*fptr)(void *__data,
fc4f7161 412 long ret,
3b82c4e1 413 unsigned long arg0) = func;
1b7b9c65 414 unsigned long args[LTTNG_SYSCALL_NR_ARGS];
5b7ac358 415
1b7b9c65 416 lttng_syscall_get_arguments(current, regs, args);
e2d5dbc7
MD
417 lttng_hlist_for_each_entry_rcu(event_priv, action_list, u.syscall.node)
418 fptr(event_priv->pub, ret, args[0]);
5b7ac358
MD
419 break;
420 }
421 case 2:
422 {
423 void (*fptr)(void *__data,
fc4f7161 424 long ret,
5b7ac358 425 unsigned long arg0,
3b82c4e1 426 unsigned long arg1) = func;
1b7b9c65 427 unsigned long args[LTTNG_SYSCALL_NR_ARGS];
5b7ac358 428
1b7b9c65 429 lttng_syscall_get_arguments(current, regs, args);
e2d5dbc7
MD
430 lttng_hlist_for_each_entry_rcu(event_priv, action_list, u.syscall.node)
431 fptr(event_priv->pub, ret, args[0], args[1]);
5b7ac358
MD
432 break;
433 }
434 case 3:
435 {
436 void (*fptr)(void *__data,
fc4f7161 437 long ret,
5b7ac358
MD
438 unsigned long arg0,
439 unsigned long arg1,
3b82c4e1 440 unsigned long arg2) = func;
1b7b9c65 441 unsigned long args[LTTNG_SYSCALL_NR_ARGS];
5b7ac358 442
1b7b9c65 443 lttng_syscall_get_arguments(current, regs, args);
e2d5dbc7
MD
444 lttng_hlist_for_each_entry_rcu(event_priv, action_list, u.syscall.node)
445 fptr(event_priv->pub, ret, args[0], args[1], args[2]);
5b7ac358
MD
446 break;
447 }
448 case 4:
449 {
450 void (*fptr)(void *__data,
fc4f7161 451 long ret,
5b7ac358
MD
452 unsigned long arg0,
453 unsigned long arg1,
454 unsigned long arg2,
3b82c4e1 455 unsigned long arg3) = func;
1b7b9c65 456 unsigned long args[LTTNG_SYSCALL_NR_ARGS];
5b7ac358 457
1b7b9c65 458 lttng_syscall_get_arguments(current, regs, args);
e2d5dbc7
MD
459 lttng_hlist_for_each_entry_rcu(event_priv, action_list, u.syscall.node)
460 fptr(event_priv->pub, ret, args[0], args[1], args[2], args[3]);
5b7ac358
MD
461 break;
462 }
463 case 5:
464 {
465 void (*fptr)(void *__data,
fc4f7161 466 long ret,
5b7ac358
MD
467 unsigned long arg0,
468 unsigned long arg1,
469 unsigned long arg2,
470 unsigned long arg3,
3b82c4e1 471 unsigned long arg4) = func;
1b7b9c65 472 unsigned long args[LTTNG_SYSCALL_NR_ARGS];
5b7ac358 473
1b7b9c65 474 lttng_syscall_get_arguments(current, regs, args);
e2d5dbc7
MD
475 lttng_hlist_for_each_entry_rcu(event_priv, action_list, u.syscall.node)
476 fptr(event_priv->pub, ret, args[0], args[1], args[2], args[3], args[4]);
5b7ac358
MD
477 break;
478 }
479 case 6:
480 {
481 void (*fptr)(void *__data,
fc4f7161 482 long ret,
5b7ac358
MD
483 unsigned long arg0,
484 unsigned long arg1,
485 unsigned long arg2,
486 unsigned long arg3,
487 unsigned long arg4,
3b82c4e1 488 unsigned long arg5) = func;
1b7b9c65 489 unsigned long args[LTTNG_SYSCALL_NR_ARGS];
5b7ac358 490
1b7b9c65 491 lttng_syscall_get_arguments(current, regs, args);
e2d5dbc7
MD
492 lttng_hlist_for_each_entry_rcu(event_priv, action_list, u.syscall.node)
493 fptr(event_priv->pub, ret, args[0], args[1], args[2],
3b82c4e1 494 args[3], args[4], args[5]);
5b7ac358
MD
495 break;
496 }
497 default:
498 break;
499 }
500}
501
3b82c4e1
MD
502void syscall_exit_event_probe(void *__data, struct pt_regs *regs, long ret)
503{
ac847066 504 struct lttng_kernel_channel_buffer *chan = __data;
3b82c4e1
MD
505 struct hlist_head *action_list, *unknown_action_list;
506 const struct trace_syscall_entry *table, *entry;
507 size_t table_len;
508 long id;
509
510 id = syscall_get_nr(current, regs);
511
512 if (unlikely(in_compat_syscall())) {
ac847066 513 struct lttng_syscall_filter *filter = chan->priv->parent.sc_filter;
3b82c4e1
MD
514
515 if (id < 0 || id >= NR_compat_syscalls
ac847066 516 || (!READ_ONCE(chan->priv->parent.syscall_all_exit) && !test_bit(id, filter->sc_compat_exit))) {
3b82c4e1
MD
517 /* System call filtered out. */
518 return;
519 }
f385fc5f
FD
520 table = compat_sc_exit_table.table;
521 table_len = compat_sc_exit_table.len;
ac847066 522 unknown_action_list = &chan->priv->parent.compat_sc_exit_unknown;
3b82c4e1 523 } else {
ac847066 524 struct lttng_syscall_filter *filter = chan->priv->parent.sc_filter;
3b82c4e1
MD
525
526 if (id < 0 || id >= NR_syscalls
ac847066 527 || (!READ_ONCE(chan->priv->parent.syscall_all_exit) && !test_bit(id, filter->sc_exit))) {
3b82c4e1
MD
528 /* System call filtered out. */
529 return;
530 }
f385fc5f
FD
531 table = sc_exit_table.table;
532 table_len = sc_exit_table.len;
ac847066 533 unknown_action_list = &chan->priv->parent.sc_exit_unknown;
3b82c4e1
MD
534 }
535 if (unlikely(id < 0 || id >= table_len)) {
536 syscall_exit_event_unknown(unknown_action_list, regs, id, ret);
537 return;
538 }
539
540 entry = &table[id];
541 if (!entry->event_func) {
542 syscall_exit_event_unknown(unknown_action_list, regs, id, ret);
543 return;
544 }
545
546 if (unlikely(in_compat_syscall())) {
ac847066 547 action_list = &chan->priv->parent.compat_sc_exit_table[id];
3b82c4e1 548 } else {
ac847066 549 action_list = &chan->priv->parent.sc_exit_table[id];
3b82c4e1
MD
550 }
551 if (unlikely(hlist_empty(action_list)))
552 return;
553
e2d5dbc7 554 syscall_exit_event_call_func(action_list, entry->event_func, entry->nrargs,
3b82c4e1
MD
555 regs, ret);
556}
557
8a8ac9a8
FD
558void syscall_exit_event_notifier_probe(void *__data, struct pt_regs *regs,
559 long ret)
560{
561 struct lttng_event_notifier_group *group = __data;
562 const struct trace_syscall_entry *table, *entry;
563 struct hlist_head *dispatch_list, *unknown_dispatch_list;
564 size_t table_len;
565 long id;
566
567 id = syscall_get_nr(current, regs);
568
569 if (unlikely(in_compat_syscall())) {
570 struct lttng_syscall_filter *filter = group->sc_filter;
571
572 if (id < 0 || id >= NR_compat_syscalls
573 || (!READ_ONCE(group->syscall_all_exit) &&
574 !test_bit(id, filter->sc_compat_exit))) {
575 /* System call filtered out. */
576 return;
577 }
f385fc5f
FD
578 table = compat_sc_exit_table.table;
579 table_len = compat_sc_exit_table.len;
8a8ac9a8
FD
580 unknown_dispatch_list = &group->event_notifier_exit_compat_unknown_syscall_dispatch;
581 } else {
582 struct lttng_syscall_filter *filter = group->sc_filter;
583
584 if (id < 0 || id >= NR_syscalls
585 || (!READ_ONCE(group->syscall_all_exit) &&
586 !test_bit(id, filter->sc_exit))) {
587 /* System call filtered out. */
588 return;
589 }
f385fc5f
FD
590 table = sc_exit_table.table;
591 table_len = sc_exit_table.len;
8a8ac9a8
FD
592 unknown_dispatch_list = &group->event_notifier_exit_unknown_syscall_dispatch;
593 }
594 /* Check if the syscall id is out of bound. */
595 if (unlikely(id < 0 || id >= table_len)) {
e2d5dbc7 596 syscall_exit_event_unknown(unknown_dispatch_list,
8a8ac9a8
FD
597 regs, id, ret);
598 return;
599 }
600
601 entry = &table[id];
e2d5dbc7
MD
602 if (!entry->event_func) {
603 syscall_entry_event_unknown(unknown_dispatch_list,
8a8ac9a8
FD
604 regs, id);
605 return;
606 }
607
608 if (unlikely(in_compat_syscall())) {
609 dispatch_list = &group->event_notifier_exit_compat_syscall_dispatch[id];
610 } else {
611 dispatch_list = &group->event_notifier_exit_syscall_dispatch[id];
612 }
613 if (unlikely(hlist_empty(dispatch_list)))
614 return;
615
e2d5dbc7
MD
616 syscall_exit_event_call_func(dispatch_list,
617 entry->event_func, entry->nrargs, regs, ret);
8a8ac9a8 618}
33a39a3c
MD
619/*
620 * noinline to diminish caller stack size.
621 * Should be called with sessions lock held.
622 */
49c50022 623static
3b82c4e1
MD
624int lttng_create_syscall_event_if_missing(const struct trace_syscall_entry *table, size_t table_len,
625 struct hlist_head *chan_table, struct lttng_event_enabler *event_enabler,
a67ba386 626 enum sc_type type)
259b6cb3 627{
ac847066
MD
628 struct lttng_kernel_channel_buffer *chan = event_enabler->chan;
629 struct lttng_kernel_session *session = chan->parent.session;
259b6cb3 630 unsigned int i;
49c50022 631
3b82c4e1 632 /* Allocate events for each syscall matching enabler, insert into table */
49c50022 633 for (i = 0; i < table_len; i++) {
437d5aa5 634 const struct lttng_kernel_event_desc *desc = table[i].desc;
606828e4 635 struct lttng_kernel_abi_event ev;
a67ba386
MD
636 struct lttng_kernel_event_recorder_private *event_recorder_priv;
637 struct lttng_kernel_event_recorder *event_recorder;
3b82c4e1
MD
638 struct hlist_head *head;
639 bool found = false;
49c50022
MD
640
641 if (!desc) {
642 /* Unknown syscall */
643 continue;
644 }
3b82c4e1
MD
645 if (lttng_desc_match_enabler(desc,
646 lttng_event_enabler_as_enabler(event_enabler)) <= 0)
647 continue;
49c50022 648 /*
3b82c4e1 649 * Check if already created.
49c50022 650 */
3b82c4e1 651 head = utils_borrow_hash_table_bucket(
a40e3229 652 session->priv->events_ht.table, LTTNG_EVENT_HT_SIZE,
437d5aa5 653 desc->event_name);
a67ba386
MD
654 lttng_hlist_for_each_entry(event_recorder_priv, head, hlist) {
655 if (event_recorder_priv->parent.desc == desc
656 && event_recorder_priv->pub->chan == event_enabler->chan)
3b82c4e1
MD
657 found = true;
658 }
659 if (found)
49c50022 660 continue;
3b82c4e1
MD
661
662 /* We need to create an event for this syscall/enabler. */
49c50022 663 memset(&ev, 0, sizeof(ev));
5b7ac358
MD
664 switch (type) {
665 case SC_TYPE_ENTRY:
606828e4
MD
666 ev.u.syscall.entryexit = LTTNG_KERNEL_ABI_SYSCALL_ENTRY;
667 ev.u.syscall.abi = LTTNG_KERNEL_ABI_SYSCALL_ABI_NATIVE;
5b7ac358
MD
668 break;
669 case SC_TYPE_EXIT:
606828e4
MD
670 ev.u.syscall.entryexit = LTTNG_KERNEL_ABI_SYSCALL_EXIT;
671 ev.u.syscall.abi = LTTNG_KERNEL_ABI_SYSCALL_ABI_NATIVE;
5b7ac358
MD
672 break;
673 case SC_TYPE_COMPAT_ENTRY:
606828e4
MD
674 ev.u.syscall.entryexit = LTTNG_KERNEL_ABI_SYSCALL_ENTRY;
675 ev.u.syscall.abi = LTTNG_KERNEL_ABI_SYSCALL_ABI_COMPAT;
5b7ac358
MD
676 break;
677 case SC_TYPE_COMPAT_EXIT:
606828e4
MD
678 ev.u.syscall.entryexit = LTTNG_KERNEL_ABI_SYSCALL_EXIT;
679 ev.u.syscall.abi = LTTNG_KERNEL_ABI_SYSCALL_ABI_COMPAT;
5b7ac358
MD
680 break;
681 }
606828e4
MD
682 strncpy(ev.name, desc->event_name, LTTNG_KERNEL_ABI_SYM_NAME_LEN - 1);
683 ev.name[LTTNG_KERNEL_ABI_SYM_NAME_LEN - 1] = '\0';
684 ev.instrumentation = LTTNG_KERNEL_ABI_SYSCALL;
a67ba386
MD
685 event_recorder = _lttng_kernel_event_recorder_create(chan, &ev, desc, ev.instrumentation);
686 WARN_ON_ONCE(!event_recorder);
687 if (IS_ERR(event_recorder)) {
49c50022
MD
688 /*
689 * If something goes wrong in event registration
690 * after the first one, we have no choice but to
691 * leave the previous events in there, until
692 * deleted by session teardown.
693 */
a67ba386 694 return PTR_ERR(event_recorder);
49c50022 695 }
a67ba386 696 hlist_add_head(&event_recorder->priv->parent.u.syscall.node, &chan_table[i]);
49c50022
MD
697 }
698 return 0;
699}
700
33a39a3c
MD
701/*
702 * Should be called with sessions lock held.
703 */
a67ba386 704int lttng_syscalls_register_event(struct lttng_event_enabler *event_enabler)
49c50022 705{
ac847066 706 struct lttng_kernel_channel_buffer *chan = event_enabler->chan;
606828e4 707 struct lttng_kernel_abi_event ev;
259b6cb3
MD
708 int ret;
709
263b6c88 710 wrapper_vmalloc_sync_mappings();
259b6cb3 711
ac847066 712 if (!chan->priv->parent.sc_table) {
259b6cb3 713 /* create syscall table mapping syscall to events */
ac847066 714 chan->priv->parent.sc_table = kzalloc(sizeof(struct lttng_kernel_event_recorder *)
f385fc5f 715 * sc_table.len, GFP_KERNEL);
ac847066 716 if (!chan->priv->parent.sc_table)
259b6cb3
MD
717 return -ENOMEM;
718 }
ac847066 719 if (!chan->priv->parent.sc_exit_table) {
5b7ac358 720 /* create syscall table mapping syscall to events */
ac847066 721 chan->priv->parent.sc_exit_table = kzalloc(sizeof(struct lttng_kernel_event_recorder *)
f385fc5f 722 * sc_exit_table.len, GFP_KERNEL);
ac847066 723 if (!chan->priv->parent.sc_exit_table)
5b7ac358
MD
724 return -ENOMEM;
725 }
726
259b6cb3 727
49c50022 728#ifdef CONFIG_COMPAT
ac847066 729 if (!chan->priv->parent.compat_sc_table) {
49c50022 730 /* create syscall table mapping compat syscall to events */
ac847066 731 chan->priv->parent.compat_sc_table = kzalloc(sizeof(struct lttng_kernel_event_recorder *)
f385fc5f 732 * compat_sc_table.len, GFP_KERNEL);
ac847066 733 if (!chan->priv->parent.compat_sc_table)
49c50022
MD
734 return -ENOMEM;
735 }
5b7ac358 736
ac847066 737 if (!chan->priv->parent.compat_sc_exit_table) {
5b7ac358 738 /* create syscall table mapping compat syscall to events */
ac847066 739 chan->priv->parent.compat_sc_exit_table = kzalloc(sizeof(struct lttng_kernel_event_recorder *)
f385fc5f 740 * compat_sc_exit_table.len, GFP_KERNEL);
ac847066 741 if (!chan->priv->parent.compat_sc_exit_table)
5b7ac358
MD
742 return -ENOMEM;
743 }
49c50022 744#endif
ac847066 745 if (hlist_empty(&chan->priv->parent.sc_unknown)) {
437d5aa5 746 const struct lttng_kernel_event_desc *desc =
d4291869 747 &__event_desc___syscall_entry_unknown;
a67ba386 748 struct lttng_kernel_event_recorder *event_recorder;
2f804c0a 749
f405cfce 750 memset(&ev, 0, sizeof(ev));
606828e4
MD
751 strncpy(ev.name, desc->event_name, LTTNG_KERNEL_ABI_SYM_NAME_LEN);
752 ev.name[LTTNG_KERNEL_ABI_SYM_NAME_LEN - 1] = '\0';
753 ev.instrumentation = LTTNG_KERNEL_ABI_SYSCALL;
754 ev.u.syscall.entryexit = LTTNG_KERNEL_ABI_SYSCALL_ENTRY;
755 ev.u.syscall.abi = LTTNG_KERNEL_ABI_SYSCALL_ABI_NATIVE;
a67ba386 756 event_recorder = _lttng_kernel_event_recorder_create(chan, &ev, desc,
3b82c4e1 757 ev.instrumentation);
a67ba386
MD
758 WARN_ON_ONCE(!event_recorder);
759 if (IS_ERR(event_recorder)) {
760 return PTR_ERR(event_recorder);
f405cfce 761 }
ac847066 762 hlist_add_head(&event_recorder->priv->parent.u.syscall.node, &chan->priv->parent.sc_unknown);
f405cfce
MD
763 }
764
ac847066 765 if (hlist_empty(&chan->priv->parent.sc_compat_unknown)) {
437d5aa5 766 const struct lttng_kernel_event_desc *desc =
d4291869 767 &__event_desc___compat_syscall_entry_unknown;
a67ba386 768 struct lttng_kernel_event_recorder *event_recorder;
b76dc1a0
MD
769
770 memset(&ev, 0, sizeof(ev));
606828e4
MD
771 strncpy(ev.name, desc->event_name, LTTNG_KERNEL_ABI_SYM_NAME_LEN);
772 ev.name[LTTNG_KERNEL_ABI_SYM_NAME_LEN - 1] = '\0';
773 ev.instrumentation = LTTNG_KERNEL_ABI_SYSCALL;
774 ev.u.syscall.entryexit = LTTNG_KERNEL_ABI_SYSCALL_ENTRY;
775 ev.u.syscall.abi = LTTNG_KERNEL_ABI_SYSCALL_ABI_COMPAT;
a67ba386 776 event_recorder = _lttng_kernel_event_recorder_create(chan, &ev, desc,
3b82c4e1 777 ev.instrumentation);
a67ba386
MD
778 WARN_ON_ONCE(!event_recorder);
779 if (IS_ERR(event_recorder)) {
780 return PTR_ERR(event_recorder);
b76dc1a0 781 }
ac847066 782 hlist_add_head(&event_recorder->priv->parent.u.syscall.node, &chan->priv->parent.sc_compat_unknown);
b76dc1a0
MD
783 }
784
ac847066 785 if (hlist_empty(&chan->priv->parent.compat_sc_exit_unknown)) {
437d5aa5 786 const struct lttng_kernel_event_desc *desc =
5b7ac358 787 &__event_desc___compat_syscall_exit_unknown;
a67ba386 788 struct lttng_kernel_event_recorder *event_recorder;
2f804c0a
MD
789
790 memset(&ev, 0, sizeof(ev));
606828e4
MD
791 strncpy(ev.name, desc->event_name, LTTNG_KERNEL_ABI_SYM_NAME_LEN);
792 ev.name[LTTNG_KERNEL_ABI_SYM_NAME_LEN - 1] = '\0';
793 ev.instrumentation = LTTNG_KERNEL_ABI_SYSCALL;
794 ev.u.syscall.entryexit = LTTNG_KERNEL_ABI_SYSCALL_EXIT;
795 ev.u.syscall.abi = LTTNG_KERNEL_ABI_SYSCALL_ABI_COMPAT;
a67ba386 796 event_recorder = _lttng_kernel_event_recorder_create(chan, &ev, desc,
3b82c4e1 797 ev.instrumentation);
a67ba386
MD
798 WARN_ON_ONCE(!event_recorder);
799 if (IS_ERR(event_recorder)) {
800 return PTR_ERR(event_recorder);
5b7ac358 801 }
ac847066 802 hlist_add_head(&event_recorder->priv->parent.u.syscall.node, &chan->priv->parent.compat_sc_exit_unknown);
5b7ac358
MD
803 }
804
ac847066 805 if (hlist_empty(&chan->priv->parent.sc_exit_unknown)) {
437d5aa5 806 const struct lttng_kernel_event_desc *desc =
5b7ac358 807 &__event_desc___syscall_exit_unknown;
a67ba386 808 struct lttng_kernel_event_recorder *event_recorder;
5b7ac358
MD
809
810 memset(&ev, 0, sizeof(ev));
606828e4
MD
811 strncpy(ev.name, desc->event_name, LTTNG_KERNEL_ABI_SYM_NAME_LEN);
812 ev.name[LTTNG_KERNEL_ABI_SYM_NAME_LEN - 1] = '\0';
813 ev.instrumentation = LTTNG_KERNEL_ABI_SYSCALL;
814 ev.u.syscall.entryexit = LTTNG_KERNEL_ABI_SYSCALL_EXIT;
815 ev.u.syscall.abi = LTTNG_KERNEL_ABI_SYSCALL_ABI_NATIVE;
a67ba386 816 event_recorder = _lttng_kernel_event_recorder_create(chan, &ev, desc,
3b82c4e1 817 ev.instrumentation);
a67ba386
MD
818 WARN_ON_ONCE(!event_recorder);
819 if (IS_ERR(event_recorder)) {
820 return PTR_ERR(event_recorder);
2f804c0a 821 }
ac847066 822 hlist_add_head(&event_recorder->priv->parent.u.syscall.node, &chan->priv->parent.sc_exit_unknown);
2f804c0a
MD
823 }
824
f385fc5f 825 ret = lttng_create_syscall_event_if_missing(sc_table.table, sc_table.len,
ac847066 826 chan->priv->parent.sc_table, event_enabler, SC_TYPE_ENTRY);
5b7ac358
MD
827 if (ret)
828 return ret;
f385fc5f 829 ret = lttng_create_syscall_event_if_missing(sc_exit_table.table, sc_exit_table.len,
ac847066 830 chan->priv->parent.sc_exit_table, event_enabler, SC_TYPE_EXIT);
49c50022
MD
831 if (ret)
832 return ret;
5b7ac358 833
49c50022 834#ifdef CONFIG_COMPAT
f385fc5f 835 ret = lttng_create_syscall_event_if_missing(compat_sc_table.table, compat_sc_table.len,
ac847066 836 chan->priv->parent.compat_sc_table, event_enabler, SC_TYPE_COMPAT_ENTRY);
5b7ac358
MD
837 if (ret)
838 return ret;
f385fc5f 839 ret = lttng_create_syscall_event_if_missing(compat_sc_exit_table.table, compat_sc_exit_table.len,
ac847066 840 chan->priv->parent.compat_sc_exit_table, event_enabler, SC_TYPE_COMPAT_EXIT);
49c50022
MD
841 if (ret)
842 return ret;
843#endif
badfe9f5 844
ac847066
MD
845 if (!chan->priv->parent.sc_filter) {
846 chan->priv->parent.sc_filter = kzalloc(sizeof(struct lttng_syscall_filter),
badfe9f5 847 GFP_KERNEL);
ac847066 848 if (!chan->priv->parent.sc_filter)
badfe9f5
MD
849 return -ENOMEM;
850 }
851
ac847066 852 if (!chan->priv->parent.sys_enter_registered) {
80f87dd2 853 ret = lttng_wrapper_tracepoint_probe_register("sys_enter",
2d6d88c6 854 (void *) syscall_entry_event_probe, chan);
80f87dd2
MD
855 if (ret)
856 return ret;
ac847066 857 chan->priv->parent.sys_enter_registered = 1;
80f87dd2 858 }
63728b02
MD
859 /*
860 * We change the name of sys_exit tracepoint due to namespace
861 * conflict with sys_exit syscall entry.
862 */
ac847066 863 if (!chan->priv->parent.sys_exit_registered) {
80f87dd2 864 ret = lttng_wrapper_tracepoint_probe_register("sys_exit",
2d6d88c6 865 (void *) syscall_exit_event_probe, chan);
80f87dd2
MD
866 if (ret) {
867 WARN_ON_ONCE(lttng_wrapper_tracepoint_probe_unregister("sys_enter",
2d6d88c6 868 (void *) syscall_entry_event_probe, chan));
80f87dd2
MD
869 return ret;
870 }
ac847066 871 chan->priv->parent.sys_exit_registered = 1;
63728b02 872 }
259b6cb3
MD
873 return ret;
874}
875
876/*
8a8ac9a8
FD
877 * Should be called with sessions lock held.
878 */
879int lttng_syscalls_register_event_notifier(
a67ba386 880 struct lttng_event_notifier_enabler *event_notifier_enabler)
8a8ac9a8
FD
881{
882 struct lttng_event_notifier_group *group = event_notifier_enabler->group;
883 unsigned int i;
884 int ret = 0;
885
886 wrapper_vmalloc_sync_mappings();
887
888 if (!group->event_notifier_syscall_dispatch) {
889 group->event_notifier_syscall_dispatch =
f385fc5f 890 kzalloc(sizeof(struct hlist_head) * sc_table.len,
8a8ac9a8
FD
891 GFP_KERNEL);
892 if (!group->event_notifier_syscall_dispatch)
893 return -ENOMEM;
894
895 /* Initialize all list_head */
f385fc5f 896 for (i = 0; i < sc_table.len; i++)
8a8ac9a8
FD
897 INIT_HLIST_HEAD(&group->event_notifier_syscall_dispatch[i]);
898
899 /* Init the unknown syscall notifier list. */
900 INIT_HLIST_HEAD(&group->event_notifier_unknown_syscall_dispatch);
901 }
902
903 if (!group->event_notifier_exit_syscall_dispatch) {
904 group->event_notifier_exit_syscall_dispatch =
f385fc5f 905 kzalloc(sizeof(struct hlist_head) * sc_table.len,
8a8ac9a8
FD
906 GFP_KERNEL);
907 if (!group->event_notifier_exit_syscall_dispatch)
908 return -ENOMEM;
909
910 /* Initialize all list_head */
f385fc5f 911 for (i = 0; i < sc_table.len; i++)
8a8ac9a8
FD
912 INIT_HLIST_HEAD(&group->event_notifier_exit_syscall_dispatch[i]);
913
914 /* Init the unknown exit syscall notifier list. */
915 INIT_HLIST_HEAD(&group->event_notifier_exit_unknown_syscall_dispatch);
916 }
917
918#ifdef CONFIG_COMPAT
919 if (!group->event_notifier_compat_syscall_dispatch) {
920 group->event_notifier_compat_syscall_dispatch =
f385fc5f 921 kzalloc(sizeof(struct hlist_head) * compat_sc_table.len,
8a8ac9a8
FD
922 GFP_KERNEL);
923 if (!group->event_notifier_syscall_dispatch)
924 return -ENOMEM;
925
926 /* Initialize all list_head */
f385fc5f 927 for (i = 0; i < compat_sc_table.len; i++)
8a8ac9a8
FD
928 INIT_HLIST_HEAD(&group->event_notifier_compat_syscall_dispatch[i]);
929
930 /* Init the unknown syscall notifier list. */
931 INIT_HLIST_HEAD(&group->event_notifier_compat_unknown_syscall_dispatch);
932 }
933
934 if (!group->event_notifier_exit_compat_syscall_dispatch) {
935 group->event_notifier_exit_compat_syscall_dispatch =
f385fc5f 936 kzalloc(sizeof(struct hlist_head) * compat_sc_exit_table.len,
8a8ac9a8
FD
937 GFP_KERNEL);
938 if (!group->event_notifier_exit_syscall_dispatch)
939 return -ENOMEM;
940
941 /* Initialize all list_head */
f385fc5f 942 for (i = 0; i < compat_sc_exit_table.len; i++)
8a8ac9a8
FD
943 INIT_HLIST_HEAD(&group->event_notifier_exit_compat_syscall_dispatch[i]);
944
945 /* Init the unknown exit syscall notifier list. */
946 INIT_HLIST_HEAD(&group->event_notifier_exit_compat_unknown_syscall_dispatch);
947 }
948#endif
949
950 if (!group->sc_filter) {
951 group->sc_filter = kzalloc(sizeof(struct lttng_syscall_filter),
952 GFP_KERNEL);
953 if (!group->sc_filter)
954 return -ENOMEM;
955 }
956
957 if (!group->sys_enter_registered) {
958 ret = lttng_wrapper_tracepoint_probe_register("sys_enter",
959 (void *) syscall_entry_event_notifier_probe, group);
960 if (ret)
961 return ret;
962 group->sys_enter_registered = 1;
963 }
964
965 if (!group->sys_exit_registered) {
966 ret = lttng_wrapper_tracepoint_probe_register("sys_exit",
967 (void *) syscall_exit_event_notifier_probe, group);
968 if (ret) {
969 WARN_ON_ONCE(lttng_wrapper_tracepoint_probe_unregister("sys_enter",
970 (void *) syscall_entry_event_notifier_probe, group));
971 return ret;
972 }
973 group->sys_exit_registered = 1;
974 }
975
976 return ret;
977}
978
979static
980int create_unknown_event_notifier(
981 struct lttng_event_notifier_enabler *event_notifier_enabler,
982 enum sc_type type)
983{
a67ba386
MD
984 struct lttng_kernel_event_notifier_private *event_notifier_priv;
985 struct lttng_kernel_event_notifier *event_notifier;
437d5aa5 986 const struct lttng_kernel_event_desc *desc;
8a8ac9a8 987 struct lttng_event_notifier_group *group = event_notifier_enabler->group;
606828e4 988 struct lttng_kernel_abi_event_notifier event_notifier_param;
8a8ac9a8 989 uint64_t user_token = event_notifier_enabler->base.user_token;
99f52fcc 990 uint64_t error_counter_index = event_notifier_enabler->error_counter_index;
8a8ac9a8
FD
991 struct lttng_enabler *base_enabler = lttng_event_notifier_enabler_as_enabler(
992 event_notifier_enabler);
993 struct hlist_head *unknown_dispatch_list;
994 int ret = 0;
995 bool found = false;
606828e4
MD
996 enum lttng_kernel_abi_syscall_abi abi;
997 enum lttng_kernel_abi_syscall_entryexit entryexit;
8a8ac9a8
FD
998 struct hlist_head *head;
999
1000 switch (type) {
1001 case SC_TYPE_ENTRY:
1002 desc = &__event_desc___syscall_entry_unknown;
1003 unknown_dispatch_list = &group->event_notifier_unknown_syscall_dispatch;
606828e4
MD
1004 entryexit = LTTNG_KERNEL_ABI_SYSCALL_ENTRY;
1005 abi = LTTNG_KERNEL_ABI_SYSCALL_ABI_NATIVE;
8a8ac9a8
FD
1006 break;
1007 case SC_TYPE_EXIT:
1008 desc = &__event_desc___syscall_exit_unknown;
1009 unknown_dispatch_list = &group->event_notifier_exit_unknown_syscall_dispatch;
606828e4
MD
1010 entryexit = LTTNG_KERNEL_ABI_SYSCALL_EXIT;
1011 abi = LTTNG_KERNEL_ABI_SYSCALL_ABI_NATIVE;
8a8ac9a8
FD
1012 break;
1013 case SC_TYPE_COMPAT_ENTRY:
1014 desc = &__event_desc___compat_syscall_entry_unknown;
1015 unknown_dispatch_list = &group->event_notifier_compat_unknown_syscall_dispatch;
606828e4
MD
1016 entryexit = LTTNG_KERNEL_ABI_SYSCALL_ENTRY;
1017 abi = LTTNG_KERNEL_ABI_SYSCALL_ABI_COMPAT;
8a8ac9a8
FD
1018 break;
1019 case SC_TYPE_COMPAT_EXIT:
1020 desc = &__event_desc___compat_syscall_exit_unknown;
1021 unknown_dispatch_list = &group->event_notifier_exit_compat_unknown_syscall_dispatch;
606828e4
MD
1022 entryexit = LTTNG_KERNEL_ABI_SYSCALL_EXIT;
1023 abi = LTTNG_KERNEL_ABI_SYSCALL_ABI_COMPAT;
8a8ac9a8
FD
1024 break;
1025 default:
1026 BUG_ON(1);
1027 }
1028
1029 /*
1030 * Check if already created.
1031 */
1032 head = utils_borrow_hash_table_bucket(group->event_notifiers_ht.table,
437d5aa5 1033 LTTNG_EVENT_NOTIFIER_HT_SIZE, desc->event_name);
a67ba386
MD
1034 lttng_hlist_for_each_entry(event_notifier_priv, head, hlist) {
1035 if (event_notifier_priv->parent.desc == desc &&
1036 event_notifier_priv->parent.user_token == base_enabler->user_token)
8a8ac9a8
FD
1037 found = true;
1038 }
1039 if (found)
1040 goto end;
1041
1042 memset(&event_notifier_param, 0, sizeof(event_notifier_param));
437d5aa5 1043 strncat(event_notifier_param.event.name, desc->event_name,
606828e4 1044 LTTNG_KERNEL_ABI_SYM_NAME_LEN - strlen(event_notifier_param.event.name) - 1);
8a8ac9a8 1045
606828e4 1046 event_notifier_param.event.name[LTTNG_KERNEL_ABI_SYM_NAME_LEN - 1] = '\0';
8a8ac9a8 1047
606828e4 1048 event_notifier_param.event.instrumentation = LTTNG_KERNEL_ABI_SYSCALL;
8a8ac9a8
FD
1049 event_notifier_param.event.u.syscall.abi = abi;
1050 event_notifier_param.event.u.syscall.entryexit = entryexit;
1051
a67ba386
MD
1052 event_notifier = _lttng_event_notifier_create(desc, user_token,
1053 error_counter_index, group, &event_notifier_param,
8a8ac9a8 1054 event_notifier_param.event.instrumentation);
a67ba386 1055 if (IS_ERR(event_notifier)) {
8a8ac9a8 1056 printk(KERN_INFO "Unable to create unknown notifier %s\n",
437d5aa5 1057 desc->event_name);
8a8ac9a8
FD
1058 ret = -ENOMEM;
1059 goto end;
1060 }
1061
a67ba386 1062 hlist_add_head_rcu(&event_notifier->priv->parent.u.syscall.node, unknown_dispatch_list);
8a8ac9a8
FD
1063
1064end:
1065 return ret;
1066}
1067
1068static int create_matching_event_notifiers(
1069 struct lttng_event_notifier_enabler *event_notifier_enabler,
a67ba386 1070 const struct trace_syscall_entry *table,
8a8ac9a8
FD
1071 size_t table_len, enum sc_type type)
1072{
1073 struct lttng_event_notifier_group *group = event_notifier_enabler->group;
437d5aa5 1074 const struct lttng_kernel_event_desc *desc;
8a8ac9a8 1075 uint64_t user_token = event_notifier_enabler->base.user_token;
99f52fcc 1076 uint64_t error_counter_index = event_notifier_enabler->error_counter_index;
8a8ac9a8
FD
1077 unsigned int i;
1078 int ret = 0;
1079
1080 /* iterate over all syscall and create event_notifier that match */
1081 for (i = 0; i < table_len; i++) {
a67ba386
MD
1082 struct lttng_kernel_event_notifier_private *event_notifier_priv;
1083 struct lttng_kernel_event_notifier *event_notifier;
606828e4 1084 struct lttng_kernel_abi_event_notifier event_notifier_param;
8a8ac9a8
FD
1085 struct hlist_head *head;
1086 int found = 0;
1087
1088 desc = table[i].desc;
1089 if (!desc) {
1090 /* Unknown syscall */
1091 continue;
1092 }
1093
1094 if (!lttng_desc_match_enabler(desc,
1095 lttng_event_notifier_enabler_as_enabler(event_notifier_enabler)))
1096 continue;
1097
1098 /*
1099 * Check if already created.
1100 */
1101 head = utils_borrow_hash_table_bucket(group->event_notifiers_ht.table,
437d5aa5 1102 LTTNG_EVENT_NOTIFIER_HT_SIZE, desc->event_name);
a67ba386
MD
1103 lttng_hlist_for_each_entry(event_notifier_priv, head, hlist) {
1104 if (event_notifier_priv->parent.desc == desc
1105 && event_notifier_priv->parent.user_token == event_notifier_enabler->base.user_token)
8a8ac9a8
FD
1106 found = 1;
1107 }
1108 if (found)
1109 continue;
1110
1111 memset(&event_notifier_param, 0, sizeof(event_notifier_param));
1112 switch (type) {
1113 case SC_TYPE_ENTRY:
606828e4
MD
1114 event_notifier_param.event.u.syscall.entryexit = LTTNG_KERNEL_ABI_SYSCALL_ENTRY;
1115 event_notifier_param.event.u.syscall.abi = LTTNG_KERNEL_ABI_SYSCALL_ABI_NATIVE;
8a8ac9a8
FD
1116 break;
1117 case SC_TYPE_EXIT:
606828e4
MD
1118 event_notifier_param.event.u.syscall.entryexit = LTTNG_KERNEL_ABI_SYSCALL_EXIT;
1119 event_notifier_param.event.u.syscall.abi = LTTNG_KERNEL_ABI_SYSCALL_ABI_NATIVE;
8a8ac9a8
FD
1120 break;
1121 case SC_TYPE_COMPAT_ENTRY:
606828e4
MD
1122 event_notifier_param.event.u.syscall.entryexit = LTTNG_KERNEL_ABI_SYSCALL_ENTRY;
1123 event_notifier_param.event.u.syscall.abi = LTTNG_KERNEL_ABI_SYSCALL_ABI_COMPAT;
8a8ac9a8
FD
1124 break;
1125 case SC_TYPE_COMPAT_EXIT:
606828e4
MD
1126 event_notifier_param.event.u.syscall.entryexit = LTTNG_KERNEL_ABI_SYSCALL_EXIT;
1127 event_notifier_param.event.u.syscall.abi = LTTNG_KERNEL_ABI_SYSCALL_ABI_COMPAT;
8a8ac9a8
FD
1128 break;
1129 }
437d5aa5 1130 strncat(event_notifier_param.event.name, desc->event_name,
606828e4
MD
1131 LTTNG_KERNEL_ABI_SYM_NAME_LEN - strlen(event_notifier_param.event.name) - 1);
1132 event_notifier_param.event.name[LTTNG_KERNEL_ABI_SYM_NAME_LEN - 1] = '\0';
1133 event_notifier_param.event.instrumentation = LTTNG_KERNEL_ABI_SYSCALL;
8a8ac9a8 1134
99f52fcc
FD
1135 event_notifier = _lttng_event_notifier_create(desc, user_token,
1136 error_counter_index, group, &event_notifier_param,
a67ba386 1137 event_notifier_param.event.instrumentation);
8a8ac9a8
FD
1138 if (IS_ERR(event_notifier)) {
1139 printk(KERN_INFO "Unable to create event_notifier %s\n",
437d5aa5 1140 desc->event_name);
8a8ac9a8
FD
1141 ret = -ENOMEM;
1142 goto end;
1143 }
1144
a67ba386 1145 event_notifier->priv->parent.u.syscall.syscall_id = i;
8a8ac9a8
FD
1146 }
1147
1148end:
1149 return ret;
1150
1151}
1152
a67ba386
MD
1153int lttng_syscalls_create_matching_event_notifiers(
1154 struct lttng_event_notifier_enabler *event_notifier_enabler)
8a8ac9a8
FD
1155{
1156 int ret;
1157 struct lttng_enabler *base_enabler =
1158 lttng_event_notifier_enabler_as_enabler(event_notifier_enabler);
606828e4 1159 enum lttng_kernel_abi_syscall_entryexit entryexit =
8a8ac9a8
FD
1160 base_enabler->event_param.u.syscall.entryexit;
1161
606828e4 1162 if (entryexit == LTTNG_KERNEL_ABI_SYSCALL_ENTRY || entryexit == LTTNG_KERNEL_ABI_SYSCALL_ENTRYEXIT) {
8a8ac9a8 1163 ret = create_matching_event_notifiers(event_notifier_enabler,
f385fc5f 1164 sc_table.table, sc_table.len, SC_TYPE_ENTRY);
8a8ac9a8
FD
1165 if (ret)
1166 goto end;
1167
1168 ret = create_matching_event_notifiers(event_notifier_enabler,
f385fc5f 1169 compat_sc_table.table, compat_sc_table.len,
8a8ac9a8
FD
1170 SC_TYPE_COMPAT_ENTRY);
1171 if (ret)
1172 goto end;
1173
1174 ret = create_unknown_event_notifier(event_notifier_enabler,
1175 SC_TYPE_ENTRY);
1176 if (ret)
1177 goto end;
1178
1179 ret = create_unknown_event_notifier(event_notifier_enabler,
1180 SC_TYPE_COMPAT_ENTRY);
1181 if (ret)
1182 goto end;
1183 }
1184
606828e4 1185 if (entryexit == LTTNG_KERNEL_ABI_SYSCALL_EXIT || entryexit == LTTNG_KERNEL_ABI_SYSCALL_ENTRYEXIT) {
8a8ac9a8 1186 ret = create_matching_event_notifiers(event_notifier_enabler,
f385fc5f 1187 sc_exit_table.table, sc_exit_table.len,
8a8ac9a8
FD
1188 SC_TYPE_EXIT);
1189 if (ret)
1190 goto end;
1191
1192 ret = create_unknown_event_notifier(event_notifier_enabler,
1193 SC_TYPE_EXIT);
1194 if (ret)
1195 goto end;
1196
1197 ret = create_matching_event_notifiers(event_notifier_enabler,
f385fc5f 1198 compat_sc_exit_table.table, compat_sc_exit_table.len,
8a8ac9a8
FD
1199 SC_TYPE_COMPAT_EXIT);
1200 if (ret)
1201 goto end;
1202
1203 ret = create_unknown_event_notifier(event_notifier_enabler,
1204 SC_TYPE_COMPAT_EXIT);
1205 if (ret)
1206 goto end;
1207 }
1208
1209end:
1210 return ret;
1211}
1212
1213/*
1214 * Unregister the syscall event_notifier probes from the callsites.
259b6cb3 1215 */
3b82c4e1 1216int lttng_syscalls_unregister_event_notifier_group(
8a8ac9a8
FD
1217 struct lttng_event_notifier_group *event_notifier_group)
1218{
1219 int ret;
1220
1221 /*
1222 * Only register the event_notifier probe on the `sys_enter` callsite for now.
1223 * At the moment, we don't think it's desirable to have one fired
1224 * event_notifier for the entry and one for the exit of a syscall.
1225 */
1226 if (event_notifier_group->sys_enter_registered) {
1227 ret = lttng_wrapper_tracepoint_probe_unregister("sys_enter",
1228 (void *) syscall_entry_event_notifier_probe, event_notifier_group);
1229 if (ret)
1230 return ret;
1231 event_notifier_group->sys_enter_registered = 0;
1232 }
1233 if (event_notifier_group->sys_exit_registered) {
1234 ret = lttng_wrapper_tracepoint_probe_unregister("sys_exit",
1235 (void *) syscall_exit_event_notifier_probe, event_notifier_group);
1236 if (ret)
1237 return ret;
1238 event_notifier_group->sys_enter_registered = 0;
1239 }
1240
1241 kfree(event_notifier_group->event_notifier_syscall_dispatch);
1242 kfree(event_notifier_group->event_notifier_exit_syscall_dispatch);
1243#ifdef CONFIG_COMPAT
1244 kfree(event_notifier_group->event_notifier_compat_syscall_dispatch);
1245 kfree(event_notifier_group->event_notifier_exit_compat_syscall_dispatch);
1246#endif
1247 return 0;
1248}
1249
ac847066 1250int lttng_syscalls_unregister_channel(struct lttng_kernel_channel_buffer *chan)
259b6cb3
MD
1251{
1252 int ret;
1253
ac847066 1254 if (!chan->priv->parent.sc_table)
259b6cb3 1255 return 0;
ac847066 1256 if (chan->priv->parent.sys_enter_registered) {
2d9cd7f3 1257 ret = lttng_wrapper_tracepoint_probe_unregister("sys_enter",
2d6d88c6 1258 (void *) syscall_entry_event_probe, chan);
80f87dd2
MD
1259 if (ret)
1260 return ret;
ac847066 1261 chan->priv->parent.sys_enter_registered = 0;
80f87dd2 1262 }
ac847066 1263 if (chan->priv->parent.sys_exit_registered) {
2d9cd7f3 1264 ret = lttng_wrapper_tracepoint_probe_unregister("sys_exit",
2d6d88c6 1265 (void *) syscall_exit_event_probe, chan);
80f87dd2
MD
1266 if (ret)
1267 return ret;
ac847066 1268 chan->priv->parent.sys_exit_registered = 0;
80f87dd2 1269 }
badfe9f5
MD
1270 return 0;
1271}
1272
ac847066 1273int lttng_syscalls_destroy_event(struct lttng_kernel_channel_buffer *chan)
badfe9f5 1274{
ac847066
MD
1275 kfree(chan->priv->parent.sc_table);
1276 kfree(chan->priv->parent.sc_exit_table);
49c50022 1277#ifdef CONFIG_COMPAT
ac847066
MD
1278 kfree(chan->priv->parent.compat_sc_table);
1279 kfree(chan->priv->parent.compat_sc_exit_table);
49c50022 1280#endif
ac847066 1281 kfree(chan->priv->parent.sc_filter);
80f87dd2
MD
1282 return 0;
1283}
1284
1285static
1286int get_syscall_nr(const char *syscall_name)
1287{
1288 int syscall_nr = -1;
1289 int i;
1290
f385fc5f 1291 for (i = 0; i < sc_table.len; i++) {
80f87dd2 1292 const struct trace_syscall_entry *entry;
5b7ac358 1293 const char *it_name;
80f87dd2 1294
f385fc5f 1295 entry = &sc_table.table[i];
80f87dd2
MD
1296 if (!entry->desc)
1297 continue;
437d5aa5 1298 it_name = entry->desc->event_name;
5b7ac358
MD
1299 it_name += strlen(SYSCALL_ENTRY_STR);
1300 if (!strcmp(syscall_name, it_name)) {
80f87dd2
MD
1301 syscall_nr = i;
1302 break;
1303 }
1304 }
1305 return syscall_nr;
1306}
1307
1308static
1309int get_compat_syscall_nr(const char *syscall_name)
1310{
1311 int syscall_nr = -1;
1312 int i;
1313
f385fc5f 1314 for (i = 0; i < compat_sc_table.len; i++) {
80f87dd2 1315 const struct trace_syscall_entry *entry;
5b7ac358 1316 const char *it_name;
80f87dd2 1317
f385fc5f 1318 entry = &compat_sc_table.table[i];
80f87dd2
MD
1319 if (!entry->desc)
1320 continue;
437d5aa5 1321 it_name = entry->desc->event_name;
5b7ac358
MD
1322 it_name += strlen(COMPAT_SYSCALL_ENTRY_STR);
1323 if (!strcmp(syscall_name, it_name)) {
80f87dd2
MD
1324 syscall_nr = i;
1325 break;
1326 }
1327 }
1328 return syscall_nr;
1329}
1330
12e579db
MD
1331static
1332uint32_t get_sc_tables_len(void)
1333{
f385fc5f 1334 return sc_table.len + compat_sc_table.len;
12e579db
MD
1335}
1336
badfe9f5 1337static
ade8a729
FD
1338const char *get_syscall_name(const char *desc_name,
1339 enum lttng_syscall_abi abi,
1340 enum lttng_syscall_entryexit entryexit)
80f87dd2 1341{
badfe9f5 1342 size_t prefix_len = 0;
80f87dd2 1343
80f87dd2 1344
ade8a729 1345 switch (entryexit) {
badfe9f5 1346 case LTTNG_SYSCALL_ENTRY:
ade8a729 1347 switch (abi) {
badfe9f5
MD
1348 case LTTNG_SYSCALL_ABI_NATIVE:
1349 prefix_len = strlen(SYSCALL_ENTRY_STR);
1350 break;
1351 case LTTNG_SYSCALL_ABI_COMPAT:
1352 prefix_len = strlen(COMPAT_SYSCALL_ENTRY_STR);
1353 break;
80f87dd2 1354 }
badfe9f5
MD
1355 break;
1356 case LTTNG_SYSCALL_EXIT:
ade8a729 1357 switch (abi) {
badfe9f5
MD
1358 case LTTNG_SYSCALL_ABI_NATIVE:
1359 prefix_len = strlen(SYSCALL_EXIT_STR);
1360 break;
1361 case LTTNG_SYSCALL_ABI_COMPAT:
1362 prefix_len = strlen(COMPAT_SYSCALL_EXIT_STR);
1363 break;
80f87dd2 1364 }
badfe9f5 1365 break;
80f87dd2 1366 }
badfe9f5 1367 WARN_ON_ONCE(prefix_len == 0);
ade8a729 1368 return desc_name + prefix_len;
badfe9f5
MD
1369}
1370
ade8a729
FD
1371static
1372int lttng_syscall_filter_enable(
1373 struct lttng_syscall_filter *filter,
1374 const char *desc_name, enum lttng_syscall_abi abi,
1375 enum lttng_syscall_entryexit entryexit)
badfe9f5 1376{
badfe9f5
MD
1377 const char *syscall_name;
1378 unsigned long *bitmap;
4fabf854 1379 u32 *refcount_map;
badfe9f5
MD
1380 int syscall_nr;
1381
ade8a729 1382 syscall_name = get_syscall_name(desc_name, abi, entryexit);
badfe9f5 1383
ade8a729 1384 switch (abi) {
badfe9f5
MD
1385 case LTTNG_SYSCALL_ABI_NATIVE:
1386 syscall_nr = get_syscall_nr(syscall_name);
1387 break;
1388 case LTTNG_SYSCALL_ABI_COMPAT:
1389 syscall_nr = get_compat_syscall_nr(syscall_name);
1390 break;
1391 default:
1392 return -EINVAL;
80f87dd2 1393 }
badfe9f5
MD
1394 if (syscall_nr < 0)
1395 return -ENOENT;
1396
ade8a729 1397 switch (entryexit) {
badfe9f5 1398 case LTTNG_SYSCALL_ENTRY:
ade8a729 1399 switch (abi) {
badfe9f5
MD
1400 case LTTNG_SYSCALL_ABI_NATIVE:
1401 bitmap = filter->sc_entry;
4fabf854 1402 refcount_map = filter->sc_entry_refcount_map;
badfe9f5
MD
1403 break;
1404 case LTTNG_SYSCALL_ABI_COMPAT:
1405 bitmap = filter->sc_compat_entry;
4fabf854 1406 refcount_map = filter->sc_compat_entry_refcount_map;
badfe9f5 1407 break;
6d9694d8
MD
1408 default:
1409 return -EINVAL;
80f87dd2 1410 }
badfe9f5
MD
1411 break;
1412 case LTTNG_SYSCALL_EXIT:
ade8a729 1413 switch (abi) {
badfe9f5
MD
1414 case LTTNG_SYSCALL_ABI_NATIVE:
1415 bitmap = filter->sc_exit;
4fabf854 1416 refcount_map = filter->sc_exit_refcount_map;
badfe9f5
MD
1417 break;
1418 case LTTNG_SYSCALL_ABI_COMPAT:
1419 bitmap = filter->sc_compat_exit;
4fabf854 1420 refcount_map = filter->sc_compat_exit_refcount_map;
badfe9f5 1421 break;
6d9694d8
MD
1422 default:
1423 return -EINVAL;
80f87dd2 1424 }
badfe9f5
MD
1425 break;
1426 default:
1427 return -EINVAL;
80f87dd2 1428 }
4fabf854
MD
1429 if (refcount_map[syscall_nr] == U32_MAX)
1430 return -EOVERFLOW;
1431 if (refcount_map[syscall_nr]++ == 0)
1432 bitmap_set(bitmap, syscall_nr, 1);
80f87dd2 1433 return 0;
80f87dd2
MD
1434}
1435
8a8ac9a8 1436int lttng_syscall_filter_enable_event_notifier(
a67ba386 1437 struct lttng_kernel_event_notifier *event_notifier)
8a8ac9a8 1438{
a67ba386
MD
1439 struct lttng_event_notifier_group *group = event_notifier->priv->group;
1440 unsigned int syscall_id = event_notifier->priv->parent.u.syscall.syscall_id;
8a8ac9a8
FD
1441 struct hlist_head *dispatch_list;
1442 int ret = 0;
1443
a67ba386 1444 WARN_ON_ONCE(event_notifier->priv->parent.instrumentation != LTTNG_KERNEL_ABI_SYSCALL);
8a8ac9a8 1445
4fabf854
MD
1446 /* Skip unknown syscall */
1447 if (syscall_id == -1U)
1448 return 0;
1449
8a8ac9a8 1450 ret = lttng_syscall_filter_enable(group->sc_filter,
a67ba386
MD
1451 event_notifier->priv->parent.desc->event_name,
1452 event_notifier->priv->parent.u.syscall.abi,
1453 event_notifier->priv->parent.u.syscall.entryexit);
4fabf854
MD
1454 if (ret)
1455 return ret;
8a8ac9a8 1456
a67ba386 1457 switch (event_notifier->priv->parent.u.syscall.entryexit) {
8a8ac9a8 1458 case LTTNG_SYSCALL_ENTRY:
a67ba386 1459 switch (event_notifier->priv->parent.u.syscall.abi) {
8a8ac9a8
FD
1460 case LTTNG_SYSCALL_ABI_NATIVE:
1461 dispatch_list = &group->event_notifier_syscall_dispatch[syscall_id];
1462 break;
1463 case LTTNG_SYSCALL_ABI_COMPAT:
1464 dispatch_list = &group->event_notifier_compat_syscall_dispatch[syscall_id];
1465 break;
6866b1c7
MJ
1466 default:
1467 ret = -EINVAL;
1468 goto end;
8a8ac9a8
FD
1469 }
1470 break;
1471 case LTTNG_SYSCALL_EXIT:
a67ba386 1472 switch (event_notifier->priv->parent.u.syscall.abi) {
8a8ac9a8
FD
1473 case LTTNG_SYSCALL_ABI_NATIVE:
1474 dispatch_list = &group->event_notifier_exit_syscall_dispatch[syscall_id];
1475 break;
1476 case LTTNG_SYSCALL_ABI_COMPAT:
1477 dispatch_list = &group->event_notifier_exit_compat_syscall_dispatch[syscall_id];
1478 break;
6866b1c7
MJ
1479 default:
1480 ret = -EINVAL;
1481 goto end;
8a8ac9a8
FD
1482 }
1483 break;
6866b1c7
MJ
1484 default:
1485 ret = -EINVAL;
1486 goto end;
8a8ac9a8
FD
1487 }
1488
a67ba386 1489 hlist_add_head_rcu(&event_notifier->priv->parent.u.syscall.node, dispatch_list);
8a8ac9a8
FD
1490
1491end:
4fabf854 1492 return ret;
8a8ac9a8
FD
1493}
1494
ade8a729 1495int lttng_syscall_filter_enable_event(
ac847066 1496 struct lttng_kernel_channel_buffer *channel,
a67ba386 1497 struct lttng_kernel_event_recorder *event_recorder)
80f87dd2 1498{
4fabf854
MD
1499 unsigned int syscall_id = event_recorder->priv->parent.u.syscall.syscall_id;
1500
a67ba386 1501 WARN_ON_ONCE(event_recorder->priv->parent.instrumentation != LTTNG_KERNEL_ABI_SYSCALL);
ade8a729 1502
4fabf854
MD
1503 /* Skip unknown syscall */
1504 if (syscall_id == -1U)
1505 return 0;
1506
ac847066 1507 return lttng_syscall_filter_enable(channel->priv->parent.sc_filter,
a67ba386
MD
1508 event_recorder->priv->parent.desc->event_name,
1509 event_recorder->priv->parent.u.syscall.abi,
1510 event_recorder->priv->parent.u.syscall.entryexit);
ade8a729
FD
1511}
1512
1513static
1514int lttng_syscall_filter_disable(
1515 struct lttng_syscall_filter *filter,
1516 const char *desc_name, enum lttng_syscall_abi abi,
1517 enum lttng_syscall_entryexit entryexit)
1518{
badfe9f5
MD
1519 const char *syscall_name;
1520 unsigned long *bitmap;
4fabf854 1521 u32 *refcount_map;
badfe9f5 1522 int syscall_nr;
80f87dd2 1523
ade8a729 1524 syscall_name = get_syscall_name(desc_name, abi, entryexit);
80f87dd2 1525
ade8a729 1526 switch (abi) {
badfe9f5
MD
1527 case LTTNG_SYSCALL_ABI_NATIVE:
1528 syscall_nr = get_syscall_nr(syscall_name);
1529 break;
1530 case LTTNG_SYSCALL_ABI_COMPAT:
1531 syscall_nr = get_compat_syscall_nr(syscall_name);
1532 break;
1533 default:
1534 return -EINVAL;
80f87dd2 1535 }
badfe9f5
MD
1536 if (syscall_nr < 0)
1537 return -ENOENT;
80f87dd2 1538
ade8a729 1539 switch (entryexit) {
badfe9f5 1540 case LTTNG_SYSCALL_ENTRY:
ade8a729 1541 switch (abi) {
badfe9f5
MD
1542 case LTTNG_SYSCALL_ABI_NATIVE:
1543 bitmap = filter->sc_entry;
4fabf854 1544 refcount_map = filter->sc_entry_refcount_map;
badfe9f5
MD
1545 break;
1546 case LTTNG_SYSCALL_ABI_COMPAT:
1547 bitmap = filter->sc_compat_entry;
4fabf854 1548 refcount_map = filter->sc_compat_entry_refcount_map;
badfe9f5 1549 break;
6d9694d8
MD
1550 default:
1551 return -EINVAL;
80f87dd2 1552 }
badfe9f5
MD
1553 break;
1554 case LTTNG_SYSCALL_EXIT:
ade8a729 1555 switch (abi) {
badfe9f5
MD
1556 case LTTNG_SYSCALL_ABI_NATIVE:
1557 bitmap = filter->sc_exit;
4fabf854 1558 refcount_map = filter->sc_exit_refcount_map;
badfe9f5
MD
1559 break;
1560 case LTTNG_SYSCALL_ABI_COMPAT:
1561 bitmap = filter->sc_compat_exit;
4fabf854 1562 refcount_map = filter->sc_compat_exit_refcount_map;
badfe9f5 1563 break;
6d9694d8
MD
1564 default:
1565 return -EINVAL;
80f87dd2 1566 }
badfe9f5
MD
1567 break;
1568 default:
1569 return -EINVAL;
80f87dd2 1570 }
4fabf854
MD
1571 if (refcount_map[syscall_nr] == 0)
1572 return -ENOENT;
1573 if (--refcount_map[syscall_nr] == 0)
1574 bitmap_clear(bitmap, syscall_nr, 1);
badfe9f5 1575 return 0;
259b6cb3 1576}
2d2464bd 1577
8a8ac9a8 1578int lttng_syscall_filter_disable_event_notifier(
a67ba386 1579 struct lttng_kernel_event_notifier *event_notifier)
8a8ac9a8 1580{
a67ba386 1581 struct lttng_event_notifier_group *group = event_notifier->priv->group;
4fabf854 1582 unsigned int syscall_id = event_notifier->priv->parent.u.syscall.syscall_id;
8a8ac9a8
FD
1583 int ret;
1584
a67ba386 1585 WARN_ON_ONCE(event_notifier->priv->parent.instrumentation != LTTNG_KERNEL_ABI_SYSCALL);
8a8ac9a8 1586
4fabf854
MD
1587 /* Skip unknown syscall */
1588 if (syscall_id == -1U)
1589 return 0;
1590
8a8ac9a8 1591 ret = lttng_syscall_filter_disable(group->sc_filter,
a67ba386
MD
1592 event_notifier->priv->parent.desc->event_name,
1593 event_notifier->priv->parent.u.syscall.abi,
1594 event_notifier->priv->parent.u.syscall.entryexit);
4fabf854
MD
1595 if (ret)
1596 return ret;
8a8ac9a8 1597
a67ba386 1598 hlist_del_rcu(&event_notifier->priv->parent.u.syscall.node);
8a8ac9a8
FD
1599 return 0;
1600}
1601
ade8a729 1602int lttng_syscall_filter_disable_event(
ac847066 1603 struct lttng_kernel_channel_buffer *channel,
a67ba386 1604 struct lttng_kernel_event_recorder *event_recorder)
ade8a729 1605{
4fabf854
MD
1606 unsigned int syscall_id = event_recorder->priv->parent.u.syscall.syscall_id;
1607
1608 /* Skip unknown syscall */
1609 if (syscall_id == -1U)
1610 return 0;
1611
ac847066 1612 return lttng_syscall_filter_disable(channel->priv->parent.sc_filter,
a67ba386
MD
1613 event_recorder->priv->parent.desc->event_name,
1614 event_recorder->priv->parent.u.syscall.abi,
1615 event_recorder->priv->parent.u.syscall.entryexit);
ade8a729
FD
1616}
1617
2d2464bd
MD
1618static
1619const struct trace_syscall_entry *syscall_list_get_entry(loff_t *pos)
1620{
1621 const struct trace_syscall_entry *entry;
1622 int iter = 0;
1623
f385fc5f
FD
1624 for (entry = sc_table.table;
1625 entry < sc_table.table + sc_table.len;
2d2464bd
MD
1626 entry++) {
1627 if (iter++ >= *pos)
1628 return entry;
1629 }
f385fc5f
FD
1630 for (entry = compat_sc_table.table;
1631 entry < compat_sc_table.table + compat_sc_table.len;
2d2464bd
MD
1632 entry++) {
1633 if (iter++ >= *pos)
1634 return entry;
1635 }
1636 /* End of list */
1637 return NULL;
1638}
1639
1640static
1641void *syscall_list_start(struct seq_file *m, loff_t *pos)
1642{
1643 return (void *) syscall_list_get_entry(pos);
1644}
1645
1646static
1647void *syscall_list_next(struct seq_file *m, void *p, loff_t *ppos)
1648{
1649 (*ppos)++;
1650 return (void *) syscall_list_get_entry(ppos);
1651}
1652
1653static
1654void syscall_list_stop(struct seq_file *m, void *p)
1655{
1656}
1657
12e579db
MD
1658static
1659int get_sc_table(const struct trace_syscall_entry *entry,
1660 const struct trace_syscall_entry **table,
1661 unsigned int *bitness)
1662{
f385fc5f 1663 if (entry >= sc_table.table && entry < sc_table.table + sc_table.len) {
12e579db
MD
1664 if (bitness)
1665 *bitness = BITS_PER_LONG;
1666 if (table)
f385fc5f 1667 *table = sc_table.table;
12e579db
MD
1668 return 0;
1669 }
f385fc5f
FD
1670 if (!(entry >= compat_sc_table.table
1671 && entry < compat_sc_table.table + compat_sc_table.len)) {
12e579db
MD
1672 return -EINVAL;
1673 }
1674 if (bitness)
1675 *bitness = 32;
1676 if (table)
f385fc5f 1677 *table = compat_sc_table.table;
12e579db
MD
1678 return 0;
1679}
1680
2d2464bd
MD
1681static
1682int syscall_list_show(struct seq_file *m, void *p)
1683{
1684 const struct trace_syscall_entry *table, *entry = p;
1685 unsigned int bitness;
d4291869 1686 unsigned long index;
12e579db 1687 int ret;
d4291869 1688 const char *name;
2d2464bd 1689
12e579db
MD
1690 ret = get_sc_table(entry, &table, &bitness);
1691 if (ret)
1692 return ret;
f4855b46
MD
1693 if (!entry->desc)
1694 return 0;
f385fc5f 1695 if (table == sc_table.table) {
d4291869 1696 index = entry - table;
437d5aa5 1697 name = &entry->desc->event_name[strlen(SYSCALL_ENTRY_STR)];
d4291869 1698 } else {
f385fc5f 1699 index = (entry - table) + sc_table.len;
437d5aa5 1700 name = &entry->desc->event_name[strlen(COMPAT_SYSCALL_ENTRY_STR)];
d4291869 1701 }
12e579db 1702 seq_printf(m, "syscall { index = %lu; name = %s; bitness = %u; };\n",
d4291869 1703 index, name, bitness);
2d2464bd
MD
1704 return 0;
1705}
1706
1707static
1708const struct seq_operations lttng_syscall_list_seq_ops = {
1709 .start = syscall_list_start,
1710 .next = syscall_list_next,
1711 .stop = syscall_list_stop,
1712 .show = syscall_list_show,
1713};
1714
1715static
1716int lttng_syscall_list_open(struct inode *inode, struct file *file)
1717{
1718 return seq_open(file, &lttng_syscall_list_seq_ops);
1719}
1720
1721const struct file_operations lttng_syscall_list_fops = {
1722 .owner = THIS_MODULE,
1723 .open = lttng_syscall_list_open,
1724 .read = seq_read,
1725 .llseek = seq_lseek,
1726 .release = seq_release,
1727};
12e579db 1728
badfe9f5
MD
1729/*
1730 * A syscall is enabled if it is traced for either entry or exit.
1731 */
ac847066 1732long lttng_channel_syscall_mask(struct lttng_kernel_channel_buffer *channel,
606828e4 1733 struct lttng_kernel_abi_syscall_mask __user *usyscall_mask)
12e579db
MD
1734{
1735 uint32_t len, sc_tables_len, bitmask_len;
1736 int ret = 0, bit;
1737 char *tmp_mask;
1738 struct lttng_syscall_filter *filter;
1739
1740 ret = get_user(len, &usyscall_mask->len);
1741 if (ret)
1742 return ret;
1743 sc_tables_len = get_sc_tables_len();
1744 bitmask_len = ALIGN(sc_tables_len, 8) >> 3;
1745 if (len < sc_tables_len) {
1746 return put_user(sc_tables_len, &usyscall_mask->len);
1747 }
1748 /* Array is large enough, we can copy array to user-space. */
1749 tmp_mask = kzalloc(bitmask_len, GFP_KERNEL);
1750 if (!tmp_mask)
1751 return -ENOMEM;
ac847066 1752 filter = channel->priv->parent.sc_filter;
12e579db 1753
f385fc5f 1754 for (bit = 0; bit < sc_table.len; bit++) {
e2129868 1755 char state;
2f25059d 1756
ac847066
MD
1757 if (channel->priv->parent.sc_table) {
1758 if (!(READ_ONCE(channel->priv->parent.syscall_all_entry)
1759 || READ_ONCE(channel->priv->parent.syscall_all_exit)) && filter)
badfe9f5
MD
1760 state = test_bit(bit, filter->sc_entry)
1761 || test_bit(bit, filter->sc_exit);
2f25059d
MD
1762 else
1763 state = 1;
1764 } else {
1765 state = 0;
1766 }
1767 bt_bitfield_write_be(tmp_mask, char, bit, 1, state);
12e579db
MD
1768 }
1769 for (; bit < sc_tables_len; bit++) {
e2129868 1770 char state;
2f25059d 1771
ac847066
MD
1772 if (channel->priv->parent.compat_sc_table) {
1773 if (!(READ_ONCE(channel->priv->parent.syscall_all_entry)
1774 || READ_ONCE(channel->priv->parent.syscall_all_exit)) && filter)
f385fc5f 1775 state = test_bit(bit - sc_table.len,
badfe9f5 1776 filter->sc_compat_entry)
f385fc5f 1777 || test_bit(bit - sc_table.len,
badfe9f5 1778 filter->sc_compat_exit);
2f25059d
MD
1779 else
1780 state = 1;
1781 } else {
1782 state = 0;
1783 }
1784 bt_bitfield_write_be(tmp_mask, char, bit, 1, state);
12e579db
MD
1785 }
1786 if (copy_to_user(usyscall_mask->mask, tmp_mask, bitmask_len))
1787 ret = -EFAULT;
1788 kfree(tmp_mask);
1789 return ret;
1790}
082d4946
MD
1791
1792int lttng_abi_syscall_list(void)
1793{
1794 struct file *syscall_list_file;
1795 int file_fd, ret;
1796
4ac10b76 1797 file_fd = lttng_get_unused_fd();
082d4946
MD
1798 if (file_fd < 0) {
1799 ret = file_fd;
1800 goto fd_error;
1801 }
1802
1803 syscall_list_file = anon_inode_getfile("[lttng_syscall_list]",
1804 &lttng_syscall_list_fops,
1805 NULL, O_RDWR);
1806 if (IS_ERR(syscall_list_file)) {
1807 ret = PTR_ERR(syscall_list_file);
1808 goto file_error;
1809 }
1810 ret = lttng_syscall_list_fops.open(NULL, syscall_list_file);
1811 if (ret < 0)
1812 goto open_error;
1813 fd_install(file_fd, syscall_list_file);
082d4946
MD
1814 return file_fd;
1815
1816open_error:
1817 fput(syscall_list_file);
1818file_error:
1819 put_unused_fd(file_fd);
1820fd_error:
1821 return ret;
1822}
This page took 0.156837 seconds and 4 git commands to generate.