Split syscall tracepoint generation in their own files
[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{
259 struct lttng_channel *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())) {
265 struct lttng_syscall_filter *filter = chan->sc_filter;
266
267 if (id < 0 || id >= NR_compat_syscalls
3b82c4e1 268 || (!READ_ONCE(chan->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;
3b82c4e1 274 unknown_action_list = &chan->sc_compat_unknown;
63aa9160
FD
275 } else {
276 struct lttng_syscall_filter *filter = chan->sc_filter;
277
278 if (id < 0 || id >= NR_syscalls
3b82c4e1 279 || (!READ_ONCE(chan->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;
3b82c4e1 285 unknown_action_list = &chan->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())) {
299 action_list = &chan->compat_sc_table[id];
300 } else {
301 action_list = &chan->sc_table[id];
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{
495 struct lttng_channel *chan = __data;
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())) {
504 struct lttng_syscall_filter *filter = chan->sc_filter;
505
506 if (id < 0 || id >= NR_compat_syscalls
507 || (!READ_ONCE(chan->syscall_all_exit) && !test_bit(id, filter->sc_compat_exit))) {
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;
3b82c4e1
MD
513 unknown_action_list = &chan->compat_sc_exit_unknown;
514 } else {
515 struct lttng_syscall_filter *filter = chan->sc_filter;
516
517 if (id < 0 || id >= NR_syscalls
518 || (!READ_ONCE(chan->syscall_all_exit) && !test_bit(id, filter->sc_exit))) {
519 /* System call filtered out. */
520 return;
521 }
ebcc64cd
FD
522 table = sc_exit_table.table;
523 table_len = sc_exit_table.len;
3b82c4e1
MD
524 unknown_action_list = &chan->sc_exit_unknown;
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())) {
538 action_list = &chan->compat_sc_exit_table[id];
539 } else {
540 action_list = &chan->sc_exit_table[id];
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
MD
615int lttng_create_syscall_event_if_missing(const struct trace_syscall_entry *table, size_t table_len,
616 struct hlist_head *chan_table, struct lttng_event_enabler *event_enabler,
a67ba386 617 enum sc_type type)
259b6cb3 618{
3b82c4e1 619 struct lttng_channel *chan = event_enabler->chan;
8cdc1a81 620 struct lttng_kernel_session *session = chan->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;
606828e4 626 struct lttng_kernel_abi_event ev;
a67ba386
MD
627 struct lttng_kernel_event_recorder_private *event_recorder_priv;
628 struct lttng_kernel_event_recorder *event_recorder;
3b82c4e1
MD
629 struct hlist_head *head;
630 bool found = false;
49c50022
MD
631
632 if (!desc) {
633 /* Unknown syscall */
634 continue;
635 }
3b82c4e1
MD
636 if (lttng_desc_match_enabler(desc,
637 lttng_event_enabler_as_enabler(event_enabler)) <= 0)
638 continue;
49c50022 639 /*
3b82c4e1 640 * Check if already created.
49c50022 641 */
3b82c4e1 642 head = utils_borrow_hash_table_bucket(
8cdc1a81 643 session->priv->events_ht.table, LTTNG_EVENT_HT_SIZE,
437d5aa5 644 desc->event_name);
a67ba386
MD
645 lttng_hlist_for_each_entry(event_recorder_priv, head, hlist) {
646 if (event_recorder_priv->parent.desc == desc
647 && event_recorder_priv->pub->chan == event_enabler->chan)
3b82c4e1
MD
648 found = true;
649 }
650 if (found)
49c50022 651 continue;
3b82c4e1
MD
652
653 /* We need to create an event for this syscall/enabler. */
49c50022 654 memset(&ev, 0, sizeof(ev));
5b7ac358
MD
655 switch (type) {
656 case SC_TYPE_ENTRY:
606828e4
MD
657 ev.u.syscall.entryexit = LTTNG_KERNEL_ABI_SYSCALL_ENTRY;
658 ev.u.syscall.abi = LTTNG_KERNEL_ABI_SYSCALL_ABI_NATIVE;
5b7ac358
MD
659 break;
660 case SC_TYPE_EXIT:
606828e4
MD
661 ev.u.syscall.entryexit = LTTNG_KERNEL_ABI_SYSCALL_EXIT;
662 ev.u.syscall.abi = LTTNG_KERNEL_ABI_SYSCALL_ABI_NATIVE;
5b7ac358
MD
663 break;
664 case SC_TYPE_COMPAT_ENTRY:
606828e4
MD
665 ev.u.syscall.entryexit = LTTNG_KERNEL_ABI_SYSCALL_ENTRY;
666 ev.u.syscall.abi = LTTNG_KERNEL_ABI_SYSCALL_ABI_COMPAT;
5b7ac358
MD
667 break;
668 case SC_TYPE_COMPAT_EXIT:
606828e4
MD
669 ev.u.syscall.entryexit = LTTNG_KERNEL_ABI_SYSCALL_EXIT;
670 ev.u.syscall.abi = LTTNG_KERNEL_ABI_SYSCALL_ABI_COMPAT;
5b7ac358
MD
671 break;
672 }
606828e4
MD
673 strncpy(ev.name, desc->event_name, LTTNG_KERNEL_ABI_SYM_NAME_LEN - 1);
674 ev.name[LTTNG_KERNEL_ABI_SYM_NAME_LEN - 1] = '\0';
675 ev.instrumentation = LTTNG_KERNEL_ABI_SYSCALL;
a67ba386
MD
676 event_recorder = _lttng_kernel_event_recorder_create(chan, &ev, desc, ev.instrumentation);
677 WARN_ON_ONCE(!event_recorder);
678 if (IS_ERR(event_recorder)) {
49c50022
MD
679 /*
680 * If something goes wrong in event registration
681 * after the first one, we have no choice but to
682 * leave the previous events in there, until
683 * deleted by session teardown.
684 */
a67ba386 685 return PTR_ERR(event_recorder);
49c50022 686 }
a67ba386 687 hlist_add_head(&event_recorder->priv->parent.u.syscall.node, &chan_table[i]);
49c50022
MD
688 }
689 return 0;
690}
691
33a39a3c
MD
692/*
693 * Should be called with sessions lock held.
694 */
a67ba386 695int lttng_syscalls_register_event(struct lttng_event_enabler *event_enabler)
49c50022 696{
3b82c4e1 697 struct lttng_channel *chan = event_enabler->chan;
606828e4 698 struct lttng_kernel_abi_event ev;
259b6cb3
MD
699 int ret;
700
263b6c88 701 wrapper_vmalloc_sync_mappings();
259b6cb3
MD
702
703 if (!chan->sc_table) {
704 /* create syscall table mapping syscall to events */
a67ba386 705 chan->sc_table = kzalloc(sizeof(struct lttng_kernel_event_recorder *)
ebcc64cd 706 * sc_table.len, GFP_KERNEL);
259b6cb3
MD
707 if (!chan->sc_table)
708 return -ENOMEM;
709 }
5b7ac358
MD
710 if (!chan->sc_exit_table) {
711 /* create syscall table mapping syscall to events */
a67ba386 712 chan->sc_exit_table = kzalloc(sizeof(struct lttng_kernel_event_recorder *)
ebcc64cd 713 * sc_exit_table.len, GFP_KERNEL);
5b7ac358
MD
714 if (!chan->sc_exit_table)
715 return -ENOMEM;
716 }
717
259b6cb3 718
49c50022
MD
719#ifdef CONFIG_COMPAT
720 if (!chan->compat_sc_table) {
721 /* create syscall table mapping compat syscall to events */
a67ba386 722 chan->compat_sc_table = kzalloc(sizeof(struct lttng_kernel_event_recorder *)
ebcc64cd 723 * compat_sc_table.len, GFP_KERNEL);
49c50022
MD
724 if (!chan->compat_sc_table)
725 return -ENOMEM;
726 }
5b7ac358
MD
727
728 if (!chan->compat_sc_exit_table) {
729 /* create syscall table mapping compat syscall to events */
a67ba386 730 chan->compat_sc_exit_table = kzalloc(sizeof(struct lttng_kernel_event_recorder *)
ebcc64cd 731 * compat_sc_exit_table.len, GFP_KERNEL);
5b7ac358
MD
732 if (!chan->compat_sc_exit_table)
733 return -ENOMEM;
734 }
49c50022 735#endif
3b82c4e1 736 if (hlist_empty(&chan->sc_unknown)) {
437d5aa5 737 const struct lttng_kernel_event_desc *desc =
d4291869 738 &__event_desc___syscall_entry_unknown;
a67ba386 739 struct lttng_kernel_event_recorder *event_recorder;
2f804c0a 740
f405cfce 741 memset(&ev, 0, sizeof(ev));
606828e4
MD
742 strncpy(ev.name, desc->event_name, LTTNG_KERNEL_ABI_SYM_NAME_LEN);
743 ev.name[LTTNG_KERNEL_ABI_SYM_NAME_LEN - 1] = '\0';
744 ev.instrumentation = LTTNG_KERNEL_ABI_SYSCALL;
745 ev.u.syscall.entryexit = LTTNG_KERNEL_ABI_SYSCALL_ENTRY;
746 ev.u.syscall.abi = LTTNG_KERNEL_ABI_SYSCALL_ABI_NATIVE;
a67ba386 747 event_recorder = _lttng_kernel_event_recorder_create(chan, &ev, desc,
3b82c4e1 748 ev.instrumentation);
a67ba386
MD
749 WARN_ON_ONCE(!event_recorder);
750 if (IS_ERR(event_recorder)) {
751 return PTR_ERR(event_recorder);
f405cfce 752 }
a67ba386 753 hlist_add_head(&event_recorder->priv->parent.u.syscall.node, &chan->sc_unknown);
f405cfce
MD
754 }
755
3b82c4e1 756 if (hlist_empty(&chan->sc_compat_unknown)) {
437d5aa5 757 const struct lttng_kernel_event_desc *desc =
d4291869 758 &__event_desc___compat_syscall_entry_unknown;
a67ba386 759 struct lttng_kernel_event_recorder *event_recorder;
b76dc1a0
MD
760
761 memset(&ev, 0, sizeof(ev));
606828e4
MD
762 strncpy(ev.name, desc->event_name, LTTNG_KERNEL_ABI_SYM_NAME_LEN);
763 ev.name[LTTNG_KERNEL_ABI_SYM_NAME_LEN - 1] = '\0';
764 ev.instrumentation = LTTNG_KERNEL_ABI_SYSCALL;
765 ev.u.syscall.entryexit = LTTNG_KERNEL_ABI_SYSCALL_ENTRY;
766 ev.u.syscall.abi = LTTNG_KERNEL_ABI_SYSCALL_ABI_COMPAT;
a67ba386 767 event_recorder = _lttng_kernel_event_recorder_create(chan, &ev, desc,
3b82c4e1 768 ev.instrumentation);
a67ba386
MD
769 WARN_ON_ONCE(!event_recorder);
770 if (IS_ERR(event_recorder)) {
771 return PTR_ERR(event_recorder);
b76dc1a0 772 }
a67ba386 773 hlist_add_head(&event_recorder->priv->parent.u.syscall.node, &chan->sc_compat_unknown);
b76dc1a0
MD
774 }
775
3b82c4e1 776 if (hlist_empty(&chan->compat_sc_exit_unknown)) {
437d5aa5 777 const struct lttng_kernel_event_desc *desc =
5b7ac358 778 &__event_desc___compat_syscall_exit_unknown;
a67ba386 779 struct lttng_kernel_event_recorder *event_recorder;
2f804c0a
MD
780
781 memset(&ev, 0, sizeof(ev));
606828e4
MD
782 strncpy(ev.name, desc->event_name, LTTNG_KERNEL_ABI_SYM_NAME_LEN);
783 ev.name[LTTNG_KERNEL_ABI_SYM_NAME_LEN - 1] = '\0';
784 ev.instrumentation = LTTNG_KERNEL_ABI_SYSCALL;
785 ev.u.syscall.entryexit = LTTNG_KERNEL_ABI_SYSCALL_EXIT;
786 ev.u.syscall.abi = LTTNG_KERNEL_ABI_SYSCALL_ABI_COMPAT;
a67ba386 787 event_recorder = _lttng_kernel_event_recorder_create(chan, &ev, desc,
3b82c4e1 788 ev.instrumentation);
a67ba386
MD
789 WARN_ON_ONCE(!event_recorder);
790 if (IS_ERR(event_recorder)) {
791 return PTR_ERR(event_recorder);
5b7ac358 792 }
a67ba386 793 hlist_add_head(&event_recorder->priv->parent.u.syscall.node, &chan->compat_sc_exit_unknown);
5b7ac358
MD
794 }
795
3b82c4e1 796 if (hlist_empty(&chan->sc_exit_unknown)) {
437d5aa5 797 const struct lttng_kernel_event_desc *desc =
5b7ac358 798 &__event_desc___syscall_exit_unknown;
a67ba386 799 struct lttng_kernel_event_recorder *event_recorder;
5b7ac358
MD
800
801 memset(&ev, 0, sizeof(ev));
606828e4
MD
802 strncpy(ev.name, desc->event_name, LTTNG_KERNEL_ABI_SYM_NAME_LEN);
803 ev.name[LTTNG_KERNEL_ABI_SYM_NAME_LEN - 1] = '\0';
804 ev.instrumentation = LTTNG_KERNEL_ABI_SYSCALL;
805 ev.u.syscall.entryexit = LTTNG_KERNEL_ABI_SYSCALL_EXIT;
806 ev.u.syscall.abi = LTTNG_KERNEL_ABI_SYSCALL_ABI_NATIVE;
a67ba386 807 event_recorder = _lttng_kernel_event_recorder_create(chan, &ev, desc,
3b82c4e1 808 ev.instrumentation);
a67ba386
MD
809 WARN_ON_ONCE(!event_recorder);
810 if (IS_ERR(event_recorder)) {
811 return PTR_ERR(event_recorder);
2f804c0a 812 }
a67ba386 813 hlist_add_head(&event_recorder->priv->parent.u.syscall.node, &chan->sc_exit_unknown);
2f804c0a
MD
814 }
815
ebcc64cd 816 ret = lttng_create_syscall_event_if_missing(sc_table.table, sc_table.len,
a67ba386 817 chan->sc_table, event_enabler, SC_TYPE_ENTRY);
5b7ac358
MD
818 if (ret)
819 return ret;
ebcc64cd 820 ret = lttng_create_syscall_event_if_missing(sc_exit_table.table, sc_exit_table.len,
a67ba386 821 chan->sc_exit_table, event_enabler, SC_TYPE_EXIT);
49c50022
MD
822 if (ret)
823 return ret;
5b7ac358 824
49c50022 825#ifdef CONFIG_COMPAT
ebcc64cd 826 ret = lttng_create_syscall_event_if_missing(compat_sc_table.table, compat_sc_table.len,
a67ba386 827 chan->compat_sc_table, event_enabler, SC_TYPE_COMPAT_ENTRY);
5b7ac358
MD
828 if (ret)
829 return ret;
ebcc64cd 830 ret = lttng_create_syscall_event_if_missing(compat_sc_exit_table.table, compat_sc_exit_table.len,
a67ba386 831 chan->compat_sc_exit_table, event_enabler, SC_TYPE_COMPAT_EXIT);
49c50022
MD
832 if (ret)
833 return ret;
834#endif
badfe9f5
MD
835
836 if (!chan->sc_filter) {
837 chan->sc_filter = kzalloc(sizeof(struct lttng_syscall_filter),
838 GFP_KERNEL);
839 if (!chan->sc_filter)
840 return -ENOMEM;
841 }
842
80f87dd2
MD
843 if (!chan->sys_enter_registered) {
844 ret = lttng_wrapper_tracepoint_probe_register("sys_enter",
2d6d88c6 845 (void *) syscall_entry_event_probe, chan);
80f87dd2
MD
846 if (ret)
847 return ret;
848 chan->sys_enter_registered = 1;
849 }
63728b02
MD
850 /*
851 * We change the name of sys_exit tracepoint due to namespace
852 * conflict with sys_exit syscall entry.
853 */
80f87dd2
MD
854 if (!chan->sys_exit_registered) {
855 ret = lttng_wrapper_tracepoint_probe_register("sys_exit",
2d6d88c6 856 (void *) syscall_exit_event_probe, chan);
80f87dd2
MD
857 if (ret) {
858 WARN_ON_ONCE(lttng_wrapper_tracepoint_probe_unregister("sys_enter",
2d6d88c6 859 (void *) syscall_entry_event_probe, chan));
80f87dd2
MD
860 return ret;
861 }
862 chan->sys_exit_registered = 1;
63728b02 863 }
259b6cb3
MD
864 return ret;
865}
866
867/*
8a8ac9a8
FD
868 * Should be called with sessions lock held.
869 */
870int lttng_syscalls_register_event_notifier(
a67ba386 871 struct lttng_event_notifier_enabler *event_notifier_enabler)
8a8ac9a8
FD
872{
873 struct lttng_event_notifier_group *group = event_notifier_enabler->group;
874 unsigned int i;
875 int ret = 0;
876
877 wrapper_vmalloc_sync_mappings();
878
879 if (!group->event_notifier_syscall_dispatch) {
880 group->event_notifier_syscall_dispatch =
ebcc64cd 881 kzalloc(sizeof(struct hlist_head) * sc_table.len,
8a8ac9a8
FD
882 GFP_KERNEL);
883 if (!group->event_notifier_syscall_dispatch)
884 return -ENOMEM;
885
886 /* Initialize all list_head */
ebcc64cd 887 for (i = 0; i < sc_table.len; i++)
8a8ac9a8
FD
888 INIT_HLIST_HEAD(&group->event_notifier_syscall_dispatch[i]);
889
890 /* Init the unknown syscall notifier list. */
891 INIT_HLIST_HEAD(&group->event_notifier_unknown_syscall_dispatch);
892 }
893
894 if (!group->event_notifier_exit_syscall_dispatch) {
895 group->event_notifier_exit_syscall_dispatch =
ebcc64cd 896 kzalloc(sizeof(struct hlist_head) * sc_table.len,
8a8ac9a8
FD
897 GFP_KERNEL);
898 if (!group->event_notifier_exit_syscall_dispatch)
899 return -ENOMEM;
900
901 /* Initialize all list_head */
ebcc64cd 902 for (i = 0; i < sc_table.len; i++)
8a8ac9a8
FD
903 INIT_HLIST_HEAD(&group->event_notifier_exit_syscall_dispatch[i]);
904
905 /* Init the unknown exit syscall notifier list. */
906 INIT_HLIST_HEAD(&group->event_notifier_exit_unknown_syscall_dispatch);
907 }
908
909#ifdef CONFIG_COMPAT
910 if (!group->event_notifier_compat_syscall_dispatch) {
911 group->event_notifier_compat_syscall_dispatch =
ebcc64cd 912 kzalloc(sizeof(struct hlist_head) * compat_sc_table.len,
8a8ac9a8
FD
913 GFP_KERNEL);
914 if (!group->event_notifier_syscall_dispatch)
915 return -ENOMEM;
916
917 /* Initialize all list_head */
ebcc64cd 918 for (i = 0; i < compat_sc_table.len; i++)
8a8ac9a8
FD
919 INIT_HLIST_HEAD(&group->event_notifier_compat_syscall_dispatch[i]);
920
921 /* Init the unknown syscall notifier list. */
922 INIT_HLIST_HEAD(&group->event_notifier_compat_unknown_syscall_dispatch);
923 }
924
925 if (!group->event_notifier_exit_compat_syscall_dispatch) {
926 group->event_notifier_exit_compat_syscall_dispatch =
ebcc64cd 927 kzalloc(sizeof(struct hlist_head) * compat_sc_exit_table.len,
8a8ac9a8
FD
928 GFP_KERNEL);
929 if (!group->event_notifier_exit_syscall_dispatch)
930 return -ENOMEM;
931
932 /* Initialize all list_head */
ebcc64cd 933 for (i = 0; i < compat_sc_exit_table.len; i++)
8a8ac9a8
FD
934 INIT_HLIST_HEAD(&group->event_notifier_exit_compat_syscall_dispatch[i]);
935
936 /* Init the unknown exit syscall notifier list. */
937 INIT_HLIST_HEAD(&group->event_notifier_exit_compat_unknown_syscall_dispatch);
938 }
939#endif
940
941 if (!group->sc_filter) {
942 group->sc_filter = kzalloc(sizeof(struct lttng_syscall_filter),
943 GFP_KERNEL);
944 if (!group->sc_filter)
945 return -ENOMEM;
946 }
947
948 if (!group->sys_enter_registered) {
949 ret = lttng_wrapper_tracepoint_probe_register("sys_enter",
950 (void *) syscall_entry_event_notifier_probe, group);
951 if (ret)
952 return ret;
953 group->sys_enter_registered = 1;
954 }
955
956 if (!group->sys_exit_registered) {
957 ret = lttng_wrapper_tracepoint_probe_register("sys_exit",
958 (void *) syscall_exit_event_notifier_probe, group);
959 if (ret) {
960 WARN_ON_ONCE(lttng_wrapper_tracepoint_probe_unregister("sys_enter",
961 (void *) syscall_entry_event_notifier_probe, group));
962 return ret;
963 }
964 group->sys_exit_registered = 1;
965 }
966
967 return ret;
968}
969
970static
971int create_unknown_event_notifier(
972 struct lttng_event_notifier_enabler *event_notifier_enabler,
973 enum sc_type type)
974{
a67ba386
MD
975 struct lttng_kernel_event_notifier_private *event_notifier_priv;
976 struct lttng_kernel_event_notifier *event_notifier;
437d5aa5 977 const struct lttng_kernel_event_desc *desc;
8a8ac9a8 978 struct lttng_event_notifier_group *group = event_notifier_enabler->group;
606828e4 979 struct lttng_kernel_abi_event_notifier event_notifier_param;
8a8ac9a8 980 uint64_t user_token = event_notifier_enabler->base.user_token;
99f52fcc 981 uint64_t error_counter_index = event_notifier_enabler->error_counter_index;
8a8ac9a8
FD
982 struct lttng_enabler *base_enabler = lttng_event_notifier_enabler_as_enabler(
983 event_notifier_enabler);
984 struct hlist_head *unknown_dispatch_list;
985 int ret = 0;
986 bool found = false;
606828e4
MD
987 enum lttng_kernel_abi_syscall_abi abi;
988 enum lttng_kernel_abi_syscall_entryexit entryexit;
8a8ac9a8
FD
989 struct hlist_head *head;
990
991 switch (type) {
992 case SC_TYPE_ENTRY:
993 desc = &__event_desc___syscall_entry_unknown;
994 unknown_dispatch_list = &group->event_notifier_unknown_syscall_dispatch;
606828e4
MD
995 entryexit = LTTNG_KERNEL_ABI_SYSCALL_ENTRY;
996 abi = LTTNG_KERNEL_ABI_SYSCALL_ABI_NATIVE;
8a8ac9a8
FD
997 break;
998 case SC_TYPE_EXIT:
999 desc = &__event_desc___syscall_exit_unknown;
1000 unknown_dispatch_list = &group->event_notifier_exit_unknown_syscall_dispatch;
606828e4
MD
1001 entryexit = LTTNG_KERNEL_ABI_SYSCALL_EXIT;
1002 abi = LTTNG_KERNEL_ABI_SYSCALL_ABI_NATIVE;
8a8ac9a8
FD
1003 break;
1004 case SC_TYPE_COMPAT_ENTRY:
1005 desc = &__event_desc___compat_syscall_entry_unknown;
1006 unknown_dispatch_list = &group->event_notifier_compat_unknown_syscall_dispatch;
606828e4
MD
1007 entryexit = LTTNG_KERNEL_ABI_SYSCALL_ENTRY;
1008 abi = LTTNG_KERNEL_ABI_SYSCALL_ABI_COMPAT;
8a8ac9a8
FD
1009 break;
1010 case SC_TYPE_COMPAT_EXIT:
1011 desc = &__event_desc___compat_syscall_exit_unknown;
1012 unknown_dispatch_list = &group->event_notifier_exit_compat_unknown_syscall_dispatch;
606828e4
MD
1013 entryexit = LTTNG_KERNEL_ABI_SYSCALL_EXIT;
1014 abi = LTTNG_KERNEL_ABI_SYSCALL_ABI_COMPAT;
8a8ac9a8
FD
1015 break;
1016 default:
1017 BUG_ON(1);
1018 }
1019
1020 /*
1021 * Check if already created.
1022 */
1023 head = utils_borrow_hash_table_bucket(group->event_notifiers_ht.table,
437d5aa5 1024 LTTNG_EVENT_NOTIFIER_HT_SIZE, desc->event_name);
a67ba386
MD
1025 lttng_hlist_for_each_entry(event_notifier_priv, head, hlist) {
1026 if (event_notifier_priv->parent.desc == desc &&
1027 event_notifier_priv->parent.user_token == base_enabler->user_token)
8a8ac9a8
FD
1028 found = true;
1029 }
1030 if (found)
1031 goto end;
1032
1033 memset(&event_notifier_param, 0, sizeof(event_notifier_param));
437d5aa5 1034 strncat(event_notifier_param.event.name, desc->event_name,
606828e4 1035 LTTNG_KERNEL_ABI_SYM_NAME_LEN - strlen(event_notifier_param.event.name) - 1);
8a8ac9a8 1036
606828e4 1037 event_notifier_param.event.name[LTTNG_KERNEL_ABI_SYM_NAME_LEN - 1] = '\0';
8a8ac9a8 1038
606828e4 1039 event_notifier_param.event.instrumentation = LTTNG_KERNEL_ABI_SYSCALL;
8a8ac9a8
FD
1040 event_notifier_param.event.u.syscall.abi = abi;
1041 event_notifier_param.event.u.syscall.entryexit = entryexit;
1042
a67ba386
MD
1043 event_notifier = _lttng_event_notifier_create(desc, user_token,
1044 error_counter_index, group, &event_notifier_param,
8a8ac9a8 1045 event_notifier_param.event.instrumentation);
a67ba386 1046 if (IS_ERR(event_notifier)) {
8a8ac9a8 1047 printk(KERN_INFO "Unable to create unknown notifier %s\n",
437d5aa5 1048 desc->event_name);
8a8ac9a8
FD
1049 ret = -ENOMEM;
1050 goto end;
1051 }
1052
a67ba386 1053 hlist_add_head_rcu(&event_notifier->priv->parent.u.syscall.node, unknown_dispatch_list);
8a8ac9a8
FD
1054
1055end:
1056 return ret;
1057}
1058
1059static int create_matching_event_notifiers(
1060 struct lttng_event_notifier_enabler *event_notifier_enabler,
a67ba386 1061 const struct trace_syscall_entry *table,
8a8ac9a8
FD
1062 size_t table_len, enum sc_type type)
1063{
1064 struct lttng_event_notifier_group *group = event_notifier_enabler->group;
437d5aa5 1065 const struct lttng_kernel_event_desc *desc;
8a8ac9a8 1066 uint64_t user_token = event_notifier_enabler->base.user_token;
99f52fcc 1067 uint64_t error_counter_index = event_notifier_enabler->error_counter_index;
8a8ac9a8
FD
1068 unsigned int i;
1069 int ret = 0;
1070
1071 /* iterate over all syscall and create event_notifier that match */
1072 for (i = 0; i < table_len; i++) {
a67ba386
MD
1073 struct lttng_kernel_event_notifier_private *event_notifier_priv;
1074 struct lttng_kernel_event_notifier *event_notifier;
606828e4 1075 struct lttng_kernel_abi_event_notifier event_notifier_param;
8a8ac9a8
FD
1076 struct hlist_head *head;
1077 int found = 0;
1078
1079 desc = table[i].desc;
1080 if (!desc) {
1081 /* Unknown syscall */
1082 continue;
1083 }
1084
1085 if (!lttng_desc_match_enabler(desc,
1086 lttng_event_notifier_enabler_as_enabler(event_notifier_enabler)))
1087 continue;
1088
1089 /*
1090 * Check if already created.
1091 */
1092 head = utils_borrow_hash_table_bucket(group->event_notifiers_ht.table,
437d5aa5 1093 LTTNG_EVENT_NOTIFIER_HT_SIZE, desc->event_name);
a67ba386
MD
1094 lttng_hlist_for_each_entry(event_notifier_priv, head, hlist) {
1095 if (event_notifier_priv->parent.desc == desc
1096 && event_notifier_priv->parent.user_token == event_notifier_enabler->base.user_token)
8a8ac9a8
FD
1097 found = 1;
1098 }
1099 if (found)
1100 continue;
1101
1102 memset(&event_notifier_param, 0, sizeof(event_notifier_param));
1103 switch (type) {
1104 case SC_TYPE_ENTRY:
606828e4
MD
1105 event_notifier_param.event.u.syscall.entryexit = LTTNG_KERNEL_ABI_SYSCALL_ENTRY;
1106 event_notifier_param.event.u.syscall.abi = LTTNG_KERNEL_ABI_SYSCALL_ABI_NATIVE;
8a8ac9a8
FD
1107 break;
1108 case SC_TYPE_EXIT:
606828e4
MD
1109 event_notifier_param.event.u.syscall.entryexit = LTTNG_KERNEL_ABI_SYSCALL_EXIT;
1110 event_notifier_param.event.u.syscall.abi = LTTNG_KERNEL_ABI_SYSCALL_ABI_NATIVE;
8a8ac9a8
FD
1111 break;
1112 case SC_TYPE_COMPAT_ENTRY:
606828e4
MD
1113 event_notifier_param.event.u.syscall.entryexit = LTTNG_KERNEL_ABI_SYSCALL_ENTRY;
1114 event_notifier_param.event.u.syscall.abi = LTTNG_KERNEL_ABI_SYSCALL_ABI_COMPAT;
8a8ac9a8
FD
1115 break;
1116 case SC_TYPE_COMPAT_EXIT:
606828e4
MD
1117 event_notifier_param.event.u.syscall.entryexit = LTTNG_KERNEL_ABI_SYSCALL_EXIT;
1118 event_notifier_param.event.u.syscall.abi = LTTNG_KERNEL_ABI_SYSCALL_ABI_COMPAT;
8a8ac9a8
FD
1119 break;
1120 }
437d5aa5 1121 strncat(event_notifier_param.event.name, desc->event_name,
606828e4
MD
1122 LTTNG_KERNEL_ABI_SYM_NAME_LEN - strlen(event_notifier_param.event.name) - 1);
1123 event_notifier_param.event.name[LTTNG_KERNEL_ABI_SYM_NAME_LEN - 1] = '\0';
1124 event_notifier_param.event.instrumentation = LTTNG_KERNEL_ABI_SYSCALL;
8a8ac9a8 1125
99f52fcc
FD
1126 event_notifier = _lttng_event_notifier_create(desc, user_token,
1127 error_counter_index, group, &event_notifier_param,
a67ba386 1128 event_notifier_param.event.instrumentation);
8a8ac9a8
FD
1129 if (IS_ERR(event_notifier)) {
1130 printk(KERN_INFO "Unable to create event_notifier %s\n",
437d5aa5 1131 desc->event_name);
8a8ac9a8
FD
1132 ret = -ENOMEM;
1133 goto end;
1134 }
1135
a67ba386 1136 event_notifier->priv->parent.u.syscall.syscall_id = i;
8a8ac9a8
FD
1137 }
1138
1139end:
1140 return ret;
1141
1142}
1143
a67ba386
MD
1144int lttng_syscalls_create_matching_event_notifiers(
1145 struct lttng_event_notifier_enabler *event_notifier_enabler)
8a8ac9a8
FD
1146{
1147 int ret;
1148 struct lttng_enabler *base_enabler =
1149 lttng_event_notifier_enabler_as_enabler(event_notifier_enabler);
606828e4 1150 enum lttng_kernel_abi_syscall_entryexit entryexit =
8a8ac9a8
FD
1151 base_enabler->event_param.u.syscall.entryexit;
1152
606828e4 1153 if (entryexit == LTTNG_KERNEL_ABI_SYSCALL_ENTRY || entryexit == LTTNG_KERNEL_ABI_SYSCALL_ENTRYEXIT) {
8a8ac9a8 1154 ret = create_matching_event_notifiers(event_notifier_enabler,
ebcc64cd 1155 sc_table.table, sc_table.len, SC_TYPE_ENTRY);
8a8ac9a8
FD
1156 if (ret)
1157 goto end;
1158
1159 ret = create_matching_event_notifiers(event_notifier_enabler,
ebcc64cd 1160 compat_sc_table.table, compat_sc_table.len,
8a8ac9a8
FD
1161 SC_TYPE_COMPAT_ENTRY);
1162 if (ret)
1163 goto end;
1164
1165 ret = create_unknown_event_notifier(event_notifier_enabler,
1166 SC_TYPE_ENTRY);
1167 if (ret)
1168 goto end;
1169
1170 ret = create_unknown_event_notifier(event_notifier_enabler,
1171 SC_TYPE_COMPAT_ENTRY);
1172 if (ret)
1173 goto end;
1174 }
1175
606828e4 1176 if (entryexit == LTTNG_KERNEL_ABI_SYSCALL_EXIT || entryexit == LTTNG_KERNEL_ABI_SYSCALL_ENTRYEXIT) {
8a8ac9a8 1177 ret = create_matching_event_notifiers(event_notifier_enabler,
ebcc64cd 1178 sc_exit_table.table, sc_exit_table.len,
8a8ac9a8
FD
1179 SC_TYPE_EXIT);
1180 if (ret)
1181 goto end;
1182
1183 ret = create_unknown_event_notifier(event_notifier_enabler,
1184 SC_TYPE_EXIT);
1185 if (ret)
1186 goto end;
1187
1188 ret = create_matching_event_notifiers(event_notifier_enabler,
ebcc64cd 1189 compat_sc_exit_table.table, compat_sc_exit_table.len,
8a8ac9a8
FD
1190 SC_TYPE_COMPAT_EXIT);
1191 if (ret)
1192 goto end;
1193
1194 ret = create_unknown_event_notifier(event_notifier_enabler,
1195 SC_TYPE_COMPAT_EXIT);
1196 if (ret)
1197 goto end;
1198 }
1199
1200end:
1201 return ret;
1202}
1203
1204/*
1205 * Unregister the syscall event_notifier probes from the callsites.
259b6cb3 1206 */
3b82c4e1 1207int lttng_syscalls_unregister_event_notifier_group(
8a8ac9a8
FD
1208 struct lttng_event_notifier_group *event_notifier_group)
1209{
1210 int ret;
1211
1212 /*
1213 * Only register the event_notifier probe on the `sys_enter` callsite for now.
1214 * At the moment, we don't think it's desirable to have one fired
1215 * event_notifier for the entry and one for the exit of a syscall.
1216 */
1217 if (event_notifier_group->sys_enter_registered) {
1218 ret = lttng_wrapper_tracepoint_probe_unregister("sys_enter",
1219 (void *) syscall_entry_event_notifier_probe, event_notifier_group);
1220 if (ret)
1221 return ret;
1222 event_notifier_group->sys_enter_registered = 0;
1223 }
1224 if (event_notifier_group->sys_exit_registered) {
1225 ret = lttng_wrapper_tracepoint_probe_unregister("sys_exit",
1226 (void *) syscall_exit_event_notifier_probe, event_notifier_group);
1227 if (ret)
1228 return ret;
1229 event_notifier_group->sys_enter_registered = 0;
1230 }
1231
1232 kfree(event_notifier_group->event_notifier_syscall_dispatch);
1233 kfree(event_notifier_group->event_notifier_exit_syscall_dispatch);
1234#ifdef CONFIG_COMPAT
1235 kfree(event_notifier_group->event_notifier_compat_syscall_dispatch);
1236 kfree(event_notifier_group->event_notifier_exit_compat_syscall_dispatch);
1237#endif
1238 return 0;
1239}
1240
3b82c4e1 1241int lttng_syscalls_unregister_channel(struct lttng_channel *chan)
259b6cb3
MD
1242{
1243 int ret;
1244
1245 if (!chan->sc_table)
1246 return 0;
80f87dd2 1247 if (chan->sys_enter_registered) {
2d9cd7f3 1248 ret = lttng_wrapper_tracepoint_probe_unregister("sys_enter",
2d6d88c6 1249 (void *) syscall_entry_event_probe, chan);
80f87dd2
MD
1250 if (ret)
1251 return ret;
1252 chan->sys_enter_registered = 0;
1253 }
1254 if (chan->sys_exit_registered) {
2d9cd7f3 1255 ret = lttng_wrapper_tracepoint_probe_unregister("sys_exit",
2d6d88c6 1256 (void *) syscall_exit_event_probe, chan);
80f87dd2
MD
1257 if (ret)
1258 return ret;
1259 chan->sys_exit_registered = 0;
1260 }
badfe9f5
MD
1261 return 0;
1262}
1263
2d6d88c6 1264int lttng_syscalls_destroy_event(struct lttng_channel *chan)
badfe9f5 1265{
259b6cb3 1266 kfree(chan->sc_table);
5b7ac358 1267 kfree(chan->sc_exit_table);
49c50022
MD
1268#ifdef CONFIG_COMPAT
1269 kfree(chan->compat_sc_table);
5b7ac358 1270 kfree(chan->compat_sc_exit_table);
49c50022 1271#endif
80f87dd2
MD
1272 kfree(chan->sc_filter);
1273 return 0;
1274}
1275
1276static
1277int get_syscall_nr(const char *syscall_name)
1278{
1279 int syscall_nr = -1;
1280 int i;
1281
ebcc64cd 1282 for (i = 0; i < sc_table.len; i++) {
80f87dd2 1283 const struct trace_syscall_entry *entry;
5b7ac358 1284 const char *it_name;
80f87dd2 1285
ebcc64cd 1286 entry = &sc_table.table[i];
80f87dd2
MD
1287 if (!entry->desc)
1288 continue;
437d5aa5 1289 it_name = entry->desc->event_name;
5b7ac358
MD
1290 it_name += strlen(SYSCALL_ENTRY_STR);
1291 if (!strcmp(syscall_name, it_name)) {
80f87dd2
MD
1292 syscall_nr = i;
1293 break;
1294 }
1295 }
1296 return syscall_nr;
1297}
1298
1299static
1300int get_compat_syscall_nr(const char *syscall_name)
1301{
1302 int syscall_nr = -1;
1303 int i;
1304
ebcc64cd 1305 for (i = 0; i < compat_sc_table.len; i++) {
80f87dd2 1306 const struct trace_syscall_entry *entry;
5b7ac358 1307 const char *it_name;
80f87dd2 1308
ebcc64cd 1309 entry = &compat_sc_table.table[i];
80f87dd2
MD
1310 if (!entry->desc)
1311 continue;
437d5aa5 1312 it_name = entry->desc->event_name;
5b7ac358
MD
1313 it_name += strlen(COMPAT_SYSCALL_ENTRY_STR);
1314 if (!strcmp(syscall_name, it_name)) {
80f87dd2
MD
1315 syscall_nr = i;
1316 break;
1317 }
1318 }
1319 return syscall_nr;
1320}
1321
12e579db
MD
1322static
1323uint32_t get_sc_tables_len(void)
1324{
ebcc64cd 1325 return sc_table.len + compat_sc_table.len;
12e579db
MD
1326}
1327
badfe9f5 1328static
ade8a729
FD
1329const char *get_syscall_name(const char *desc_name,
1330 enum lttng_syscall_abi abi,
1331 enum lttng_syscall_entryexit entryexit)
80f87dd2 1332{
badfe9f5 1333 size_t prefix_len = 0;
80f87dd2 1334
80f87dd2 1335
ade8a729 1336 switch (entryexit) {
badfe9f5 1337 case LTTNG_SYSCALL_ENTRY:
ade8a729 1338 switch (abi) {
badfe9f5
MD
1339 case LTTNG_SYSCALL_ABI_NATIVE:
1340 prefix_len = strlen(SYSCALL_ENTRY_STR);
1341 break;
1342 case LTTNG_SYSCALL_ABI_COMPAT:
1343 prefix_len = strlen(COMPAT_SYSCALL_ENTRY_STR);
1344 break;
80f87dd2 1345 }
badfe9f5
MD
1346 break;
1347 case LTTNG_SYSCALL_EXIT:
ade8a729 1348 switch (abi) {
badfe9f5
MD
1349 case LTTNG_SYSCALL_ABI_NATIVE:
1350 prefix_len = strlen(SYSCALL_EXIT_STR);
1351 break;
1352 case LTTNG_SYSCALL_ABI_COMPAT:
1353 prefix_len = strlen(COMPAT_SYSCALL_EXIT_STR);
1354 break;
80f87dd2 1355 }
badfe9f5 1356 break;
80f87dd2 1357 }
badfe9f5 1358 WARN_ON_ONCE(prefix_len == 0);
ade8a729 1359 return desc_name + prefix_len;
badfe9f5
MD
1360}
1361
ade8a729
FD
1362static
1363int lttng_syscall_filter_enable(
1364 struct lttng_syscall_filter *filter,
1365 const char *desc_name, enum lttng_syscall_abi abi,
1366 enum lttng_syscall_entryexit entryexit)
badfe9f5 1367{
badfe9f5
MD
1368 const char *syscall_name;
1369 unsigned long *bitmap;
1370 int syscall_nr;
1371
ade8a729 1372 syscall_name = get_syscall_name(desc_name, abi, entryexit);
badfe9f5 1373
ade8a729 1374 switch (abi) {
badfe9f5
MD
1375 case LTTNG_SYSCALL_ABI_NATIVE:
1376 syscall_nr = get_syscall_nr(syscall_name);
1377 break;
1378 case LTTNG_SYSCALL_ABI_COMPAT:
1379 syscall_nr = get_compat_syscall_nr(syscall_name);
1380 break;
1381 default:
1382 return -EINVAL;
80f87dd2 1383 }
badfe9f5
MD
1384 if (syscall_nr < 0)
1385 return -ENOENT;
1386
ade8a729 1387 switch (entryexit) {
badfe9f5 1388 case LTTNG_SYSCALL_ENTRY:
ade8a729 1389 switch (abi) {
badfe9f5
MD
1390 case LTTNG_SYSCALL_ABI_NATIVE:
1391 bitmap = filter->sc_entry;
1392 break;
1393 case LTTNG_SYSCALL_ABI_COMPAT:
1394 bitmap = filter->sc_compat_entry;
1395 break;
6d9694d8
MD
1396 default:
1397 return -EINVAL;
80f87dd2 1398 }
badfe9f5
MD
1399 break;
1400 case LTTNG_SYSCALL_EXIT:
ade8a729 1401 switch (abi) {
badfe9f5
MD
1402 case LTTNG_SYSCALL_ABI_NATIVE:
1403 bitmap = filter->sc_exit;
1404 break;
1405 case LTTNG_SYSCALL_ABI_COMPAT:
1406 bitmap = filter->sc_compat_exit;
1407 break;
6d9694d8
MD
1408 default:
1409 return -EINVAL;
80f87dd2 1410 }
badfe9f5
MD
1411 break;
1412 default:
1413 return -EINVAL;
80f87dd2 1414 }
badfe9f5
MD
1415 if (test_bit(syscall_nr, bitmap))
1416 return -EEXIST;
1417 bitmap_set(bitmap, syscall_nr, 1);
80f87dd2 1418 return 0;
80f87dd2
MD
1419}
1420
8a8ac9a8 1421int lttng_syscall_filter_enable_event_notifier(
a67ba386 1422 struct lttng_kernel_event_notifier *event_notifier)
8a8ac9a8 1423{
a67ba386
MD
1424 struct lttng_event_notifier_group *group = event_notifier->priv->group;
1425 unsigned int syscall_id = event_notifier->priv->parent.u.syscall.syscall_id;
8a8ac9a8
FD
1426 struct hlist_head *dispatch_list;
1427 int ret = 0;
1428
a67ba386 1429 WARN_ON_ONCE(event_notifier->priv->parent.instrumentation != LTTNG_KERNEL_ABI_SYSCALL);
8a8ac9a8
FD
1430
1431 ret = lttng_syscall_filter_enable(group->sc_filter,
a67ba386
MD
1432 event_notifier->priv->parent.desc->event_name,
1433 event_notifier->priv->parent.u.syscall.abi,
1434 event_notifier->priv->parent.u.syscall.entryexit);
8a8ac9a8
FD
1435 if (ret) {
1436 goto end;
1437 }
1438
a67ba386 1439 switch (event_notifier->priv->parent.u.syscall.entryexit) {
8a8ac9a8 1440 case LTTNG_SYSCALL_ENTRY:
a67ba386 1441 switch (event_notifier->priv->parent.u.syscall.abi) {
8a8ac9a8
FD
1442 case LTTNG_SYSCALL_ABI_NATIVE:
1443 dispatch_list = &group->event_notifier_syscall_dispatch[syscall_id];
1444 break;
1445 case LTTNG_SYSCALL_ABI_COMPAT:
1446 dispatch_list = &group->event_notifier_compat_syscall_dispatch[syscall_id];
1447 break;
6866b1c7
MJ
1448 default:
1449 ret = -EINVAL;
1450 goto end;
8a8ac9a8
FD
1451 }
1452 break;
1453 case LTTNG_SYSCALL_EXIT:
a67ba386 1454 switch (event_notifier->priv->parent.u.syscall.abi) {
8a8ac9a8
FD
1455 case LTTNG_SYSCALL_ABI_NATIVE:
1456 dispatch_list = &group->event_notifier_exit_syscall_dispatch[syscall_id];
1457 break;
1458 case LTTNG_SYSCALL_ABI_COMPAT:
1459 dispatch_list = &group->event_notifier_exit_compat_syscall_dispatch[syscall_id];
1460 break;
6866b1c7
MJ
1461 default:
1462 ret = -EINVAL;
1463 goto end;
8a8ac9a8
FD
1464 }
1465 break;
6866b1c7
MJ
1466 default:
1467 ret = -EINVAL;
1468 goto end;
8a8ac9a8
FD
1469 }
1470
a67ba386 1471 hlist_add_head_rcu(&event_notifier->priv->parent.u.syscall.node, dispatch_list);
8a8ac9a8
FD
1472
1473end:
1474 return ret ;
1475}
1476
ade8a729
FD
1477int lttng_syscall_filter_enable_event(
1478 struct lttng_channel *channel,
a67ba386 1479 struct lttng_kernel_event_recorder *event_recorder)
80f87dd2 1480{
a67ba386 1481 WARN_ON_ONCE(event_recorder->priv->parent.instrumentation != LTTNG_KERNEL_ABI_SYSCALL);
ade8a729
FD
1482
1483 return lttng_syscall_filter_enable(channel->sc_filter,
a67ba386
MD
1484 event_recorder->priv->parent.desc->event_name,
1485 event_recorder->priv->parent.u.syscall.abi,
1486 event_recorder->priv->parent.u.syscall.entryexit);
ade8a729
FD
1487}
1488
1489static
1490int lttng_syscall_filter_disable(
1491 struct lttng_syscall_filter *filter,
1492 const char *desc_name, enum lttng_syscall_abi abi,
1493 enum lttng_syscall_entryexit entryexit)
1494{
badfe9f5
MD
1495 const char *syscall_name;
1496 unsigned long *bitmap;
1497 int syscall_nr;
80f87dd2 1498
ade8a729 1499 syscall_name = get_syscall_name(desc_name, abi, entryexit);
80f87dd2 1500
ade8a729 1501 switch (abi) {
badfe9f5
MD
1502 case LTTNG_SYSCALL_ABI_NATIVE:
1503 syscall_nr = get_syscall_nr(syscall_name);
1504 break;
1505 case LTTNG_SYSCALL_ABI_COMPAT:
1506 syscall_nr = get_compat_syscall_nr(syscall_name);
1507 break;
1508 default:
1509 return -EINVAL;
80f87dd2 1510 }
badfe9f5
MD
1511 if (syscall_nr < 0)
1512 return -ENOENT;
80f87dd2 1513
ade8a729 1514 switch (entryexit) {
badfe9f5 1515 case LTTNG_SYSCALL_ENTRY:
ade8a729 1516 switch (abi) {
badfe9f5
MD
1517 case LTTNG_SYSCALL_ABI_NATIVE:
1518 bitmap = filter->sc_entry;
1519 break;
1520 case LTTNG_SYSCALL_ABI_COMPAT:
1521 bitmap = filter->sc_compat_entry;
1522 break;
6d9694d8
MD
1523 default:
1524 return -EINVAL;
80f87dd2 1525 }
badfe9f5
MD
1526 break;
1527 case LTTNG_SYSCALL_EXIT:
ade8a729 1528 switch (abi) {
badfe9f5
MD
1529 case LTTNG_SYSCALL_ABI_NATIVE:
1530 bitmap = filter->sc_exit;
1531 break;
1532 case LTTNG_SYSCALL_ABI_COMPAT:
1533 bitmap = filter->sc_compat_exit;
1534 break;
6d9694d8
MD
1535 default:
1536 return -EINVAL;
80f87dd2 1537 }
badfe9f5
MD
1538 break;
1539 default:
1540 return -EINVAL;
80f87dd2 1541 }
badfe9f5
MD
1542 if (!test_bit(syscall_nr, bitmap))
1543 return -EEXIST;
1544 bitmap_clear(bitmap, syscall_nr, 1);
80f87dd2 1545
badfe9f5 1546 return 0;
259b6cb3 1547}
2d2464bd 1548
8a8ac9a8 1549int lttng_syscall_filter_disable_event_notifier(
a67ba386 1550 struct lttng_kernel_event_notifier *event_notifier)
8a8ac9a8 1551{
a67ba386 1552 struct lttng_event_notifier_group *group = event_notifier->priv->group;
8a8ac9a8
FD
1553 int ret;
1554
a67ba386 1555 WARN_ON_ONCE(event_notifier->priv->parent.instrumentation != LTTNG_KERNEL_ABI_SYSCALL);
8a8ac9a8
FD
1556
1557 ret = lttng_syscall_filter_disable(group->sc_filter,
a67ba386
MD
1558 event_notifier->priv->parent.desc->event_name,
1559 event_notifier->priv->parent.u.syscall.abi,
1560 event_notifier->priv->parent.u.syscall.entryexit);
8a8ac9a8
FD
1561 WARN_ON_ONCE(ret != 0);
1562
a67ba386 1563 hlist_del_rcu(&event_notifier->priv->parent.u.syscall.node);
8a8ac9a8
FD
1564 return 0;
1565}
1566
ade8a729
FD
1567int lttng_syscall_filter_disable_event(
1568 struct lttng_channel *channel,
a67ba386 1569 struct lttng_kernel_event_recorder *event_recorder)
ade8a729
FD
1570{
1571 return lttng_syscall_filter_disable(channel->sc_filter,
a67ba386
MD
1572 event_recorder->priv->parent.desc->event_name,
1573 event_recorder->priv->parent.u.syscall.abi,
1574 event_recorder->priv->parent.u.syscall.entryexit);
ade8a729
FD
1575}
1576
2d2464bd
MD
1577static
1578const struct trace_syscall_entry *syscall_list_get_entry(loff_t *pos)
1579{
1580 const struct trace_syscall_entry *entry;
1581 int iter = 0;
1582
ebcc64cd
FD
1583 for (entry = sc_table.table;
1584 entry < sc_table.table + sc_table.len;
2d2464bd
MD
1585 entry++) {
1586 if (iter++ >= *pos)
1587 return entry;
1588 }
ebcc64cd
FD
1589 for (entry = compat_sc_table.table;
1590 entry < compat_sc_table.table + compat_sc_table.len;
2d2464bd
MD
1591 entry++) {
1592 if (iter++ >= *pos)
1593 return entry;
1594 }
1595 /* End of list */
1596 return NULL;
1597}
1598
1599static
1600void *syscall_list_start(struct seq_file *m, loff_t *pos)
1601{
1602 return (void *) syscall_list_get_entry(pos);
1603}
1604
1605static
1606void *syscall_list_next(struct seq_file *m, void *p, loff_t *ppos)
1607{
1608 (*ppos)++;
1609 return (void *) syscall_list_get_entry(ppos);
1610}
1611
1612static
1613void syscall_list_stop(struct seq_file *m, void *p)
1614{
1615}
1616
12e579db
MD
1617static
1618int get_sc_table(const struct trace_syscall_entry *entry,
1619 const struct trace_syscall_entry **table,
1620 unsigned int *bitness)
1621{
ebcc64cd 1622 if (entry >= sc_table.table && entry < sc_table.table + sc_table.len) {
12e579db
MD
1623 if (bitness)
1624 *bitness = BITS_PER_LONG;
1625 if (table)
ebcc64cd 1626 *table = sc_table.table;
12e579db
MD
1627 return 0;
1628 }
ebcc64cd
FD
1629 if (!(entry >= compat_sc_table.table
1630 && entry < compat_sc_table.table + compat_sc_table.len)) {
12e579db
MD
1631 return -EINVAL;
1632 }
1633 if (bitness)
1634 *bitness = 32;
1635 if (table)
ebcc64cd 1636 *table = compat_sc_table.table;
12e579db
MD
1637 return 0;
1638}
1639
2d2464bd
MD
1640static
1641int syscall_list_show(struct seq_file *m, void *p)
1642{
1643 const struct trace_syscall_entry *table, *entry = p;
1644 unsigned int bitness;
d4291869 1645 unsigned long index;
12e579db 1646 int ret;
d4291869 1647 const char *name;
2d2464bd 1648
12e579db
MD
1649 ret = get_sc_table(entry, &table, &bitness);
1650 if (ret)
1651 return ret;
f4855b46
MD
1652 if (!entry->desc)
1653 return 0;
ebcc64cd 1654 if (table == sc_table.table) {
d4291869 1655 index = entry - table;
437d5aa5 1656 name = &entry->desc->event_name[strlen(SYSCALL_ENTRY_STR)];
d4291869 1657 } else {
ebcc64cd 1658 index = (entry - table) + sc_table.len;
437d5aa5 1659 name = &entry->desc->event_name[strlen(COMPAT_SYSCALL_ENTRY_STR)];
d4291869 1660 }
12e579db 1661 seq_printf(m, "syscall { index = %lu; name = %s; bitness = %u; };\n",
d4291869 1662 index, name, bitness);
2d2464bd
MD
1663 return 0;
1664}
1665
1666static
1667const struct seq_operations lttng_syscall_list_seq_ops = {
1668 .start = syscall_list_start,
1669 .next = syscall_list_next,
1670 .stop = syscall_list_stop,
1671 .show = syscall_list_show,
1672};
1673
1674static
1675int lttng_syscall_list_open(struct inode *inode, struct file *file)
1676{
1677 return seq_open(file, &lttng_syscall_list_seq_ops);
1678}
1679
1680const struct file_operations lttng_syscall_list_fops = {
1681 .owner = THIS_MODULE,
1682 .open = lttng_syscall_list_open,
1683 .read = seq_read,
1684 .llseek = seq_lseek,
1685 .release = seq_release,
1686};
12e579db 1687
badfe9f5
MD
1688/*
1689 * A syscall is enabled if it is traced for either entry or exit.
1690 */
12e579db 1691long lttng_channel_syscall_mask(struct lttng_channel *channel,
606828e4 1692 struct lttng_kernel_abi_syscall_mask __user *usyscall_mask)
12e579db
MD
1693{
1694 uint32_t len, sc_tables_len, bitmask_len;
1695 int ret = 0, bit;
1696 char *tmp_mask;
1697 struct lttng_syscall_filter *filter;
1698
1699 ret = get_user(len, &usyscall_mask->len);
1700 if (ret)
1701 return ret;
1702 sc_tables_len = get_sc_tables_len();
1703 bitmask_len = ALIGN(sc_tables_len, 8) >> 3;
1704 if (len < sc_tables_len) {
1705 return put_user(sc_tables_len, &usyscall_mask->len);
1706 }
1707 /* Array is large enough, we can copy array to user-space. */
1708 tmp_mask = kzalloc(bitmask_len, GFP_KERNEL);
1709 if (!tmp_mask)
1710 return -ENOMEM;
1711 filter = channel->sc_filter;
1712
ebcc64cd 1713 for (bit = 0; bit < sc_table.len; bit++) {
e2129868 1714 char state;
2f25059d
MD
1715
1716 if (channel->sc_table) {
3b82c4e1
MD
1717 if (!(READ_ONCE(channel->syscall_all_entry)
1718 || READ_ONCE(channel->syscall_all_exit)) && filter)
badfe9f5
MD
1719 state = test_bit(bit, filter->sc_entry)
1720 || test_bit(bit, filter->sc_exit);
2f25059d
MD
1721 else
1722 state = 1;
1723 } else {
1724 state = 0;
1725 }
1726 bt_bitfield_write_be(tmp_mask, char, bit, 1, state);
12e579db
MD
1727 }
1728 for (; bit < sc_tables_len; bit++) {
e2129868 1729 char state;
2f25059d
MD
1730
1731 if (channel->compat_sc_table) {
3b82c4e1
MD
1732 if (!(READ_ONCE(channel->syscall_all_entry)
1733 || READ_ONCE(channel->syscall_all_exit)) && filter)
ebcc64cd 1734 state = test_bit(bit - sc_table.len,
badfe9f5 1735 filter->sc_compat_entry)
ebcc64cd 1736 || test_bit(bit - sc_table.len,
badfe9f5 1737 filter->sc_compat_exit);
2f25059d
MD
1738 else
1739 state = 1;
1740 } else {
1741 state = 0;
1742 }
1743 bt_bitfield_write_be(tmp_mask, char, bit, 1, state);
12e579db
MD
1744 }
1745 if (copy_to_user(usyscall_mask->mask, tmp_mask, bitmask_len))
1746 ret = -EFAULT;
1747 kfree(tmp_mask);
1748 return ret;
1749}
082d4946
MD
1750
1751int lttng_abi_syscall_list(void)
1752{
1753 struct file *syscall_list_file;
1754 int file_fd, ret;
1755
4ac10b76 1756 file_fd = lttng_get_unused_fd();
082d4946
MD
1757 if (file_fd < 0) {
1758 ret = file_fd;
1759 goto fd_error;
1760 }
1761
1762 syscall_list_file = anon_inode_getfile("[lttng_syscall_list]",
1763 &lttng_syscall_list_fops,
1764 NULL, O_RDWR);
1765 if (IS_ERR(syscall_list_file)) {
1766 ret = PTR_ERR(syscall_list_file);
1767 goto file_error;
1768 }
1769 ret = lttng_syscall_list_fops.open(NULL, syscall_list_file);
1770 if (ret < 0)
1771 goto open_error;
1772 fd_install(file_fd, syscall_list_file);
082d4946
MD
1773 return file_fd;
1774
1775open_error:
1776 fput(syscall_list_file);
1777file_error:
1778 put_unused_fd(file_fd);
1779fd_error:
1780 return ret;
1781}
This page took 0.140382 seconds and 4 git commands to generate.