/** * Function responsible for setting up the rename syscall for * the seccomp filter sandbox. */ static int sb_rename(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(rename)) { rc = seccomp_rule_add_2(ctx, SCMP_ACT_ALLOW, SCMP_SYS(rename), SCMP_CMP_STR(0, SCMP_CMP_EQ, param->value), SCMP_CMP_STR(1, SCMP_CMP_EQ, param->value2)); if (rc != 0) { log_err(LD_BUG,"(Sandbox) failed to add rename syscall, received " "libseccomp error %d", rc); return rc; } } } return 0; }
/** * Function responsible for setting up the fcntl64 syscall for * the seccomp filter sandbox. */ static int sb_fcntl64(scmp_filter_ctx ctx, sandbox_cfg_t *filter) { int rc = 0; (void) filter; rc = seccomp_rule_add_1(ctx, SCMP_ACT_ALLOW, SCMP_SYS(fcntl64), SCMP_CMP(1, SCMP_CMP_EQ, F_GETFL)); if (rc) return rc; rc = seccomp_rule_add_2(ctx, SCMP_ACT_ALLOW, SCMP_SYS(fcntl64), SCMP_CMP(1, SCMP_CMP_EQ, F_SETFL), SCMP_CMP(2, SCMP_CMP_EQ, O_RDWR|O_NONBLOCK)); if (rc) return rc; rc = seccomp_rule_add_1(ctx, SCMP_ACT_ALLOW, SCMP_SYS(fcntl64), SCMP_CMP(1, SCMP_CMP_EQ, F_GETFD)); if (rc) return rc; rc = seccomp_rule_add_2(ctx, SCMP_ACT_ALLOW, SCMP_SYS(fcntl64), SCMP_CMP(1, SCMP_CMP_EQ, F_SETFD), SCMP_CMP(2, SCMP_CMP_EQ, FD_CLOEXEC)); if (rc) return rc; return 0; }
/** * Function responsible for setting up the openat syscall for * the seccomp filter sandbox. */ static int sb_openat(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(openat)) { rc = seccomp_rule_add_3(ctx, SCMP_ACT_ALLOW, SCMP_SYS(openat), SCMP_CMP(0, SCMP_CMP_EQ, AT_FDCWD), SCMP_CMP_STR(1, SCMP_CMP_EQ, param->value), SCMP_CMP(2, SCMP_CMP_EQ, O_RDONLY|O_NONBLOCK|O_LARGEFILE|O_DIRECTORY| O_CLOEXEC)); if (rc != 0) { log_err(LD_BUG,"(Sandbox) failed to add openat 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; }
/** * Function responsible for setting up the futex syscall for * the seccomp filter sandbox. */ static int sb_futex(scmp_filter_ctx ctx, sandbox_cfg_t *filter) { int rc = 0; (void) filter; // can remove rc = seccomp_rule_add_1(ctx, SCMP_ACT_ALLOW, SCMP_SYS(futex), SCMP_CMP(1, SCMP_CMP_EQ, FUTEX_WAIT_BITSET_PRIVATE|FUTEX_CLOCK_REALTIME)); if (rc) return rc; rc = seccomp_rule_add_1(ctx, SCMP_ACT_ALLOW, SCMP_SYS(futex), SCMP_CMP(1, SCMP_CMP_EQ, FUTEX_WAKE_PRIVATE)); if (rc) return rc; rc = seccomp_rule_add_1(ctx, SCMP_ACT_ALLOW, SCMP_SYS(futex), SCMP_CMP(1, SCMP_CMP_EQ, FUTEX_WAIT_PRIVATE)); if (rc) return rc; return 0; }
/** * Function responsible for setting up the setsockopt syscall for * the seccomp filter sandbox. */ static int sb_setsockopt(scmp_filter_ctx ctx, sandbox_cfg_t *filter) { int rc = 0; (void) filter; #ifdef __i386__ rc = seccomp_rule_add(ctx, SCMP_ACT_ALLOW, SCMP_SYS(setsockopt), 0); if (rc) return rc; #endif rc = seccomp_rule_add(ctx, SCMP_ACT_ALLOW, SCMP_SYS(setsockopt), 2, SCMP_CMP(1, SCMP_CMP_EQ, SOL_SOCKET), SCMP_CMP(2, SCMP_CMP_EQ, SO_REUSEADDR)); if (rc) return rc; #ifdef IP_TRANSPARENT rc = seccomp_rule_add(ctx, SCMP_ACT_ALLOW, SCMP_SYS(setsockopt), 2, SCMP_CMP(1, SCMP_CMP_EQ, SOL_IP), SCMP_CMP(2, SCMP_CMP_EQ, IP_TRANSPARENT)); if (rc) return rc; #endif return 0; }
/** * 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; }
int main() { char *addr; int fd,ret; char buf[20]={0}; char sc[128]={0}; scmp_filter_ctx ctx; ctx = seccomp_init(SCMP_ACT_KILL); if (!ctx) { perror("seccomp_init"); return -1; } ret = seccomp_rule_add(ctx,SCMP_ACT_ALLOW,SCMP_SYS(write),0); if(ret) { perror("add rule"); return -1; } ret = seccomp_rule_add(ctx,SCMP_ACT_ALLOW,SCMP_SYS(access),0); if(ret) { perror("add rule"); return -1; } fd = open("./.passwd",O_RDONLY); if(fd == -1) { perror("open"); return -1; } read(fd,buf,20); addr = mmap(0,4096,PROT_READ|PROT_WRITE,MAP_SHARED |MAP_ANONYMOUS,-1,0); if (addr == (char*)-1) { perror("mmap"); return -1; } memset(addr,0,4096); memcpy(addr,"MCSC",4); memcpy(addr+4,"2014",4); memcpy(&addr[8],buf,20); printf("put you shellcode here : "); fflush(stdout); ssize_t rc = read(0,sc,128); sc[rc-1]=0; seccomp_load(ctx); ((void (*)(void))sc)(); return 0; }
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); }
static int setup(struct spt *spt) { if (diskfile == NULL) return 0; /* not present */ diskfd = open(diskfile, O_RDWR); if (diskfd == -1) err(1, "Could not open disk: %s", diskfile); off_t capacity = lseek(diskfd, 0, SEEK_END); if (capacity == -1) err(1, "%s: Could not determine capacity", diskfile); if (capacity < 512) errx(1, "%s: Backing storage must be at least 1 block (512 bytes) " "in size", diskfile); spt->bi->blocki.present = 1; spt->bi->blocki.block_size = 512; spt->bi->blocki.capacity = capacity; spt->bi->blocki.hostfd = diskfd; int rc = -1; /* * When reading or writing to the file descriptor, enforce that the * operation cannot be performed beyond the (detected) capacity, otherwise, * when backed by a regular file, the guest could grow the file size * arbitrarily. * * The Solo5 API mandates that reads/writes must be equal to block_size, so * we implement the above by ensuring that (A2 == block_size) && (A3 <= * (capacity - block_size) holds. */ rc = seccomp_rule_add(spt->sc_ctx, SCMP_ACT_ALLOW, SCMP_SYS(pread64), 3, SCMP_A0(SCMP_CMP_EQ, diskfd), SCMP_A2(SCMP_CMP_EQ, spt->bi->blocki.block_size), SCMP_A3(SCMP_CMP_LE, (spt->bi->blocki.capacity - spt->bi->blocki.block_size))); if (rc != 0) errx(1, "seccomp_rule_add(pread64, fd=%d) failed: %s", diskfd, strerror(-rc)); rc = seccomp_rule_add(spt->sc_ctx, SCMP_ACT_ALLOW, SCMP_SYS(pwrite64), 3, SCMP_A0(SCMP_CMP_EQ, diskfd), SCMP_A2(SCMP_CMP_EQ, spt->bi->blocki.block_size), SCMP_A3(SCMP_CMP_LE, (spt->bi->blocki.capacity - spt->bi->blocki.block_size))); if (rc != 0) errx(1, "seccomp_rule_add(pwrite64, fd=%d) failed: %s", diskfd, strerror(-rc)); return 0; }
/** * Function responsible for setting up the time syscall for * the seccomp filter sandbox. */ static int sb_time(scmp_filter_ctx ctx, sandbox_cfg_t *filter) { (void) filter; return seccomp_rule_add(ctx, SCMP_ACT_ALLOW, SCMP_SYS(time), 1, SCMP_CMP(0, SCMP_CMP_EQ, 0)); }
/** * Function responsible for setting up the socket syscall for * the seccomp filter sandbox. */ static int sb_socket(scmp_filter_ctx ctx, sandbox_cfg_t *filter) { int rc = 0; int i; (void) filter; #ifdef __i386__ rc = seccomp_rule_add_0(ctx, SCMP_ACT_ALLOW, SCMP_SYS(socket)); if (rc) return rc; #endif rc = seccomp_rule_add_2(ctx, SCMP_ACT_ALLOW, SCMP_SYS(socket), SCMP_CMP(0, SCMP_CMP_EQ, PF_FILE), SCMP_CMP_MASKED(1, SOCK_CLOEXEC|SOCK_NONBLOCK, SOCK_STREAM)); if (rc) return rc; for (i = 0; i < 2; ++i) { const int pf = i ? PF_INET : PF_INET6; rc = seccomp_rule_add_3(ctx, SCMP_ACT_ALLOW, SCMP_SYS(socket), SCMP_CMP(0, SCMP_CMP_EQ, pf), SCMP_CMP_MASKED(1, SOCK_CLOEXEC|SOCK_NONBLOCK, SOCK_STREAM), SCMP_CMP(2, SCMP_CMP_EQ, IPPROTO_TCP)); if (rc) return rc; rc = seccomp_rule_add_3(ctx, SCMP_ACT_ALLOW, SCMP_SYS(socket), SCMP_CMP(0, SCMP_CMP_EQ, pf), SCMP_CMP_MASKED(1, SOCK_CLOEXEC|SOCK_NONBLOCK, SOCK_DGRAM), SCMP_CMP(2, SCMP_CMP_EQ, IPPROTO_IP)); if (rc) return rc; } rc = seccomp_rule_add_3(ctx, SCMP_ACT_ALLOW, SCMP_SYS(socket), SCMP_CMP(0, SCMP_CMP_EQ, PF_NETLINK), SCMP_CMP(1, SCMP_CMP_EQ, SOCK_RAW), SCMP_CMP(2, SCMP_CMP_EQ, 0)); if (rc) return rc; return 0; }
/** * Function responsible for setting up the fcntl64 syscall for * the seccomp filter sandbox. * * NOTE: does not NEED to be here.. currently only occurs before filter; will * keep just in case for the future. */ static int sb_mprotect(scmp_filter_ctx ctx, sandbox_cfg_t *filter) { int rc = 0; (void) filter; rc = seccomp_rule_add_1(ctx, SCMP_ACT_ALLOW, SCMP_SYS(mprotect), SCMP_CMP(2, SCMP_CMP_EQ, PROT_READ)); if (rc) return rc; rc = seccomp_rule_add_1(ctx, SCMP_ACT_ALLOW, SCMP_SYS(mprotect), SCMP_CMP(2, SCMP_CMP_EQ, PROT_NONE)); if (rc) return rc; return 0; }
/** * Function responsible for setting up the rt_sigprocmask syscall for * the seccomp filter sandbox. */ static int sb_rt_sigprocmask(scmp_filter_ctx ctx, sandbox_cfg_t *filter) { int rc = 0; (void) filter; rc = seccomp_rule_add_1(ctx, SCMP_ACT_ALLOW, SCMP_SYS(rt_sigprocmask), SCMP_CMP(0, SCMP_CMP_EQ, SIG_UNBLOCK)); if (rc) return rc; rc = seccomp_rule_add_1(ctx, SCMP_ACT_ALLOW, SCMP_SYS(rt_sigprocmask), SCMP_CMP(0, SCMP_CMP_EQ, SIG_SETMASK)); if (rc) return rc; return 0; }
/** * Function responsible for setting up the flock syscall for * the seccomp filter sandbox. * * NOTE: does not need to be here, occurs before filter is applied. */ static int sb_flock(scmp_filter_ctx ctx, sandbox_cfg_t *filter) { int rc = 0; (void) filter; rc = seccomp_rule_add_1(ctx, SCMP_ACT_ALLOW, SCMP_SYS(flock), SCMP_CMP(1, SCMP_CMP_EQ, LOCK_EX|LOCK_NB)); if (rc) return rc; rc = seccomp_rule_add_1(ctx, SCMP_ACT_ALLOW, SCMP_SYS(flock), SCMP_CMP(1, SCMP_CMP_EQ, LOCK_UN)); if (rc) return rc; return 0; }
/** * Function responsible for setting up the getsockopt syscall for * the seccomp filter sandbox. */ static int sb_getsockopt(scmp_filter_ctx ctx, sandbox_cfg_t *filter) { int rc = 0; (void) filter; #ifdef __i386__ rc = seccomp_rule_add_0(ctx, SCMP_ACT_ALLOW, SCMP_SYS(getsockopt)); if (rc) return rc; #endif rc = seccomp_rule_add_2(ctx, SCMP_ACT_ALLOW, SCMP_SYS(getsockopt), SCMP_CMP(1, SCMP_CMP_EQ, SOL_SOCKET), SCMP_CMP(2, SCMP_CMP_EQ, SO_ERROR)); if (rc) return rc; #ifdef HAVE_SYSTEMD rc = seccomp_rule_add_2(ctx, SCMP_ACT_ALLOW, SCMP_SYS(getsockopt), SCMP_CMP(1, SCMP_CMP_EQ, SOL_SOCKET), SCMP_CMP(2, SCMP_CMP_EQ, SO_SNDBUF)); if (rc) return rc; #endif #ifdef HAVE_LINUX_NETFILTER_IPV4_H rc = seccomp_rule_add_2(ctx, SCMP_ACT_ALLOW, SCMP_SYS(getsockopt), SCMP_CMP(1, SCMP_CMP_EQ, SOL_IP), SCMP_CMP(2, SCMP_CMP_EQ, SO_ORIGINAL_DST)); if (rc) return rc; #endif #ifdef HAVE_LINUX_NETFILTER_IPV6_IP6_TABLES_H rc = seccomp_rule_add_2(ctx, SCMP_ACT_ALLOW, SCMP_SYS(getsockopt), SCMP_CMP(1, SCMP_CMP_EQ, SOL_IPV6), SCMP_CMP(2, SCMP_CMP_EQ, IP6T_SO_ORIGINAL_DST)); if (rc) return rc; #endif return 0; }
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); }
/** * Function responsible for setting up the mmap2 syscall for * the seccomp filter sandbox. */ static int sb_mmap2(scmp_filter_ctx ctx, sandbox_cfg_t *filter) { int rc = 0; (void)filter; rc = seccomp_rule_add_2(ctx, SCMP_ACT_ALLOW, SCMP_SYS(mmap2), SCMP_CMP(2, SCMP_CMP_EQ, PROT_READ), SCMP_CMP(3, SCMP_CMP_EQ, MAP_PRIVATE)); if (rc) { return rc; } rc = seccomp_rule_add_2(ctx, SCMP_ACT_ALLOW, SCMP_SYS(mmap2), SCMP_CMP(2, SCMP_CMP_EQ, PROT_NONE), SCMP_CMP(3, SCMP_CMP_EQ, MAP_PRIVATE|MAP_ANONYMOUS|MAP_NORESERVE)); if (rc) { return rc; } rc = seccomp_rule_add_2(ctx, SCMP_ACT_ALLOW, SCMP_SYS(mmap2), SCMP_CMP(2, SCMP_CMP_EQ, PROT_READ|PROT_WRITE), SCMP_CMP(3, SCMP_CMP_EQ, MAP_PRIVATE|MAP_ANONYMOUS)); if (rc) { return rc; } rc = seccomp_rule_add_2(ctx, SCMP_ACT_ALLOW, SCMP_SYS(mmap2), SCMP_CMP(2, SCMP_CMP_EQ, PROT_READ|PROT_WRITE), SCMP_CMP(3, SCMP_CMP_EQ,MAP_PRIVATE|MAP_ANONYMOUS|MAP_STACK)); if (rc) { return rc; } rc = seccomp_rule_add_2(ctx, SCMP_ACT_ALLOW, SCMP_SYS(mmap2), SCMP_CMP(2, SCMP_CMP_EQ, PROT_READ|PROT_WRITE), SCMP_CMP(3, SCMP_CMP_EQ, MAP_PRIVATE|MAP_FIXED|MAP_DENYWRITE)); if (rc) { return rc; } rc = seccomp_rule_add_2(ctx, SCMP_ACT_ALLOW, SCMP_SYS(mmap2), SCMP_CMP(2, SCMP_CMP_EQ, PROT_READ|PROT_WRITE), SCMP_CMP(3, SCMP_CMP_EQ, MAP_PRIVATE|MAP_FIXED|MAP_ANONYMOUS)); if (rc) { return rc; } rc = seccomp_rule_add_2(ctx, SCMP_ACT_ALLOW, SCMP_SYS(mmap2), SCMP_CMP(2, SCMP_CMP_EQ, PROT_READ|PROT_EXEC), SCMP_CMP(3, SCMP_CMP_EQ, MAP_PRIVATE|MAP_DENYWRITE)); if (rc) { return rc; } return 0; }
/** * Function responsible for setting up the socket syscall for * the seccomp filter sandbox. */ static int sb_socket(scmp_filter_ctx ctx, sandbox_cfg_t *filter) { int rc = 0; (void) filter; #ifdef __i386__ rc = seccomp_rule_add(ctx, SCMP_ACT_ALLOW, SCMP_SYS(socket), 0); if (rc) return rc; #endif rc = seccomp_rule_add(ctx, SCMP_ACT_ALLOW, SCMP_SYS(socket), 3, SCMP_CMP(0, SCMP_CMP_EQ, PF_FILE), SCMP_CMP(1, SCMP_CMP_EQ, SOCK_STREAM|SOCK_CLOEXEC|SOCK_NONBLOCK), SCMP_CMP(2, SCMP_CMP_EQ, IPPROTO_IP)); if (rc) return rc; rc = seccomp_rule_add(ctx, SCMP_ACT_ALLOW, SCMP_SYS(socket), 3, SCMP_CMP(0, SCMP_CMP_EQ, PF_INET), SCMP_CMP(1, SCMP_CMP_EQ, SOCK_STREAM|SOCK_CLOEXEC), SCMP_CMP(2, SCMP_CMP_EQ, IPPROTO_TCP)); if (rc) return rc; rc = seccomp_rule_add(ctx, SCMP_ACT_ALLOW, SCMP_SYS(socket), 3, SCMP_CMP(0, SCMP_CMP_EQ, PF_INET), SCMP_CMP(1, SCMP_CMP_EQ, SOCK_DGRAM|SOCK_CLOEXEC|SOCK_NONBLOCK), SCMP_CMP(2, SCMP_CMP_EQ, IPPROTO_IP)); if (rc) return rc; rc = seccomp_rule_add(ctx, SCMP_ACT_ALLOW, SCMP_SYS(socket), 3, SCMP_CMP(0, SCMP_CMP_EQ, PF_NETLINK), SCMP_CMP(1, SCMP_CMP_EQ, SOCK_RAW), SCMP_CMP(2, SCMP_CMP_EQ, 0)); if (rc) return rc; return 0; }
/** * Function responsible for setting up the time syscall for * the seccomp filter sandbox. */ static int sb_time(scmp_filter_ctx ctx, sandbox_cfg_t *filter) { (void) filter; #ifdef __NR_time return seccomp_rule_add_1(ctx, SCMP_ACT_ALLOW, SCMP_SYS(time), SCMP_CMP(0, SCMP_CMP_EQ, 0)); #else return 0; #endif }
/** * Function responsible for setting up the getsockopt syscall for * the seccomp filter sandbox. */ static int sb_getsockopt(scmp_filter_ctx ctx, sandbox_cfg_t *filter) { int rc = 0; (void) filter; #ifdef __i386__ rc = seccomp_rule_add(ctx, SCMP_ACT_ALLOW, SCMP_SYS(getsockopt), 0); if (rc) return rc; #endif rc = seccomp_rule_add(ctx, SCMP_ACT_ALLOW, SCMP_SYS(getsockopt), 2, SCMP_CMP(1, SCMP_CMP_EQ, SOL_SOCKET), SCMP_CMP(2, SCMP_CMP_EQ, SO_ERROR)); if (rc) return rc; return 0; }
/** * Function responsible for setting up the socketpair syscall for * the seccomp filter sandbox. */ static int sb_socketpair(scmp_filter_ctx ctx, sandbox_cfg_t *filter) { int rc = 0; (void) filter; #ifdef __i386__ rc = seccomp_rule_add_0(ctx, SCMP_ACT_ALLOW, SCMP_SYS(socketpair)); if (rc) return rc; #endif rc = seccomp_rule_add_2(ctx, SCMP_ACT_ALLOW, SCMP_SYS(socketpair), SCMP_CMP(0, SCMP_CMP_EQ, PF_FILE), SCMP_CMP(1, SCMP_CMP_EQ, SOCK_STREAM|SOCK_CLOEXEC)); if (rc) return rc; return 0; }
/** * Function responsible for setting up the accept4 syscall for * the seccomp filter sandbox. */ static int sb_accept4(scmp_filter_ctx ctx, sandbox_cfg_t *filter) { int rc = 0; (void)filter; #ifdef __i386__ rc = seccomp_rule_add_1(ctx, SCMP_ACT_ALLOW, SCMP_SYS(socketcall), SCMP_CMP(0, SCMP_CMP_EQ, 18)); if (rc) { return rc; } #endif rc = seccomp_rule_add_1(ctx, SCMP_ACT_ALLOW, SCMP_SYS(accept4), SCMP_CMP_MASKED(3, SOCK_CLOEXEC|SOCK_NONBLOCK, 0)); if (rc) { return rc; } return 0; }
/** * Function responsible for setting up the mremap syscall for * the seccomp filter sandbox. * * NOTE: so far only occurs before filter is applied. */ static int sb_mremap(scmp_filter_ctx ctx, sandbox_cfg_t *filter) { int rc = 0; (void) filter; rc = seccomp_rule_add_1(ctx, SCMP_ACT_ALLOW, SCMP_SYS(mremap), SCMP_CMP(3, SCMP_CMP_EQ, MREMAP_MAYMOVE)); if (rc) return rc; return 0; }
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() { printf("step 1: unrestricted\n"); // ensure none of our children will ever be granted more priv // (via setuid, capabilities, ...) prctl(PR_SET_NO_NEW_PRIVS, 1); // ensure no escape is possible via ptrace prctl(PR_SET_DUMPABLE, 0); // Init the filter scmp_filter_ctx ctx; ctx = seccomp_init(SCMP_ACT_KILL); // default action: kill // setup basic whitelist seccomp_rule_add(ctx, SCMP_ACT_ALLOW, SCMP_SYS(rt_sigreturn), 0); seccomp_rule_add(ctx, SCMP_ACT_ALLOW, SCMP_SYS(exit), 0); seccomp_rule_add(ctx, SCMP_ACT_ALLOW, SCMP_SYS(read), 0); seccomp_rule_add(ctx, SCMP_ACT_ALLOW, SCMP_SYS(write), 0); // setup our rule seccomp_rule_add(ctx, SCMP_ACT_ALLOW, SCMP_SYS(dup2), 2, SCMP_A0(SCMP_CMP_EQ, 1), SCMP_A1(SCMP_CMP_EQ, 2)); // build and load the filter seccomp_load(ctx); printf("step 2: only 'write' and dup2(1, 2) syscalls\n"); // Redirect stderr to stdout dup2(1, 2); printf("step 3: stderr redirected to stdout\n"); // Duplicate stderr to arbitrary fd dup2(2, 42); printf("step 4: !! YOU SHOULD NOT SEE ME !!\n"); // Success (well, not so in this case...) return 0; }
/** * Function responsible for setting up the socket syscall for * the seccomp filter sandbox. */ static int sb_socket(scmp_filter_ctx ctx, sandbox_cfg_t *filter) { int rc = 0; int i, j; (void) filter; #ifdef __i386__ rc = seccomp_rule_add_0(ctx, SCMP_ACT_ALLOW, SCMP_SYS(socket)); if (rc) return rc; #endif rc = seccomp_rule_add_2(ctx, SCMP_ACT_ALLOW, SCMP_SYS(socket), SCMP_CMP(0, SCMP_CMP_EQ, PF_FILE), SCMP_CMP_MASKED(1, SOCK_CLOEXEC|SOCK_NONBLOCK, SOCK_STREAM)); if (rc) return rc; for (i = 0; i < 2; ++i) { const int pf = i ? PF_INET : PF_INET6; for (j=0; j < 3; ++j) { const int type = (j == 0) ? SOCK_STREAM : SOCK_DGRAM; const int protocol = (j == 0) ? IPPROTO_TCP : (j == 1) ? IPPROTO_IP : IPPROTO_UDP; rc = seccomp_rule_add_3(ctx, SCMP_ACT_ALLOW, SCMP_SYS(socket), SCMP_CMP(0, SCMP_CMP_EQ, pf), SCMP_CMP_MASKED(1, SOCK_CLOEXEC|SOCK_NONBLOCK, type), SCMP_CMP(2, SCMP_CMP_EQ, protocol)); if (rc) return rc; } } rc = seccomp_rule_add_3(ctx, SCMP_ACT_ALLOW, SCMP_SYS(socket), SCMP_CMP(0, SCMP_CMP_EQ, PF_UNIX), SCMP_CMP_MASKED(1, SOCK_CLOEXEC|SOCK_NONBLOCK, SOCK_STREAM), SCMP_CMP(2, SCMP_CMP_EQ, 0)); if (rc) return rc; rc = seccomp_rule_add_3(ctx, SCMP_ACT_ALLOW, SCMP_SYS(socket), SCMP_CMP(0, SCMP_CMP_EQ, PF_UNIX), SCMP_CMP_MASKED(1, SOCK_CLOEXEC|SOCK_NONBLOCK, SOCK_DGRAM), SCMP_CMP(2, SCMP_CMP_EQ, 0)); if (rc) return rc; rc = seccomp_rule_add_3(ctx, SCMP_ACT_ALLOW, SCMP_SYS(socket), SCMP_CMP(0, SCMP_CMP_EQ, PF_NETLINK), SCMP_CMP(1, SCMP_CMP_EQ, SOCK_RAW), SCMP_CMP(2, SCMP_CMP_EQ, 0)); if (rc) return rc; return 0; }
/** * Function responsible for setting up the fcntl64 syscall for * the seccomp filter sandbox. * * NOTE: if multiple filters need to be added, the PR_SECCOMP parameter needs * to be whitelisted in this function. */ static int sb_prctl(scmp_filter_ctx ctx, sandbox_cfg_t *filter) { int rc = 0; (void) filter; rc = seccomp_rule_add_1(ctx, SCMP_ACT_ALLOW, SCMP_SYS(prctl), SCMP_CMP(0, SCMP_CMP_EQ, PR_SET_DUMPABLE)); if (rc) return rc; return 0; }
/** * Function responsible for setting up the poll syscall for * the seccomp filter sandbox. */ static int sb_poll(scmp_filter_ctx ctx, sandbox_cfg_t *filter) { int rc = 0; (void) filter; rc = seccomp_rule_add_2(ctx, SCMP_ACT_ALLOW, SCMP_SYS(poll), SCMP_CMP(1, SCMP_CMP_EQ, 1), SCMP_CMP(2, SCMP_CMP_EQ, 10)); if (rc) return rc; return 0; }
/** * Function responsible for setting up the epoll_ctl syscall for * the seccomp filter sandbox. * * Note: basically allows everything but will keep for now.. */ static int sb_epoll_ctl(scmp_filter_ctx ctx, sandbox_cfg_t *filter) { int rc = 0; (void) filter; rc = seccomp_rule_add_1(ctx, SCMP_ACT_ALLOW, SCMP_SYS(epoll_ctl), SCMP_CMP(1, SCMP_CMP_EQ, EPOLL_CTL_ADD)); if (rc) return rc; rc = seccomp_rule_add_1(ctx, SCMP_ACT_ALLOW, SCMP_SYS(epoll_ctl), SCMP_CMP(1, SCMP_CMP_EQ, EPOLL_CTL_MOD)); if (rc) return rc; rc = seccomp_rule_add_1(ctx, SCMP_ACT_ALLOW, SCMP_SYS(epoll_ctl), SCMP_CMP(1, SCMP_CMP_EQ, EPOLL_CTL_DEL)); if (rc) return rc; return 0; }