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