mirror of
https://github.com/netblue30/firejail.git
synced 2026-05-15 14:16:14 -06:00
seccomp rework
This commit is contained in:
parent
646d046c4c
commit
322ce2cdc9
10 changed files with 106 additions and 385 deletions
|
|
@ -1,207 +0,0 @@
|
|||
/*
|
||||
* Copyright (C) 2014-2016 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 <errno.h>
|
||||
//#include <attr/xattr.h>
|
||||
|
||||
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},
|
||||
#ifdef ENOATTR
|
||||
{"ENOATTR", ENOATTR},
|
||||
#endif
|
||||
};
|
||||
|
||||
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) {
|
||||
EUID_ASSERT();
|
||||
|
||||
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";
|
||||
}
|
||||
#endif // HAVE_SECCOMP
|
||||
|
|
@ -222,7 +222,6 @@ typedef struct config_t {
|
|||
char *seccomp_list;// optional seccomp list on top of default filter
|
||||
char *seccomp_list_drop; // seccomp drop list
|
||||
char *seccomp_list_keep; // seccomp keep list
|
||||
char **seccomp_list_errno; // seccomp errno[nr] lists
|
||||
char *protocol; // protocol list
|
||||
|
||||
// rlimits
|
||||
|
|
@ -496,12 +495,12 @@ void fs_private_home_list(void);
|
|||
|
||||
|
||||
// seccomp.c
|
||||
char *seccomp_check_list(const char *str);
|
||||
int seccomp_load(const char *fname);
|
||||
void seccomp_filter_32(void);
|
||||
void seccomp_filter_64(void);
|
||||
int seccomp_filter_drop(int enforce_seccomp);
|
||||
int seccomp_filter_keep(void);
|
||||
int seccomp_filter_errno(void);
|
||||
void seccomp_print_filter_name(const char *name);
|
||||
void seccomp_print_filter(pid_t pid);
|
||||
|
||||
|
|
|
|||
|
|
@ -851,9 +851,6 @@ int main(int argc, char **argv) {
|
|||
int custom_profile = 0; // custom profile loaded
|
||||
char *custom_profile_dir = NULL; // custom profile directory
|
||||
int arg_noprofile = 0; // use default.profile if none other found/specified
|
||||
#ifdef HAVE_SECCOMP
|
||||
int highest_errno = errno_highest_nr();
|
||||
#endif
|
||||
|
||||
// build /run/firejail directory structure
|
||||
preproc_build_firejail_dir();
|
||||
|
|
@ -1155,9 +1152,7 @@ int main(int argc, char **argv) {
|
|||
exit(1);
|
||||
}
|
||||
arg_seccomp = 1;
|
||||
cfg.seccomp_list = strdup(argv[i] + 10);
|
||||
if (!cfg.seccomp_list)
|
||||
errExit("strdup");
|
||||
cfg.seccomp_list = seccomp_check_list(argv[i] + 10);
|
||||
}
|
||||
else {
|
||||
fprintf(stderr, "Error: seccomp feature is disabled in Firejail configuration file\n");
|
||||
|
|
@ -1171,9 +1166,7 @@ int main(int argc, char **argv) {
|
|||
exit(1);
|
||||
}
|
||||
arg_seccomp = 1;
|
||||
cfg.seccomp_list_drop = strdup(argv[i] + 15);
|
||||
if (!cfg.seccomp_list_drop)
|
||||
errExit("strdup");
|
||||
cfg.seccomp_list_drop = seccomp_check_list(argv[i] + 15);
|
||||
}
|
||||
else {
|
||||
fprintf(stderr, "Error: seccomp feature is disabled in Firejail configuration file\n");
|
||||
|
|
@ -1187,43 +1180,7 @@ int main(int argc, char **argv) {
|
|||
exit(1);
|
||||
}
|
||||
arg_seccomp = 1;
|
||||
cfg.seccomp_list_keep = strdup(argv[i] + 15);
|
||||
if (!cfg.seccomp_list_keep)
|
||||
errExit("strdup");
|
||||
}
|
||||
else {
|
||||
fprintf(stderr, "Error: seccomp feature is disabled in Firejail configuration file\n");
|
||||
exit(1);
|
||||
}
|
||||
}
|
||||
else if (strncmp(argv[i], "--seccomp.e", 11) == 0 && strchr(argv[i], '=')) {
|
||||
if (checkcfg(CFG_SECCOMP)) {
|
||||
if (arg_seccomp && !cfg.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 (!cfg.seccomp_list_errno)
|
||||
cfg.seccomp_list_errno = calloc(highest_errno+1, sizeof(cfg.seccomp_list_errno[0]));
|
||||
|
||||
if (cfg.seccomp_list_errno[nr]) {
|
||||
fprintf(stderr, "Error: errno %s already configured\n", errnoname);
|
||||
free(errnoname);
|
||||
exit(1);
|
||||
}
|
||||
arg_seccomp = 1;
|
||||
cfg.seccomp_list_errno[nr] = strdup(eq+1);
|
||||
if (!cfg.seccomp_list_errno[nr])
|
||||
errExit("strdup");
|
||||
free(errnoname);
|
||||
cfg.seccomp_list_keep = seccomp_check_list(argv[i] + 15);
|
||||
}
|
||||
else {
|
||||
fprintf(stderr, "Error: seccomp feature is disabled in Firejail configuration file\n");
|
||||
|
|
@ -2606,13 +2563,6 @@ int main(int argc, char **argv) {
|
|||
waitpid(child, &status, 0);
|
||||
|
||||
// free globals
|
||||
#ifdef HAVE_SECCOMP
|
||||
if (cfg.seccomp_list_errno) {
|
||||
for (i = 0; i < highest_errno; i++)
|
||||
free(cfg.seccomp_list_errno[i]);
|
||||
free(cfg.seccomp_list_errno);
|
||||
}
|
||||
#endif
|
||||
if (cfg.profile) {
|
||||
ProfileEntry *prf = cfg.profile;
|
||||
while (prf != NULL) {
|
||||
|
|
|
|||
|
|
@ -529,9 +529,7 @@ int profile_check_line(char *ptr, int lineno, const char *fname) {
|
|||
#ifdef HAVE_SECCOMP
|
||||
if (checkcfg(CFG_SECCOMP)) {
|
||||
arg_seccomp = 1;
|
||||
cfg.seccomp_list = strdup(ptr + 8);
|
||||
if (!cfg.seccomp_list)
|
||||
errExit("strdup");
|
||||
cfg.seccomp_list = seccomp_check_list(ptr + 8);
|
||||
}
|
||||
else
|
||||
fprintf(stderr, "Warning: user seccomp feature is disabled in Firejail configuration file\n");
|
||||
|
|
@ -545,9 +543,7 @@ int profile_check_line(char *ptr, int lineno, const char *fname) {
|
|||
#ifdef HAVE_SECCOMP
|
||||
if (checkcfg(CFG_SECCOMP)) {
|
||||
arg_seccomp = 1;
|
||||
cfg.seccomp_list_drop = strdup(ptr + 13);
|
||||
if (!cfg.seccomp_list_drop)
|
||||
errExit("strdup");
|
||||
cfg.seccomp_list_drop = seccomp_check_list(ptr + 13);
|
||||
}
|
||||
else
|
||||
fprintf(stderr, "Warning: user seccomp feature is disabled in Firejail configuration file\n");
|
||||
|
|
@ -560,9 +556,7 @@ int profile_check_line(char *ptr, int lineno, const char *fname) {
|
|||
#ifdef HAVE_SECCOMP
|
||||
if (checkcfg(CFG_SECCOMP)) {
|
||||
arg_seccomp = 1;
|
||||
cfg.seccomp_list_keep= strdup(ptr + 13);
|
||||
if (!cfg.seccomp_list_keep)
|
||||
errExit("strdup");
|
||||
cfg.seccomp_list_keep= seccomp_check_list(ptr + 13);
|
||||
}
|
||||
else
|
||||
fprintf(stderr, "Warning: user seccomp feature is disabled in Firejail configuration file\n");
|
||||
|
|
@ -576,7 +570,7 @@ int profile_check_line(char *ptr, int lineno, const char *fname) {
|
|||
arg_caps_list = strdup(ptr + 10);
|
||||
if (!arg_caps_list)
|
||||
errExit("strdup");
|
||||
// verify seccomp list and exit if problems
|
||||
// verify caps list and exit if problems
|
||||
if (caps_check_list(arg_caps_list, NULL))
|
||||
exit(1);
|
||||
return 0;
|
||||
|
|
@ -588,7 +582,7 @@ int profile_check_line(char *ptr, int lineno, const char *fname) {
|
|||
arg_caps_list = strdup(ptr + 10);
|
||||
if (!arg_caps_list)
|
||||
errExit("strdup");
|
||||
// verify seccomp list and exit if problems
|
||||
// verify caps list and exit if problems
|
||||
if (caps_check_list(arg_caps_list, NULL))
|
||||
exit(1);
|
||||
return 0;
|
||||
|
|
|
|||
|
|
@ -847,8 +847,6 @@ assert(0);
|
|||
if (arg_seccomp == 1) {
|
||||
if (cfg.seccomp_list_keep)
|
||||
seccomp_filter_keep();
|
||||
else if (cfg.seccomp_list_errno)
|
||||
seccomp_filter_errno();
|
||||
else
|
||||
seccomp_filter_drop(enforce_seccomp);
|
||||
}
|
||||
|
|
|
|||
|
|
@ -22,6 +22,34 @@
|
|||
#include "firejail.h"
|
||||
#include "../include/seccomp.h"
|
||||
|
||||
char *seccomp_check_list(const char *str) {
|
||||
assert(str);
|
||||
if (strlen(str) == 0) {
|
||||
fprintf(stderr, "Error: empty syscall lists are not allowed\n");
|
||||
exit(1);
|
||||
}
|
||||
|
||||
int len = strlen(str) + 1;
|
||||
char *rv = malloc(len);
|
||||
if (!rv)
|
||||
errExit("malloc");
|
||||
memset(rv, 0, len);
|
||||
|
||||
const char *ptr1 = str;
|
||||
char *ptr2 = rv;
|
||||
while (*ptr1 != '\0') {
|
||||
if (isalnum(*ptr1) || *ptr1 == '_' || *ptr1 == ',' || *ptr1 == ':')
|
||||
*ptr2++ = *ptr1++;
|
||||
else {
|
||||
fprintf(stderr, "Error: invalid syscall list\n");
|
||||
exit(1);
|
||||
}
|
||||
}
|
||||
|
||||
return rv;
|
||||
}
|
||||
|
||||
|
||||
int seccomp_load(const char *fname) {
|
||||
assert(fname);
|
||||
|
||||
|
|
@ -136,10 +164,6 @@ int seccomp_filter_drop(int enforce_seccomp) {
|
|||
#endif
|
||||
if (arg_debug)
|
||||
printf("Build default+drop seccomp filter\n");
|
||||
if (strlen(cfg.seccomp_list) == 0) {
|
||||
fprintf(stderr, "Error: empty syscall lists are not allowed\n");
|
||||
exit(1);
|
||||
}
|
||||
|
||||
// build the seccomp filter as a regular user
|
||||
int rv;
|
||||
|
|
@ -157,10 +181,6 @@ int seccomp_filter_drop(int enforce_seccomp) {
|
|||
else if (cfg.seccomp_list == NULL && cfg.seccomp_list_drop) {
|
||||
if (arg_debug)
|
||||
printf("Build drop seccomp filter\n");
|
||||
if (strlen(cfg.seccomp_list_drop) == 0) {
|
||||
fprintf(stderr, "Error: empty syscall lists are not allowed\n");
|
||||
exit(1);
|
||||
}
|
||||
|
||||
// build the seccomp filter as a regular user
|
||||
int rv;
|
||||
|
|
@ -199,10 +219,6 @@ int seccomp_filter_drop(int enforce_seccomp) {
|
|||
int seccomp_filter_keep(void) {
|
||||
if (arg_debug)
|
||||
printf("Build drop seccomp filter\n");
|
||||
if (strlen(cfg.seccomp_list_keep) == 0) {
|
||||
fprintf(stderr, "Error: empty syscall lists are not allowed\n");
|
||||
exit(1);
|
||||
}
|
||||
|
||||
// build the seccomp filter as a regular user
|
||||
int rv = sbox_run(SBOX_USER | SBOX_CAPS_NONE | SBOX_SECCOMP, 4,
|
||||
|
|
@ -216,38 +232,6 @@ int seccomp_filter_keep(void) {
|
|||
return seccomp_load(RUN_SECCOMP_CFG);
|
||||
}
|
||||
|
||||
// errno filter for seccomp option
|
||||
int seccomp_filter_errno(void) {
|
||||
#if 0 //todo: disabled temporarely, bring it back
|
||||
int i;
|
||||
int higest_errno = errno_highest_nr();
|
||||
filter_init();
|
||||
|
||||
// apply errno list
|
||||
|
||||
for (i = 0; i < higest_errno; i++) {
|
||||
if (cfg.seccomp_list_errno[i]) {
|
||||
if (syscall_check_list(cfg.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 /run/firejail/mnt/seccomp
|
||||
// in order to use it in --join operations
|
||||
write_seccomp_file();
|
||||
return seccomp_load(RUN_SECCOMP_CFG);
|
||||
#else
|
||||
printf("*** --seccomp.<errno> is temporarily disabled, it will be brought back soon ***\n");
|
||||
return 0;
|
||||
#endif
|
||||
}
|
||||
|
||||
void seccomp_print_filter_name(const char *name) {
|
||||
EUID_ASSERT();
|
||||
if (!name || strlen(name) == 0) {
|
||||
|
|
|
|||
|
|
@ -40,7 +40,7 @@ static void usage(void) {
|
|||
int main(int argc, char **argv) {
|
||||
#if 0
|
||||
{
|
||||
system("cat /proc/self/status");
|
||||
//system("cat /proc/self/status");
|
||||
int i;
|
||||
for (i = 0; i < argc; i++)
|
||||
printf("*%s* ", argv[i]);
|
||||
|
|
|
|||
|
|
@ -107,7 +107,7 @@ void protocol_build_filter(const char *prlist, const char *fname) {
|
|||
assert(fname);
|
||||
|
||||
#ifndef SYS_socket
|
||||
fprintf(stderr, "Warning: --protocol not supported on this platform\n");
|
||||
fprintf(stderr, "Warning fseccomp: --protocol not supported on this platform\n");
|
||||
return;
|
||||
#else
|
||||
// build the filter
|
||||
|
|
|
|||
|
|
@ -67,12 +67,52 @@ void syscall_print(void) {
|
|||
printf("\n");
|
||||
}
|
||||
|
||||
// allowed input:
|
||||
// - syscall
|
||||
// - syscall(error)
|
||||
static void syscall_process_name(const char *name, int *syscall_nr, int *error_nr) {
|
||||
assert(name);
|
||||
if (strlen(name) == 0)
|
||||
goto error;
|
||||
*error_nr = -1;
|
||||
|
||||
// syntax check
|
||||
char *str = strdup(name);
|
||||
if (!str)
|
||||
errExit("strdup");
|
||||
|
||||
char *syscall_name = str;
|
||||
char *error_name = strchr(str, ':');
|
||||
if (error_name) {
|
||||
*error_name = '\0';
|
||||
error_name++;
|
||||
}
|
||||
if (strlen(syscall_name) == 0) {
|
||||
free(str);
|
||||
goto error;
|
||||
}
|
||||
|
||||
*syscall_nr = syscall_find_name(syscall_name);
|
||||
if (error_name) {
|
||||
*error_nr = errno_find_name(error_name);
|
||||
if (*error_nr == -1)
|
||||
*syscall_nr = -1;
|
||||
}
|
||||
|
||||
free(str);
|
||||
return;
|
||||
|
||||
error:
|
||||
fprintf(stderr, "Error fseccomp: invalid syscall list entry %s\n", name);
|
||||
exit(1);
|
||||
}
|
||||
|
||||
// return 1 if error, 0 if OK
|
||||
int syscall_check_list(const char *slist, void (*callback)(int fd, int syscall, int arg), int fd, int arg) {
|
||||
// don't allow empty lists
|
||||
if (slist == NULL || *slist == '\0') {
|
||||
fprintf(stderr, "Error: empty syscall lists are not allowed\n");
|
||||
return -1;
|
||||
fprintf(stderr, "Error fseccomp: empty syscall lists are not allowed\n");
|
||||
exit(1);
|
||||
}
|
||||
|
||||
// work on a copy of the string
|
||||
|
|
@ -80,29 +120,28 @@ int syscall_check_list(const char *slist, void (*callback)(int fd, int syscall,
|
|||
if (!str)
|
||||
errExit("strdup");
|
||||
|
||||
char *ptr = str;
|
||||
char *start = str;
|
||||
while (*ptr != '\0') {
|
||||
if (islower(*ptr) || isdigit(*ptr) || *ptr == '_')
|
||||
;
|
||||
else if (*ptr == ',') {
|
||||
*ptr = '\0';
|
||||
int nr = syscall_find_name(start);
|
||||
if (nr == -1)
|
||||
fprintf(stderr, "Warning: syscall %s not found\n", start);
|
||||
else if (callback != NULL)
|
||||
callback(fd, nr, arg);
|
||||
|
||||
start = ptr + 1;
|
||||
}
|
||||
ptr++;
|
||||
char *ptr =strtok(str, ",");
|
||||
if (ptr == NULL) {
|
||||
fprintf(stderr, "Error fseccomp: empty syscall lists are not allowed\n");
|
||||
exit(1);
|
||||
}
|
||||
if (*start != '\0') {
|
||||
int nr = syscall_find_name(start);
|
||||
if (nr == -1)
|
||||
fprintf(stderr, "Warning: syscall %s not found\n", start);
|
||||
else if (callback != NULL)
|
||||
callback(fd, nr, arg);
|
||||
|
||||
while (ptr) {
|
||||
printf("ptr %s\n", ptr);
|
||||
|
||||
int syscall_nr;
|
||||
int error_nr;
|
||||
syscall_process_name(ptr, &syscall_nr, &error_nr);
|
||||
printf("%d, %d\n", syscall_nr, error_nr);
|
||||
if (syscall_nr == -1)
|
||||
fprintf(stderr, "Warning fseccomp: syscall %s not found\n", ptr);
|
||||
else if (callback != NULL) {
|
||||
if (error_nr != -1)
|
||||
filter_add_errno(fd, syscall_nr, error_nr);
|
||||
else
|
||||
callback(fd, syscall_nr, arg);
|
||||
}
|
||||
ptr = strtok(NULL, ",");
|
||||
}
|
||||
|
||||
free(str);
|
||||
|
|
|
|||
|
|
@ -8,23 +8,23 @@ spawn $env(SHELL)
|
|||
match_max 100000
|
||||
|
||||
send -- "touch seccomp-test-file\r"
|
||||
sleep 1
|
||||
after 100
|
||||
|
||||
send -- "firejail --seccomp.enoent=unlinkat rm seccomp-test-file\r"
|
||||
send -- "firejail --seccomp=unlinkat:ENOENT rm seccomp-test-file\r"
|
||||
expect {
|
||||
timeout {puts "TESTING ERROR 0\n";exit}
|
||||
"No such file or directory"
|
||||
}
|
||||
sleep 1
|
||||
|
||||
send -- "firejail --seccomp.enoent=unlinkat --debug rm seccomp-test-file\r"
|
||||
send -- "firejail --seccomp=unlinkat:ENOENT --debug rm seccomp-test-file\r"
|
||||
expect {
|
||||
timeout {puts "TESTING ERROR 1\n";exit}
|
||||
"unlinkat 2 ENOENT"
|
||||
}
|
||||
sleep 1
|
||||
|
||||
send -- "firejail --seccomp.enoent=unlinkat,mkdir\r"
|
||||
send -- "firejail --seccomp=unlinkat:ENOENT,mkdir:ENOENT\r"
|
||||
expect {
|
||||
timeout {puts "TESTING ERROR 2\n";exit}
|
||||
"Child process initialized"
|
||||
|
|
@ -49,42 +49,6 @@ puts "\n"
|
|||
send -- "exit\r"
|
||||
sleep 1
|
||||
|
||||
|
||||
send -- "firejail --seccomp.enoent=unlinkat --seccomp.enoent=mkdir\r"
|
||||
expect {
|
||||
timeout {puts "TESTING ERROR 5\n";exit}
|
||||
"errno enoent already configured"
|
||||
}
|
||||
sleep 1
|
||||
|
||||
send -- "firejail --seccomp.enoent=unlinkat --seccomp.eperm=mkdir\r"
|
||||
expect {
|
||||
timeout {puts "TESTING ERROR 6\n";exit}
|
||||
"Child process initialized"
|
||||
}
|
||||
sleep 1
|
||||
send -- "rm seccomp-test-file\r"
|
||||
expect {
|
||||
timeout {puts "TESTING ERROR 7\n";exit}
|
||||
"No such file or directory"
|
||||
}
|
||||
after 100
|
||||
puts "\n"
|
||||
|
||||
send -- "mkdir seccomp-test-dir\r"
|
||||
expect {
|
||||
timeout {puts "TESTING ERROR 8\n";exit}
|
||||
"Operation not permitted"
|
||||
}
|
||||
after 100
|
||||
puts "\n"
|
||||
|
||||
send -- "exit\r"
|
||||
sleep 1
|
||||
|
||||
|
||||
|
||||
|
||||
send -- "rm seccomp-test-file\r"
|
||||
after 100
|
||||
puts "all done\n"
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue