]>
git.ipfire.org Git - thirdparty/systemd.git/blob - src/analyze/analyze-syscall-filter.c
1 /* SPDX-License-Identifier: LGPL-2.1-or-later */
3 #include "analyze-syscall-filter.h"
7 #include "nulstr-util.h"
8 #include "seccomp-util.h"
11 #include "terminal-util.h"
15 static int load_kernel_syscalls(Set
**ret
) {
16 _cleanup_set_free_ Set
*syscalls
= NULL
;
17 _cleanup_fclose_
FILE *f
= NULL
;
20 /* Let's read the available system calls from the list of available tracing events. Slightly dirty,
21 * but good enough for analysis purposes. */
23 f
= fopen("/sys/kernel/tracing/available_events", "re");
25 /* We tried the non-debugfs mount point and that didn't work. If it wasn't mounted, maybe the
26 * old debugfs mount point works? */
27 f
= fopen("/sys/kernel/debug/tracing/available_events", "re");
29 return log_full_errno(IN_SET(errno
, EPERM
, EACCES
, ENOENT
) ? LOG_DEBUG
: LOG_WARNING
, errno
,
30 "Can't read open tracefs' available_events file: %m");
34 _cleanup_free_
char *line
= NULL
;
37 r
= read_line(f
, LONG_LINE_MAX
, &line
);
39 return log_error_errno(r
, "Failed to read system call list: %m");
43 e
= startswith(line
, "syscalls:sys_enter_");
47 /* These are named differently inside the kernel than their external name for historical
48 * reasons. Let's hide them here. */
49 if (STR_IN_SET(e
, "newuname", "newfstat", "newstat", "newlstat", "sysctl"))
52 r
= set_put_strdup(&syscalls
, e
);
54 return log_error_errno(r
, "Failed to add system call to list: %m");
57 *ret
= TAKE_PTR(syscalls
);
61 static void syscall_set_remove(Set
*s
, const SyscallFilterSet
*set
) {
67 NULSTR_FOREACH(syscall
, set
->value
) {
68 if (syscall
[0] == '@')
71 free(set_remove(s
, syscall
));
75 static void dump_syscall_filter(const SyscallFilterSet
*set
) {
85 NULSTR_FOREACH(syscall
, set
->value
)
86 printf(" %s%s%s\n", syscall
[0] == '@' ? ansi_underline() : "", syscall
, ansi_normal());
89 int verb_syscall_filters(int argc
, char *argv
[], void *userdata
) {
92 pager_open(arg_pager_flags
);
94 if (strv_isempty(strv_skip(argv
, 1))) {
95 _cleanup_set_free_ Set
*kernel
= NULL
, *known
= NULL
;
97 int k
= 0; /* explicit initialization to appease gcc */
99 NULSTR_FOREACH(sys
, syscall_filter_sets
[SYSCALL_FILTER_SET_KNOWN
].value
)
100 if (set_put_strdup(&known
, sys
) < 0)
104 k
= load_kernel_syscalls(&kernel
);
106 for (int i
= 0; i
< _SYSCALL_FILTER_SET_MAX
; i
++) {
107 const SyscallFilterSet
*set
= syscall_filter_sets
+ i
;
111 dump_syscall_filter(set
);
112 syscall_set_remove(kernel
, set
);
113 if (i
!= SYSCALL_FILTER_SET_KNOWN
)
114 syscall_set_remove(known
, set
);
118 if (arg_quiet
) /* Let's not show the extra stuff in quiet mode */
121 if (!set_isempty(known
)) {
122 _cleanup_free_
char **l
= NULL
;
125 "# %sUngrouped System Calls%s (known but not included in any of the groups except @known):\n",
126 ansi_highlight(), ansi_normal());
128 l
= set_get_strv(known
);
134 STRV_FOREACH(syscall
, l
)
135 printf("# %s\n", *syscall
);
142 log_notice_errno(k
, "# Not showing unlisted system calls, couldn't retrieve kernel system call list: %m");
143 } else if (!set_isempty(kernel
)) {
144 _cleanup_free_
char **l
= NULL
;
147 "# %sUnlisted System Calls%s (supported by the local kernel, but not included in any of the groups listed above):\n",
148 ansi_highlight(), ansi_normal());
150 l
= set_get_strv(kernel
);
156 STRV_FOREACH(syscall
, l
)
157 printf("# %s\n", *syscall
);
160 STRV_FOREACH(name
, strv_skip(argv
, 1)) {
161 const SyscallFilterSet
*set
;
166 set
= syscall_filter_set_find(*name
);
168 /* make sure the error appears below normal output */
171 return log_error_errno(SYNTHETIC_ERRNO(ENOENT
),
172 "Filter set \"%s\" not found.", *name
);
175 dump_syscall_filter(set
);
183 int verb_syscall_filters(int argc
, char *argv
[], void *userdata
) {
184 return log_error_errno(SYNTHETIC_ERRNO(EOPNOTSUPP
), "Not compiled with syscall filters, sorry.");