syscall instrumentation: add missing forward declarations for old kernels
[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 <wrapper/limits.h>
32#include <lttng/events.h>
33#include <lttng/events-internal.h>
34#include <lttng/utils.h>
35
36#include "lttng-syscalls.h"
37
38#ifndef CONFIG_COMPAT
39# ifndef is_compat_task
40# define is_compat_task() (0)
41# endif
42#endif
43
44/* in_compat_syscall appears in kernel 4.6. */
45#ifndef in_compat_syscall
46 #define in_compat_syscall() is_compat_task()
47#endif
48
49enum sc_type {
50 SC_TYPE_ENTRY,
51 SC_TYPE_EXIT,
52 SC_TYPE_COMPAT_ENTRY,
53 SC_TYPE_COMPAT_EXIT,
54};
55
56#define SYSCALL_ENTRY_TOK syscall_entry_
57#define COMPAT_SYSCALL_ENTRY_TOK compat_syscall_entry_
58#define SYSCALL_EXIT_TOK syscall_exit_
59#define COMPAT_SYSCALL_EXIT_TOK compat_syscall_exit_
60
61#define SYSCALL_ENTRY_STR __stringify(SYSCALL_ENTRY_TOK)
62#define COMPAT_SYSCALL_ENTRY_STR __stringify(COMPAT_SYSCALL_ENTRY_TOK)
63#define SYSCALL_EXIT_STR __stringify(SYSCALL_EXIT_TOK)
64#define COMPAT_SYSCALL_EXIT_STR __stringify(COMPAT_SYSCALL_EXIT_TOK)
65
66void syscall_entry_event_probe(void *__data, struct pt_regs *regs, long id);
67void syscall_exit_event_probe(void *__data, struct pt_regs *regs, long ret);
68
69/*
70 * Forward declarations for old kernels.
71 */
72struct mmsghdr;
73struct rlimit64;
74struct oldold_utsname;
75struct old_utsname;
76struct sel_arg_struct;
77struct mmap_arg_struct;
78struct file_handle;
79struct user_msghdr;
80struct __kernel_old_itimerval;
81struct open_how;
82struct mount_attr;
83struct futex_waitv;
84
85/*
86 * Forward declaration for kernels >= 5.6
87 */
88struct timex;
89struct timeval;
90struct itimerval;
91struct itimerspec;
92
93#if (LTTNG_LINUX_VERSION_CODE >= LTTNG_KERNEL_VERSION(5,6,0))
94typedef __kernel_old_time_t time_t;
95#endif
96
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
103/*
104 * Create LTTng tracepoint probes.
105 */
106#define LTTNG_PACKAGE_BUILD
107#define CREATE_TRACE_POINTS
108#define TP_MODULE_NOINIT
109#define TRACE_INCLUDE_PATH instrumentation/syscalls/headers
110
111#define PARAMS(args...) args
112
113/* Handle unknown syscalls */
114#undef TRACE_SYSTEM
115#define TRACE_SYSTEM syscalls_unknown
116#include <instrumentation/syscalls/headers/syscalls_unknown.h>
117#undef TRACE_SYSTEM
118
119#undef TP_PROBE_CB
120
121extern const struct trace_syscall_table sc_table;
122extern const struct trace_syscall_table compat_sc_table;
123
124/* Event syscall exit table */
125extern const struct trace_syscall_table sc_exit_table;
126extern const struct trace_syscall_table compat_sc_exit_table;
127
128
129#undef SC_EXIT
130
131#undef CREATE_SYSCALL_TABLE
132
133struct lttng_syscall_filter {
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);
138
139 /*
140 * Reference counters keeping track of number of events enabled
141 * for each bit.
142 */
143 u32 sc_entry_refcount_map[NR_syscalls];
144 u32 sc_exit_refcount_map[NR_syscalls];
145 u32 sc_compat_entry_refcount_map[NR_compat_syscalls];
146 u32 sc_compat_exit_refcount_map[NR_compat_syscalls];
147};
148
149static void syscall_entry_event_unknown(struct hlist_head *unknown_action_list_head,
150 struct pt_regs *regs, long id)
151{
152 unsigned long args[LTTNG_SYSCALL_NR_ARGS];
153 struct lttng_kernel_event_common_private *event_priv;
154
155 lttng_syscall_get_arguments(current, regs, args);
156 lttng_hlist_for_each_entry_rcu(event_priv, unknown_action_list_head, u.syscall.node) {
157 if (unlikely(in_compat_syscall()))
158 __event_probe__compat_syscall_entry_unknown(event_priv->pub, id, args);
159 else
160 __event_probe__syscall_entry_unknown(event_priv->pub, id, args);
161 }
162}
163
164static __always_inline
165void syscall_entry_event_call_func(struct hlist_head *action_list,
166 void *func, unsigned int nrargs,
167 struct pt_regs *regs)
168{
169 struct lttng_kernel_event_common_private *event_priv;
170
171 switch (nrargs) {
172 case 0:
173 {
174 void (*fptr)(void *__data) = func;
175
176 lttng_hlist_for_each_entry_rcu(event_priv, action_list, u.syscall.node)
177 fptr(event_priv->pub);
178 break;
179 }
180 case 1:
181 {
182 void (*fptr)(void *__data, unsigned long arg0) = func;
183 unsigned long args[LTTNG_SYSCALL_NR_ARGS];
184
185 lttng_syscall_get_arguments(current, regs, args);
186 lttng_hlist_for_each_entry_rcu(event_priv, action_list, u.syscall.node)
187 fptr(event_priv->pub, args[0]);
188 break;
189 }
190 case 2:
191 {
192 void (*fptr)(void *__data,
193 unsigned long arg0,
194 unsigned long arg1) = func;
195 unsigned long args[LTTNG_SYSCALL_NR_ARGS];
196
197 lttng_syscall_get_arguments(current, regs, args);
198 lttng_hlist_for_each_entry_rcu(event_priv, action_list, u.syscall.node)
199 fptr(event_priv->pub, args[0], args[1]);
200 break;
201 }
202 case 3:
203 {
204 void (*fptr)(void *__data,
205 unsigned long arg0,
206 unsigned long arg1,
207 unsigned long arg2) = 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]);
213 break;
214 }
215 case 4:
216 {
217 void (*fptr)(void *__data,
218 unsigned long arg0,
219 unsigned long arg1,
220 unsigned long arg2,
221 unsigned long arg3) = func;
222 unsigned long args[LTTNG_SYSCALL_NR_ARGS];
223
224 lttng_syscall_get_arguments(current, regs, args);
225 lttng_hlist_for_each_entry_rcu(event_priv, action_list, u.syscall.node)
226 fptr(event_priv->pub, args[0], args[1], args[2], args[3]);
227 break;
228 }
229 case 5:
230 {
231 void (*fptr)(void *__data,
232 unsigned long arg0,
233 unsigned long arg1,
234 unsigned long arg2,
235 unsigned long arg3,
236 unsigned long arg4) = func;
237 unsigned long args[LTTNG_SYSCALL_NR_ARGS];
238
239 lttng_syscall_get_arguments(current, regs, args);
240 lttng_hlist_for_each_entry_rcu(event_priv, action_list, u.syscall.node)
241 fptr(event_priv->pub, args[0], args[1], args[2], args[3], args[4]);
242 break;
243 }
244 case 6:
245 {
246 void (*fptr)(void *__data,
247 unsigned long arg0,
248 unsigned long arg1,
249 unsigned long arg2,
250 unsigned long arg3,
251 unsigned long arg4,
252 unsigned long arg5) = func;
253 unsigned long args[LTTNG_SYSCALL_NR_ARGS];
254
255 lttng_syscall_get_arguments(current, regs, args);
256 lttng_hlist_for_each_entry_rcu(event_priv, action_list, u.syscall.node)
257 fptr(event_priv->pub, args[0], args[1], args[2],
258 args[3], args[4], args[5]);
259 break;
260 }
261 default:
262 break;
263 }
264}
265
266void syscall_entry_event_probe(void *__data, struct pt_regs *regs, long id)
267{
268 struct lttng_kernel_syscall_table *syscall_table = __data;
269 struct hlist_head *action_list, *unknown_action_list;
270 const struct trace_syscall_entry *table, *entry;
271 size_t table_len;
272
273 if (unlikely(in_compat_syscall())) {
274 struct lttng_syscall_filter *filter = syscall_table->sc_filter;
275
276 if (id < 0 || id >= NR_compat_syscalls
277 || (!READ_ONCE(syscall_table->syscall_all_entry) && !test_bit(id, filter->sc_compat_entry))) {
278 /* System call filtered out. */
279 return;
280 }
281 table = compat_sc_table.table;
282 table_len = compat_sc_table.len;
283 unknown_action_list = &syscall_table->compat_unknown_syscall_dispatch;
284 } else {
285 struct lttng_syscall_filter *filter = syscall_table->sc_filter;
286
287 if (id < 0 || id >= NR_syscalls
288 || (!READ_ONCE(syscall_table->syscall_all_entry) && !test_bit(id, filter->sc_entry))) {
289 /* System call filtered out. */
290 return;
291 }
292 table = sc_table.table;
293 table_len = sc_table.len;
294 unknown_action_list = &syscall_table->unknown_syscall_dispatch;
295 }
296 if (unlikely(id < 0 || id >= table_len)) {
297 syscall_entry_event_unknown(unknown_action_list, regs, id);
298 return;
299 }
300
301 entry = &table[id];
302 if (!entry->event_func) {
303 syscall_entry_event_unknown(unknown_action_list, regs, id);
304 return;
305 }
306
307 if (unlikely(in_compat_syscall())) {
308 action_list = &syscall_table->compat_syscall_dispatch[id];
309 } else {
310 action_list = &syscall_table->syscall_dispatch[id];
311 }
312 if (unlikely(hlist_empty(action_list)))
313 return;
314
315 syscall_entry_event_call_func(action_list, entry->event_func, entry->nrargs, regs);
316}
317
318static void syscall_exit_event_unknown(struct hlist_head *unknown_action_list_head,
319 struct pt_regs *regs, long id, long ret)
320{
321 unsigned long args[LTTNG_SYSCALL_NR_ARGS];
322 struct lttng_kernel_event_common_private *event_priv;
323
324 lttng_syscall_get_arguments(current, regs, args);
325 lttng_hlist_for_each_entry_rcu(event_priv, unknown_action_list_head, u.syscall.node) {
326 if (unlikely(in_compat_syscall()))
327 __event_probe__compat_syscall_exit_unknown(event_priv->pub, id, ret,
328 args);
329 else
330 __event_probe__syscall_exit_unknown(event_priv->pub, id, ret, args);
331 }
332}
333
334static __always_inline
335void syscall_exit_event_call_func(struct hlist_head *action_list,
336 void *func, unsigned int nrargs,
337 struct pt_regs *regs, long ret)
338{
339 struct lttng_kernel_event_common_private *event_priv;
340
341 switch (nrargs) {
342 case 0:
343 {
344 void (*fptr)(void *__data, long ret) = func;
345
346 lttng_hlist_for_each_entry_rcu(event_priv, action_list, u.syscall.node)
347 fptr(event_priv->pub, ret);
348 break;
349 }
350 case 1:
351 {
352 void (*fptr)(void *__data,
353 long ret,
354 unsigned long arg0) = func;
355 unsigned long args[LTTNG_SYSCALL_NR_ARGS];
356
357 lttng_syscall_get_arguments(current, regs, args);
358 lttng_hlist_for_each_entry_rcu(event_priv, action_list, u.syscall.node)
359 fptr(event_priv->pub, ret, args[0]);
360 break;
361 }
362 case 2:
363 {
364 void (*fptr)(void *__data,
365 long ret,
366 unsigned long arg0,
367 unsigned long arg1) = 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]);
373 break;
374 }
375 case 3:
376 {
377 void (*fptr)(void *__data,
378 long ret,
379 unsigned long arg0,
380 unsigned long arg1,
381 unsigned long arg2) = func;
382 unsigned long args[LTTNG_SYSCALL_NR_ARGS];
383
384 lttng_syscall_get_arguments(current, regs, args);
385 lttng_hlist_for_each_entry_rcu(event_priv, action_list, u.syscall.node)
386 fptr(event_priv->pub, ret, args[0], args[1], args[2]);
387 break;
388 }
389 case 4:
390 {
391 void (*fptr)(void *__data,
392 long ret,
393 unsigned long arg0,
394 unsigned long arg1,
395 unsigned long arg2,
396 unsigned long arg3) = func;
397 unsigned long args[LTTNG_SYSCALL_NR_ARGS];
398
399 lttng_syscall_get_arguments(current, regs, args);
400 lttng_hlist_for_each_entry_rcu(event_priv, action_list, u.syscall.node)
401 fptr(event_priv->pub, ret, args[0], args[1], args[2], args[3]);
402 break;
403 }
404 case 5:
405 {
406 void (*fptr)(void *__data,
407 long ret,
408 unsigned long arg0,
409 unsigned long arg1,
410 unsigned long arg2,
411 unsigned long arg3,
412 unsigned long arg4) = func;
413 unsigned long args[LTTNG_SYSCALL_NR_ARGS];
414
415 lttng_syscall_get_arguments(current, regs, args);
416 lttng_hlist_for_each_entry_rcu(event_priv, action_list, u.syscall.node)
417 fptr(event_priv->pub, ret, args[0], args[1], args[2], args[3], args[4]);
418 break;
419 }
420 case 6:
421 {
422 void (*fptr)(void *__data,
423 long ret,
424 unsigned long arg0,
425 unsigned long arg1,
426 unsigned long arg2,
427 unsigned long arg3,
428 unsigned long arg4,
429 unsigned long arg5) = func;
430 unsigned long args[LTTNG_SYSCALL_NR_ARGS];
431
432 lttng_syscall_get_arguments(current, regs, args);
433 lttng_hlist_for_each_entry_rcu(event_priv, action_list, u.syscall.node)
434 fptr(event_priv->pub, ret, args[0], args[1], args[2],
435 args[3], args[4], args[5]);
436 break;
437 }
438 default:
439 break;
440 }
441}
442
443void syscall_exit_event_probe(void *__data, struct pt_regs *regs, long ret)
444{
445 struct lttng_kernel_syscall_table *syscall_table = __data;
446 struct hlist_head *action_list, *unknown_action_list;
447 const struct trace_syscall_entry *table, *entry;
448 size_t table_len;
449 long id;
450
451 id = syscall_get_nr(current, regs);
452
453 if (unlikely(in_compat_syscall())) {
454 struct lttng_syscall_filter *filter = syscall_table->sc_filter;
455
456 if (id < 0 || id >= NR_compat_syscalls
457 || (!READ_ONCE(syscall_table->syscall_all_exit) && !test_bit(id, filter->sc_compat_exit))) {
458 /* System call filtered out. */
459 return;
460 }
461 table = compat_sc_exit_table.table;
462 table_len = compat_sc_exit_table.len;
463 unknown_action_list = &syscall_table->compat_unknown_syscall_exit_dispatch;
464 } else {
465 struct lttng_syscall_filter *filter = syscall_table->sc_filter;
466
467 if (id < 0 || id >= NR_syscalls
468 || (!READ_ONCE(syscall_table->syscall_all_exit) && !test_bit(id, filter->sc_exit))) {
469 /* System call filtered out. */
470 return;
471 }
472 table = sc_exit_table.table;
473 table_len = sc_exit_table.len;
474 unknown_action_list = &syscall_table->unknown_syscall_exit_dispatch;
475 }
476 if (unlikely(id < 0 || id >= table_len)) {
477 syscall_exit_event_unknown(unknown_action_list, regs, id, ret);
478 return;
479 }
480
481 entry = &table[id];
482 if (!entry->event_func) {
483 syscall_exit_event_unknown(unknown_action_list, regs, id, ret);
484 return;
485 }
486
487 if (unlikely(in_compat_syscall())) {
488 action_list = &syscall_table->compat_syscall_exit_dispatch[id];
489 } else {
490 action_list = &syscall_table->syscall_exit_dispatch[id];
491 }
492 if (unlikely(hlist_empty(action_list)))
493 return;
494
495 syscall_exit_event_call_func(action_list, entry->event_func, entry->nrargs,
496 regs, ret);
497}
498
499static
500struct lttng_kernel_syscall_table *get_syscall_table_from_enabler(struct lttng_event_enabler_common *event_enabler)
501{
502 switch (event_enabler->enabler_type) {
503 case LTTNG_EVENT_ENABLER_TYPE_RECORDER:
504 {
505 struct lttng_event_recorder_enabler *event_recorder_enabler =
506 container_of(event_enabler, struct lttng_event_recorder_enabler, parent);
507 return &event_recorder_enabler->chan->priv->parent.syscall_table;
508 }
509 case LTTNG_EVENT_ENABLER_TYPE_NOTIFIER:
510 {
511 struct lttng_event_notifier_enabler *event_notifier_enabler =
512 container_of(event_enabler, struct lttng_event_notifier_enabler, parent);
513 return &event_notifier_enabler->group->syscall_table;
514 }
515 default:
516 return NULL;
517 }
518}
519
520static
521struct lttng_kernel_syscall_table *get_syscall_table_from_event(struct lttng_kernel_event_common *event)
522{
523 switch (event->type) {
524 case LTTNG_KERNEL_EVENT_TYPE_RECORDER:
525 {
526 struct lttng_kernel_event_recorder *event_recorder =
527 container_of(event, struct lttng_kernel_event_recorder, parent);
528 return &event_recorder->chan->priv->parent.syscall_table;
529 }
530 case LTTNG_KERNEL_EVENT_TYPE_NOTIFIER:
531 {
532 struct lttng_kernel_event_notifier *event_notifier =
533 container_of(event, struct lttng_kernel_event_notifier, parent);
534 return &event_notifier->priv->group->syscall_table;
535 }
536 default:
537 return NULL;
538 }
539}
540
541static
542void lttng_syscall_event_enabler_create_event(struct lttng_event_enabler_common *syscall_event_enabler,
543 const struct lttng_kernel_event_desc *desc, enum sc_type type, unsigned int syscall_nr)
544{
545 struct lttng_kernel_event_common *event;
546
547 switch (syscall_event_enabler->enabler_type) {
548 case LTTNG_EVENT_ENABLER_TYPE_RECORDER:
549 {
550 struct lttng_event_recorder_enabler *syscall_event_recorder_enabler =
551 container_of(syscall_event_enabler, struct lttng_event_recorder_enabler, parent);
552 struct lttng_event_recorder_enabler *event_recorder_enabler;
553 struct lttng_kernel_abi_event ev;
554
555 /* We need to create an event for this syscall/enabler. */
556 memset(&ev, 0, sizeof(ev));
557 switch (type) {
558 case SC_TYPE_ENTRY:
559 ev.u.syscall.entryexit = LTTNG_KERNEL_ABI_SYSCALL_ENTRY;
560 ev.u.syscall.abi = LTTNG_KERNEL_ABI_SYSCALL_ABI_NATIVE;
561 break;
562 case SC_TYPE_EXIT:
563 ev.u.syscall.entryexit = LTTNG_KERNEL_ABI_SYSCALL_EXIT;
564 ev.u.syscall.abi = LTTNG_KERNEL_ABI_SYSCALL_ABI_NATIVE;
565 break;
566 case SC_TYPE_COMPAT_ENTRY:
567 ev.u.syscall.entryexit = LTTNG_KERNEL_ABI_SYSCALL_ENTRY;
568 ev.u.syscall.abi = LTTNG_KERNEL_ABI_SYSCALL_ABI_COMPAT;
569 break;
570 case SC_TYPE_COMPAT_EXIT:
571 ev.u.syscall.entryexit = LTTNG_KERNEL_ABI_SYSCALL_EXIT;
572 ev.u.syscall.abi = LTTNG_KERNEL_ABI_SYSCALL_ABI_COMPAT;
573 break;
574 }
575 strncpy(ev.name, desc->event_name, LTTNG_KERNEL_ABI_SYM_NAME_LEN - 1);
576 ev.name[LTTNG_KERNEL_ABI_SYM_NAME_LEN - 1] = '\0';
577 ev.instrumentation = LTTNG_KERNEL_ABI_SYSCALL;
578 event_recorder_enabler = lttng_event_recorder_enabler_create(LTTNG_ENABLER_FORMAT_NAME, &ev,
579 syscall_event_recorder_enabler->chan);
580 WARN_ON_ONCE(!event_recorder_enabler);
581 if (!event_recorder_enabler)
582 return;
583 event = _lttng_kernel_event_create(&event_recorder_enabler->parent, desc);
584 WARN_ON_ONCE(IS_ERR(event));
585 lttng_event_enabler_destroy(&event_recorder_enabler->parent);
586 if (IS_ERR(event)) {
587 printk(KERN_INFO "Unable to create event recorder %s\n", desc->event_name);
588 return;
589 }
590 event->priv->u.syscall.syscall_id = syscall_nr;
591 break;
592 }
593 case LTTNG_EVENT_ENABLER_TYPE_NOTIFIER:
594 {
595 struct lttng_event_notifier_enabler *syscall_event_notifier_enabler =
596 container_of(syscall_event_enabler, struct lttng_event_notifier_enabler, parent);
597 struct lttng_event_notifier_enabler *event_notifier_enabler;
598 struct lttng_kernel_abi_event_notifier event_notifier_param;
599 uint64_t user_token = syscall_event_enabler->user_token;
600 uint64_t error_counter_index = syscall_event_notifier_enabler->error_counter_index;
601
602 memset(&event_notifier_param, 0, sizeof(event_notifier_param));
603 switch (type) {
604 case SC_TYPE_ENTRY:
605 event_notifier_param.event.u.syscall.entryexit = LTTNG_KERNEL_ABI_SYSCALL_ENTRY;
606 event_notifier_param.event.u.syscall.abi = LTTNG_KERNEL_ABI_SYSCALL_ABI_NATIVE;
607 break;
608 case SC_TYPE_EXIT:
609 event_notifier_param.event.u.syscall.entryexit = LTTNG_KERNEL_ABI_SYSCALL_EXIT;
610 event_notifier_param.event.u.syscall.abi = LTTNG_KERNEL_ABI_SYSCALL_ABI_NATIVE;
611 break;
612 case SC_TYPE_COMPAT_ENTRY:
613 event_notifier_param.event.u.syscall.entryexit = LTTNG_KERNEL_ABI_SYSCALL_ENTRY;
614 event_notifier_param.event.u.syscall.abi = LTTNG_KERNEL_ABI_SYSCALL_ABI_COMPAT;
615 break;
616 case SC_TYPE_COMPAT_EXIT:
617 event_notifier_param.event.u.syscall.entryexit = LTTNG_KERNEL_ABI_SYSCALL_EXIT;
618 event_notifier_param.event.u.syscall.abi = LTTNG_KERNEL_ABI_SYSCALL_ABI_COMPAT;
619 break;
620 }
621 strncat(event_notifier_param.event.name, desc->event_name,
622 LTTNG_KERNEL_ABI_SYM_NAME_LEN - strlen(event_notifier_param.event.name) - 1);
623 event_notifier_param.event.name[LTTNG_KERNEL_ABI_SYM_NAME_LEN - 1] = '\0';
624 event_notifier_param.event.instrumentation = LTTNG_KERNEL_ABI_SYSCALL;
625 event_notifier_param.event.token = user_token;
626 event_notifier_param.error_counter_index = error_counter_index;
627
628 event_notifier_enabler = lttng_event_notifier_enabler_create(LTTNG_ENABLER_FORMAT_NAME,
629 &event_notifier_param, syscall_event_notifier_enabler->group);
630 WARN_ON_ONCE(!event_notifier_enabler);
631 event = _lttng_kernel_event_create(&event_notifier_enabler->parent, desc);
632 WARN_ON_ONCE(IS_ERR(event));
633 lttng_event_enabler_destroy(&event_notifier_enabler->parent);
634 if (IS_ERR(event)) {
635 printk(KERN_INFO "Unable to create event notifier %s\n", desc->event_name);
636 return;
637 }
638 event->priv->u.syscall.syscall_id = syscall_nr;
639 break;
640 }
641 default:
642 break;
643 }
644}
645
646static
647void lttng_syscall_event_enabler_create_matching_syscall_table_events(struct lttng_event_enabler_common *syscall_event_enabler_common,
648 const struct trace_syscall_entry *table, size_t table_len, enum sc_type type)
649{
650 struct lttng_event_ht *events_ht = lttng_get_event_ht_from_enabler(syscall_event_enabler_common);
651 const struct lttng_kernel_event_desc *desc;
652 unsigned int i;
653
654#ifndef CONFIG_COMPAT
655 if (type == SC_TYPE_COMPAT_ENTRY || type == SC_TYPE_COMPAT_EXIT)
656 return;
657#endif
658 /* iterate over all syscall and create event that match */
659 for (i = 0; i < table_len; i++) {
660 struct lttng_kernel_event_common_private *event_priv;
661 struct hlist_head *head;
662 bool found = false;
663
664 desc = table[i].desc;
665 if (!desc) {
666 /* Unknown syscall */
667 continue;
668 }
669
670 if (!lttng_desc_match_enabler(desc, syscall_event_enabler_common))
671 continue;
672
673 /*
674 * Check if already created.
675 */
676 head = utils_borrow_hash_table_bucket(events_ht->table, LTTNG_EVENT_HT_SIZE, desc->event_name);
677 lttng_hlist_for_each_entry(event_priv, head, hlist_node) {
678 if (lttng_event_enabler_desc_match_event(syscall_event_enabler_common, desc, event_priv->pub)) {
679 found = true;
680 break;
681 }
682 }
683 if (found)
684 continue;
685
686 lttng_syscall_event_enabler_create_event(syscall_event_enabler_common, desc, type, i);
687 }
688}
689
690static
691bool lttng_syscall_event_enabler_is_wildcard_all(struct lttng_event_enabler_common *event_enabler)
692{
693 if (event_enabler->event_param.instrumentation != LTTNG_KERNEL_ABI_SYSCALL)
694 return false;
695 if (event_enabler->event_param.u.syscall.abi != LTTNG_KERNEL_ABI_SYSCALL_ABI_ALL)
696 return false;
697 if (event_enabler->event_param.u.syscall.match != LTTNG_KERNEL_ABI_SYSCALL_MATCH_NAME)
698 return false;
699 if (strcmp(event_enabler->event_param.name, "*"))
700 return false;
701 return true;
702}
703
704static
705void create_unknown_syscall_event(struct lttng_event_enabler_common *event_enabler, enum sc_type type)
706{
707 struct lttng_event_ht *events_ht = lttng_get_event_ht_from_enabler(event_enabler);
708 struct lttng_kernel_event_common_private *event_priv;
709 const struct lttng_kernel_event_desc *desc;
710 bool found = false;
711 struct hlist_head *head;
712
713#ifndef CONFIG_COMPAT
714 if (type == SC_TYPE_COMPAT_ENTRY || type == SC_TYPE_COMPAT_EXIT)
715 return;
716#endif
717 /*
718 * Considering that currently system calls can only be enabled on a per
719 * name basis (or wildcard based on a name), unknown syscall events are
720 * only used when matching *all* system calls, because this is the only
721 * case which can be associated with an unknown system call.
722 *
723 * When enabling system call on a per system call number basis will be
724 * supported, this will need to be revisited.
725 */
726 if (!lttng_syscall_event_enabler_is_wildcard_all(event_enabler))
727 return;
728
729 switch (type) {
730 case SC_TYPE_ENTRY:
731 desc = &__event_desc___syscall_entry_unknown;
732 break;
733 case SC_TYPE_EXIT:
734 desc = &__event_desc___syscall_exit_unknown;
735 break;
736 case SC_TYPE_COMPAT_ENTRY:
737 desc = &__event_desc___compat_syscall_entry_unknown;
738 break;
739 case SC_TYPE_COMPAT_EXIT:
740 desc = &__event_desc___compat_syscall_exit_unknown;
741 break;
742 default:
743 WARN_ON_ONCE(1);
744 }
745
746 /*
747 * Check if already created.
748 */
749 head = utils_borrow_hash_table_bucket(events_ht->table, LTTNG_EVENT_HT_SIZE, desc->event_name);
750 lttng_hlist_for_each_entry(event_priv, head, hlist_node) {
751 if (lttng_event_enabler_desc_match_event(event_enabler, desc, event_priv->pub)) {
752 found = true;
753 break;
754 }
755 }
756 if (!found)
757 lttng_syscall_event_enabler_create_event(event_enabler, desc, type, -1U);
758}
759
760static
761void lttng_syscall_event_enabler_create_matching_events(struct lttng_event_enabler_common *event_enabler)
762{
763 enum lttng_kernel_abi_syscall_entryexit entryexit = event_enabler->event_param.u.syscall.entryexit;
764
765 if (entryexit == LTTNG_KERNEL_ABI_SYSCALL_ENTRY || entryexit == LTTNG_KERNEL_ABI_SYSCALL_ENTRYEXIT) {
766 lttng_syscall_event_enabler_create_matching_syscall_table_events(event_enabler,
767 sc_table.table, sc_table.len, SC_TYPE_ENTRY);
768 lttng_syscall_event_enabler_create_matching_syscall_table_events(event_enabler,
769 compat_sc_table.table, compat_sc_table.len, SC_TYPE_COMPAT_ENTRY);
770 create_unknown_syscall_event(event_enabler, SC_TYPE_ENTRY);
771 create_unknown_syscall_event(event_enabler, SC_TYPE_COMPAT_ENTRY);
772 }
773
774 if (entryexit == LTTNG_KERNEL_ABI_SYSCALL_EXIT || entryexit == LTTNG_KERNEL_ABI_SYSCALL_ENTRYEXIT) {
775 lttng_syscall_event_enabler_create_matching_syscall_table_events(event_enabler,
776 sc_exit_table.table, sc_exit_table.len, SC_TYPE_EXIT);
777 lttng_syscall_event_enabler_create_matching_syscall_table_events(event_enabler,
778 compat_sc_exit_table.table, compat_sc_exit_table.len, SC_TYPE_COMPAT_EXIT);
779 create_unknown_syscall_event(event_enabler, SC_TYPE_EXIT);
780 create_unknown_syscall_event(event_enabler, SC_TYPE_COMPAT_EXIT);
781 }
782}
783
784/*
785 * Should be called with sessions lock held.
786 */
787int lttng_event_enabler_create_syscall_events_if_missing(struct lttng_event_enabler_common *syscall_event_enabler)
788{
789 struct lttng_kernel_syscall_table *syscall_table = get_syscall_table_from_enabler(syscall_event_enabler);
790 int ret;
791
792 if (!syscall_table->syscall_dispatch) {
793 /* create syscall table mapping syscall to events */
794 syscall_table->syscall_dispatch = kzalloc(sizeof(struct hlist_head) * sc_table.len, GFP_KERNEL);
795 if (!syscall_table->syscall_dispatch)
796 return -ENOMEM;
797 }
798 if (!syscall_table->syscall_exit_dispatch) {
799 /* create syscall table mapping syscall to events */
800 syscall_table->syscall_exit_dispatch = kzalloc(sizeof(struct hlist_head) * sc_exit_table.len, GFP_KERNEL);
801 if (!syscall_table->syscall_exit_dispatch)
802 return -ENOMEM;
803 }
804
805#ifdef CONFIG_COMPAT
806 if (!syscall_table->compat_syscall_dispatch) {
807 /* create syscall table mapping compat syscall to events */
808 syscall_table->compat_syscall_dispatch = kzalloc(sizeof(struct hlist_head) * compat_sc_table.len, GFP_KERNEL);
809 if (!syscall_table->compat_syscall_dispatch)
810 return -ENOMEM;
811 }
812
813 if (!syscall_table->compat_syscall_exit_dispatch) {
814 /* create syscall table mapping compat syscall to events */
815 syscall_table->compat_syscall_exit_dispatch = kzalloc(sizeof(struct hlist_head) * compat_sc_exit_table.len, GFP_KERNEL);
816 if (!syscall_table->compat_syscall_exit_dispatch)
817 return -ENOMEM;
818 }
819#endif
820 if (!syscall_table->sc_filter) {
821 syscall_table->sc_filter = kzalloc(sizeof(struct lttng_syscall_filter),
822 GFP_KERNEL);
823 if (!syscall_table->sc_filter)
824 return -ENOMEM;
825 }
826
827 if (!syscall_table->sys_enter_registered) {
828 ret = lttng_wrapper_tracepoint_probe_register("sys_enter",
829 (void *) syscall_entry_event_probe, syscall_table);
830 if (ret)
831 return ret;
832 syscall_table->sys_enter_registered = 1;
833 }
834 if (!syscall_table->sys_exit_registered) {
835 ret = lttng_wrapper_tracepoint_probe_register("sys_exit",
836 (void *) syscall_exit_event_probe, syscall_table);
837 if (ret) {
838 WARN_ON_ONCE(lttng_wrapper_tracepoint_probe_unregister("sys_enter",
839 (void *) syscall_entry_event_probe, syscall_table));
840 return ret;
841 }
842 syscall_table->sys_exit_registered = 1;
843 }
844
845 lttng_syscall_event_enabler_create_matching_events(syscall_event_enabler);
846
847 return 0;
848}
849
850int lttng_syscalls_unregister_syscall_table(struct lttng_kernel_syscall_table *syscall_table)
851{
852 int ret;
853
854 if (!syscall_table->syscall_dispatch)
855 return 0;
856 if (syscall_table->sys_enter_registered) {
857 ret = lttng_wrapper_tracepoint_probe_unregister("sys_enter",
858 (void *) syscall_entry_event_probe, syscall_table);
859 if (ret)
860 return ret;
861 syscall_table->sys_enter_registered = 0;
862 }
863 if (syscall_table->sys_exit_registered) {
864 ret = lttng_wrapper_tracepoint_probe_unregister("sys_exit",
865 (void *) syscall_exit_event_probe, syscall_table);
866 if (ret)
867 return ret;
868 syscall_table->sys_exit_registered = 0;
869 }
870 return 0;
871}
872
873int lttng_syscalls_destroy_syscall_table(struct lttng_kernel_syscall_table *syscall_table)
874{
875 kfree(syscall_table->syscall_dispatch);
876 kfree(syscall_table->syscall_exit_dispatch);
877#ifdef CONFIG_COMPAT
878 kfree(syscall_table->compat_syscall_dispatch);
879 kfree(syscall_table->compat_syscall_exit_dispatch);
880#endif
881 kfree(syscall_table->sc_filter);
882 return 0;
883}
884
885static
886uint32_t get_sc_tables_len(void)
887{
888 return sc_table.len + compat_sc_table.len;
889}
890
891static
892const char *get_syscall_name(const char *desc_name,
893 enum lttng_syscall_abi abi,
894 enum lttng_syscall_entryexit entryexit)
895{
896 size_t prefix_len = 0;
897
898
899 switch (entryexit) {
900 case LTTNG_SYSCALL_ENTRY:
901 switch (abi) {
902 case LTTNG_SYSCALL_ABI_NATIVE:
903 prefix_len = strlen(SYSCALL_ENTRY_STR);
904 break;
905 case LTTNG_SYSCALL_ABI_COMPAT:
906 prefix_len = strlen(COMPAT_SYSCALL_ENTRY_STR);
907 break;
908 }
909 break;
910 case LTTNG_SYSCALL_EXIT:
911 switch (abi) {
912 case LTTNG_SYSCALL_ABI_NATIVE:
913 prefix_len = strlen(SYSCALL_EXIT_STR);
914 break;
915 case LTTNG_SYSCALL_ABI_COMPAT:
916 prefix_len = strlen(COMPAT_SYSCALL_EXIT_STR);
917 break;
918 }
919 break;
920 }
921 WARN_ON_ONCE(prefix_len == 0);
922 return desc_name + prefix_len;
923}
924
925static
926int lttng_syscall_filter_enable(
927 struct lttng_syscall_filter *filter,
928 const char *desc_name, enum lttng_syscall_abi abi,
929 enum lttng_syscall_entryexit entryexit,
930 unsigned int syscall_id)
931{
932 const char *syscall_name;
933 unsigned long *bitmap;
934 u32 *refcount_map;
935
936 syscall_name = get_syscall_name(desc_name, abi, entryexit);
937
938 switch (entryexit) {
939 case LTTNG_SYSCALL_ENTRY:
940 switch (abi) {
941 case LTTNG_SYSCALL_ABI_NATIVE:
942 bitmap = filter->sc_entry;
943 refcount_map = filter->sc_entry_refcount_map;
944 break;
945 case LTTNG_SYSCALL_ABI_COMPAT:
946 bitmap = filter->sc_compat_entry;
947 refcount_map = filter->sc_compat_entry_refcount_map;
948 break;
949 default:
950 return -EINVAL;
951 }
952 break;
953 case LTTNG_SYSCALL_EXIT:
954 switch (abi) {
955 case LTTNG_SYSCALL_ABI_NATIVE:
956 bitmap = filter->sc_exit;
957 refcount_map = filter->sc_exit_refcount_map;
958 break;
959 case LTTNG_SYSCALL_ABI_COMPAT:
960 bitmap = filter->sc_compat_exit;
961 refcount_map = filter->sc_compat_exit_refcount_map;
962 break;
963 default:
964 return -EINVAL;
965 }
966 break;
967 default:
968 return -EINVAL;
969 }
970 if (refcount_map[syscall_id] == U32_MAX)
971 return -EOVERFLOW;
972 if (refcount_map[syscall_id]++ == 0)
973 bitmap_set(bitmap, syscall_id, 1);
974 return 0;
975}
976
977int lttng_syscall_filter_enable_event(struct lttng_kernel_event_common *event)
978{
979 struct lttng_kernel_syscall_table *syscall_table = get_syscall_table_from_event(event);
980 unsigned int syscall_id = event->priv->u.syscall.syscall_id;
981 struct hlist_head *dispatch_list;
982 int ret = 0;
983
984 WARN_ON_ONCE(event->priv->instrumentation != LTTNG_KERNEL_ABI_SYSCALL);
985
986 /* Unknown syscall */
987 if (syscall_id == -1U) {
988 switch (event->priv->u.syscall.entryexit) {
989 case LTTNG_SYSCALL_ENTRY:
990 switch (event->priv->u.syscall.abi) {
991 case LTTNG_SYSCALL_ABI_NATIVE:
992 dispatch_list = &syscall_table->unknown_syscall_dispatch;
993 break;
994 case LTTNG_SYSCALL_ABI_COMPAT:
995 dispatch_list = &syscall_table->compat_unknown_syscall_dispatch;
996 break;
997 default:
998 ret = -EINVAL;
999 goto end;
1000 }
1001 break;
1002 case LTTNG_SYSCALL_EXIT:
1003 switch (event->priv->u.syscall.abi) {
1004 case LTTNG_SYSCALL_ABI_NATIVE:
1005 dispatch_list = &syscall_table->unknown_syscall_exit_dispatch;
1006 break;
1007 case LTTNG_SYSCALL_ABI_COMPAT:
1008 dispatch_list = &syscall_table->compat_unknown_syscall_exit_dispatch;
1009 break;
1010 default:
1011 ret = -EINVAL;
1012 goto end;
1013 }
1014 break;
1015 default:
1016 ret = -EINVAL;
1017 goto end;
1018 }
1019 } else {
1020 ret = lttng_syscall_filter_enable(syscall_table->sc_filter,
1021 event->priv->desc->event_name, event->priv->u.syscall.abi,
1022 event->priv->u.syscall.entryexit, syscall_id);
1023 if (ret)
1024 return ret;
1025
1026 switch (event->priv->u.syscall.entryexit) {
1027 case LTTNG_SYSCALL_ENTRY:
1028 switch (event->priv->u.syscall.abi) {
1029 case LTTNG_SYSCALL_ABI_NATIVE:
1030 dispatch_list = &syscall_table->syscall_dispatch[syscall_id];
1031 break;
1032 case LTTNG_SYSCALL_ABI_COMPAT:
1033 dispatch_list = &syscall_table->compat_syscall_dispatch[syscall_id];
1034 break;
1035 default:
1036 ret = -EINVAL;
1037 goto end;
1038 }
1039 break;
1040 case LTTNG_SYSCALL_EXIT:
1041 switch (event->priv->u.syscall.abi) {
1042 case LTTNG_SYSCALL_ABI_NATIVE:
1043 dispatch_list = &syscall_table->syscall_exit_dispatch[syscall_id];
1044 break;
1045 case LTTNG_SYSCALL_ABI_COMPAT:
1046 dispatch_list = &syscall_table->compat_syscall_exit_dispatch[syscall_id];
1047 break;
1048 default:
1049 ret = -EINVAL;
1050 goto end;
1051 }
1052 break;
1053 default:
1054 ret = -EINVAL;
1055 goto end;
1056 }
1057 }
1058
1059 hlist_add_head_rcu(&event->priv->u.syscall.node, dispatch_list);
1060end:
1061 return ret;
1062}
1063
1064static
1065int lttng_syscall_filter_disable(struct lttng_syscall_filter *filter,
1066 const char *desc_name, enum lttng_syscall_abi abi,
1067 enum lttng_syscall_entryexit entryexit,
1068 unsigned int syscall_id)
1069{
1070 const char *syscall_name;
1071 unsigned long *bitmap;
1072 u32 *refcount_map;
1073
1074 syscall_name = get_syscall_name(desc_name, abi, entryexit);
1075
1076 switch (entryexit) {
1077 case LTTNG_SYSCALL_ENTRY:
1078 switch (abi) {
1079 case LTTNG_SYSCALL_ABI_NATIVE:
1080 bitmap = filter->sc_entry;
1081 refcount_map = filter->sc_entry_refcount_map;
1082 break;
1083 case LTTNG_SYSCALL_ABI_COMPAT:
1084 bitmap = filter->sc_compat_entry;
1085 refcount_map = filter->sc_compat_entry_refcount_map;
1086 break;
1087 default:
1088 return -EINVAL;
1089 }
1090 break;
1091 case LTTNG_SYSCALL_EXIT:
1092 switch (abi) {
1093 case LTTNG_SYSCALL_ABI_NATIVE:
1094 bitmap = filter->sc_exit;
1095 refcount_map = filter->sc_exit_refcount_map;
1096 break;
1097 case LTTNG_SYSCALL_ABI_COMPAT:
1098 bitmap = filter->sc_compat_exit;
1099 refcount_map = filter->sc_compat_exit_refcount_map;
1100 break;
1101 default:
1102 return -EINVAL;
1103 }
1104 break;
1105 default:
1106 return -EINVAL;
1107 }
1108 if (refcount_map[syscall_id] == 0)
1109 return -ENOENT;
1110 if (--refcount_map[syscall_id] == 0)
1111 bitmap_clear(bitmap, syscall_id, 1);
1112 return 0;
1113}
1114
1115int lttng_syscall_filter_disable_event(struct lttng_kernel_event_common *event)
1116{
1117 struct lttng_kernel_syscall_table *syscall_table = get_syscall_table_from_event(event);
1118 unsigned int syscall_id = event->priv->u.syscall.syscall_id;
1119 int ret;
1120
1121 /* Except for unknown syscall */
1122 if (syscall_id != -1U) {
1123 ret = lttng_syscall_filter_disable(syscall_table->sc_filter,
1124 event->priv->desc->event_name, event->priv->u.syscall.abi,
1125 event->priv->u.syscall.entryexit, syscall_id);
1126 if (ret)
1127 return ret;
1128 }
1129 hlist_del_rcu(&event->priv->u.syscall.node);
1130 return 0;
1131}
1132
1133void lttng_syscall_table_set_wildcard_all(struct lttng_event_enabler_common *event_enabler)
1134{
1135 struct lttng_kernel_syscall_table *syscall_table = get_syscall_table_from_enabler(event_enabler);
1136 enum lttng_kernel_abi_syscall_entryexit entryexit;
1137 int enabled = event_enabler->enabled;
1138
1139 if (!lttng_syscall_event_enabler_is_wildcard_all(event_enabler))
1140 return;
1141 entryexit = event_enabler->event_param.u.syscall.entryexit;
1142 if (entryexit == LTTNG_KERNEL_ABI_SYSCALL_ENTRY || entryexit == LTTNG_KERNEL_ABI_SYSCALL_ENTRYEXIT)
1143 WRITE_ONCE(syscall_table->syscall_all_entry, enabled);
1144
1145 if (entryexit == LTTNG_KERNEL_ABI_SYSCALL_EXIT || entryexit == LTTNG_KERNEL_ABI_SYSCALL_ENTRYEXIT)
1146 WRITE_ONCE(syscall_table->syscall_all_exit, enabled);
1147}
1148
1149static
1150const struct trace_syscall_entry *syscall_list_get_entry(loff_t *pos)
1151{
1152 const struct trace_syscall_entry *entry;
1153 int iter = 0;
1154
1155 for (entry = sc_table.table;
1156 entry < sc_table.table + sc_table.len;
1157 entry++) {
1158 if (iter++ >= *pos)
1159 return entry;
1160 }
1161 for (entry = compat_sc_table.table;
1162 entry < compat_sc_table.table + compat_sc_table.len;
1163 entry++) {
1164 if (iter++ >= *pos)
1165 return entry;
1166 }
1167 /* End of list */
1168 return NULL;
1169}
1170
1171static
1172void *syscall_list_start(struct seq_file *m, loff_t *pos)
1173{
1174 return (void *) syscall_list_get_entry(pos);
1175}
1176
1177static
1178void *syscall_list_next(struct seq_file *m, void *p, loff_t *ppos)
1179{
1180 (*ppos)++;
1181 return (void *) syscall_list_get_entry(ppos);
1182}
1183
1184static
1185void syscall_list_stop(struct seq_file *m, void *p)
1186{
1187}
1188
1189static
1190int get_sc_table(const struct trace_syscall_entry *entry,
1191 const struct trace_syscall_entry **table,
1192 unsigned int *bitness)
1193{
1194 if (entry >= sc_table.table && entry < sc_table.table + sc_table.len) {
1195 if (bitness)
1196 *bitness = BITS_PER_LONG;
1197 if (table)
1198 *table = sc_table.table;
1199 return 0;
1200 }
1201 if (!(entry >= compat_sc_table.table
1202 && entry < compat_sc_table.table + compat_sc_table.len)) {
1203 return -EINVAL;
1204 }
1205 if (bitness)
1206 *bitness = 32;
1207 if (table)
1208 *table = compat_sc_table.table;
1209 return 0;
1210}
1211
1212static
1213int syscall_list_show(struct seq_file *m, void *p)
1214{
1215 const struct trace_syscall_entry *table, *entry = p;
1216 unsigned int bitness;
1217 unsigned long index;
1218 int ret;
1219 const char *name;
1220
1221 ret = get_sc_table(entry, &table, &bitness);
1222 if (ret)
1223 return ret;
1224 if (!entry->desc)
1225 return 0;
1226 if (table == sc_table.table) {
1227 index = entry - table;
1228 name = &entry->desc->event_name[strlen(SYSCALL_ENTRY_STR)];
1229 } else {
1230 index = (entry - table) + sc_table.len;
1231 name = &entry->desc->event_name[strlen(COMPAT_SYSCALL_ENTRY_STR)];
1232 }
1233 seq_printf(m, "syscall { index = %lu; name = %s; bitness = %u; };\n",
1234 index, name, bitness);
1235 return 0;
1236}
1237
1238static
1239const struct seq_operations lttng_syscall_list_seq_ops = {
1240 .start = syscall_list_start,
1241 .next = syscall_list_next,
1242 .stop = syscall_list_stop,
1243 .show = syscall_list_show,
1244};
1245
1246static
1247int lttng_syscall_list_open(struct inode *inode, struct file *file)
1248{
1249 return seq_open(file, &lttng_syscall_list_seq_ops);
1250}
1251
1252const struct file_operations lttng_syscall_list_fops = {
1253 .owner = THIS_MODULE,
1254 .open = lttng_syscall_list_open,
1255 .read = seq_read,
1256 .llseek = seq_lseek,
1257 .release = seq_release,
1258};
1259
1260/*
1261 * A syscall is enabled if it is traced for either entry or exit.
1262 */
1263long lttng_syscall_table_get_active_mask(struct lttng_kernel_syscall_table *syscall_table,
1264 struct lttng_kernel_abi_syscall_mask __user *usyscall_mask)
1265{
1266 uint32_t len, sc_tables_len, bitmask_len;
1267 int ret = 0, bit;
1268 char *tmp_mask;
1269 struct lttng_syscall_filter *filter;
1270
1271 ret = get_user(len, &usyscall_mask->len);
1272 if (ret)
1273 return ret;
1274 sc_tables_len = get_sc_tables_len();
1275 bitmask_len = ALIGN(sc_tables_len, 8) >> 3;
1276 if (len < sc_tables_len) {
1277 return put_user(sc_tables_len, &usyscall_mask->len);
1278 }
1279 /* Array is large enough, we can copy array to user-space. */
1280 tmp_mask = kzalloc(bitmask_len, GFP_KERNEL);
1281 if (!tmp_mask)
1282 return -ENOMEM;
1283 filter = syscall_table->sc_filter;
1284
1285 for (bit = 0; bit < sc_table.len; bit++) {
1286 char state;
1287
1288 if (syscall_table->syscall_dispatch) {
1289 if (!(READ_ONCE(syscall_table->syscall_all_entry)
1290 || READ_ONCE(syscall_table->syscall_all_exit)) && filter)
1291 state = test_bit(bit, filter->sc_entry)
1292 || test_bit(bit, filter->sc_exit);
1293 else
1294 state = 1;
1295 } else {
1296 state = 0;
1297 }
1298 bt_bitfield_write_be(tmp_mask, char, bit, 1, state);
1299 }
1300 for (; bit < sc_tables_len; bit++) {
1301 char state;
1302
1303 if (syscall_table->compat_syscall_dispatch) {
1304 if (!(READ_ONCE(syscall_table->syscall_all_entry)
1305 || READ_ONCE(syscall_table->syscall_all_exit)) && filter)
1306 state = test_bit(bit - sc_table.len,
1307 filter->sc_compat_entry)
1308 || test_bit(bit - sc_table.len,
1309 filter->sc_compat_exit);
1310 else
1311 state = 1;
1312 } else {
1313 state = 0;
1314 }
1315 bt_bitfield_write_be(tmp_mask, char, bit, 1, state);
1316 }
1317 if (copy_to_user(usyscall_mask->mask, tmp_mask, bitmask_len))
1318 ret = -EFAULT;
1319 kfree(tmp_mask);
1320 return ret;
1321}
1322
1323int lttng_abi_syscall_list(void)
1324{
1325 struct file *syscall_list_file;
1326 int file_fd, ret;
1327
1328 file_fd = lttng_get_unused_fd();
1329 if (file_fd < 0) {
1330 ret = file_fd;
1331 goto fd_error;
1332 }
1333
1334 syscall_list_file = anon_inode_getfile("[lttng_syscall_list]",
1335 &lttng_syscall_list_fops,
1336 NULL, O_RDWR);
1337 if (IS_ERR(syscall_list_file)) {
1338 ret = PTR_ERR(syscall_list_file);
1339 goto file_error;
1340 }
1341 ret = lttng_syscall_list_fops.open(NULL, syscall_list_file);
1342 if (ret < 0)
1343 goto open_error;
1344 fd_install(file_fd, syscall_list_file);
1345 return file_fd;
1346
1347open_error:
1348 fput(syscall_list_file);
1349file_error:
1350 put_unused_fd(file_fd);
1351fd_error:
1352 return ret;
1353}
This page took 0.02855 seconds and 4 git commands to generate.