int main(int argc, char *argv[]) { if (argc < 6 || strcmp(argv[1], "--error") || (strcmp(argv[3], "--allow") && strcmp(argv[3], "--deny"))) { usage(argv[0]); return 1; } const int err = parse_positive(argv[2]); if (err < 0) { return 2; } const bool default_block = !strcmp(argv[3], "--allow"); if (-1 == prctl(PR_SET_NO_NEW_PRIVS, 1, 0, 0, 0)) { perror("prctl"); return 10; } uint32_t rule_action = !default_block ? SCMP_ACT_ERRNO(err) : SCMP_ACT_ALLOW; scmp_filter_ctx ctx = seccomp_init(default_block ? SCMP_ACT_ERRNO(err) : SCMP_ACT_ALLOW); int arg = 4; for (; arg < argc; ++arg) { if (!strcmp(argv[arg], "--")) { ++arg; break; } const int syscall_no = parse_positive(argv[arg]); if (syscall_no < 0) { seccomp_release(ctx); return 5; } if (seccomp_rule_add(ctx, rule_action, syscall_no, 0)) { perror("rule add"); fprintf(stderr, "not a valid syscall number for a rule: '%s'\n", argv[arg]); seccomp_release(ctx); return 20; } } if (arg == argc) { usage(argv[0]); return 3; } if (seccomp_load(ctx)) { perror("load"); seccomp_release(ctx); return 4; } seccomp_release(ctx); execvp(argv[arg], &argv[arg]); perror("execve"); return 5; }
/** * Function responsible for setting up the open syscall for * the seccomp filter sandbox. */ static int sb_open(scmp_filter_ctx ctx, sandbox_cfg_t *filter) { int rc; sandbox_cfg_t *elem = NULL; // for each dynamic parameter filters for (elem = filter; elem != NULL; elem = elem->next) { smp_param_t *param = elem->param; if (param != NULL && param->prot == 1 && param->syscall == SCMP_SYS(open)) { rc = seccomp_rule_add_1(ctx, SCMP_ACT_ALLOW, SCMP_SYS(open), SCMP_CMP_STR(0, SCMP_CMP_EQ, param->value)); if (rc != 0) { log_err(LD_BUG,"(Sandbox) failed to add open syscall, received " "libseccomp error %d", rc); return rc; } } } rc = seccomp_rule_add_1(ctx, SCMP_ACT_ERRNO(EACCES), SCMP_SYS(open), SCMP_CMP_MASKED(1, O_CLOEXEC|O_NONBLOCK|O_NOCTTY|O_NOFOLLOW, O_RDONLY)); if (rc != 0) { log_err(LD_BUG,"(Sandbox) failed to add open syscall, received libseccomp " "error %d", rc); return rc; } return 0; }
static int seccomp_add_default_syscall_filter(scmp_filter_ctx ctx, uint64_t cap_list_retain) { unsigned i; int r; static const struct { uint64_t capability; int syscall_num; } blacklist[] = { { CAP_SYS_RAWIO, SCMP_SYS(iopl) }, { CAP_SYS_RAWIO, SCMP_SYS(ioperm) }, { CAP_SYS_BOOT, SCMP_SYS(kexec_load) }, { CAP_SYS_ADMIN, SCMP_SYS(swapon) }, { CAP_SYS_ADMIN, SCMP_SYS(swapoff) }, { CAP_SYS_ADMIN, SCMP_SYS(open_by_handle_at) }, { CAP_SYS_MODULE, SCMP_SYS(init_module) }, { CAP_SYS_MODULE, SCMP_SYS(finit_module) }, { CAP_SYS_MODULE, SCMP_SYS(delete_module) }, { CAP_SYSLOG, SCMP_SYS(syslog) }, }; for (i = 0; i < ELEMENTSOF(blacklist); i++) { if (cap_list_retain & (1ULL << blacklist[i].capability)) continue; r = seccomp_rule_add(ctx, SCMP_ACT_ERRNO(EPERM), blacklist[i].syscall_num, 0); if (r == -EFAULT) continue; /* unknown syscall */ if (r < 0) { log_error_errno(r, "Failed to block syscall: %m"); return r; } } return 0; }
void sandboxify() { if (seccomp_init(SCMP_ACT_TRAP) < 0) ERROR("Cannot go into SECCOMPv2"); seccomp_rule_add(SCMP_ACT_ALLOW, SCMP_SYS(open), 0); seccomp_rule_add(SCMP_ACT_ALLOW, SCMP_SYS(openat), 0); // XXXX // seccomp_rule_add(SCMP_ACT_ERRNO(EPERM), SCMP_SYS(open), 0); seccomp_rule_add(SCMP_ACT_ERRNO(EPERM), SCMP_SYS(access), 0); seccomp_rule_add(SCMP_ACT_ERRNO(EPERM), SCMP_SYS(fcntl), 0); // XXXX seccomp_rule_add(SCMP_ACT_ERRNO(EPERM), SCMP_SYS(fstat), 0); seccomp_rule_add(SCMP_ACT_ERRNO(EPERM), SCMP_SYS(fstat64), 0); seccomp_rule_add(SCMP_ACT_ERRNO(EPERM), SCMP_SYS(stat64), 0); seccomp_rule_add(SCMP_ACT_ALLOW, SCMP_SYS(getdents), 0); // XXXX seccomp_rule_add(SCMP_ACT_ALLOW, SCMP_SYS(stat), 0); // XXXX seccomp_rule_add(SCMP_ACT_ALLOW, SCMP_SYS(dup), 0); // XXXX seccomp_rule_add(SCMP_ACT_ALLOW, SCMP_SYS(lseek), 0); // XXXX seccomp_rule_add(SCMP_ACT_ALLOW, SCMP_SYS(close), 0); seccomp_rule_add(SCMP_ACT_ALLOW, SCMP_SYS(read), 0); seccomp_rule_add(SCMP_ACT_ALLOW, SCMP_SYS(getdents64), 0); seccomp_rule_add(SCMP_ACT_ALLOW, SCMP_SYS(write), 0); // seccomp_rule_add(SCMP_ACT_ALLOW, SCMP_SYS(writev), 0); // XXX // seccomp_rule_add(SCMP_ACT_ALLOW, SCMP_SYS(mprotect), 0); // XXX // seccomp_rule_add(SCMP_ACT_ALLOW, SCMP_SYS(futex), 0); // XXX seccomp_rule_add(SCMP_ACT_ALLOW, SCMP_SYS(mmap2), 0); seccomp_rule_add(SCMP_ACT_ALLOW, SCMP_SYS(mmap), 0); seccomp_rule_add(SCMP_ACT_ALLOW, SCMP_SYS(munmap), 0); seccomp_rule_add(SCMP_ACT_ALLOW, SCMP_SYS(mremap), 0); seccomp_rule_add(SCMP_ACT_ALLOW, SCMP_SYS(brk), 0); seccomp_rule_add(SCMP_ACT_ALLOW, SCMP_SYS(gettimeofday), 0); seccomp_rule_add(SCMP_ACT_ALLOW, SCMP_SYS(time), 0); seccomp_rule_add(SCMP_ACT_ALLOW, SCMP_SYS(exit_group), 0); #ifdef DEBUG_SECCOMP if (install_syscall_reporter()) ERROR("Cannot install syscall reporter"); #endif if (seccomp_load() < 0) ERROR("Cannot load SECCOMP filters"); seccomp_release(); }
int lxc_read_seccomp_config(struct lxc_conf *conf) { FILE *f; int ret; if (!conf->seccomp) return 0; #if HAVE_SCMP_FILTER_CTX /* XXX for debug, pass in SCMP_ACT_TRAP */ conf->seccomp_ctx = seccomp_init(SCMP_ACT_ERRNO(31)); ret = !conf->seccomp_ctx; #else ret = seccomp_init(SCMP_ACT_ERRNO(31)) < 0; #endif if (ret) { ERROR("failed initializing seccomp"); return -1; } /* turn of no-new-privs. We don't want it in lxc, and it breaks * with apparmor */ if (seccomp_attr_set( #if HAVE_SCMP_FILTER_CTX conf->seccomp_ctx, #endif SCMP_FLTATR_CTL_NNP, 0)) { ERROR("failed to turn off n-new-privs\n"); return -1; } process_lock(); f = fopen(conf->seccomp, "r"); process_unlock(); if (!f) { SYSERROR("failed to open seccomp policy file %s\n", conf->seccomp); return -1; } ret = parse_config(f, conf); process_lock(); fclose(f); process_unlock(); return ret; }
u_int32_t pcm_string_to_policy(const char *str) { if(strcasecmp(str, "ALLOW") == 0) { return SCMP_ACT_ALLOW; } else if(strcasecmp(str, "KILL") == 0) { return SCMP_ACT_KILL; } else if(strcasecmp(str, "ERRNO") == 0) { return SCMP_ACT_ERRNO(EPERM); } return -1; }
static int sb__sysctl(scmp_filter_ctx ctx, sandbox_cfg_t *filter) { int rc; (void) filter; (void) ctx; rc = seccomp_rule_add_0(ctx, SCMP_ACT_ERRNO(EPERM), SCMP_SYS(_sysctl)); if (rc != 0) { log_err(LD_BUG,"(Sandbox) failed to add _sysctl syscall, " "received libseccomp error %d", rc); return rc; } return 0; }
bool do_resolve_add_rule(uint32_t arch, char *line, scmp_filter_ctx ctx, uint32_t action) { int nr, ret; ret = seccomp_arch_exist(ctx, arch); if (arch && ret != 0) { ERROR("BUG: Seccomp: rule and context arch do not match (arch " "%d): %s.", arch, strerror(-ret)); return false; } if (strncmp(line, "reject_force_umount", 19) == 0) { INFO("Setting Seccomp rule to reject force umounts."); ret = seccomp_rule_add_exact(ctx, SCMP_ACT_ERRNO(EACCES), SCMP_SYS(umount2), 1, SCMP_A1(SCMP_CMP_MASKED_EQ , MNT_FORCE , MNT_FORCE )); if (ret < 0) { ERROR("Failed (%d) loading rule to reject force " "umount: %s.", ret, strerror(-ret)); return false; } return true; } nr = seccomp_syscall_resolve_name(line); if (nr == __NR_SCMP_ERROR) { WARN("Seccomp: failed to resolve syscall: %s.", line); WARN("This syscall will NOT be blacklisted."); return true; } if (nr < 0) { WARN("Seccomp: got negative for syscall: %d: %s.", nr, line); WARN("This syscall will NOT be blacklisted."); return true; } ret = seccomp_rule_add_exact(ctx, action, nr, 0); if (ret < 0) { ERROR("Failed (%d) loading rule for %s (nr %d action %d): %s.", ret, line, nr, action, strerror(-ret)); return false; } return true; }
static uint32_t get_v2_default_action(char *line) { uint32_t ret_action = -1; while (*line == ' ') line++; // after 'whitelist' or 'blacklist' comes default behavior if (strncmp(line, "kill", 4) == 0) ret_action = SCMP_ACT_KILL; else if (strncmp(line, "errno", 5) == 0) { int e; if (sscanf(line+5, "%d", &e) != 1) { ERROR("Bad errno value in %s", line); return -2; } ret_action = SCMP_ACT_ERRNO(e); } else if (strncmp(line, "allow", 5) == 0) ret_action = SCMP_ACT_ALLOW; else if (strncmp(line, "trap", 4) == 0) ret_action = SCMP_ACT_TRAP; return ret_action; }
int main(int argc, char* argv[], char* envp[]) { if (argc<3 || !strcmp(argv[1], "-?") || !strcmp(argv[1], "--help") || !strcmp(argv[1], "--version")) { fprintf(stderr, "Usage: limit_syscalls syscall1 syscall2 ... syscallN -- program [arguments]\n"); fprintf(stderr, "Example:\n" " limit_syscalls execve exit write read open close mmap2 fstat64 access mprotect set_thread_area -- /bin/echo qqq\n"); fprintf(stderr, "Advanced:\n"); fprintf(stderr, " LIMIT_SYSCALLS_DEFAULT_ACTION={a,k,eN} - by default allow, kill or return error N\n"); fprintf(stderr, " some_syscall,A0>=3,A4<<1000,A1!=4,A2&&0x0F==0x0F - compare arguments\n"); fprintf(stderr, " some_syscall,{a,k,eN} - allow, kill or return error N for this rule\n"); fprintf(stderr, "Some more example:\n"); fprintf(stderr," LIMIT_SYSCALLS_DEFAULT_ACTION=a limit_syscalls 'write,A0==1,e0' -- /usr/bin/printf --help\n"); fprintf(stderr," (this makes write to stdout in /usr/bin/printf silently fail, looping it)\n"); return 126; } // ECHRNG, just to provide more or less noticable message when we block a syscall uint32_t default_action = SCMP_ACT_ERRNO(44); if (getenv("LIMIT_SYSCALLS_DEFAULT_ACTION")) { const char* e = getenv("LIMIT_SYSCALLS_DEFAULT_ACTION"); if(!strcmp(e, "a")) default_action=SCMP_ACT_ALLOW; else if(!strcmp(e, "k")) default_action=SCMP_ACT_KILL; else if(e[0] == 'e') { int errno_; if (sscanf(e+1,"%i", &errno_)!=1) { fprintf(stderr, "LIMIT_SYSCALLS_DEFAULT_ACTION=e<number> expected\n"); return 109; } default_action=SCMP_ACT_ERRNO(errno_); } else { fprintf(stderr, "LIMIT_SYSCALLS_DEFAULT_ACTION should be a, k or e<number>\n"); return 110; } } scmp_filter_ctx ctx = seccomp_init(default_action); if (!ctx) { perror("seccomp_init"); return 126; } int i; for (i=1; i<argc; ++i) { if (!strcmp(argv[i], "--")) break; const char* syscall_name = strtok(argv[i], ","); int syscall = seccomp_syscall_resolve_name(argv[i]); if (syscall == __NR_SCMP_ERROR) { fprintf(stderr, "Failed to resolve syscall %s\n", syscall_name); return 125; } int nargs = 0; struct scmp_arg_cmp args[6]; uint32_t action = SCMP_ACT_ALLOW; const char* aa = strtok(NULL, ","); for (;aa; aa=strtok(NULL, ",")) { if (aa[0]=='A') { if(nargs==6) { fprintf(stderr, "Maximum comparator count (6) exceed in %s\n", argv[i]); return 103; } if( !(aa[1]>='0' && aa[1]<='5') ) { fprintf(stderr, "A[0-5] expected in %s\n", argv[i]); return 100; } int cmp = 0; /* invalid value */ if(!strncmp(aa+2, "!=", 2)) cmp=SCMP_CMP_NE; if(!strncmp(aa+2, "<<", 2)) cmp=SCMP_CMP_LT; if(!strncmp(aa+2, "<=", 2)) cmp=SCMP_CMP_LE; if(!strncmp(aa+2, "==", 2)) cmp=SCMP_CMP_EQ; if(!strncmp(aa+2, ">=", 2)) cmp=SCMP_CMP_GE; if(!strncmp(aa+2, ">>", 2)) cmp=SCMP_CMP_GT; if(!strncmp(aa+2, "&&", 2)) cmp=SCMP_CMP_MASKED_EQ; if (!cmp) { fprintf(stderr, "After An there should be comparison operator like" " != << <= == => >> ot &&; in %s\n", argv[i]); return 101; } if (cmp != SCMP_CMP_MASKED_EQ) { scmp_datum_t datum; if(sscanf(aa+4, "%lli", &datum)!=1) { fprintf(stderr, "After AxOP there should be some sort of number in %s\n", argv[i]); return 102; } args[nargs++] = SCMP_CMP(aa[1]-'0', cmp, datum); } else { scmp_datum_t mask; scmp_datum_t datum; if(sscanf(aa+4, "%lli==%lli", &mask, &datum)!=2) { fprintf(stderr, "After Ax&& there should be number==number; in %s\n", argv[i]); return 104; } args[nargs++] = SCMP_CMP(aa[1]-'0', SCMP_CMP_MASKED_EQ, mask, datum); } } else if (aa[0]=='e') { int errno_; if (sscanf(aa+1,"%i", &errno_)!=1) { fprintf(stderr, "After e should be number in %s\n", argv[i]); return 105; } action = SCMP_ACT_ERRNO(errno_); } else if (aa[0]=='k') { action = SCMP_ACT_KILL; } else if (aa[0]=='a') { action = SCMP_ACT_ALLOW; } else { fprintf(stderr, "Unknown %c in %s\n", aa[0], argv[i]); return 107; } } int ret = seccomp_rule_add_hack(ctx, action, syscall, nargs, args); if (ret!=0) { fprintf(stderr, "seccomp_rule_add returned %d\n", ret); return 124; } } int ret = seccomp_load(ctx); if (ret!=0) { fprintf(stderr, "seccomp_load returned %d\n", ret); } execve(argv[i+1], argv+i+1, envp); perror("execve"); return 123; }
int main(int argc, char *argv[]) { int opt = 0; bool autoall = FALSE; int configsetup = 0; int checkconfig = 0; const char *export = "export"; /* display export before the foo=bar or not */ bool dolist = FALSE, listadd = FALSE, listroute = FALSE, liststart = FALSE, listignore = FALSE, listall = FALSE, liststack = FALSE; char *configfile = NULL; const char *varprefix = ""; int exit_status = 0; struct starter_conn *conn = NULL; const char *ctlbase = NULL; bool resolvip = TRUE; /* default to looking up names */ #if 0 /* efence settings */ extern int EF_PROTECT_BELOW; extern int EF_PROTECT_FREE; EF_PROTECT_BELOW = 1; EF_PROTECT_FREE = 1; #endif progname = argv[0]; rootdir[0] = '\0'; tool_init_log(); while ((opt = getopt_long(argc, argv, "", longopts, 0)) != EOF) { switch (opt) { case 'h': /* usage: */ usage(); break; case 'a': autoall = TRUE; break; case 'D': verbose++; lex_verbosity++; break; case 'T': configsetup++; /* ??? is this not idempotent? */ break; case 'K': checkconfig++; /* ??? is this not idempotent? */ break; case 'N': export = ""; break; case 'C': configfile = clone_str(optarg, "config file name"); break; case 'c': ctlbase = clone_str(optarg, "control base"); break; case 'L': listadd = TRUE; dolist = TRUE; break; case 'r': listroute = TRUE; dolist = TRUE; break; case 's': liststart = TRUE; dolist = TRUE; break; case 'S': liststack = TRUE; dolist = TRUE; break; case 'i': listignore = TRUE; dolist = TRUE; break; case 'A': listall = TRUE; dolist = TRUE; break; case 'P': varprefix = optarg; break; case 'R': printf("setting rootdir=%s\n", optarg); jam_str(rootdir, sizeof(rootdir), optarg); break; case 'd': case 'n': printf("Warning: options --defaultroute and --defaultroutenexthop are obsolete and were ignored\n"); break; default: usage(); } } /* if nothing to add, then complain */ if (optind == argc && !autoall && !dolist && !configsetup && !checkconfig) usage(); if (verbose > 3) { yydebug = 1; } char *confdir = IPSEC_CONFDIR; if (configfile == NULL) { /* ??? see code clone in programs/readwriteconf/readwriteconf.c */ configfile = alloc_bytes(strlen(confdir) + sizeof("/ipsec.conf"), "conf file"); /* calculate default value for configfile */ strcpy(configfile, confdir); /* safe: see allocation above */ if (configfile[0] != '\0' && configfile[strlen(configfile) - 1] != '/') strcat(configfile, "/"); /* safe: see allocation above */ strcat(configfile, "ipsec.conf"); /* safe: see allocation above */ } if (verbose) printf("opening file: %s\n", configfile); starter_use_log(verbose != 0, TRUE, verbose == 0); if (configsetup || checkconfig || dolist) { /* skip if we have no use for them... causes delays */ resolvip = FALSE; } struct starter_config *cfg = NULL; { err_t err = NULL; cfg = confread_load(configfile, &err, resolvip, ctlbase, configsetup); if (cfg == NULL) { fprintf(stderr, "cannot load config '%s': %s\n", configfile, err); exit(3); } else if (checkconfig) { confread_free(cfg); exit(0); } } #ifdef HAVE_SECCOMP switch(cfg->setup.options[KBF_SECCOMP]) { case SECCOMP_ENABLED: init_seccomp_addconn(SCMP_ACT_KILL); break; case SECCOMP_TOLERANT: init_seccomp_addconn(SCMP_ACT_ERRNO(EACCES)); break; case SECCOMP_DISABLED: break; default: bad_case(cfg->setup.options[KBF_SECCOMP]); } #endif if (autoall) { if (verbose) printf("loading all conns according to their auto= settings\n"); /* * Load all conns marked as auto=add or better. * First, do the auto=route and auto=add conns to quickly * get routes in place, then do auto=start as these can be * slower. * This mimics behaviour of the old _plutoload */ if (verbose) printf(" Pass #1: Loading auto=add, auto=route and auto=start connections\n"); for (conn = cfg->conns.tqh_first; conn != NULL; conn = conn->link.tqe_next) { if (conn->desired_state == STARTUP_ADD || conn->desired_state == STARTUP_ONDEMAND || conn->desired_state == STARTUP_START) { if (verbose) printf(" %s", conn->name); resolve_defaultroute(conn); starter_whack_add_conn(cfg, conn); } } /* * We loaded all connections. Now tell pluto to listen, * then route the conns and resolve default route. */ starter_whack_listen(cfg); if (verbose) printf(" Pass #2: Routing auto=route and auto=start connections\n"); for (conn = cfg->conns.tqh_first; conn != NULL; conn = conn->link.tqe_next) { if (conn->desired_state == STARTUP_ADD || conn->desired_state == STARTUP_ONDEMAND || conn->desired_state == STARTUP_START) { if (verbose) printf(" %s", conn->name); resolve_defaultroute(conn); if (conn->desired_state == STARTUP_ONDEMAND || conn->desired_state == STARTUP_START) { starter_whack_route_conn(cfg, conn); } } } if (verbose) printf(" Pass #3: Initiating auto=start connections\n"); for (conn = cfg->conns.tqh_first; conn != NULL; conn = conn->link.tqe_next) { if (conn->desired_state == STARTUP_START) { if (verbose) printf(" %s", conn->name); starter_whack_initiate_conn(cfg, conn); } } if (verbose) printf("\n"); } else { /* load named conns, regardless of their state */ int connum; if (verbose) printf("loading named conns:"); for (connum = optind; connum < argc; connum++) { char *connname = argv[connum]; if (verbose) printf(" %s", connname); for (conn = cfg->conns.tqh_first; conn != NULL; conn = conn->link.tqe_next) { if (streq(conn->name, connname)) { if (conn->state == STATE_ADDED) { printf("\nconn %s already added\n", conn->name); } else if (conn->state == STATE_FAILED) { printf("\nconn %s did not load properly\n", conn->name); } else { resolve_defaultroute(conn); exit_status = starter_whack_add_conn( cfg, conn); conn->state = STATE_ADDED; } break; } } if (conn == NULL) { /* * only if we don't find it, do we now look * for aliases */ for (conn = cfg->conns.tqh_first; conn != NULL; conn = conn->link.tqe_next) { if (conn->strings_set[KSCF_CONNALIAS] && lsw_alias_cmp(connname, conn-> strings[KSCF_CONNALIAS] )) { if (conn->state == STATE_ADDED) { printf("\nalias: %s conn %s already added\n", connname, conn->name); } else if (conn->state == STATE_FAILED) { printf("\nalias: %s conn %s did not load properly\n", connname, conn->name); } else { resolve_defaultroute( conn); exit_status = starter_whack_add_conn( cfg, conn); conn->state = STATE_ADDED; } break; } } } if (conn == NULL) { exit_status++; if (!verbose) { printf("conn '%s': not found (tried aliases)\n", connname); } else { printf(" (notfound)\n"); } } } } if (listall) { if (verbose) printf("listing all conns\n"); for (conn = cfg->conns.tqh_first; conn != NULL; conn = conn->link.tqe_next) printf("%s ", conn->name); printf("\n"); } else { if (listadd) { if (verbose) printf("listing all conns marked as auto=add\n"); /* list all conns marked as auto=add */ for (conn = cfg->conns.tqh_first; conn != NULL; conn = conn->link.tqe_next) { if (conn->desired_state == STARTUP_ADD) printf("%s ", conn->name); } } if (listroute) { if (verbose) printf("listing all conns marked as auto=route and auto=start\n"); /* * list all conns marked as auto=route or start or * better */ for (conn = cfg->conns.tqh_first; conn != NULL; conn = conn->link.tqe_next) { if (conn->desired_state == STARTUP_START || conn->desired_state == STARTUP_ONDEMAND) printf("%s ", conn->name); } } if (liststart && !listroute) { if (verbose) printf("listing all conns marked as auto=start\n"); /* list all conns marked as auto=start */ for (conn = cfg->conns.tqh_first; conn != NULL; conn = conn->link.tqe_next) { if (conn->desired_state == STARTUP_START) printf("%s ", conn->name); } } if (listignore) { if (verbose) printf("listing all conns marked as auto=ignore\n"); /* list all conns marked as auto=start */ for (conn = cfg->conns.tqh_first; conn != NULL; conn = conn->link.tqe_next) { if (conn->desired_state == STARTUP_IGNORE) printf("%s ", conn->name); } printf("\n"); } } if (liststack) { const struct keyword_def *kd; for (kd = ipsec_conf_keywords_v2; kd->keyname != NULL; kd++) { if (strstr(kd->keyname, "protostack")) { if (cfg->setup.strings[kd->field]) { printf("%s\n", cfg->setup.strings[kd->field]); } else { /* implicit default */ printf("netkey\n"); } } } confread_free(cfg); exit(0); } if (configsetup) { const struct keyword_def *kd; printf("%s %sconfreadstatus=''\n", export, varprefix); for (kd = ipsec_conf_keywords_v2; kd->keyname != NULL; kd++) { if ((kd->validity & kv_config) == 0) continue; switch (kd->type) { case kt_string: case kt_filename: case kt_dirname: case kt_loose_enum: if (cfg->setup.strings[kd->field]) { printf("%s %s%s='%s'\n", export, varprefix, kd->keyname, cfg->setup.strings[kd->field]); } break; case kt_bool: printf("%s %s%s='%s'\n", export, varprefix, kd->keyname, cfg->setup.options[kd->field] ? "yes" : "no"); break; case kt_list: printf("%s %s%s='", export, varprefix, kd->keyname); confwrite_list(stdout, "", cfg->setup.options[kd->field], kd); printf("'\n"); break; case kt_obsolete: printf("# obsolete option '%s%s' ignored\n", varprefix, kd->keyname); break; default: if (cfg->setup.options[kd->field] || cfg->setup.options_set[kd->field]) { printf("%s %s%s='%d'\n", export, varprefix, kd->keyname, cfg->setup.options[kd->field]); } break; } }
int setup_seccomp(uint64_t cap_list_retain) { scmp_filter_ctx seccomp; int r; seccomp = seccomp_init(SCMP_ACT_ALLOW); if (!seccomp) return log_oom(); r = seccomp_add_secondary_archs(seccomp); if (r < 0) { log_error_errno(r, "Failed to add secondary archs to seccomp filter: %m"); goto finish; } r = seccomp_add_default_syscall_filter(seccomp, cap_list_retain); if (r < 0) goto finish; /* Audit is broken in containers, much of the userspace audit hookup will fail if running inside a container. We don't care and just turn off creation of audit sockets. This will make socket(AF_NETLINK, *, NETLINK_AUDIT) fail with EAFNOSUPPORT which audit userspace uses as indication that audit is disabled in the kernel. */ r = seccomp_rule_add( seccomp, SCMP_ACT_ERRNO(EAFNOSUPPORT), SCMP_SYS(socket), 2, SCMP_A0(SCMP_CMP_EQ, AF_NETLINK), SCMP_A2(SCMP_CMP_EQ, NETLINK_AUDIT)); if (r < 0) { log_error_errno(r, "Failed to add audit seccomp rule: %m"); goto finish; } r = seccomp_attr_set(seccomp, SCMP_FLTATR_CTL_NNP, 0); if (r < 0) { log_error_errno(r, "Failed to unset NO_NEW_PRIVS: %m"); goto finish; } r = seccomp_load(seccomp); if (r == -EINVAL) { log_debug_errno(r, "Kernel is probably not configured with CONFIG_SECCOMP. Disabling seccomp audit filter: %m"); r = 0; goto finish; } if (r < 0) { log_error_errno(r, "Failed to install seccomp audit filter: %m"); goto finish; } finish: seccomp_release(seccomp); return r; }
int waive(const int flags) { scmp_filter_ctx ctx; int ret = -1; ctx = seccomp_init(SCMP_ACT_ALLOW); if (NULL == ctx) goto out; if (0 != (WAIVE_SOCKET & flags)) { if (0 != seccomp_rule_add(ctx, SCMP_ACT_ERRNO(EPERM), SCMP_SYS(socket), 0)) goto release; if (0 != seccomp_rule_add(ctx, SCMP_ACT_ERRNO(EPERM), SCMP_SYS(socketpair), 0)) goto release; } else { if (0 != (WAIVE_INET & flags)) { if (0 != seccomp_rule_add(ctx, SCMP_ACT_ERRNO(EPERM), SCMP_SYS(socket), 1, SCMP_A0(SCMP_CMP_EQ, AF_INET))) goto release; if (0 != seccomp_rule_add(ctx, SCMP_ACT_ERRNO(EPERM), SCMP_SYS(socket), 1, SCMP_A0(SCMP_CMP_EQ, AF_INET6))) goto release; if (0 != seccomp_rule_add(ctx, SCMP_ACT_ERRNO(EPERM), SCMP_SYS(socketpair), 1, SCMP_A0(SCMP_CMP_EQ, AF_INET))) goto release; if (0 != seccomp_rule_add(ctx, SCMP_ACT_ERRNO(EPERM), SCMP_SYS(socketpair), 1, SCMP_A0(SCMP_CMP_EQ, AF_INET6))) goto release; } if (0 != (WAIVE_UN & flags)) { if (0 != seccomp_rule_add(ctx, SCMP_ACT_ERRNO(EPERM), SCMP_SYS(socket), 1, SCMP_A0(SCMP_CMP_EQ, AF_UNIX))) goto release; if (0 != seccomp_rule_add(ctx, SCMP_ACT_ERRNO(EPERM), SCMP_SYS(socketpair), 1, SCMP_A0(SCMP_CMP_EQ, AF_UNIX))) goto release; } if (0 != (WAIVE_PACKET & flags)) { if (0 != seccomp_rule_add(ctx, SCMP_ACT_ERRNO(EPERM), SCMP_SYS(socket), 1, SCMP_A0(SCMP_CMP_EQ, AF_PACKET))) goto release; if (0 != seccomp_rule_add(ctx, SCMP_ACT_ERRNO(EPERM), SCMP_SYS(socketpair), 1, SCMP_A0(SCMP_CMP_EQ, AF_PACKET))) goto release; } } if (0 != (WAIVE_MOUNT & flags)) { if (0 != seccomp_rule_add(ctx, SCMP_ACT_ERRNO(EPERM), SCMP_SYS(mount), 0)) goto release; if (0 != seccomp_rule_add(ctx, SCMP_ACT_ERRNO(EPERM), SCMP_SYS(umount), 0)) goto release; if (0 != seccomp_rule_add(ctx, SCMP_ACT_ERRNO(EPERM), SCMP_SYS(umount2), 0)) goto release; } if (0 != (WAIVE_OPEN & flags)) { if (0 != seccomp_rule_add(ctx, SCMP_ACT_ERRNO(EPERM), SCMP_SYS(open), 0)) goto release; if (0 != seccomp_rule_add(ctx, SCMP_ACT_ERRNO(EPERM), SCMP_SYS(openat), 0)) goto release; if (0 != seccomp_rule_add(ctx, SCMP_ACT_ERRNO(EPERM), SCMP_SYS(creat), 0)) goto release; } if (0 != (WAIVE_EXEC & flags)) { if (0 != seccomp_rule_add(ctx, SCMP_ACT_ERRNO(EPERM), SCMP_SYS(execve), 0)) goto release; #ifdef __NR_execveat if (0 != seccomp_rule_add(ctx, SCMP_ACT_ERRNO(EPERM), SCMP_SYS(execveat), 0)) goto release; #endif if (0 != seccomp_rule_add(ctx, SCMP_ACT_ERRNO(EPERM), SCMP_SYS(mprotect), 1, SCMP_A2(SCMP_CMP_EQ, PROT_EXEC))) goto release; if (0 != seccomp_rule_add(ctx, SCMP_ACT_ERRNO(EPERM), SCMP_SYS(mprotect), 1, SCMP_A2(SCMP_CMP_EQ, PROT_READ | PROT_EXEC))) goto release; if (0 != seccomp_rule_add(ctx, SCMP_ACT_ERRNO(EPERM), SCMP_SYS(mprotect), 1, SCMP_A2(SCMP_CMP_EQ, PROT_WRITE | PROT_EXEC))) goto release; if (0 != seccomp_rule_add(ctx, SCMP_ACT_ERRNO(EPERM), SCMP_SYS(mprotect), 1, SCMP_A2(SCMP_CMP_EQ, PROT_READ | PROT_WRITE | PROT_EXEC))) goto release; if (0 != seccomp_rule_add(ctx, SCMP_ACT_ERRNO(EPERM), SCMP_SYS(mmap), 1, SCMP_A2(SCMP_CMP_EQ, PROT_READ | PROT_EXEC))) goto release; if (0 != seccomp_rule_add(ctx, SCMP_ACT_ERRNO(EPERM), SCMP_SYS(mmap), 1, SCMP_A2(SCMP_CMP_EQ, PROT_WRITE | PROT_EXEC))) goto release; if (0 != seccomp_rule_add(ctx, SCMP_ACT_ERRNO(EPERM), SCMP_SYS(mmap), 1, SCMP_A2(SCMP_CMP_EQ, PROT_READ | PROT_WRITE | PROT_EXEC))) goto release; if (0 != seccomp_rule_add(ctx, SCMP_ACT_ERRNO(EPERM), SCMP_SYS(mmap2), 1, SCMP_A2(SCMP_CMP_EQ, PROT_WRITE | PROT_EXEC))) goto release; if (0 != seccomp_rule_add(ctx, SCMP_ACT_ERRNO(EPERM), SCMP_SYS(mmap2), 1, SCMP_A2(SCMP_CMP_EQ, PROT_READ | PROT_WRITE | PROT_EXEC))) goto release; } if (0 != (WAIVE_CLONE & flags)) { if (0 != seccomp_rule_add(ctx, SCMP_ACT_ERRNO(EPERM), SCMP_SYS(clone), 0)) goto release; } if (0 != (WAIVE_KILL & flags)) { if (0 != seccomp_rule_add(ctx, SCMP_ACT_ERRNO(EPERM), SCMP_SYS(kill), 1, SCMP_A0(SCMP_CMP_NE, 0))) goto release; if (0 != seccomp_rule_add(ctx, SCMP_ACT_ERRNO(EPERM), SCMP_SYS(tkill), 1, SCMP_A0(SCMP_CMP_NE, 0))) goto release; if (0 != seccomp_rule_add(ctx, SCMP_ACT_ERRNO(EPERM), SCMP_SYS(tgkill), 1, SCMP_A0(SCMP_CMP_NE, 0))) goto release; } if (0 != (WAIVE_PIPE & flags)) { if (0 != seccomp_rule_add(ctx, SCMP_ACT_ERRNO(EPERM), SCMP_SYS(pipe), 0)) goto release; if (0 != seccomp_rule_add(ctx, SCMP_ACT_ERRNO(EPERM), SCMP_SYS(pipe2), 0)) goto release; if (0 != seccomp_rule_add(ctx, SCMP_ACT_ERRNO(EPERM), SCMP_SYS(mknod), 0)) goto release; if (0 != seccomp_rule_add(ctx, SCMP_ACT_ERRNO(EPERM), SCMP_SYS(mknodat), 0)) goto release; } if (0 == seccomp_load(ctx)) ret = 0; release: seccomp_release(ctx); out: return ret; }
gboolean tracker_seccomp_init (void) { scmp_filter_ctx ctx; ctx = seccomp_init (SCMP_ACT_TRAP); if (ctx == NULL) return FALSE; /* Memory management */ ALLOW_RULE (brk); ALLOW_RULE (mmap); ALLOW_RULE (mmap2); ALLOW_RULE (munmap); ALLOW_RULE (mremap); ALLOW_RULE (mprotect); ALLOW_RULE (madvise); ERROR_RULE (mlock, EPERM); ERROR_RULE (mlock2, EPERM); ERROR_RULE (munlock, EPERM); ERROR_RULE (mlockall, EPERM); ERROR_RULE (munlockall, EPERM); /* Process management */ ALLOW_RULE (exit_group); ALLOW_RULE (getuid); ALLOW_RULE (getuid32); ALLOW_RULE (geteuid); ALLOW_RULE (geteuid32); ALLOW_RULE (getppid); ALLOW_RULE (gettid); ALLOW_RULE (exit); ALLOW_RULE (getrusage); ALLOW_RULE (getrlimit); /* Basic filesystem access */ ALLOW_RULE (fstat); ALLOW_RULE (fstat64); ALLOW_RULE (stat); ALLOW_RULE (stat64); ALLOW_RULE (statfs); ALLOW_RULE (statfs64); ALLOW_RULE (lstat); ALLOW_RULE (lstat64); ALLOW_RULE (access); ALLOW_RULE (getdents); ALLOW_RULE (getdents64); ALLOW_RULE (readlink); ALLOW_RULE (readlinkat); ALLOW_RULE (utime); ALLOW_RULE (time); ALLOW_RULE (fsync); ALLOW_RULE (umask); /* Processes and threads */ ALLOW_RULE (clone); ALLOW_RULE (futex); ALLOW_RULE (set_robust_list); ALLOW_RULE (rt_sigaction); ALLOW_RULE (rt_sigprocmask); ALLOW_RULE (sched_yield); ALLOW_RULE (sched_getaffinity); ALLOW_RULE (nanosleep); /* Main loops */ ALLOW_RULE (poll); ALLOW_RULE (ppoll); ALLOW_RULE (fcntl); ALLOW_RULE (fcntl64); ALLOW_RULE (eventfd); ALLOW_RULE (eventfd2); ALLOW_RULE (pipe); ALLOW_RULE (pipe2); /* System */ ALLOW_RULE (uname); ALLOW_RULE (sysinfo); ALLOW_RULE (prctl); ALLOW_RULE (getrandom); ALLOW_RULE (clock_gettime); ALLOW_RULE (clock_getres); ALLOW_RULE (gettimeofday); /* Descriptors */ ALLOW_RULE (close); ALLOW_RULE (read); ALLOW_RULE (pread64); ALLOW_RULE (lseek); ALLOW_RULE (_llseek); ALLOW_RULE (fadvise64); ALLOW_RULE (write); ALLOW_RULE (writev); ALLOW_RULE (dup); /* Needed by some GStreamer modules doing crazy stuff, less * scary thanks to the restriction below about sockets being * local. */ ALLOW_RULE (connect); ALLOW_RULE (send); ALLOW_RULE (sendto); ALLOW_RULE (sendmsg); ALLOW_RULE (recv); ALLOW_RULE (recvmsg); ALLOW_RULE (recvfrom); ALLOW_RULE (getsockname); ALLOW_RULE (getpeername); ALLOW_RULE (shutdown); /* Special requirements for socket/socketpair, only on AF_UNIX/AF_LOCAL */ if (seccomp_rule_add (ctx, SCMP_ACT_ALLOW, SCMP_SYS(socket), 1, SCMP_CMP(0, SCMP_CMP_EQ, AF_UNIX)) < 0) goto out; if (seccomp_rule_add (ctx, SCMP_ACT_ALLOW, SCMP_SYS(socket), 1, SCMP_CMP(0, SCMP_CMP_EQ, AF_LOCAL)) < 0) goto out; if (seccomp_rule_add (ctx, SCMP_ACT_ALLOW, SCMP_SYS(socketpair), 1, SCMP_CMP(0, SCMP_CMP_EQ, AF_UNIX)) < 0) goto out; if (seccomp_rule_add (ctx, SCMP_ACT_ALLOW, SCMP_SYS(socketpair), 1, SCMP_CMP(0, SCMP_CMP_EQ, AF_LOCAL)) < 0) goto out; /* Special requirements for ioctl, allowed on stdout/stderr */ if (seccomp_rule_add (ctx, SCMP_ACT_ALLOW, SCMP_SYS(ioctl), 1, SCMP_CMP(0, SCMP_CMP_EQ, 1)) < 0) goto out; if (seccomp_rule_add (ctx, SCMP_ACT_ALLOW, SCMP_SYS(ioctl), 1, SCMP_CMP(0, SCMP_CMP_EQ, 2)) < 0) goto out; /* Special requirements for open, allow O_RDONLY calls, but fail * if write permissions are requested. */ if (seccomp_rule_add (ctx, SCMP_ACT_ALLOW, SCMP_SYS(open), 1, SCMP_CMP(1, SCMP_CMP_MASKED_EQ, O_WRONLY | O_RDWR, 0)) < 0) goto out; if (seccomp_rule_add (ctx, SCMP_ACT_ERRNO (EACCES), SCMP_SYS(open), 1, SCMP_CMP(1, SCMP_CMP_MASKED_EQ, O_WRONLY, O_WRONLY)) < 0) goto out; if (seccomp_rule_add (ctx, SCMP_ACT_ERRNO (EACCES), SCMP_SYS(open), 1, SCMP_CMP(1, SCMP_CMP_MASKED_EQ, O_RDWR, O_RDWR)) < 0) goto out; /* Special requirements for dup2/dup3, no fiddling with stdin/out/err */ if (seccomp_rule_add (ctx, SCMP_ACT_ALLOW, SCMP_SYS(dup2), 1, SCMP_CMP(1, SCMP_CMP_GT, 2)) < 0) goto out; if (seccomp_rule_add (ctx, SCMP_ACT_ALLOW, SCMP_SYS(dup3), 1, SCMP_CMP(1, SCMP_CMP_GT, 2)) < 0) goto out; g_debug ("Loading seccomp rules."); if (seccomp_load (ctx) >= 0) return TRUE; out: g_critical ("Failed to load seccomp rules."); seccomp_release (ctx); return FALSE; }