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