mirror of
https://github.com/netblue30/firejail.git
synced 2026-05-15 14:16:14 -06:00
add a new option --debug-syscall-groups - part 1
This option allows to list all seccomp groups and their syscalls defined for the architecture in use. Usage examples: `firejail --debug-syscall-groups` `firejail --debug-syscall-groups=@chown,@mount,@swap` `firejail --debug-syscall-groups=@all` This is the first part.
This commit is contained in:
parent
4af62ee2da
commit
88a75a650d
4 changed files with 225 additions and 31 deletions
|
|
@ -604,6 +604,22 @@ static void run_cmd_and_exit(int i, int argc, char **argv) {
|
|||
else
|
||||
exit_err_feature("seccomp");
|
||||
}
|
||||
else if (strcmp(argv[i], "--debug-syscall-groups") == 0) {
|
||||
if (checkcfg(CFG_SECCOMP)) {
|
||||
int rv = sbox_run(SBOX_USER | SBOX_CAPS_NONE | SBOX_SECCOMP, 2, PATH_FSECCOMP_MAIN, "debug-syscall-groups");
|
||||
exit(rv);
|
||||
}
|
||||
else
|
||||
exit_err_feature("seccomp");
|
||||
}
|
||||
else if (strncmp(argv[i], "--debug-syscall-groups=", 23) == 0) {
|
||||
if (checkcfg(CFG_SECCOMP)) {
|
||||
syscall_in_groups_print(argv[i] + 23);
|
||||
exit(0);
|
||||
}
|
||||
else
|
||||
exit_err_feature("seccomp");
|
||||
}
|
||||
else if (strcmp(argv[i], "--debug-errnos") == 0) {
|
||||
if (checkcfg(CFG_SECCOMP)) {
|
||||
int rv = sbox_run(SBOX_USER | SBOX_CAPS_NONE | SBOX_SECCOMP, 2, PATH_FSECCOMP_MAIN, "debug-errnos");
|
||||
|
|
|
|||
|
|
@ -26,6 +26,7 @@ static const char *const usage_str =
|
|||
"Usage:\n"
|
||||
"\tfseccomp debug-syscalls\n"
|
||||
"\tfseccomp debug-syscalls32\n"
|
||||
"\tfseccomp debug-syscall-groups\n"
|
||||
"\tfseccomp debug-errnos\n"
|
||||
"\tfseccomp debug-protocols\n"
|
||||
"\tfseccomp protocol build list file\n"
|
||||
|
|
@ -98,6 +99,8 @@ printf("\n");
|
|||
syscall_print();
|
||||
else if (argc == 2 && strcmp(argv[1], "debug-syscalls32") == 0)
|
||||
syscall_print_32();
|
||||
else if (argc == 2 && strcmp(argv[1], "debug-syscall-groups") == 0)
|
||||
syscall_groups_print();
|
||||
else if (argc == 2 && strcmp(argv[1], "debug-errnos") == 0)
|
||||
errno_print();
|
||||
else if (argc == 2 && strcmp(argv[1], "debug-protocols") == 0)
|
||||
|
|
|
|||
|
|
@ -37,6 +37,8 @@ const char *errno_find_nr(int nr);
|
|||
// syscall.c
|
||||
void syscall_print(void);
|
||||
void syscall_print_32(void);
|
||||
void syscall_groups_print(void);
|
||||
void syscall_in_groups_print(const char *name);
|
||||
typedef void (filter_fn)(int fd, int syscall, int arg, void *ptrarg, bool native);
|
||||
int syscall_check_list(const char *slist, filter_fn *callback, int fd, int arg, void *ptrarg, bool native);
|
||||
const char *syscall_find_nr(int nr);
|
||||
|
|
|
|||
|
|
@ -38,6 +38,7 @@ typedef struct {
|
|||
|
||||
typedef struct {
|
||||
const char * const name;
|
||||
const char * const description;
|
||||
const char * const list;
|
||||
} SyscallGroupList;
|
||||
|
||||
|
|
@ -135,7 +136,9 @@ static const SyscallEntry syslist32[] = {
|
|||
};
|
||||
|
||||
static const SyscallGroupList sysgroups[] = {
|
||||
{ .name = "@aio", .list =
|
||||
{ .name = "@aio",
|
||||
.description = "Asynchronous I/O and io_uring operations.",
|
||||
.list =
|
||||
#ifdef SYS_io_cancel
|
||||
"io_cancel,"
|
||||
#endif
|
||||
|
|
@ -167,7 +170,9 @@ static const SyscallGroupList sysgroups[] = {
|
|||
"io_uring_setup"
|
||||
#endif
|
||||
},
|
||||
{ .name = "@basic-io", .list =
|
||||
{ .name = "@basic-io",
|
||||
.description = "Basic file-descriptor read, write, seek and dup operations.",
|
||||
.list =
|
||||
#ifdef SYS__llseek
|
||||
"_llseek,"
|
||||
#endif
|
||||
|
|
@ -220,7 +225,9 @@ static const SyscallGroupList sysgroups[] = {
|
|||
"writev"
|
||||
#endif
|
||||
},
|
||||
{ .name = "@chown", .list =
|
||||
{ .name = "@chown",
|
||||
.description = "Change file owner and group metadata.",
|
||||
.list =
|
||||
#ifdef SYS_chown
|
||||
"chown,"
|
||||
#endif
|
||||
|
|
@ -243,7 +250,9 @@ static const SyscallGroupList sysgroups[] = {
|
|||
"lchown32"
|
||||
#endif
|
||||
},
|
||||
{ .name = "@clock", .list =
|
||||
{ .name = "@clock",
|
||||
.description = "System clock adjustment.",
|
||||
.list =
|
||||
#ifdef SYS_adjtimex
|
||||
"adjtimex,"
|
||||
#endif
|
||||
|
|
@ -263,7 +272,9 @@ static const SyscallGroupList sysgroups[] = {
|
|||
"old_adjtimex"
|
||||
#endif
|
||||
},
|
||||
{ .name = "@cpu-emulation", .list =
|
||||
{ .name = "@cpu-emulation",
|
||||
.description = "Legacy CPU, segment and VM86 emulation helpers.",
|
||||
.list =
|
||||
#ifdef SYS_modify_ldt
|
||||
"modify_ldt,"
|
||||
#endif
|
||||
|
|
@ -284,7 +295,9 @@ static const SyscallGroupList sysgroups[] = {
|
|||
// arm64, alpha, arc32, armeabi, armoabi, csky, hexagon32, loongarch64, m68k, mips_n32, mips_n64, nios2, openrisc32, parisc32, parisc64, riscv32, riscv64, s390_32, s390_64, sparc32, sparc64, superh and xtensa
|
||||
#endif
|
||||
},
|
||||
{ .name = "@debug", .list =
|
||||
{ .name = "@debug",
|
||||
.description = "Low-level debugging, tracing, and perf monitoring interfaces.",
|
||||
.list =
|
||||
#ifdef SYS_lookup_dcookie
|
||||
"lookup_dcookie,"
|
||||
#endif
|
||||
|
|
@ -313,7 +326,9 @@ static const SyscallGroupList sysgroups[] = {
|
|||
"uretprobe" // occasional breakages with seccomp reported, see https://lwn.net/Articles/1005662
|
||||
#endif
|
||||
},
|
||||
{ .name = "@default", .list =
|
||||
{ .name = "@default",
|
||||
.description = "Broad set of syscalls usually considered unsafe or rarely used.",
|
||||
.list =
|
||||
"@clock,"
|
||||
"@cpu-emulation,"
|
||||
"@debug,"
|
||||
|
|
@ -399,7 +414,9 @@ static const SyscallGroupList sysgroups[] = {
|
|||
"vmsplice"
|
||||
#endif
|
||||
},
|
||||
{ .name = "@default-keep", .list =
|
||||
{ .name = "@default-keep",
|
||||
.description = "Minimal core exec and other syscalls usually kept even under strict filters.",
|
||||
.list =
|
||||
#ifdef SYS_arch_prctl
|
||||
"arch_prctl," // breaks glibc, i386 and x86_64 only
|
||||
#endif
|
||||
|
|
@ -434,7 +451,9 @@ static const SyscallGroupList sysgroups[] = {
|
|||
"time"
|
||||
#endif
|
||||
},
|
||||
{ .name = "@default-nodebuggers", .list =
|
||||
{ .name = "@default-nodebuggers",
|
||||
.description = "Debugger and introspection syscalls, also includes the @default group.",
|
||||
.list =
|
||||
"@default,"
|
||||
#ifdef SYS_personality
|
||||
"personality,"
|
||||
|
|
@ -446,7 +465,9 @@ static const SyscallGroupList sysgroups[] = {
|
|||
"ptrace"
|
||||
#endif
|
||||
},
|
||||
{ .name = "@file-system", .list =
|
||||
{ .name = "@file-system",
|
||||
.description = "Filesystem access: path navigation, metadata, open, create, remove, and inotify.",
|
||||
.list =
|
||||
#ifdef SYS_access
|
||||
"access,"
|
||||
#endif
|
||||
|
|
@ -724,7 +745,9 @@ static const SyscallGroupList sysgroups[] = {
|
|||
"utimes"
|
||||
#endif
|
||||
},
|
||||
{ .name = "@io-event", .list =
|
||||
{ .name = "@io-event",
|
||||
.description = "Evented I/O multiplexing.",
|
||||
.list =
|
||||
#ifdef SYS__newselect
|
||||
"_newselect,"
|
||||
#endif
|
||||
|
|
@ -774,7 +797,9 @@ static const SyscallGroupList sysgroups[] = {
|
|||
"select"
|
||||
#endif
|
||||
},
|
||||
{ .name = "@ipc", .list =
|
||||
{ .name = "@ipc",
|
||||
.description = "Inter-process communication: pipes, SysV IPC and POSIX message queues.",
|
||||
.list =
|
||||
#ifdef SYS_ipc
|
||||
"ipc,"
|
||||
#endif
|
||||
|
|
@ -860,7 +885,9 @@ static const SyscallGroupList sysgroups[] = {
|
|||
"shmget"
|
||||
#endif
|
||||
},
|
||||
{ .name = "@keyring", .list =
|
||||
{ .name = "@keyring",
|
||||
.description = "Kernel keyring and key management operations.",
|
||||
.list =
|
||||
#ifdef SYS_add_key
|
||||
"add_key,"
|
||||
#endif
|
||||
|
|
@ -871,7 +898,9 @@ static const SyscallGroupList sysgroups[] = {
|
|||
"request_key"
|
||||
#endif
|
||||
},
|
||||
{ .name = "@memfd", .list =
|
||||
{ .name = "@memfd",
|
||||
.description = "Anonymous in-kernel file-like memory objects.",
|
||||
.list =
|
||||
#ifdef SYS_memfd_create
|
||||
"memfd_create,"
|
||||
#endif
|
||||
|
|
@ -879,7 +908,9 @@ static const SyscallGroupList sysgroups[] = {
|
|||
"memfd_secret"
|
||||
#endif
|
||||
},
|
||||
{ .name = "@memlock", .list =
|
||||
{ .name = "@memlock",
|
||||
.description = "Lock and unlock memory to and from RAM (no swapping).",
|
||||
.list =
|
||||
#ifdef SYS_mlock
|
||||
"mlock,"
|
||||
#endif
|
||||
|
|
@ -896,7 +927,9 @@ static const SyscallGroupList sysgroups[] = {
|
|||
"munlockall"
|
||||
#endif
|
||||
},
|
||||
{ .name = "@module", .list =
|
||||
{ .name = "@module",
|
||||
.description = "Load, initialize, and unload kernel modules.",
|
||||
.list =
|
||||
#ifdef SYS_delete_module
|
||||
"delete_module,"
|
||||
#endif
|
||||
|
|
@ -907,7 +940,9 @@ static const SyscallGroupList sysgroups[] = {
|
|||
"init_module"
|
||||
#endif
|
||||
},
|
||||
{ .name = "@mount", .list =
|
||||
{ .name = "@mount",
|
||||
.description = "Mount, unmount, manage filesystems and mount namespaces.",
|
||||
.list =
|
||||
#ifdef SYS_chroot
|
||||
"chroot,"
|
||||
#endif
|
||||
|
|
@ -960,7 +995,9 @@ static const SyscallGroupList sysgroups[] = {
|
|||
"umount2"
|
||||
#endif
|
||||
},
|
||||
{ .name = "@network-io", .list =
|
||||
{ .name = "@network-io",
|
||||
.description = "Create and use sockets, send and receive network data.",
|
||||
.list =
|
||||
#ifdef SYS_accept
|
||||
"accept,"
|
||||
#endif
|
||||
|
|
@ -1028,7 +1065,9 @@ static const SyscallGroupList sysgroups[] = {
|
|||
"socketpair"
|
||||
#endif
|
||||
},
|
||||
{ .name = "@obsolete", .list =
|
||||
{ .name = "@obsolete",
|
||||
.description = "Deprecated or very old arch-specific legacy syscalls.",
|
||||
.list =
|
||||
#ifdef SYS__sysctl
|
||||
"_sysctl,"
|
||||
#endif
|
||||
|
|
@ -1417,7 +1456,9 @@ static const SyscallGroupList sysgroups[] = {
|
|||
"__dummy_syscall__" // workaround for arm64, loongarch64 and riscv64 which don't have any of above defined and empty syscall lists are not allowed
|
||||
#endif
|
||||
},
|
||||
{ .name = "@privileged", .list =
|
||||
{ .name = "@privileged",
|
||||
.description = "Highly privileged operations: IDs, mounts, modules, raw I/O, reboot, etc.",
|
||||
.list =
|
||||
"@chown,"
|
||||
"@clock,"
|
||||
"@module,"
|
||||
|
|
@ -1500,7 +1541,9 @@ static const SyscallGroupList sysgroups[] = {
|
|||
"vhangup"
|
||||
#endif
|
||||
},
|
||||
{ .name = "@process", .list =
|
||||
{ .name = "@process",
|
||||
.description = "Process and thread lifecycle, IDs, signals sending, namespaces and futex-related helpers.",
|
||||
.list =
|
||||
#ifdef SYS_arc_gettls
|
||||
"arc_gettls,"
|
||||
#endif
|
||||
|
|
@ -1721,7 +1764,9 @@ static const SyscallGroupList sysgroups[] = {
|
|||
"waitpid"
|
||||
#endif
|
||||
},
|
||||
{ .name = "@raw-io", .list =
|
||||
{ .name = "@raw-io",
|
||||
.description = "Direct port/PCI and low-level device I/O.",
|
||||
.list =
|
||||
#ifdef SYS_ioperm
|
||||
"ioperm,"
|
||||
#endif
|
||||
|
|
@ -1748,7 +1793,9 @@ static const SyscallGroupList sysgroups[] = {
|
|||
// arm64, arc32, hexagon32, loongarch64, m68k, mips_n32, mips_n64, nios2, openrisc32, parisc32, parisc64, riscv32, riscv64, superh and xtensa
|
||||
#endif
|
||||
},
|
||||
{ .name = "@reboot", .list =
|
||||
{ .name = "@reboot",
|
||||
.description = "Reboot and kexec-related operations.",
|
||||
.list =
|
||||
#ifdef SYS_kexec_file_load
|
||||
"kexec_file_load,"
|
||||
#endif
|
||||
|
|
@ -1759,7 +1806,9 @@ static const SyscallGroupList sysgroups[] = {
|
|||
"reboot"
|
||||
#endif
|
||||
},
|
||||
{ .name = "@resources", .list =
|
||||
{ .name = "@resources",
|
||||
.description = "Resource limits, priorities, CPU affinity and NUMA memory policies.",
|
||||
.list =
|
||||
#ifdef SYS_getdtablesize
|
||||
"getdtablesize,"
|
||||
#endif
|
||||
|
|
@ -1821,7 +1870,9 @@ static const SyscallGroupList sysgroups[] = {
|
|||
"ugetrlimit"
|
||||
#endif
|
||||
},
|
||||
{ .name = "@sandbox", .list =
|
||||
{ .name = "@sandbox",
|
||||
.description = "Seccomp and Landlock sandbox configuration syscalls.",
|
||||
.list =
|
||||
#ifdef SYS_landlock_add_rule
|
||||
"landlock_add_rule,"
|
||||
#endif
|
||||
|
|
@ -1835,7 +1886,9 @@ static const SyscallGroupList sysgroups[] = {
|
|||
"seccomp"
|
||||
#endif
|
||||
},
|
||||
{ .name = "@setuid", .list =
|
||||
{ .name = "@setuid",
|
||||
.description = "Change user and group IDs.",
|
||||
.list =
|
||||
#ifdef SYS_setgid
|
||||
"setgid,"
|
||||
#endif
|
||||
|
|
@ -1879,7 +1932,9 @@ static const SyscallGroupList sysgroups[] = {
|
|||
"setuid32"
|
||||
#endif
|
||||
},
|
||||
{ .name = "@signal", .list =
|
||||
{ .name = "@signal",
|
||||
.description = "Signal handling, masks, signal delivery and signalfd-based interfaces.",
|
||||
.list =
|
||||
#ifdef SYS_osf_sigprocmask
|
||||
"osf_sigprocmask,"
|
||||
#endif
|
||||
|
|
@ -1944,7 +1999,9 @@ static const SyscallGroupList sysgroups[] = {
|
|||
"utrap_install"
|
||||
#endif
|
||||
},
|
||||
{ .name = "@swap", .list =
|
||||
{ .name = "@swap",
|
||||
.description = "Enable and disable swap devices and partitions.",
|
||||
.list =
|
||||
#ifdef SYS_osf_swapon
|
||||
"osf_swapon,"
|
||||
#endif
|
||||
|
|
@ -1955,7 +2012,9 @@ static const SyscallGroupList sysgroups[] = {
|
|||
"swapon"
|
||||
#endif
|
||||
},
|
||||
{ .name = "@sync", .list =
|
||||
{ .name = "@sync",
|
||||
.description = "Synchronize file data and memory mappings to storage.",
|
||||
.list =
|
||||
#ifdef SYS_arm_sync_file_range
|
||||
"arm_sync_file_range,"
|
||||
#endif
|
||||
|
|
@ -1981,7 +2040,9 @@ static const SyscallGroupList sysgroups[] = {
|
|||
"syncfs"
|
||||
#endif
|
||||
},
|
||||
{ .name = "@system-service", .list =
|
||||
{ .name = "@system-service",
|
||||
.description = "Extended system call set focusing on the user (program).",
|
||||
.list =
|
||||
"@aio,"
|
||||
"@basic-io,"
|
||||
"@chown,"
|
||||
|
|
@ -2214,7 +2275,9 @@ static const SyscallGroupList sysgroups[] = {
|
|||
"vmsplice"
|
||||
#endif
|
||||
},
|
||||
{ .name = "@timer", .list =
|
||||
{ .name = "@timer",
|
||||
.description = "Timers, sleeps and interval operations.",
|
||||
.list =
|
||||
#ifdef SYS_alarm
|
||||
"alarm,"
|
||||
#endif
|
||||
|
|
@ -2341,6 +2404,116 @@ void syscall_print_32(void) {
|
|||
printf("\n");
|
||||
}
|
||||
|
||||
void syscall_groups_print(void) {
|
||||
int i;
|
||||
int elems = sizeof(sysgroups) / sizeof(sysgroups[0]);
|
||||
|
||||
printf ("%-23s %s\n", "Group", "Description");
|
||||
printf ("─────────────────────────────────────────────────────────────────────────────\n");
|
||||
|
||||
for (i = 0; i < elems; i++) {
|
||||
printf ("%-23s %s\n", sysgroups[i].name, sysgroups[i].description);
|
||||
}
|
||||
}
|
||||
|
||||
void is_syscall_groups_exist(const char *groups_list)
|
||||
{
|
||||
int i;
|
||||
int elems = sizeof(sysgroups) / sizeof(sysgroups[0]);
|
||||
int no_match = 0;
|
||||
char *copy = strdup(groups_list); // duplicate the string for tokenization, since strtok modifies the string
|
||||
char *token = strtok(copy, ",");
|
||||
char *new_str = malloc(strlen(copy) + 1); // unrecognized groups go here
|
||||
|
||||
if ((copy == NULL) || (new_str == NULL)) {
|
||||
fprintf(stderr, "Memory allocation failed\n");
|
||||
exit(1);
|
||||
}
|
||||
|
||||
new_str[0] = '\0'; // init with an empty string
|
||||
|
||||
while (token != NULL) {
|
||||
if (strcmp(token, "@all") == 0) {
|
||||
token = strtok(NULL, ",");
|
||||
continue;
|
||||
}
|
||||
|
||||
for (i = 0; i < elems; i++) {
|
||||
if (strcmp(token, sysgroups[i].name) == 0)
|
||||
{
|
||||
no_match = 0;
|
||||
break;
|
||||
}
|
||||
else
|
||||
no_match = 1;
|
||||
}
|
||||
|
||||
if (no_match) {
|
||||
if (new_str[0] != '\0')
|
||||
strcat(new_str, ",");
|
||||
strcat(new_str, token);
|
||||
}
|
||||
|
||||
token = strtok(NULL, ",");
|
||||
}
|
||||
|
||||
if (new_str[0] != '\0') {
|
||||
fprintf(stderr, "Unrecognized group(s): %s\n", new_str);
|
||||
fprintf(stderr, "See --debug-syscall-groups for valid groups\n");
|
||||
free(copy);
|
||||
free(new_str);
|
||||
exit(1);
|
||||
}
|
||||
|
||||
free(copy);
|
||||
free(new_str);
|
||||
}
|
||||
|
||||
void syscall_in_groups_print(const char *groups_list) {
|
||||
if (groups_list == NULL || *groups_list == '\0') {
|
||||
fprintf(stderr, "Value for --debug-syscall-groups can not be empty\n");
|
||||
exit(1);
|
||||
}
|
||||
|
||||
is_syscall_groups_exist(groups_list);
|
||||
|
||||
int i;
|
||||
int elems = sizeof(sysgroups) / sizeof(sysgroups[0]);
|
||||
char *copy = strdup(groups_list);
|
||||
|
||||
if (copy == NULL) {
|
||||
fprintf(stderr, "Memory allocation failed\n");
|
||||
exit(1);
|
||||
}
|
||||
|
||||
char *token = strtok(copy, ",");
|
||||
|
||||
while (token != NULL) {
|
||||
for (i = 0; i < elems; i++) {
|
||||
if ((strcmp(token, "@all") == 0) || (strcmp(token, sysgroups[i].name) == 0)) {
|
||||
if (strcmp(sysgroups[i].list, "__dummy_syscall__") == 0) {
|
||||
printf ("%s=(There are no system calls defined in this group for the current architecture)\n", sysgroups[i].name);
|
||||
continue;
|
||||
}
|
||||
|
||||
int len = strlen(sysgroups[i].list);
|
||||
char new_list[len + 1];
|
||||
|
||||
strcpy(new_list, sysgroups[i].list);
|
||||
|
||||
if (len > 0 && new_list[len - 1] == ',') // remove the last comma if present
|
||||
new_list[len - 1] = '\0';
|
||||
|
||||
printf ("%s=%s\n", sysgroups[i].name, new_list);
|
||||
}
|
||||
}
|
||||
|
||||
token = strtok(NULL, ",");
|
||||
}
|
||||
|
||||
free(copy);
|
||||
}
|
||||
|
||||
static const char *syscall_find_group(const char *name) {
|
||||
int i;
|
||||
int elems = sizeof(sysgroups) / sizeof(sysgroups[0]);
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue