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