From 081d1fbf2ac9cd547ac68e8494eace3434926f12 Mon Sep 17 00:00:00 2001 From: Matias Wadman Date: Wed, 23 Sep 2015 22:44:48 +0200 Subject: Add seccomp errno filter support --- src/firejail/errno.c | 214 ++++++++++++++++++++++++++++++++++++++++++++ src/firejail/firejail.h | 9 +- src/firejail/main.c | 43 +++++++++ src/firejail/sandbox.c | 2 + src/firejail/seccomp.c | 144 ++++++++++++++++++++++------- src/firejail/syscall.c | 6 +- src/man/firejail.txt | 9 ++ src/tools/extract_errnos.sh | 4 + 8 files changed, 393 insertions(+), 38 deletions(-) create mode 100644 src/firejail/errno.c create mode 100644 src/tools/extract_errnos.sh diff --git a/src/firejail/errno.c b/src/firejail/errno.c new file mode 100644 index 000000000..c6c5f8f6a --- /dev/null +++ b/src/firejail/errno.c @@ -0,0 +1,214 @@ +/* + * Copyright (C) 2015 Firejail Authors + * + * This file is part of firejail project + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License along + * with this program; if not, write to the Free Software Foundation, Inc., + * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. +*/ + +#ifdef HAVE_SECCOMP +#include "firejail.h" +#include +#include + +typedef struct { + char *name; + int nr; +} ErrnoEntry; + +static ErrnoEntry errnolist[] = { +// +// code generated using tools/extract-errnos +// + "EPERM", EPERM, + "ENOENT", ENOENT, + "ESRCH", ESRCH, + "EINTR", EINTR, + "EIO", EIO, + "ENXIO", ENXIO, + "E2BIG", E2BIG, + "ENOEXEC", ENOEXEC, + "EBADF", EBADF, + "ECHILD", ECHILD, + "EAGAIN", EAGAIN, + "ENOMEM", ENOMEM, + "EACCES", EACCES, + "EFAULT", EFAULT, + "ENOTBLK", ENOTBLK, + "EBUSY", EBUSY, + "EEXIST", EEXIST, + "EXDEV", EXDEV, + "ENODEV", ENODEV, + "ENOTDIR", ENOTDIR, + "EISDIR", EISDIR, + "EINVAL", EINVAL, + "ENFILE", ENFILE, + "EMFILE", EMFILE, + "ENOTTY", ENOTTY, + "ETXTBSY", ETXTBSY, + "EFBIG", EFBIG, + "ENOSPC", ENOSPC, + "ESPIPE", ESPIPE, + "EROFS", EROFS, + "EMLINK", EMLINK, + "EPIPE", EPIPE, + "EDOM", EDOM, + "ERANGE", ERANGE, + "EDEADLK", EDEADLK, + "ENAMETOOLONG", ENAMETOOLONG, + "ENOLCK", ENOLCK, + "ENOSYS", ENOSYS, + "ENOTEMPTY", ENOTEMPTY, + "ELOOP", ELOOP, + "EWOULDBLOCK", EWOULDBLOCK, + "ENOMSG", ENOMSG, + "EIDRM", EIDRM, + "ECHRNG", ECHRNG, + "EL2NSYNC", EL2NSYNC, + "EL3HLT", EL3HLT, + "EL3RST", EL3RST, + "ELNRNG", ELNRNG, + "EUNATCH", EUNATCH, + "ENOCSI", ENOCSI, + "EL2HLT", EL2HLT, + "EBADE", EBADE, + "EBADR", EBADR, + "EXFULL", EXFULL, + "ENOANO", ENOANO, + "EBADRQC", EBADRQC, + "EBADSLT", EBADSLT, + "EDEADLOCK", EDEADLOCK, + "EBFONT", EBFONT, + "ENOSTR", ENOSTR, + "ENODATA", ENODATA, + "ETIME", ETIME, + "ENOSR", ENOSR, + "ENONET", ENONET, + "ENOPKG", ENOPKG, + "EREMOTE", EREMOTE, + "ENOLINK", ENOLINK, + "EADV", EADV, + "ESRMNT", ESRMNT, + "ECOMM", ECOMM, + "EPROTO", EPROTO, + "EMULTIHOP", EMULTIHOP, + "EDOTDOT", EDOTDOT, + "EBADMSG", EBADMSG, + "EOVERFLOW", EOVERFLOW, + "ENOTUNIQ", ENOTUNIQ, + "EBADFD", EBADFD, + "EREMCHG", EREMCHG, + "ELIBACC", ELIBACC, + "ELIBBAD", ELIBBAD, + "ELIBSCN", ELIBSCN, + "ELIBMAX", ELIBMAX, + "ELIBEXEC", ELIBEXEC, + "EILSEQ", EILSEQ, + "ERESTART", ERESTART, + "ESTRPIPE", ESTRPIPE, + "EUSERS", EUSERS, + "ENOTSOCK", ENOTSOCK, + "EDESTADDRREQ", EDESTADDRREQ, + "EMSGSIZE", EMSGSIZE, + "EPROTOTYPE", EPROTOTYPE, + "ENOPROTOOPT", ENOPROTOOPT, + "EPROTONOSUPPORT", EPROTONOSUPPORT, + "ESOCKTNOSUPPORT", ESOCKTNOSUPPORT, + "EOPNOTSUPP", EOPNOTSUPP, + "EPFNOSUPPORT", EPFNOSUPPORT, + "EAFNOSUPPORT", EAFNOSUPPORT, + "EADDRINUSE", EADDRINUSE, + "EADDRNOTAVAIL", EADDRNOTAVAIL, + "ENETDOWN", ENETDOWN, + "ENETUNREACH", ENETUNREACH, + "ENETRESET", ENETRESET, + "ECONNABORTED", ECONNABORTED, + "ECONNRESET", ECONNRESET, + "ENOBUFS", ENOBUFS, + "EISCONN", EISCONN, + "ENOTCONN", ENOTCONN, + "ESHUTDOWN", ESHUTDOWN, + "ETOOMANYREFS", ETOOMANYREFS, + "ETIMEDOUT", ETIMEDOUT, + "ECONNREFUSED", ECONNREFUSED, + "EHOSTDOWN", EHOSTDOWN, + "EHOSTUNREACH", EHOSTUNREACH, + "EALREADY", EALREADY, + "EINPROGRESS", EINPROGRESS, + "ESTALE", ESTALE, + "EUCLEAN", EUCLEAN, + "ENOTNAM", ENOTNAM, + "ENAVAIL", ENAVAIL, + "EISNAM", EISNAM, + "EREMOTEIO", EREMOTEIO, + "EDQUOT", EDQUOT, + "ENOMEDIUM", ENOMEDIUM, + "EMEDIUMTYPE", EMEDIUMTYPE, + "ECANCELED", ECANCELED, + "ENOKEY", ENOKEY, + "EKEYEXPIRED", EKEYEXPIRED, + "EKEYREVOKED", EKEYREVOKED, + "EKEYREJECTED", EKEYREJECTED, + "EOWNERDEAD", EOWNERDEAD, + "ENOTRECOVERABLE", ENOTRECOVERABLE, + "ERFKILL", ERFKILL, + "EHWPOISON", EHWPOISON, + "ENOTSUP", ENOTSUP, + "ENOATTR", ENOATTR, +}; + +int errno_highest_nr(void) { + int i, max = 0; + int elems = sizeof(errnolist) / sizeof(errnolist[0]); + for (i = 0; i < elems; i++) { + if (errnolist[i].nr > max) + max = errnolist[i].nr; + } + + return max; +} + +int errno_find_name(const char *name) { + int i; + int elems = sizeof(errnolist) / sizeof(errnolist[0]); + for (i = 0; i < elems; i++) { + if (strcasecmp(name, errnolist[i].name) == 0) + return errnolist[i].nr; + } + + return -1; +} + +char *errno_find_nr(int nr) { + int i; + int elems = sizeof(errnolist) / sizeof(errnolist[0]); + for (i = 0; i < elems; i++) { + if (nr == errnolist[i].nr) + return errnolist[i].name; + } + + return "unknown"; +} + +void errno_print(void) { + int i; + int elems = sizeof(errnolist) / sizeof(errnolist[0]); + for (i = 0; i < elems; i++) { + printf("%d\t- %s\n", errnolist[i].nr, errnolist[i].name); + } + printf("\n"); +} + +#endif // HAVE_SECCOMP diff --git a/src/firejail/firejail.h b/src/firejail/firejail.h index cef4b673c..589fdb42a 100644 --- a/src/firejail/firejail.h +++ b/src/firejail/firejail.h @@ -147,6 +147,7 @@ extern int arg_seccomp; // enable default seccomp filter extern char *arg_seccomp_list;// optional seccomp list on top of default filter extern char *arg_seccomp_list_drop; // seccomp drop list extern char *arg_seccomp_list_keep; // seccomp keep list +extern char **arg_seccomp_list_errno; // seccomp errno[nr] lists extern int arg_caps_default_filter; // enable default capabilities filter extern int arg_caps_drop; // drop list @@ -335,7 +336,7 @@ void caps_print_filter_name(const char *name); // syscall.c const char *syscall_find_nr(int nr); // return -1 if error, 0 if no error -int syscall_check_list(const char *slist, void (*callback)(int)); +int syscall_check_list(const char *slist, void (*callback)(int syscall, int arg), int arg); // print all available syscalls void syscall_print(void); @@ -392,5 +393,11 @@ void env_apply(void); // fs_whitelist.c void fs_whitelist(void); +// errno.c +int errno_highest_errno(void); +int errno_find_name(const char *name); +char *errno_find_nr(int nr); +void errno_print(void); + #endif diff --git a/src/firejail/main.c b/src/firejail/main.c index 9d94630ef..ea04ea73f 100644 --- a/src/firejail/main.c +++ b/src/firejail/main.c @@ -61,6 +61,7 @@ int arg_seccomp = 0; // enable default seccomp filter char *arg_seccomp_list = NULL; // optional seccomp list on top of default filter char *arg_seccomp_list_drop = NULL; // seccomp drop list char *arg_seccomp_list_keep = NULL; // seccomp keep list +char **arg_seccomp_list_errno = NULL; // seccomp errno[nr] lists int arg_caps_default_filter = 0; // enable default capabilities filter int arg_caps_drop = 0; // drop list @@ -302,6 +303,10 @@ static void run_cmd_and_exit(int i, int argc, char **argv) { syscall_print(); exit(0); } + else if (strcmp(argv[i], "--debug-errnos") == 0) { + errno_print(); + exit(0); + } else if (strncmp(argv[i], "--seccomp.print=", 16) == 0) { // join sandbox by pid or by name pid_t pid; @@ -387,6 +392,7 @@ int main(int argc, char **argv) { int arg_cgroup = 0; int custom_profile = 0; // custom profile loaded int arg_noprofile = 0; // use generic.profile if none other found/specified + int highest_errno = errno_highest_nr(); // check if we already have a sandbox running int rv = check_kernel_procs(); @@ -478,6 +484,34 @@ int main(int argc, char **argv) { if (!arg_seccomp_list_keep) errExit("strdup"); } + else if (strncmp(argv[i], "--seccomp.e", 11) == 0 && strchr(argv[i], '=')) { + if (arg_seccomp && !arg_seccomp_list_errno) { + fprintf(stderr, "Error: seccomp already enabled\n"); + exit(1); + } + char *eq = strchr(argv[i], '='); + char *errnoname = strndup(argv[i] + 10, eq - (argv[i] + 10)); + int nr = errno_find_name(errnoname); + if (nr == -1) { + fprintf(stderr, "Error: unknown errno %s\n", errnoname); + free(errnoname); + exit(1); + } + + if (!arg_seccomp_list_errno) + arg_seccomp_list_errno = calloc(highest_errno+1, sizeof(arg_seccomp_list_errno[0])); + + if (arg_seccomp_list_errno[nr]) { + fprintf(stderr, "Error: errno %s already configured\n", errnoname); + free(errnoname); + exit(1); + } + arg_seccomp = 1; + arg_seccomp_list_errno[nr] = strdup(eq+1); + if (!arg_seccomp_list_errno[nr]) + errExit("strdup"); + free(errnoname); + } #endif else if (strcmp(argv[i], "--caps") == 0) arg_caps_default_filter = 1; @@ -1288,6 +1322,15 @@ int main(int argc, char **argv) { // wait for the child to finish waitpid(child, NULL, 0); + + // free globals + if (arg_seccomp_list_errno) { + for (i = 0; i < highest_errno; i++) + free(arg_seccomp_list_errno[i]); + free(arg_seccomp_list_errno); + } + myexit(0); + return 0; } diff --git a/src/firejail/sandbox.c b/src/firejail/sandbox.c index c1a6d92ec..ddfcc8404 100644 --- a/src/firejail/sandbox.c +++ b/src/firejail/sandbox.c @@ -410,6 +410,8 @@ int sandbox(void* sandbox_arg) { if (arg_seccomp == 1) { if (arg_seccomp_list_keep) seccomp_filter_keep(); // this will also save the fmyilter to MNT_DIR/seccomp file + else if (arg_seccomp_list_errno) + seccomp_filter_errno(); // this will also save the filter to MNT_DIR/seccomp file else seccomp_filter_drop(); // this will also save the filter to MNT_DIR/seccomp file } diff --git a/src/firejail/seccomp.c b/src/firejail/seccomp.c index 47988dbf4..4f6b7b326 100644 --- a/src/firejail/seccomp.c +++ b/src/firejail/seccomp.c @@ -109,6 +109,10 @@ struct seccomp_data { BPF_JUMP(BPF_JMP+BPF_JEQ+BPF_K, syscall_nr, 0, 1), \ BPF_STMT(BPF_RET+BPF_K, SECCOMP_RET_ALLOW) +#define ERRNO(syscall_nr, nr) \ + BPF_JUMP(BPF_JMP+BPF_JEQ+BPF_K, syscall_nr, 0, 1), \ + BPF_STMT(BPF_RET+BPF_K, SECCOMP_RET_ERRNO | nr) + #define RETURN_ALLOW \ BPF_STMT(BPF_RET+BPF_K, SECCOMP_RET_ALLOW) @@ -157,6 +161,11 @@ void filter_debug(void) { printf(" BLACKLIST %d %s\n", *nr, syscall_find_nr(*nr)); i += 2; } + else if (*ptr == 0x15 && *(ptr +14) == 0x5 && *(ptr + 15) == 0) { + int err = *(ptr + 13) << 8 | *(ptr + 12); + printf(" ERRNO %d %s %d %s\n", *nr, syscall_find_nr(*nr), err, errno_find_nr(err)); + i += 2; + } else if (*ptr == 0x06 && *(ptr +6) == 0 && *(ptr + 7) == 0 ) { printf(" KILL_PROCESS\n"); i++; @@ -216,7 +225,7 @@ static void filter_realloc(void) { sfilter_alloc_size += SECSIZE; } -static void filter_add_whitelist(int syscall) { +static void filter_add_whitelist(int syscall, int arg) { assert(sfilter); assert(sfilter_alloc_size); assert(sfilter_index); @@ -242,7 +251,7 @@ static void filter_add_whitelist(int syscall) { sfilter_index += sizeof(filter) / sizeof(struct sock_filter); } -static void filter_add_blacklist(int syscall) { +static void filter_add_blacklist(int syscall, int arg) { assert(sfilter); assert(sfilter_alloc_size); assert(sfilter_index); @@ -268,6 +277,32 @@ static void filter_add_blacklist(int syscall) { sfilter_index += sizeof(filter) / sizeof(struct sock_filter); } +static void filter_add_errno(int syscall, int arg) { + assert(sfilter); + assert(sfilter_alloc_size); + assert(sfilter_index); +// if (arg_debug) +// printf("Errno syscall %d %d %s\n", syscall, arg, syscall_find_nr(syscall)); + + if ((sfilter_index + 2) > sfilter_alloc_size) + filter_realloc(); + + struct sock_filter filter[] = { + ERRNO(syscall, arg) + }; +#if 0 +{ + int i; + unsigned char *ptr = (unsigned char *) &filter[0]; + for (i = 0; i < sizeof(filter); i++, ptr++) + printf("%x, ", (*ptr) & 0xff); + printf("\n"); +} +#endif + memcpy(&sfilter[sfilter_index], filter, sizeof(filter)); + sfilter_index += sizeof(filter) / sizeof(struct sock_filter); +} + static void filter_end_blacklist(void) { assert(sfilter); assert(sfilter_alloc_size); @@ -405,96 +440,96 @@ int seccomp_filter_drop(void) { // default seccomp if (arg_seccomp_list_drop == NULL) { #ifdef SYS_mount - filter_add_blacklist(SYS_mount); + filter_add_blacklist(SYS_mount, 0); #endif #ifdef SYS_umount2 - filter_add_blacklist(SYS_umount2); + filter_add_blacklist(SYS_umount2, 0); #endif #ifdef SYS_ptrace - filter_add_blacklist(SYS_ptrace); + filter_add_blacklist(SYS_ptrace, 0); #endif #ifdef SYS_kexec_load - filter_add_blacklist(SYS_kexec_load); + filter_add_blacklist(SYS_kexec_load, 0); #endif #ifdef SYS_open_by_handle_at - filter_add_blacklist(SYS_open_by_handle_at); + filter_add_blacklist(SYS_open_by_handle_at, 0); #endif #ifdef SYS_init_module - filter_add_blacklist(SYS_init_module); + filter_add_blacklist(SYS_init_module, 0); #endif #ifdef SYS_finit_module // introduced in 2013 - filter_add_blacklist(SYS_finit_module); + filter_add_blacklist(SYS_finit_module, 0); #endif #ifdef SYS_delete_module - filter_add_blacklist(SYS_delete_module); + filter_add_blacklist(SYS_delete_module, 0); #endif #ifdef SYS_iopl - filter_add_blacklist(SYS_iopl); + filter_add_blacklist(SYS_iopl, 0); #endif #ifdef SYS_ioperm - filter_add_blacklist(SYS_ioperm); + filter_add_blacklist(SYS_ioperm, 0); #endif #ifdef SYS_ni_syscall // new io permisions call on arm devices - filter_add_blacklist(SYS_ni_syscall); + filter_add_blacklist(SYS_ni_syscall, 0); #endif #ifdef SYS_swapon - filter_add_blacklist(SYS_swapon); + filter_add_blacklist(SYS_swapon, 0); #endif #ifdef SYS_swapoff - filter_add_blacklist(SYS_swapoff); + filter_add_blacklist(SYS_swapoff, 0); #endif #ifdef SYS_syslog - filter_add_blacklist(SYS_syslog); + filter_add_blacklist(SYS_syslog, 0); #endif #ifdef SYS_process_vm_readv - filter_add_blacklist(SYS_process_vm_readv); + filter_add_blacklist(SYS_process_vm_readv, 0); #endif #ifdef SYS_process_vm_writev - filter_add_blacklist(SYS_process_vm_writev); + filter_add_blacklist(SYS_process_vm_writev, 0); #endif // mknod removed in 0.9.29 //#ifdef SYS_mknod -// filter_add_blacklist(SYS_mknod); +// filter_add_blacklist(SYS_mknod, 0); //#endif // new syscalls in 0.9,23 #ifdef SYS_sysfs - filter_add_blacklist(SYS_sysfs); + filter_add_blacklist(SYS_sysfs, 0); #endif #ifdef SYS__sysctl - filter_add_blacklist(SYS__sysctl); + filter_add_blacklist(SYS__sysctl, 0); #endif #ifdef SYS_adjtimex - filter_add_blacklist(SYS_adjtimex); + filter_add_blacklist(SYS_adjtimex, 0); #endif #ifdef SYS_clock_adjtime - filter_add_blacklist(SYS_clock_adjtime); + filter_add_blacklist(SYS_clock_adjtime, 0); #endif #ifdef SYS_lookup_dcookie - filter_add_blacklist(SYS_lookup_dcookie); + filter_add_blacklist(SYS_lookup_dcookie, 0); #endif #ifdef SYS_perf_event_open - filter_add_blacklist(SYS_perf_event_open); + filter_add_blacklist(SYS_perf_event_open, 0); #endif #ifdef SYS_fanotify_init - filter_add_blacklist(SYS_fanotify_init); + filter_add_blacklist(SYS_fanotify_init, 0); #endif #ifdef SYS_kcmp - filter_add_blacklist(SYS_kcmp); + filter_add_blacklist(SYS_kcmp, 0); #endif } // default seccomp filter with additional drop list if (arg_seccomp_list && arg_seccomp_list_drop == NULL) { - if (syscall_check_list(arg_seccomp_list, filter_add_blacklist)) { + if (syscall_check_list(arg_seccomp_list, filter_add_blacklist, 0)) { fprintf(stderr, "Error: cannot load seccomp filter\n"); exit(1); } } // drop list else if (arg_seccomp_list == NULL && arg_seccomp_list_drop) { - if (syscall_check_list(arg_seccomp_list_drop, filter_add_blacklist)) { + if (syscall_check_list(arg_seccomp_list_drop, filter_add_blacklist, 0)) { fprintf(stderr, "Error: cannot load seccomp filter\n"); exit(1); } @@ -531,14 +566,14 @@ int seccomp_filter_keep(void) { filter_init(); // these 4 syscalls are used by firejail after the seccomp filter is initialized - filter_add_whitelist(SYS_setuid); - filter_add_whitelist(SYS_setgid); - filter_add_whitelist(SYS_setgroups); - filter_add_whitelist(SYS_dup); + filter_add_whitelist(SYS_setuid, 0); + filter_add_whitelist(SYS_setgid, 0); + filter_add_whitelist(SYS_setgroups, 0); + filter_add_whitelist(SYS_dup, 0); // apply keep list if (arg_seccomp_list_keep) { - if (syscall_check_list(arg_seccomp_list_keep, filter_add_whitelist)) { + if (syscall_check_list(arg_seccomp_list_keep, filter_add_whitelist, 0)) { fprintf(stderr, "Error: cannot load seccomp filter\n"); exit(1); } @@ -569,6 +604,47 @@ int seccomp_filter_keep(void) { return 0; } +// errno filter for seccomp option +int seccomp_filter_errno(void) { + int i; + int higest_errno = errno_highest_nr(); + filter_init(); + + // apply errno list + + for (i = 0; i < higest_errno; i++) { + if (arg_seccomp_list_errno[i]) { + if (syscall_check_list(arg_seccomp_list_errno[i], filter_add_errno, i)) { + fprintf(stderr, "Error: cannot load seccomp filter\n"); + exit(1); + } + } + } + + filter_end_blacklist(); + if (arg_debug) + filter_debug(); + + // save seccomp filter in /tmp/firejail/mnt/seccomp + // in order to use it in --join operations + write_seccomp_file(); + + struct sock_fprog prog = { + .len = sfilter_index, + .filter = sfilter, + }; + + if (prctl(PR_SET_SECCOMP, SECCOMP_MODE_FILTER, &prog) || prctl(PR_SET_NO_NEW_PRIVS, 1, 0, 0, 0)) { + fprintf(stderr, "Warning: seccomp disabled, it requires a Linux kernel version 3.5 or newer.\n"); + return 1; + } + else if (arg_debug) { + printf("seccomp enabled\n"); + } + + return 0; +} + void seccomp_set(void) { diff --git a/src/firejail/syscall.c b/src/firejail/syscall.c index a74a00662..2ae3da100 100644 --- a/src/firejail/syscall.c +++ b/src/firejail/syscall.c @@ -4889,7 +4889,7 @@ static int syscall_find_name(const char *name) { } // return 1 if error, 0 if OK -int syscall_check_list(const char *slist, void (*callback)(int)) { +int syscall_check_list(const char *slist, void (*callback)(int syscall, int arg), int arg) { // don't allow empty lists if (slist == NULL || *slist == '\0') { fprintf(stderr, "Error: empty syscall lists are not allowed\n"); @@ -4912,7 +4912,7 @@ int syscall_check_list(const char *slist, void (*callback)(int)) { if (nr == -1) fprintf(stderr, "Warning: syscall %s not found\n", start); else if (callback != NULL) - callback(nr); + callback(nr, arg); start = ptr + 1; } @@ -4923,7 +4923,7 @@ int syscall_check_list(const char *slist, void (*callback)(int)) { if (nr == -1) fprintf(stderr, "Warning: syscall %s not found\n", start); else if (callback != NULL) - callback(nr); + callback(nr, arg); } free(str); diff --git a/src/man/firejail.txt b/src/man/firejail.txt index 3f4fba00e..3f22a1d2a 100644 --- a/src/man/firejail.txt +++ b/src/man/firejail.txt @@ -845,6 +845,15 @@ Example: .br $ firejail \-\-shell=none \-\-seccomp.keep=poll,select,[...] transmission-gtk .TP +\fB\-\-seccomp.=syscall,syscall,syscall +Enable seccomp filter, and return errno for the syscalls specified by the command. +.br + +.br +Example: +.br +$ firejail \-\-shell=none \-\-seccomp.einval=kill kill 1 +.TP \fB\-\-seccomp.print=name Print the seccomp filter for the sandbox started using \-\-name option. .br diff --git a/src/tools/extract_errnos.sh b/src/tools/extract_errnos.sh new file mode 100644 index 000000000..43b225828 --- /dev/null +++ b/src/tools/extract_errnos.sh @@ -0,0 +1,4 @@ +echo -e "#include \n#include " | \ + cpp -dD | \ + grep "^#define E" | \ + sed -e '{s/#define \(.*\) .*/\t"\1", \1,/g}' -- cgit v1.2.3-54-g00ecf