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