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