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; }
void drop_privileges(void) { scmp_filter_ctx ctx = seccomp_init(DENY_ACTION); if (ctx == NULL) { return; } int rc = 0; rc |= seccomp_rule_add(ctx, SCMP_ACT_ALLOW, SCMP_SYS(sigreturn), 0); rc |= seccomp_rule_add(ctx, SCMP_ACT_ALLOW, SCMP_SYS(rt_sigprocmask), 0); rc |= seccomp_rule_add(ctx, SCMP_ACT_ALLOW, SCMP_SYS(futex), 0); rc |= seccomp_rule_add(ctx, SCMP_ACT_ALLOW, SCMP_SYS(epoll_wait), 0); rc |= seccomp_rule_add(ctx, SCMP_ACT_ALLOW, SCMP_SYS(epoll_pwait), 0); rc |= seccomp_rule_add(ctx, SCMP_ACT_ALLOW, SCMP_SYS(accept4), 0); rc |= seccomp_rule_add(ctx, SCMP_ACT_ALLOW, SCMP_SYS(accept), 0); rc |= seccomp_rule_add(ctx, SCMP_ACT_ALLOW, SCMP_SYS(write), 0); rc |= seccomp_rule_add(ctx, SCMP_ACT_ALLOW, SCMP_SYS(writev), 0); rc |= seccomp_rule_add(ctx, SCMP_ACT_ALLOW, SCMP_SYS(fstat), 0); rc |= seccomp_rule_add(ctx, SCMP_ACT_ALLOW, SCMP_SYS(mmap), 0); rc |= seccomp_rule_add(ctx, SCMP_ACT_ALLOW, SCMP_SYS(munmap), 0); rc |= seccomp_rule_add(ctx, SCMP_ACT_ALLOW, SCMP_SYS(shmctl), 0); rc |= seccomp_rule_add(ctx, SCMP_ACT_ALLOW, SCMP_SYS(exit_group), 0); rc |= seccomp_rule_add(ctx, SCMP_ACT_ALLOW, SCMP_SYS(brk), 0); rc |= seccomp_rule_add(ctx, SCMP_ACT_ALLOW, SCMP_SYS(ioctl), 1, SCMP_A1(SCMP_CMP_EQ, TIOCGWINSZ)); rc |= seccomp_rule_add(ctx, SCMP_ACT_ALLOW, SCMP_SYS(ioctl), 1, SCMP_A1(SCMP_CMP_EQ, TCGETS)); #ifdef MEMCACHED_DEBUG rc |= seccomp_rule_add(ctx, SCMP_ACT_ALLOW, SCMP_SYS(open), 0); rc |= seccomp_rule_add(ctx, SCMP_ACT_ALLOW, SCMP_SYS(fcntl), 0); rc |= seccomp_rule_add(ctx, SCMP_ACT_ALLOW, SCMP_SYS(read), 0); rc |= seccomp_rule_add(ctx, SCMP_ACT_ALLOW, SCMP_SYS(readv), 0); rc |= seccomp_rule_add(ctx, SCMP_ACT_ALLOW, SCMP_SYS(lseek), 0); rc |= seccomp_rule_add(ctx, SCMP_ACT_ALLOW, SCMP_SYS(close), 0); rc |= seccomp_rule_add(ctx, SCMP_ACT_ALLOW, SCMP_SYS(getpid), 0); if (settings.relaxed_privileges) { rc |= seccomp_rule_add(ctx, SCMP_ACT_ALLOW, SCMP_SYS(openat), 0); rc |= seccomp_rule_add(ctx, SCMP_ACT_ALLOW, SCMP_SYS(mkdir), 0); rc |= seccomp_rule_add(ctx, SCMP_ACT_ALLOW, SCMP_SYS(access), 0); } #endif if (rc != 0) { goto fail; } rc = seccomp_load(ctx); if (rc < 0) { goto fail; } seccomp_release(ctx); return; fail: seccomp_release(ctx); fprintf(stderr, "Failed to set a seccomp profile on the main thread\n"); exit(EXIT_FAILURE); }
static void init_seccomp_addconn(uint32_t def_action) { scmp_filter_ctx ctx = seccomp_init(def_action); int rc = 0; if (ctx == NULL) { printf("seccomp_init_addconn() failed!"); exit(EXIT_SECCOMP_FAIL); } rc |= seccomp_rule_add(ctx, SCMP_ACT_ALLOW, SCMP_SYS(access), 0); rc |= seccomp_rule_add(ctx, SCMP_ACT_ALLOW, SCMP_SYS(arch_prctl), 0); rc |= seccomp_rule_add(ctx, SCMP_ACT_ALLOW, SCMP_SYS(brk), 0); rc |= seccomp_rule_add(ctx, SCMP_ACT_ALLOW, SCMP_SYS(close), 0); rc |= seccomp_rule_add(ctx, SCMP_ACT_ALLOW, SCMP_SYS(connect), 0); rc |= seccomp_rule_add(ctx, SCMP_ACT_ALLOW, SCMP_SYS(exit_group), 0); rc |= seccomp_rule_add(ctx, SCMP_ACT_ALLOW, SCMP_SYS(fcntl), 0); rc |= seccomp_rule_add(ctx, SCMP_ACT_ALLOW, SCMP_SYS(fstat), 0); rc |= seccomp_rule_add(ctx, SCMP_ACT_ALLOW, SCMP_SYS(getrlimit), 0); rc |= seccomp_rule_add(ctx, SCMP_ACT_ALLOW, SCMP_SYS(ioctl), 0); rc |= seccomp_rule_add(ctx, SCMP_ACT_ALLOW, SCMP_SYS(mmap), 0); rc |= seccomp_rule_add(ctx, SCMP_ACT_ALLOW, SCMP_SYS(mprotect), 0); rc |= seccomp_rule_add(ctx, SCMP_ACT_ALLOW, SCMP_SYS(open), 0); rc |= seccomp_rule_add(ctx, SCMP_ACT_ALLOW, SCMP_SYS(prctl), 0); rc |= seccomp_rule_add(ctx, SCMP_ACT_ALLOW, SCMP_SYS(read), 0); rc |= seccomp_rule_add(ctx, SCMP_ACT_ALLOW, SCMP_SYS(readlink), 0); rc |= seccomp_rule_add(ctx, SCMP_ACT_ALLOW, SCMP_SYS(rt_sigaction), 0); rc |= seccomp_rule_add(ctx, SCMP_ACT_ALLOW, SCMP_SYS(rt_sigprocmask), 0); rc |= seccomp_rule_add(ctx, SCMP_ACT_ALLOW, SCMP_SYS(set_robust_list), 0); rc |= seccomp_rule_add(ctx, SCMP_ACT_ALLOW, SCMP_SYS(set_tid_address), 0); rc |= seccomp_rule_add(ctx, SCMP_ACT_ALLOW, SCMP_SYS(socket), 0); rc |= seccomp_rule_add(ctx, SCMP_ACT_ALLOW, SCMP_SYS(socketpair), 0); rc |= seccomp_rule_add(ctx, SCMP_ACT_ALLOW, SCMP_SYS(statfs), 0); rc |= seccomp_rule_add(ctx, SCMP_ACT_ALLOW, SCMP_SYS(write), 0); if (rc != 0) { printf("seccomp_rule_add() failed!"); seccomp_release(ctx); exit(EXIT_SECCOMP_FAIL); } rc = seccomp_load(ctx); if (rc < 0) { printf("seccomp_load() failed!"); seccomp_release(ctx); exit(EXIT_SECCOMP_FAIL); } }
int seccomp_start(void) { int rc = 0; unsigned int i = 0; scmp_filter_ctx ctx; ctx = seccomp_init(SCMP_ACT_KILL); if (ctx == NULL) { rc = -1; goto seccomp_return; } for (i = 0; i < ARRAY_SIZE(seccomp_whitelist); i++) { rc = seccomp_rule_add(ctx, SCMP_ACT_ALLOW, seccomp_whitelist[i].num, 0); if (rc < 0) { goto seccomp_return; } rc = seccomp_syscall_priority(ctx, seccomp_whitelist[i].num, seccomp_whitelist[i].priority); if (rc < 0) { goto seccomp_return; } } rc = seccomp_load(ctx); seccomp_return: seccomp_release(ctx); return rc; }
void setup_seccomp() { scmp_filter_ctx ctx = seccomp_init(SCMP_ACT_KILL); if(!ctx) exit(-1); if(seccomp_rule_add(ctx, SCMP_ACT_ALLOW, SCMP_SYS(open), 0)) exit(-1); if(seccomp_rule_add(ctx, SCMP_ACT_ALLOW, SCMP_SYS(socket), 0)) exit(-1); #if (SCMP_SYS(setsockopt)) #warning System does not have sys_setsockopt, the expected way to do SO_REUSEADDR. if(seccomp_rule_add(ctx, SCMP_ACT_ALLOW, SCMP_SYS(setsockopt), 0)) exit(-1); #endif #ifdef NEEDS_SOCKETCALL #warning NEEDS_SOCKETCALL=1 has been set, I wish it was not needed on some systems. if(seccomp_rule_add(ctx, SCMP_ACT_ALLOW, SCMP_SYS(socketcall), 0)) exit(-1); #endif if(seccomp_rule_add(ctx, SCMP_ACT_ALLOW, SCMP_SYS(bind), 0)) exit(-1); if(seccomp_rule_add(ctx, SCMP_ACT_ALLOW, SCMP_SYS(listen), 0)) exit(-1); if(seccomp_rule_add(ctx, SCMP_ACT_ALLOW, SCMP_SYS(rt_sigaction), 0)) exit(-1); if(seccomp_rule_add(ctx, SCMP_ACT_ALLOW, SCMP_SYS(accept), 0)) exit(-1); if(seccomp_rule_add(ctx, SCMP_ACT_ALLOW, SCMP_SYS(clone), 0)) exit(-1); if(seccomp_rule_add(ctx, SCMP_ACT_ALLOW, SCMP_SYS(setresuid32), 0)) exit(-1); if(seccomp_rule_add(ctx, SCMP_ACT_ALLOW, SCMP_SYS(setresgid32), 0)) exit(-1); if(seccomp_rule_add(ctx, SCMP_ACT_ALLOW, SCMP_SYS(alarm), 0)) exit(-1); if(seccomp_rule_add(ctx, SCMP_ACT_ALLOW, SCMP_SYS(dup2), 0)) exit(-1); if(seccomp_rule_add(ctx, SCMP_ACT_ALLOW, SCMP_SYS(close), 0)) exit(-1); if(seccomp_rule_add(ctx, SCMP_ACT_ALLOW, SCMP_SYS(write), 0)) exit(-1); if(seccomp_rule_add(ctx, SCMP_ACT_ALLOW, SCMP_SYS(read), 0)) exit(-1); if(seccomp_rule_add(ctx, SCMP_ACT_ALLOW, SCMP_SYS(exit_group), 0)) exit(-1); // Allow further restrictions. if(seccomp_rule_add(ctx, SCMP_ACT_ALLOW, SCMP_SYS(prctl), 1, SCMP_A0(SCMP_CMP_EQ, PR_SET_NO_NEW_PRIVS))) exit(-1); if(seccomp_rule_add(ctx, SCMP_ACT_ALLOW, SCMP_SYS(prctl), 1, SCMP_A0(SCMP_CMP_EQ, PR_SET_SECCOMP))) exit(-1); if(seccomp_load(ctx)) exit(-1); seccomp_release(ctx); }
scmp_filter_ctx get_new_ctx(enum lxc_hostarch_t n_arch, uint32_t default_policy_action) { scmp_filter_ctx ctx; int ret; uint32_t arch; switch(n_arch) { case lxc_seccomp_arch_i386: arch = SCMP_ARCH_X86; break; case lxc_seccomp_arch_amd64: arch = SCMP_ARCH_X86_64; break; case lxc_seccomp_arch_arm: arch = SCMP_ARCH_ARM; break; #ifdef SCMP_ARCH_PPC64LE case lxc_seccomp_arch_ppc64le: arch = SCMP_ARCH_PPC64LE; break; #endif #ifdef SCMP_ARCH_PPC64 case lxc_seccomp_arch_ppc64: arch = SCMP_ARCH_PPC64; break; #endif #ifdef SCMP_ARCH_PPC case lxc_seccomp_arch_ppc: arch = SCMP_ARCH_PPC; break; #endif default: return NULL; } if ((ctx = seccomp_init(default_policy_action)) == NULL) { ERROR("Error initializing seccomp context"); return NULL; } if (seccomp_attr_set(ctx, SCMP_FLTATR_CTL_NNP, 0)) { ERROR("failed to turn off n-new-privs"); seccomp_release(ctx); return NULL; } ret = seccomp_arch_add(ctx, arch); if (ret != 0) { ERROR("Seccomp error %d (%s) adding arch: %d", ret, strerror(ret), (int)n_arch); seccomp_release(ctx); return NULL; } if (seccomp_arch_remove(ctx, SCMP_ARCH_NATIVE) != 0) { ERROR("Seccomp error removing native arch"); seccomp_release(ctx); return NULL; } return ctx; }
int main(int argc, char *argv[]) { int rc; struct util_options opts; scmp_filter_ctx ctx = NULL; rc = util_getopt(argc, argv, &opts); if (rc < 0) goto out; ctx = seccomp_init(SCMP_ACT_KILL); if (ctx == NULL) return ENOMEM; rc = seccomp_rule_add(ctx, SCMP_ACT_ALLOW, SCMP_SYS(open), 0); if (rc != 0) goto out; rc = seccomp_rule_add(ctx, SCMP_ACT_ALLOW, SCMP_SYS(close), 0); if (rc != 0) goto out; rc = seccomp_rule_add(ctx, SCMP_ACT_ALLOW, SCMP_SYS(read), 3, SCMP_A0(SCMP_CMP_EQ, STDIN_FILENO), SCMP_A1(SCMP_CMP_NE, 0x0), SCMP_A2(SCMP_CMP_LT, SSIZE_MAX)); if (rc != 0) goto out; rc = seccomp_rule_add(ctx, SCMP_ACT_ALLOW, SCMP_SYS(write), 3, SCMP_A0(SCMP_CMP_EQ, STDOUT_FILENO), SCMP_A1(SCMP_CMP_NE, 0x0), SCMP_A2(SCMP_CMP_LT, SSIZE_MAX)); if (rc != 0) goto out; rc = seccomp_rule_add(ctx, SCMP_ACT_ALLOW, SCMP_SYS(write), 3, SCMP_A0(SCMP_CMP_EQ, STDERR_FILENO), SCMP_A1(SCMP_CMP_NE, 0x0), SCMP_A2(SCMP_CMP_LT, SSIZE_MAX)); if (rc != 0) goto out; rc = seccomp_rule_add(ctx, SCMP_ACT_ALLOW, SCMP_SYS(close), 0); if (rc != 0) goto out; rc = seccomp_rule_add(ctx, SCMP_ACT_ALLOW, SCMP_SYS(rt_sigreturn), 0); if (rc != 0) goto out; rc = util_filter_output(&opts, ctx); if (rc) goto out; out: seccomp_release(ctx); return (rc < 0 ? -rc : rc); }
int main(int argc, char *argv[]) { int rc; struct util_options opts; scmp_filter_ctx ctx = NULL; rc = util_getopt(argc, argv, &opts); if (rc < 0) goto out; ctx = seccomp_init(SCMP_ACT_KILL); if (ctx == NULL) return ENOMEM; rc = seccomp_arch_remove(ctx, SCMP_ARCH_NATIVE); if (rc != 0) goto out; rc = seccomp_arch_add(ctx, SCMP_ARCH_X86); if (rc != 0) goto out; rc = seccomp_arch_add(ctx, SCMP_ARCH_X86_64); if (rc != 0) goto out; rc = seccomp_arch_add(ctx, SCMP_ARCH_X32); if (rc != 0) goto out; rc = seccomp_rule_add(ctx, SCMP_ACT_ALLOW, SCMP_SYS(socket), 0); if (rc != 0) goto out; rc = seccomp_rule_add(ctx, SCMP_ACT_ALLOW, SCMP_SYS(connect), 0); if (rc != 0) goto out; rc = seccomp_rule_add(ctx, SCMP_ACT_ALLOW, SCMP_SYS(accept), 0); if (rc != 0) goto out; rc = seccomp_rule_add(ctx, SCMP_ACT_ALLOW, SCMP_SYS(accept4), 0); if (rc != 0) goto out; rc = seccomp_rule_add(ctx, SCMP_ACT_ALLOW, SCMP_SYS(shutdown), 0); if (rc != 0) goto out; rc = util_filter_output(&opts, ctx); if (rc) goto out; out: seccomp_release(ctx); return (rc < 0 ? -rc : rc); }
void lxc_seccomp_free(struct lxc_conf *conf) { free(conf->seccomp); conf->seccomp = NULL; #if HAVE_SCMP_FILTER_CTX if (conf->seccomp_ctx) { seccomp_release(conf->seccomp_ctx); conf->seccomp_ctx = NULL; } #endif }
void pcm_install_policy() { int rc; rc = seccomp_load(PCM_GLOBAL.seccomp); if(rc < 0) { errx(EXIT_FAILURE, "Failed to load the seccomp policy into the process"); } seccomp_release(PCM_GLOBAL.seccomp); PCM_GLOBAL.seccomp = NULL; }
int main(int argc, char *argv[]) { int rc; scmp_filter_ctx ctx = NULL; rc = util_action_parse(argv[1]); if (rc != SCMP_ACT_ALLOW) { rc = 1; goto out; } rc = util_trap_install(); if (rc != 0) goto out; ctx = seccomp_init(SCMP_ACT_TRAP); if (ctx == NULL) return ENOMEM; rc = seccomp_rule_add(ctx, SCMP_ACT_ALLOW, SCMP_SYS(open), 0); if (rc != 0) goto out; rc = seccomp_rule_add(ctx, SCMP_ACT_ALLOW, SCMP_SYS(openat), 0); if (rc != 0) goto out; rc = seccomp_rule_add(ctx, SCMP_ACT_ALLOW, SCMP_SYS(write), 0); if (rc != 0) goto out; rc = seccomp_rule_add(ctx, SCMP_ACT_ALLOW, SCMP_SYS(close), 0); if (rc != 0) goto out; rc = seccomp_rule_add(ctx, SCMP_ACT_ALLOW, SCMP_SYS(rt_sigreturn), 0); if (rc != 0) goto out; rc = seccomp_rule_add(ctx, SCMP_ACT_ALLOW, SCMP_SYS(exit_group), 0); if (rc != 0) goto out; rc = seccomp_load(ctx); if (rc != 0) goto out; rc = util_file_write("/dev/null"); if (rc != 0) goto out; rc = 160; out: seccomp_release(ctx); return (rc < 0 ? -rc : rc); }
static void setup_seccomp() { scmp_filter_ctx ctx; unsigned int i; int ret; /* Make sure the lists are in sync */ INSIST((sizeof(scmp_syscalls) / sizeof(int)) == (sizeof(scmp_syscall_names) / sizeof(const char *))); ctx = seccomp_init(SCMP_ACT_KILL); if (ctx == NULL) { isc_log_write(ns_g_lctx, NS_LOGCATEGORY_GENERAL, NS_LOGMODULE_MAIN, ISC_LOG_WARNING, "libseccomp activation failed"); return; } for (i = 0 ; i < sizeof(scmp_syscalls)/sizeof(*(scmp_syscalls)); i++) { ret = seccomp_rule_add(ctx, SCMP_ACT_ALLOW, scmp_syscalls[i], 0); if (ret < 0) isc_log_write(ns_g_lctx, NS_LOGCATEGORY_GENERAL, NS_LOGMODULE_MAIN, ISC_LOG_WARNING, "libseccomp rule failed: %s", scmp_syscall_names[i]); else isc_log_write(ns_g_lctx, NS_LOGCATEGORY_GENERAL, NS_LOGMODULE_MAIN, ISC_LOG_DEBUG(9), "added libseccomp rule: %s", scmp_syscall_names[i]); } ret = seccomp_load(ctx); if (ret < 0) { isc_log_write(ns_g_lctx, NS_LOGCATEGORY_GENERAL, NS_LOGMODULE_MAIN, ISC_LOG_WARNING, "libseccomp unable to load filter"); } else { isc_log_write(ns_g_lctx, NS_LOGCATEGORY_GENERAL, NS_LOGMODULE_MAIN, ISC_LOG_NOTICE, "libseccomp sandboxing active"); } /* * Release filter in ctx. Filters already loaded are not * affected. */ seccomp_release(ctx); }
int main(int argc, char *argv[]) { int rc; struct util_options opts; scmp_filter_ctx ctx = NULL; rc = util_getopt(argc, argv, &opts); if (rc < 0) goto out; ctx = seccomp_init(SCMP_ACT_KILL); if (ctx == NULL) return ENOMEM; /* the syscall and argument numbers are all fake to make the test * simpler */ rc = seccomp_syscall_priority(ctx, 1000, 3); if (rc != 0) goto out; rc = seccomp_syscall_priority(ctx, 1001, 2); if (rc != 0) goto out; rc = seccomp_syscall_priority(ctx, 1002, 1); if (rc != 0) goto out; rc = seccomp_rule_add_exact(ctx, SCMP_ACT_ALLOW, 1000, 2, SCMP_A0(SCMP_CMP_EQ, 0), SCMP_A1(SCMP_CMP_EQ, 1)); if (rc != 0) goto out; rc = seccomp_rule_add_exact(ctx, SCMP_ACT_ALLOW, 1001, 1, SCMP_A0(SCMP_CMP_EQ, 0)); if (rc != 0) goto out; rc = seccomp_rule_add_exact(ctx, SCMP_ACT_ALLOW, 1002, 0); if (rc != 0) goto out; rc = util_filter_output(&opts, ctx); if (rc) goto out; out: seccomp_release(ctx); return (rc < 0 ? -rc : rc); }
void poe_init_seccomp(uint32_t act) { scmp_filter_ctx ctx = seccomp_init(act); if (!ctx) ERROR("seccomp_init() failed"); for (int i = 0; i < syscall_rules_count; i++) { struct syscall_rule rule = syscall_rules[i]; if (seccomp_rule_add(ctx, rule.action, rule.syscall, 0) < 0) ERROR("seccomp_rule_add() failed"); } int rc = seccomp_load(ctx); if (rc < 0) ERROR("seccomp_load() failed: %s", strerror(-rc)); seccomp_release(ctx); }
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 installSyscallFilter (void) { // Use SCMP_ACT_TRAP to get a core dump. scmp_filter_ctx ctx = seccomp_init (SCMP_ACT_KILL); if (ctx == NULL) { return 1; } // Memory allocation. seccomp_rule_add (ctx, SCMP_ACT_ALLOW, SCMP_SYS (mmap), 0); seccomp_rule_add (ctx, SCMP_ACT_ALLOW, SCMP_SYS (munmap), 0); seccomp_rule_add (ctx, SCMP_ACT_ALLOW, SCMP_SYS (mremap), 0); seccomp_rule_add (ctx, SCMP_ACT_ALLOW, SCMP_SYS (brk), 0); // I/O seccomp_rule_add (ctx, SCMP_ACT_ALLOW, SCMP_SYS (read), 0); seccomp_rule_add (ctx, SCMP_ACT_ALLOW, SCMP_SYS (write), 0); // Clean exit seccomp_rule_add (ctx, SCMP_ACT_ALLOW, SCMP_SYS (exit), 0); seccomp_rule_add (ctx, SCMP_ACT_ALLOW, SCMP_SYS (exit_group), 0); // The bowels of stdio want to know the size of a file, even for stdout. seccomp_rule_add (ctx, SCMP_ACT_ALLOW, SCMP_SYS (fstat), 0); // seems unnecessary, but this comes from // main/parse.c:2764 : tagFilePosition (&tagfpos); seccomp_rule_add (ctx, SCMP_ACT_ALLOW, SCMP_SYS (lseek), 0); // libxml2 uses pthread_once, which in turn uses a futex seccomp_rule_add (ctx, SCMP_ACT_ALLOW, SCMP_SYS (futex), 0); verbose ("Entering sandbox\n"); int err = seccomp_load (ctx); if (err < 0) { error (WARNING, "Failed to install syscall filter"); /* Error handling is done in upper layer. */ } seccomp_release (ctx); return err; }
/** * Function responsible for setting up and enabling a global syscall filter. * The function is a prototype developed for stage 1 of sandboxing Tor. * Returns 0 on success. */ static int install_syscall_filter(sandbox_cfg_t* cfg) { int rc = 0; scmp_filter_ctx ctx; ctx = seccomp_init(SCMP_ACT_TRAP); if (ctx == NULL) { log_err(LD_BUG,"(Sandbox) failed to initialise libseccomp context"); rc = -1; goto end; } // protectign sandbox parameter strings if ((rc = prot_strings(ctx, cfg))) { goto end; } // add parameter filters if ((rc = add_param_filter(ctx, cfg))) { log_err(LD_BUG, "(Sandbox) failed to add param filters!"); goto end; } // adding filters with no parameters if ((rc = add_noparam_filter(ctx))) { log_err(LD_BUG, "(Sandbox) failed to add param filters!"); goto end; } // loading the seccomp2 filter if ((rc = seccomp_load(ctx))) { log_err(LD_BUG, "(Sandbox) failed to load: %d (%s)!", rc, strerror(-rc)); goto end; } // marking the sandbox as active sandbox_active = 1; end: seccomp_release(ctx); return (rc < 0 ? -rc : rc); }
int main(int argc, char *argv[]) { int rc; struct util_options opts; scmp_filter_ctx ctx = NULL; rc = util_getopt(argc, argv, &opts); if (rc < 0) goto out; ctx = seccomp_init(SCMP_ACT_KILL); if (ctx == NULL) return ENOMEM; rc = seccomp_rule_add_exact(ctx, SCMP_ACT_ALLOW, SCMP_SYS(read), 0); if (rc != 0) goto out; rc = seccomp_rule_add_exact(ctx, SCMP_ACT_ALLOW, SCMP_SYS(write), 0); if (rc != 0) goto out; rc = seccomp_rule_add_exact(ctx, SCMP_ACT_ALLOW, SCMP_SYS(close), 0); if (rc != 0) goto out; rc = seccomp_rule_add_exact(ctx, SCMP_ACT_ALLOW, SCMP_SYS(rt_sigreturn), 0); if (rc != 0) goto out; rc = util_filter_output(&opts, ctx); if (rc) goto out; out: seccomp_release(ctx); return (rc < 0 ? -rc : rc); }
int main(int argc, char *argv[]) { int rc; struct util_options opts; scmp_filter_ctx ctx = NULL; rc = util_getopt(argc, argv, &opts); if (rc < 0) goto out; ctx = seccomp_init(SCMP_ACT_ALLOW); if (ctx == NULL) return ENOMEM; rc = util_filter_output(&opts, ctx); if (rc) goto out; out: seccomp_release(ctx); return (rc < 0 ? -rc : rc); }
int main(int argc, char *argv[]) { int rc; struct util_options opts; scmp_filter_ctx ctx = NULL; rc = util_getopt(argc, argv, &opts); if (rc < 0) goto out; ctx = seccomp_init(SCMP_ACT_KILL); if (ctx == NULL) return ENOMEM; rc = seccomp_arch_remove(ctx, SCMP_ARCH_NATIVE); if (rc != 0) goto out; rc = seccomp_arch_add(ctx, SCMP_ARCH_X86); if (rc != 0) goto out; rc = seccomp_rule_add(ctx, SCMP_ACT_ALLOW, SCMP_SYS(tuxcall), 0); if (rc != 0) goto out; rc = seccomp_rule_add_exact(ctx, SCMP_ACT_ALLOW, SCMP_SYS(tuxcall), 0); if (rc != -EDOM) goto out; rc = util_filter_output(&opts, ctx); if (rc) goto out; out: seccomp_release(ctx); return (rc < 0 ? -rc : rc); }
void GenHash::calcGenHash() { sandbox_init(); // cannot excute execve prctl(PR_SET_NO_NEW_PRIVS, 1, 0, 0, 0); kDebug() << "execve" << execve("ls",NULL,NULL); if (child_pid){ KParts::ReadOnlyPart * part = qobject_cast<KParts::ReadOnlyPart *>(parent()); QFile file(KFileDialog::getOpenFileName(KUrl("kfiledialog:///konqueror"), i18n("*"), part->widget(), i18n("Open File To make MD5."))); if (!file.open(QIODevice::ReadOnly)) { return; } // TODO QFile //char s[1024]; // write file content { close(pipe_fd[0]); QByteArray s = file.readAll(); char *ch = s.data(); if (write(pipe_fd[1], ch, s.size()) < 0) { perror("write"); } close(pipe_fd[1]); } //read result { close(pipe_result_fd[1]); char result[128]; if (read(pipe_result_fd[0], &result[0], 128) < 0){ perror("read"); } close(pipe_result_fd[0]); KMessageBox::information(part->widget(),i18n("Md5 : %1").arg(QString(QByteArray(result, 128)))); } }else{ scmp_filter_ctx ctx = seccomp_init(SCMP_ACT_KILL); seccomp_rule_add(ctx, SCMP_ACT_ALLOW, SCMP_SYS(close), 0); seccomp_rule_add(ctx, SCMP_ACT_ALLOW, SCMP_SYS(read), 3, SCMP_A0(SCMP_CMP_EQ, (scmp_datum_t)pipe_fd[0]), SCMP_A1(SCMP_CMP_EQ, (scmp_datum_t)buff), SCMP_A2(SCMP_CMP_LE, 1024)); seccomp_rule_add(ctx, SCMP_ACT_ALLOW, SCMP_SYS(write), 1, SCMP_CMP(0, SCMP_CMP_EQ, (scmp_datum_t)pipe_result_fd[1])); seccomp_load(ctx); seccomp_release(ctx); calcMD5(); } }
void drop_sys(int syscall) { scmp_filter_ctx ctx = seccomp_init(SCMP_ACT_ALLOW); if(seccomp_rule_add(ctx, SCMP_ACT_KILL, syscall, 0)) exit(-1); if(seccomp_load(ctx)) exit(-1); seccomp_release(ctx); }
int main(int argc, char *argv[]) { int rc; struct util_options opts; scmp_filter_ctx ctx = NULL; rc = util_getopt(argc, argv, &opts); if (rc < 0) goto out; ctx = seccomp_init(SCMP_ACT_KILL); if (ctx == NULL) return ENOMEM; rc = seccomp_arch_remove(ctx, SCMP_ARCH_NATIVE); if (rc != 0) goto out; rc = seccomp_arch_add(ctx, seccomp_arch_resolve_name("x86")); if (rc != 0) goto out; rc = seccomp_arch_add(ctx, seccomp_arch_resolve_name("x86_64")); if (rc != 0) goto out; rc = seccomp_arch_add(ctx, seccomp_arch_resolve_name("x32")); if (rc != 0) goto out; rc = seccomp_arch_add(ctx, seccomp_arch_resolve_name("arm")); if (rc != 0) goto out; rc = seccomp_arch_add(ctx, seccomp_arch_resolve_name("aarch64")); if (rc != 0) goto out; rc = seccomp_arch_add(ctx, seccomp_arch_resolve_name("mipsel")); if (rc != 0) goto out; rc = seccomp_arch_add(ctx, seccomp_arch_resolve_name("mipsel64")); if (rc != 0) goto out; rc = seccomp_arch_add(ctx, seccomp_arch_resolve_name("mipsel64n32")); if (rc != 0) goto out; rc = seccomp_rule_add(ctx, SCMP_ACT_ALLOW, SCMP_SYS(read), 1, SCMP_A0(SCMP_CMP_EQ, STDIN_FILENO)); if (rc != 0) goto out; rc = seccomp_rule_add(ctx, SCMP_ACT_ALLOW, SCMP_SYS(write), 1, SCMP_A0(SCMP_CMP_EQ, STDOUT_FILENO)); if (rc != 0) goto out; rc = seccomp_rule_add(ctx, SCMP_ACT_ALLOW, SCMP_SYS(write), 1, SCMP_A0(SCMP_CMP_EQ, STDERR_FILENO)); if (rc != 0) goto out; rc = seccomp_rule_add(ctx, SCMP_ACT_ALLOW, SCMP_SYS(close), 0); if (rc != 0) goto out; rc = seccomp_rule_add(ctx, SCMP_ACT_ALLOW, SCMP_SYS(rt_sigreturn), 0); if (rc != 0) goto out; rc = util_filter_output(&opts, ctx); if (rc) goto out; out: seccomp_release(ctx); return (rc < 0 ? -rc : rc); }
int main(int argc, char *argv[]) { char *filename = read_opts(argc, argv); /* set up an rnn context */ rnn_init(); rnndb = rnn_newdb(); rnn_parsefile(rnndb, "fifo/nv_objects.xml"); if (rnndb->estatus) demmt_abort(); rnn_prepdb(rnndb); domain = rnn_finddomain(rnndb, "SUBCHAN"); if (!domain) demmt_abort(); rnndb_g80_texture = rnn_newdb(); rnn_parsefile(rnndb_g80_texture, "graph/g80_texture.xml"); if (rnndb_g80_texture->estatus) demmt_abort(); rnn_parsefile(rnndb_g80_texture, "graph/gm107_texture.xml"); if (rnndb_g80_texture->estatus) demmt_abort(); rnn_prepdb(rnndb_g80_texture); rnndb_gf100_shaders = rnn_newdb(); rnn_parsefile(rnndb_gf100_shaders, "graph/gf100_shaders.xml"); if (rnndb_gf100_shaders->estatus) demmt_abort(); rnn_prepdb(rnndb_gf100_shaders); gf100_shaders_ctx = rnndec_newcontext(rnndb_gf100_shaders); gf100_shaders_ctx->colors = colors; /* doesn't matter which, just needs to exist to make it * possible to modify later. */ rnndec_varadd(gf100_shaders_ctx, "GF100_SHADER_KIND", "FP"); rnndb_nvrm_object = rnn_newdb(); rnn_parsefile(rnndb_nvrm_object, "../docs/nvrm/rnndb/nvrm_object.xml"); if (rnndb_nvrm_object->estatus) demmt_abort(); rnn_prepdb(rnndb_nvrm_object); tic_domain = rnn_finddomain(rnndb_g80_texture, "TIC"); tic2_domain = rnn_finddomain(rnndb_g80_texture, "TIC2"); tsc_domain = rnn_finddomain(rnndb_g80_texture, "TSC"); gf100_sp_header_domain = rnn_finddomain(rnndb_gf100_shaders, "GF100_SP_HEADER"); gf100_fp_header_domain = rnn_finddomain(rnndb_gf100_shaders, "GF100_FP_HEADER"); if (!gf100_sp_header_domain || !gf100_fp_header_domain) demmt_abort(); gk104_cp_header_domain = rnn_finddomain(rnndb, "GK104_COMPUTE_LAUNCH_DESC"); if (!gk104_cp_header_domain) demmt_abort(); if (filename) { close(0); if (open_input(filename) == NULL) { perror("open"); exit(1); } free(filename); } if (pager_enabled) { int pipe_fds[2]; pid_t pid; if (pipe(pipe_fds) < 0) { perror("pipe"); demmt_abort(); } pid = fork(); if (pid < 0) { perror("fork"); demmt_abort(); } if (pid > 0) { char *less_argv[] = { "less", "-ScR", NULL }; close(pipe_fds[1]); dup2(pipe_fds[0], 0); close(pipe_fds[0]); execvp(less_argv[0], less_argv); perror("exec"); demmt_abort(); } close(pipe_fds[0]); dup2(pipe_fds[1], 1); dup2(pipe_fds[1], 2); close(pipe_fds[1]); } #ifdef LIBSECCOMP_AVAILABLE if (seccomp_level) { int rc; scmp_filter_ctx ctx; if (seccomp_level == 2) ctx = seccomp_init(SCMP_ACT_KILL); else ctx = seccomp_init(SCMP_ACT_TRACE(1234)); if (!ctx) { fprintf(stderr, "seccomp_init failed\n"); exit(1); } rc = seccomp_rule_add_exact(ctx, SCMP_ACT_ALLOW, SCMP_SYS(read), 1, SCMP_A0(SCMP_CMP_EQ, 0)); if (rc != 0) exit(1); seccomp_syscall_priority(ctx, SCMP_SYS(read), 254); rc = seccomp_rule_add_exact(ctx, SCMP_ACT_ALLOW, SCMP_SYS(write), 1, SCMP_A0(SCMP_CMP_LE, 2)); if (rc != 0) exit(1); seccomp_syscall_priority(ctx, SCMP_SYS(write), 255); rc = seccomp_rule_add_exact(ctx, SCMP_ACT_ALLOW, SCMP_SYS(rt_sigreturn), 0); if (rc != 0) exit(1); rc = seccomp_rule_add_exact(ctx, SCMP_ACT_ALLOW, SCMP_SYS(fstat), 1, SCMP_A0(SCMP_CMP_EQ, 1)); if (rc != 0) exit(1); rc = seccomp_rule_add_exact(ctx, SCMP_ACT_ALLOW, SCMP_SYS(mmap), 0); if (rc != 0) exit(1); rc = seccomp_rule_add_exact(ctx, SCMP_ACT_ALLOW, SCMP_SYS(brk), 0); if (rc != 0) exit(1); rc = seccomp_rule_add_exact(ctx, SCMP_ACT_ALLOW, SCMP_SYS(munmap), 0); if (rc != 0) exit(1); rc = seccomp_rule_add_exact(ctx, SCMP_ACT_ALLOW, SCMP_SYS(mremap), 0); if (rc != 0) exit(1); rc = seccomp_rule_add_exact(ctx, SCMP_ACT_ALLOW, SCMP_SYS(exit_group), 0); if (rc != 0) exit(1); rc = seccomp_rule_add_exact(ctx, SCMP_ACT_ALLOW, SCMP_SYS(ioctl), 2, SCMP_A0(SCMP_CMP_EQ, 1), SCMP_A1(SCMP_CMP_EQ, 0x5401/*TCGETS*/)); if (rc != 0) exit(1); rc = seccomp_load(ctx); if (rc != 0) { fprintf(stderr, "seccomp_load failed with error: %d\n", rc); exit(1); } seccomp_release(ctx); } #endif mmt_decode(&demmt_funcs.base, NULL); fflush(stdout); fini_macrodis(); demmt_cleanup_isas(); rnndec_freecontext(gf100_shaders_ctx); rnn_freedb(rnndb); rnn_freedb(rnndb_g80_texture); rnn_freedb(rnndb_gf100_shaders); rnn_freedb(rnndb_nvrm_object); rnn_fini(); return 0; }
int main(int argc, char *argv[]) { const char *argv0 = argv[0]; int opt, optidx; bool separate_read_write = false; bool proxy = false; struct sockaddr_in proxy_sin; bool join = false; #ifdef HAVE_SECCOMP int nrules = 0; uint32_t def_action = SCMP_ACT_ALLOW; char *fixed = (char *)mmap((void *)0x800000, 0x1000, PROT_READ|PROT_WRITE, MAP_PRIVATE|MAP_ANONYMOUS|MAP_FIXED, -1, 0); #endif struct option longopts[] = { {"abstract" , no_argument , 0 , 'a'} , {"directory" , required_argument , 0 , 'd'} , {"environment" , required_argument , 0 , 'e'} , {"join" , no_argument , 0 , 'j'} , {"policy" , required_argument , 0 , 'o'} , {"proxy" , required_argument , 0 , 'p'} , {"seccomp" , required_argument , 0 , 'c'} , {"separate" , no_argument , 0 , 's'} , {0 , 0 , 0 , 0} , }; while ((opt = getopt_long(argc, argv, "+0ac:d:e:hjo:p:s", longopts, &optidx)) != -1) { switch (opt) { case 'a': af_unix = true; break; case 'c': { #ifdef HAVE_SECCOMP char *pp = optarg, *p, *qq, *q, *saved0, *saved1; for (; ; pp = NULL) { p = strtok_r(pp, " \t,", &saved0); if (! p) break; bool negative = false; int num, pos, nfilters = 0; enum scmp_compare op; if (nrules >= SIZE(scmp_rules)) errx(BAD_ARG, "too many rules"); if (*p == '+') p++; else if (*p == '-') p++, negative = true; scmp_rules[nrules].action = negative ? SCMP_ACT_TRAP : SCMP_ACT_ALLOW; for (qq = p; ; qq = NULL) { q = strtok_r(qq, ":", &saved1); if (! q) break; if (qq) { num = seccomp_syscall_resolve_name(q); if (num < 0) errx(BAD_ARG, "unknown syscall \"%s\"", q); scmp_rules[nrules].syscall = num; } else { if (nfilters >= SIZE(scmp_rules[0].arg_array)) errx(BAD_ARG, "too many filters"); if (! ('0' <= *q && *q <= '5')) errx(BAD_ARG, "argument position should be 0-5"); pos = *q-'0'; REP(i, nfilters) if (pos == scmp_rules[nrules].arg_array[i].arg) errx(BAD_ARG, "duplicate argument position %d", pos); q++; if (*q == '=') q++, op = SCMP_CMP_EQ; else if (*q == '!' && q[1] == '=') q += 2, op = SCMP_CMP_NE; else if (*q == '<') { if (q[1] == '=') q += 2, op = SCMP_CMP_LE; else q++, op = SCMP_CMP_LT; } else if (*q == '>') { if (q[1] == '=') q += 2, op = SCMP_CMP_GE; else q++, op = SCMP_CMP_GT; } else errx(BAD_ARG, "unknown operator \"%c\"", *q); scmp_datum_t val = strtol(q, &q, 0); if (*q) errx(BAD_ARG, "invalid number"); scmp_rules[nrules].arg_array[nfilters++] = SCMP_CMP(pos, op, val); } } scmp_rules[nrules].arg_cnt = nfilters; nrules++; } #else errx(ERR_SYSCALL, "HAVE_SECCOMP not enabled"); #endif break; } case 'd': Chdir(optarg); break; case 'h': show_help(STDOUT_FILENO, argv0); break; case 'j': join = true; break; case 'e': putenv(optarg); break; case 'o': #ifdef HAVE_SECCOMP if (optarg[0] == 'k') def_action = SCMP_ACT_KILL; else if (optarg[0] == 't') def_action = SCMP_ACT_TRAP; else if (optarg[0] == 'a') def_action = SCMP_ACT_ALLOW; #else errx(ERR_SYSCALL, "HAVE_SECCOMP not enabled"); #endif break; case 'p': // proxy { char *p = strchr(optarg, ':'); if (! p) errx(BAD_ARG, "no semicolon"); *p = '\0'; proxy_sin.sin_family = AF_INET; if (inet_aton(optarg, &proxy_sin.sin_addr) < 0) errx(BAD_ARG, "gethostbyname: %s", strerror(errno)); proxy_sin.sin_port = htons(strtol(p+1, &p, 10)); if (*p) errx(BAD_ARG, "port"); proxy = true; } break; case 's': separate_read_write = true; break; default: show_help(STDERR_FILENO, argv0); break; } } argc -= optind; argv += optind; if (argc < 1) { show_help(STDERR_FILENO, argv0); return BAD_ARG; } char buf[4096]; int pipe_p2c[2], pipe_c2p1[2], pipe_c2p2[2]; if (af_unix) { unix_p2c.sun_family = AF_UNIX; unix_c2p1.sun_family = AF_UNIX; unix_c2p2.sun_family = AF_UNIX; unix_p2c.sun_path[0] = '\0'; unix_c2p1.sun_path[0] = '\0'; unix_c2p2.sun_path[0] = '\0'; sprintf(unix_p2c.sun_path+1, "/tmp/unix/%d-%d.in", getuid(), getpid()); sprintf(unix_c2p1.sun_path+1, "/tmp/unix/%d-%d.out", getuid(), getpid()); sprintf(unix_c2p2.sun_path+1, "/tmp/unix/%d-%d.err", getuid(), getpid()); pipe_p2c[0] = socket(AF_UNIX, SOCK_STREAM, 0); pipe_c2p1[1] = socket(AF_UNIX, SOCK_STREAM, 0); if (! join) pipe_c2p2[1] = socket(AF_UNIX, SOCK_STREAM, 0); atexit(atexit_rm); if (bind(pipe_p2c[0], &unix_p2c, sizeof unix_p2c) < 0 || bind(pipe_c2p1[1], &unix_c2p1, sizeof unix_c2p1) < 0) return perror(""), 0; if (! join && bind(pipe_c2p2[1], &unix_c2p2, sizeof unix_c2p2) < 0) return perror(""), 0; if (listen(pipe_p2c[0], 1) < 0 || listen(pipe_c2p1[1], 1) < 0) return perror(""), 0; if (! join && listen(pipe_c2p2[1], 1) < 0) return perror(""), 0; } else { Pipe(pipe_p2c); Pipe(pipe_c2p1); if (! join) Pipe(pipe_c2p2); } child = Fork(); if (! child) { // child if (af_unix) { // close bound sockets close(pipe_p2c[0]); close(pipe_c2p1[1]); close(pipe_c2p2[1]); // domain sockets for client pipe_p2c[1] = socket(AF_UNIX, SOCK_STREAM, 0); pipe_c2p1[0] = socket(AF_UNIX, SOCK_STREAM, 0); if (! join) pipe_c2p2[0] = socket(AF_UNIX, SOCK_STREAM, 0); if (connect(pipe_p2c[1], &unix_p2c, sizeof unix_p2c) < 0 || connect(pipe_c2p1[0], &unix_c2p1, sizeof unix_c2p1) < 0) return 0; dup2(pipe_p2c[1], STDIN_FILENO); close(pipe_p2c[1]); dup2(pipe_c2p1[0], STDOUT_FILENO); close(pipe_c2p1[0]); if (join) dup2(STDOUT_FILENO, STDERR_FILENO); else { connect(pipe_c2p2[0], &unix_c2p2, sizeof unix_c2p2); dup2(pipe_c2p2[0], STDERR_FILENO); close(pipe_c2p2[0]); } } else { close(pipe_p2c[1]); dup2(pipe_p2c[0], STDIN_FILENO); close(pipe_p2c[0]); close(pipe_c2p1[0]); dup2(pipe_c2p1[1], STDOUT_FILENO); close(pipe_c2p1[1]); if (join) dup2(STDOUT_FILENO, STDERR_FILENO); else { close(pipe_c2p2[0]); dup2(pipe_c2p2[1], STDERR_FILENO); close(pipe_c2p2[1]); } } #ifdef HAVE_SECCOMP scmp_filter_ctx ctx = seccomp_init(def_action); if (ctx == NULL) return 1; REP(i, nrules) { int ret = seccomp_rule_add_array(ctx, scmp_rules[i].action, scmp_rules[i].syscall, scmp_rules[i].arg_cnt, scmp_rules[i].arg_array); if (ret < 0) return 1; } if (seccomp_load(ctx) < 0) return 1; seccomp_release(ctx); strcpy(fixed, *argv); execv(fixed, argv); // execve will change the first argument #else execvp(*argv, argv); #endif } else {
void drop_worker_privileges(void) { scmp_filter_ctx ctx = seccomp_init(DENY_ACTION); if (ctx == NULL) { return; } int rc = 0; rc |= seccomp_rule_add(ctx, SCMP_ACT_ALLOW, SCMP_SYS(sigreturn), 0); rc |= seccomp_rule_add(ctx, SCMP_ACT_ALLOW, SCMP_SYS(rt_sigprocmask), 0); rc |= seccomp_rule_add(ctx, SCMP_ACT_ALLOW, SCMP_SYS(futex), 0); rc |= seccomp_rule_add(ctx, SCMP_ACT_ALLOW, SCMP_SYS(epoll_wait), 0); rc |= seccomp_rule_add(ctx, SCMP_ACT_ALLOW, SCMP_SYS(epoll_pwait), 0); rc |= seccomp_rule_add(ctx, SCMP_ACT_ALLOW, SCMP_SYS(epoll_ctl), 0); rc |= seccomp_rule_add(ctx, SCMP_ACT_ALLOW, SCMP_SYS(poll), 0); rc |= seccomp_rule_add(ctx, SCMP_ACT_ALLOW, SCMP_SYS(read), 0); rc |= seccomp_rule_add(ctx, SCMP_ACT_ALLOW, SCMP_SYS(readv), 0); rc |= seccomp_rule_add(ctx, SCMP_ACT_ALLOW, SCMP_SYS(mprotect), 0); rc |= seccomp_rule_add(ctx, SCMP_ACT_ALLOW, SCMP_SYS(getpeername), 0); rc |= seccomp_rule_add(ctx, SCMP_ACT_ALLOW, SCMP_SYS(close), 0); rc |= seccomp_rule_add(ctx, SCMP_ACT_ALLOW, SCMP_SYS(sendmsg), 0); rc |= seccomp_rule_add(ctx, SCMP_ACT_ALLOW, SCMP_SYS(getrusage), 0); rc |= seccomp_rule_add(ctx, SCMP_ACT_ALLOW, SCMP_SYS(mmap), 0); rc |= seccomp_rule_add(ctx, SCMP_ACT_ALLOW, SCMP_SYS(mremap), 0); rc |= seccomp_rule_add(ctx, SCMP_ACT_ALLOW, SCMP_SYS(munmap), 0); rc |= seccomp_rule_add(ctx, SCMP_ACT_ALLOW, SCMP_SYS(recvfrom), 0); rc |= seccomp_rule_add(ctx, SCMP_ACT_ALLOW, SCMP_SYS(brk), 0); rc |= seccomp_rule_add(ctx, SCMP_ACT_ALLOW, SCMP_SYS(ioctl), 1, SCMP_A1(SCMP_CMP_EQ, TIOCGWINSZ)); // for spawning the LRU crawler rc |= seccomp_rule_add(ctx, SCMP_ACT_ALLOW, SCMP_SYS(clone), 0); rc |= seccomp_rule_add(ctx, SCMP_ACT_ALLOW, SCMP_SYS(set_robust_list), 0); rc |= seccomp_rule_add(ctx, SCMP_ACT_ALLOW, SCMP_SYS(madvise), 0); rc |= seccomp_rule_add(ctx, SCMP_ACT_ALLOW, SCMP_SYS(exit), 0); // stat rc |= seccomp_rule_add(ctx, SCMP_ACT_ALLOW, SCMP_SYS(getsockname), 0); rc |= seccomp_rule_add(ctx, SCMP_ACT_ALLOW, SCMP_SYS(getpid), 0); if (settings.shutdown_command) { rc |= seccomp_rule_add(ctx, SCMP_ACT_ALLOW, SCMP_SYS(tgkill), 0); rc |= seccomp_rule_add(ctx, SCMP_ACT_ALLOW, SCMP_SYS(tkill), 0); rc |= seccomp_rule_add(ctx, SCMP_ACT_ALLOW, SCMP_SYS(exit_group), 0); rc |= seccomp_rule_add(ctx, SCMP_ACT_ALLOW, SCMP_SYS(fstat), 0); rc |= seccomp_rule_add(ctx, SCMP_ACT_ALLOW, SCMP_SYS(getpid), 0); rc |= seccomp_rule_add(ctx, SCMP_ACT_ALLOW, SCMP_SYS(gettid), 0); } if (settings.relaxed_privileges) { rc |= seccomp_rule_add(ctx, SCMP_ACT_ALLOW, SCMP_SYS(openat), 0); rc |= seccomp_rule_add(ctx, SCMP_ACT_ALLOW, SCMP_SYS(mkdir), 0); rc |= seccomp_rule_add(ctx, SCMP_ACT_ALLOW, SCMP_SYS(access), 0); rc |= seccomp_rule_add(ctx, SCMP_ACT_ALLOW, SCMP_SYS(open), 0); rc |= seccomp_rule_add(ctx, SCMP_ACT_ALLOW, SCMP_SYS(fcntl), 0); rc |= seccomp_rule_add(ctx, SCMP_ACT_ALLOW, SCMP_SYS(lseek), 0); rc |= seccomp_rule_add(ctx, SCMP_ACT_ALLOW, SCMP_SYS(write), 0); rc |= seccomp_rule_add(ctx, SCMP_ACT_ALLOW, SCMP_SYS(writev), 0); } else { // stdout rc |= seccomp_rule_add(ctx, SCMP_ACT_ALLOW, SCMP_SYS(write), 1, SCMP_A0(SCMP_CMP_EQ, 1)); rc |= seccomp_rule_add(ctx, SCMP_ACT_ALLOW, SCMP_SYS(writev), 1, SCMP_A0(SCMP_CMP_EQ, 1)); // stderr rc |= seccomp_rule_add(ctx, SCMP_ACT_ALLOW, SCMP_SYS(write), 1, SCMP_A0(SCMP_CMP_EQ, 2)); rc |= seccomp_rule_add(ctx, SCMP_ACT_ALLOW, SCMP_SYS(writev), 1, SCMP_A0(SCMP_CMP_EQ, 2)); } if (rc != 0) { goto fail; } rc = seccomp_load(ctx); if (rc < 0) { goto fail; } seccomp_release(ctx); return; fail: seccomp_release(ctx); fprintf(stderr, "Failed to set a seccomp profile on a worker thread\n"); exit(EXIT_FAILURE); }
int disable_system_calls(struct worker_st *ws) { int ret; scmp_filter_ctx ctx; ctx = seccomp_init(SCMP_ACT_KILL); if (ctx == NULL) { oclog(ws, LOG_DEBUG, "could not initialize seccomp"); return -1; } #define ADD_SYSCALL(name, ...) \ ret = seccomp_rule_add(ctx, SCMP_ACT_ALLOW, SCMP_SYS(name), __VA_ARGS__); \ /* libseccomp returns EDOM for pseudo-syscalls due to a bug */ \ if (ret < 0 && ret != -EDOM) { \ oclog(ws, LOG_DEBUG, "could not add " #name " to seccomp filter: %s", strerror(-ret)); \ ret = -1; \ goto fail; \ } ADD_SYSCALL(time, 0); ADD_SYSCALL(gettimeofday, 0); ADD_SYSCALL(recvmsg, 0); ADD_SYSCALL(sendmsg, 0); ADD_SYSCALL(read, 0); ADD_SYSCALL(write, 0); ADD_SYSCALL(writev, 0); ADD_SYSCALL(send, 0); ADD_SYSCALL(recv, 0); /* it seems we need to add sendto and recvfrom * since send() and recv() aren't real system * calls. */ ADD_SYSCALL(sendto, 0); ADD_SYSCALL(recvfrom, 0); ADD_SYSCALL(select, 0); ADD_SYSCALL(alarm, 0); ADD_SYSCALL(close, 0); ADD_SYSCALL(exit, 0); ADD_SYSCALL(exit_group, 0); ADD_SYSCALL(socket, 0); ADD_SYSCALL(connect, 0); /* this we need to get the MTU from * the TUN device */ ADD_SYSCALL(ioctl, 1, SCMP_A1(SCMP_CMP_EQ, (int)SIOCGIFDSTADDR)); ADD_SYSCALL(ioctl, 1, SCMP_A1(SCMP_CMP_EQ, (int)SIOCGIFADDR)); ADD_SYSCALL(ioctl, 1, SCMP_A1(SCMP_CMP_EQ, (int)SIOCGIFMTU)); ret = seccomp_load(ctx); if (ret < 0) { oclog(ws, LOG_DEBUG, "could not load seccomp filter"); ret = -1; goto fail; } ret = 0; fail: seccomp_release(ctx); return ret; }
int child_process(void *clone_args){ FILE *log_fp = ((struct clone_args *)clone_args)->log_fp; struct config *config = ((struct clone_args *)clone_args)->config; FILE *in_file = NULL, *out_file = NULL, *err_file = NULL; struct rlimit memory_limit, cpu_time_rlimit; gid_t group_list[] = {config->gid}; #ifndef __APPLE__ int i; int syscalls_whitelist[] = {SCMP_SYS(read), SCMP_SYS(fstat), SCMP_SYS(mmap), SCMP_SYS(mprotect), SCMP_SYS(munmap), SCMP_SYS(open), SCMP_SYS(arch_prctl), SCMP_SYS(brk), SCMP_SYS(access), SCMP_SYS(exit_group), SCMP_SYS(close)}; int syscalls_whitelist_length = sizeof(syscalls_whitelist) / sizeof(int); scmp_filter_ctx ctx = NULL; #endif // child process // On success, these system calls return 0. // On error, -1 is returned, and errno is set appropriately. if (config->max_memory != MEMORY_UNLIMITED) { memory_limit.rlim_cur = memory_limit.rlim_max = (rlim_t) (config->max_memory) * 2; if (setrlimit(RLIMIT_AS, &memory_limit) == -1) { LOG_FATAL(log_fp, "setrlimit memory failed, errno: %d", errno); ERROR(log_fp, SETRLIMIT_FAILED); } } if (config->max_cpu_time != CPU_TIME_UNLIMITED) { // cpu time if (set_timer(config->max_cpu_time / 1000, config->max_cpu_time % 1000, 1) != SUCCESS) { LOG_FATAL(log_fp, "set cpu time timer failed"); ERROR(log_fp, SETITIMER_FAILED); } // real time if (set_timer(config->max_real_time / 1000, config->max_real_time % 1000, 0) != SUCCESS) { LOG_FATAL(log_fp, "set real time timer failed"); ERROR(log_fp, SETITIMER_FAILED); } // child process can not inherit timeout rules from parent process defined by setitimer, so we use setrlimit to // control child process max running time cpu_time_rlimit.rlim_cur = cpu_time_rlimit.rlim_max = (config->max_cpu_time + 1000) / 1000; if (setrlimit(RLIMIT_CPU, &cpu_time_rlimit) == -1) { LOG_FATAL(log_fp, "setrlimit cpu time failed, errno: %d", errno); ERROR(log_fp, SETRLIMIT_FAILED); } } // read stdin from in file // On success, these system calls return the new descriptor. // On error, -1 is returned, and errno is set appropriately. if (config->in_file != NULL) { if ((in_file = fopen(config->in_file, "r")) == NULL) { LOG_FATAL(log_fp, "failed to open stdin redirect file"); ERROR(log_fp, DUP2_FAILED); } if (dup2(fileno(in_file), fileno(stdin)) == -1) { LOG_FATAL(log_fp, "dup2 stdin failed, errno: %d", errno); ERROR(log_fp, DUP2_FAILED); } } // write stdout to out file if (config->out_file != NULL) { if ((out_file = fopen(config->out_file, "w")) == NULL) { LOG_FATAL(log_fp, "failed to open stdout redirect file"); ERROR(log_fp, DUP2_FAILED); } if (dup2(fileno(out_file), fileno(stdout)) == -1) { LOG_FATAL(log_fp, "dup2 stdout failed, errno: %d", errno); ERROR(log_fp, DUP2_FAILED); } } // write stderr to err file if (config->err_file != NULL) { // if err_file and out_file are the same path, we use out_file pointer as err_file pointer, to avoid conflict if (strcmp(config->out_file, config->err_file) == 0) { err_file = out_file; } else { if ((err_file = fopen(config->err_file, "w")) == NULL) { LOG_FATAL(log_fp, "failed to open stderr redirect file"); ERROR(log_fp, DUP2_FAILED); } } if (dup2(fileno(err_file), fileno(stderr)) == -1) { LOG_FATAL(log_fp, "dup2 stdout failed, errno: %d", errno); ERROR(log_fp, DUP2_FAILED); } } if (config->gid != -1 && (setgid(config->gid) == -1 || setgroups(sizeof(group_list) / sizeof(gid_t), group_list) == -1)) { LOG_FATAL(log_fp, "setgid failed, errno: %d", errno); ERROR(log_fp, SET_GID_FAILED); } if (config->uid != -1 && setuid(config->uid) == -1) { LOG_FATAL(log_fp, "setuid failed, errno: %d", errno); ERROR(log_fp, SET_UID_FAILED); } #ifndef __APPLE__ if (config->use_sandbox != 0) { // load seccomp rules ctx = seccomp_init(SCMP_ACT_KILL); if (!ctx) { LOG_FATAL(log_fp, "init seccomp failed"); ERROR(log_fp, LOAD_SECCOMP_FAILED); } for (i = 0; i < syscalls_whitelist_length; i++) { if (seccomp_rule_add(ctx, SCMP_ACT_ALLOW, syscalls_whitelist[i], 0) != 0) { LOG_FATAL(log_fp, "load syscall white list failed"); ERROR(log_fp, LOAD_SECCOMP_FAILED); } } // add extra rule for execve if (seccomp_rule_add(ctx, SCMP_ACT_ALLOW, SCMP_SYS(execve), 1, SCMP_A0(SCMP_CMP_EQ, (scmp_datum_t)(config->path))) != 0) { LOG_FATAL(log_fp, "load execve rule failed"); ERROR(log_fp, LOAD_SECCOMP_FAILED); } // only fd 0 1 2 are allowed if (seccomp_rule_add(ctx, SCMP_ACT_ALLOW, SCMP_SYS(write), 1, SCMP_A0(SCMP_CMP_LE, 2)) != 0) { LOG_FATAL(log_fp, "load dup2 rule failed"); ERROR(log_fp, LOAD_SECCOMP_FAILED); } if (seccomp_load(ctx) != 0) { LOG_FATAL(log_fp, "seccomp load failed"); ERROR(log_fp, LOAD_SECCOMP_FAILED); } seccomp_release(ctx); } #endif execve(config->path, config->args, config->env); LOG_FATAL(log_fp, "execve failed, errno: %d", errno); ERROR(log_fp, EXCEVE_FAILED); return 1; }
scmp_filter_ctx sc_prepare_seccomp_context(const char *filter_profile) { int rc = 0; scmp_filter_ctx ctx = NULL; FILE *f = NULL; size_t lineno = 0; uid_t real_uid, effective_uid, saved_uid; struct preprocess pre; struct seccomp_args sargs; debug("preparing seccomp profile associated with security tag %s", filter_profile); // initialize hsearch map sc_map_init(); ctx = seccomp_init(SCMP_ACT_KILL); if (ctx == NULL) { errno = ENOMEM; die("seccomp_init() failed"); } // Setup native arch and any compatibility archs sc_add_seccomp_archs(ctx); // Disable NO_NEW_PRIVS because it interferes with exec transitions in // AppArmor. Unfortunately this means that security policies must be // very careful to not allow the following otherwise apps can escape // the sandbox: // - seccomp syscall // - prctl with PR_SET_SECCOMP // - ptrace (trace) in AppArmor // - capability sys_admin in AppArmor // Note that with NO_NEW_PRIVS disabled, CAP_SYS_ADMIN is required to // change the seccomp sandbox. if (getresuid(&real_uid, &effective_uid, &saved_uid) != 0) die("could not find user IDs"); // If running privileged or capable of raising, disable nnp if (real_uid == 0 || effective_uid == 0 || saved_uid == 0) if (seccomp_attr_set(ctx, SCMP_FLTATR_CTL_NNP, 0) != 0) die("Cannot disable nnp"); // Note that secure_gettenv will always return NULL when suid, so // SNAPPY_LAUNCHER_SECCOMP_PROFILE_DIR can't be (ab)used in that case. if (secure_getenv("SNAPPY_LAUNCHER_SECCOMP_PROFILE_DIR") != NULL) filter_profile_dir = secure_getenv("SNAPPY_LAUNCHER_SECCOMP_PROFILE_DIR"); char profile_path[512]; // arbitrary path name limit must_snprintf(profile_path, sizeof(profile_path), "%s/%s", filter_profile_dir, filter_profile); f = fopen(profile_path, "r"); if (f == NULL) { fprintf(stderr, "Can not open %s (%s)\n", profile_path, strerror(errno)); die("aborting"); } // Note, preprocess_filter() die()s on error preprocess_filter(f, &pre); if (pre.unrestricted) { seccomp_release(ctx); ctx = NULL; goto out; } // FIXME: right now complain mode is the equivalent to unrestricted. // We'll want to change this once we seccomp logging is in order. if (pre.complain) { seccomp_release(ctx); ctx = NULL; goto out; } char buf[SC_MAX_LINE_LENGTH]; while (fgets(buf, sizeof(buf), f) != NULL) { lineno++; // skip policy-irrelevant lines if (validate_and_trim_line(buf, sizeof(buf), lineno) == 0) continue; char *buf_copy = strdup(buf); if (buf_copy == NULL) die("Out of memory"); int pr_rc = parse_line(buf_copy, &sargs); free(buf_copy); if (pr_rc != PARSE_OK) { // as this is a syscall whitelist an invalid syscall // is ok and the error can be ignored if (pr_rc == PARSE_INVALID_SYSCALL) continue; die("could not parse line"); } rc = seccomp_rule_add_exact_array(ctx, SCMP_ACT_ALLOW, sargs.syscall_nr, sargs.length, sargs.arg_cmp); if (rc != 0) { rc = seccomp_rule_add_array(ctx, SCMP_ACT_ALLOW, sargs.syscall_nr, sargs.length, sargs.arg_cmp); if (rc != 0) { fprintf(stderr, "seccomp_rule_add_array failed with %i for '%s'\n", rc, buf); errno = 0; die("aborting"); } } } out: if (f != NULL) { if (fclose(f) != 0) die("could not close seccomp file"); } sc_map_destroy(); return ctx; }
/** * Initialize seccomp. * * @param remote file descriptor to talk with the unprivileged process * @param monitored monitored child * @return negative on failures or 0 if everything was setup */ int priv_seccomp_init(int remote, int child) { int rc = -1; scmp_filter_ctx ctx; log_debug("seccomp", "initialize libseccomp filter"); monitored = child; if (priv_seccomp_trap_install() < 0) { log_warn("seccomp", "unable to install SIGSYS handler"); goto failure_scmp; } if ((ctx = seccomp_init(SCMP_ACT_TRAP)) == NULL) { log_warnx("seccomp", "unable to initialize libseccomp subsystem"); goto failure_scmp; } if ((rc = seccomp_rule_add(ctx, SCMP_ACT_ALLOW, SCMP_SYS(read), 1, SCMP_CMP(0, SCMP_CMP_EQ, remote))) < 0 || (rc = seccomp_rule_add(ctx, SCMP_ACT_ALLOW, SCMP_SYS(write), 1, SCMP_CMP(0, SCMP_CMP_EQ, remote))) < 0) { errno = -rc; log_warn("seccomp", "unable to allow read/write on remote socket"); goto failure_scmp; } /* We are far more generic from here. */ if ((rc = seccomp_rule_add(ctx, SCMP_ACT_ALLOW, SCMP_SYS(read), 0)) < 0 || (rc = seccomp_rule_add(ctx, SCMP_ACT_ALLOW, SCMP_SYS(write), 0)) < 0 || /* write needed for */ (rc = seccomp_rule_add(ctx, SCMP_ACT_ALLOW, SCMP_SYS(open), 0)) < 0 || (rc = seccomp_rule_add(ctx, SCMP_ACT_ALLOW, SCMP_SYS(kill), 0)) < 0 || (rc = seccomp_rule_add(ctx, SCMP_ACT_ALLOW, SCMP_SYS(socket), 0)) < 0 || (rc = seccomp_rule_add(ctx, SCMP_ACT_ALLOW, SCMP_SYS(bind), 0)) < 0 || (rc = seccomp_rule_add(ctx, SCMP_ACT_ALLOW, SCMP_SYS(setsockopt), 0)) < 0 || (rc = seccomp_rule_add(ctx, SCMP_ACT_ALLOW, SCMP_SYS(uname), 0)) < 0 || (rc = seccomp_rule_add(ctx, SCMP_ACT_ALLOW, SCMP_SYS(unlink), 0)) < 0 || (rc = seccomp_rule_add(ctx, SCMP_ACT_ALLOW, SCMP_SYS(ioctl), 0)) < 0 || (rc = seccomp_rule_add(ctx, SCMP_ACT_ALLOW, SCMP_SYS(sendmsg), 0)) < 0 || (rc = seccomp_rule_add(ctx, SCMP_ACT_ALLOW, SCMP_SYS(wait4), 0)) < 0 || (rc = seccomp_rule_add(ctx, SCMP_ACT_ALLOW, SCMP_SYS(stat), 0)) < 0 || (rc = seccomp_rule_add(ctx, SCMP_ACT_ALLOW, SCMP_SYS(rt_sigreturn), 0)) < 0 || (rc = seccomp_rule_add(ctx, SCMP_ACT_ALLOW, SCMP_SYS(close), 0)) < 0 || /* The following are for resolving addresses */ (rc = seccomp_rule_add(ctx, SCMP_ACT_ALLOW, SCMP_SYS(mmap), 0)) < 0 || (rc = seccomp_rule_add(ctx, SCMP_ACT_ALLOW, SCMP_SYS(munmap), 0)) < 0 || (rc = seccomp_rule_add(ctx, SCMP_ACT_ALLOW, SCMP_SYS(fstat), 0)) < 0 || (rc = seccomp_rule_add(ctx, SCMP_ACT_ALLOW, SCMP_SYS(connect), 0)) < 0 || (rc = seccomp_rule_add(ctx, SCMP_ACT_ALLOW, SCMP_SYS(futex), 0)) < 0 || (rc = seccomp_rule_add(ctx, SCMP_ACT_ALLOW, SCMP_SYS(exit_group), 0)) < 0) { errno = -rc; log_warn("seccomp", "unable to build seccomp rules"); goto failure_scmp; } if ((rc = seccomp_load(ctx)) < 0) { errno = -rc; log_warn("seccomp", "unable to load libseccomp filter"); goto failure_scmp; } failure_scmp: seccomp_release(ctx); return rc; }