diff --git a/exile.c b/exile.c index 77d7fd9..067b7ad 100644 --- a/exile.c +++ b/exile.c @@ -280,7 +280,7 @@ static struct syscall_vow_map exile_vow_map[] = {EXILE_SYS(copy_file_range), EXILE_SYSCALL_VOW_STDIO}, {EXILE_SYS(statx), EXILE_SYSCALL_VOW_RPATH}, {EXILE_SYS(rseq), EXILE_SYSCALL_VOW_THREAD}, - {EXILE_SYS(clone3), EXILE_SYSCALL_VOW_CLONE}, + {EXILE_SYS(clone3), EXILE_SYSCALL_VOW_CLONE|EXILE_SYSCALL_VOW_THREAD}, {EXILE_SYS(close_range), EXILE_SYSCALL_VOW_STDIO}, {EXILE_SYS(openat2), EXILE_SYSCALL_VOW_RPATH|EXILE_SYSCALL_VOW_WPATH}, {EXILE_SYS(faccessat2), EXILE_SYSCALL_VOW_RPATH}, @@ -521,7 +521,7 @@ int get_vow_argfilter(long syscall, uint64_t vow_promises, struct sock_filter *f current_count = COUNT_EXILE_SYSCALL_FILTER(open_filter); break; case EXILE_SYS(openat2): - *policy = EXILE_SYSCALL_DENY_RET_ERROR; + *policy = EXILE_SYSCALL_DENY_RET_NOSYS; return 0; break; case EXILE_SYS(socket): @@ -539,7 +539,7 @@ int get_vow_argfilter(long syscall, uint64_t vow_promises, struct sock_filter *f case EXILE_SYS(clone3): if((vow_promises & EXILE_SYSCALL_VOW_CLONE) == 0) { - *policy = EXILE_SYSCALL_DENY_RET_ERROR; + *policy = EXILE_SYSCALL_DENY_RET_NOSYS; return 0; } break; @@ -1075,6 +1075,10 @@ static struct sock_filter *append_syscall_to_bpf(struct exile_syscall_policy *sy { action = SECCOMP_RET_ERRNO|EACCES; } + if(action == EXILE_SYSCALL_DENY_RET_NOSYS) + { + action = SECCOMP_RET_ERRNO|ENOSYS; + } long syscall = syscallpolicy->syscall; struct sock_filter syscall_load = BPF_STMT(BPF_LD+BPF_W+BPF_ABS, offsetof(struct seccomp_data, nr)); @@ -1141,7 +1145,7 @@ static struct sock_filter *append_syscall_to_bpf(struct exile_syscall_policy *sy static int is_valid_syscall_policy(unsigned int policy) { - return policy == EXILE_SYSCALL_ALLOW || policy == EXILE_SYSCALL_DENY_RET_ERROR || policy == EXILE_SYSCALL_DENY_KILL_PROCESS; + return policy == EXILE_SYSCALL_ALLOW || policy == EXILE_SYSCALL_DENY_RET_ERROR || policy == EXILE_SYSCALL_DENY_KILL_PROCESS || policy == EXILE_SYSCALL_DENY_RET_NOSYS; } /* diff --git a/exile.h b/exile.h index d395851..4898f17 100644 --- a/exile.h +++ b/exile.h @@ -75,6 +75,7 @@ #define EXILE_UNSHARE_NETWORK 1<<1 #define EXILE_UNSHARE_USER 1<<2 #define EXILE_UNSHARE_MOUNT 1<<3 +#define EXILE_UNSHARE_AUTOMATIC 1<<4 #ifndef EXILE_LOG_ERROR #define EXILE_LOG_ERROR(...) do { fprintf(stderr, "exile.h: %s(): Error: ", __func__); fprintf(stderr, __VA_ARGS__); } while(0) @@ -273,6 +274,7 @@ struct exile_path_policy #define EXILE_SYSCALL_ALLOW 1 #define EXILE_SYSCALL_DENY_KILL_PROCESS 2 #define EXILE_SYSCALL_DENY_RET_ERROR 3 +#define EXILE_SYSCALL_DENY_RET_NOSYS 4 #define EXILE_BPF_NOP \ BPF_STMT(BPF_JMP+BPF_JA,0) diff --git a/test.c b/test.c index 592a174..d1e0dd5 100644 --- a/test.c +++ b/test.c @@ -643,6 +643,24 @@ int test_vows_from_str() return 0; } +int test_clone3_nosys() +{ + struct exile_policy *policy = exile_init_policy(); + policy->vow_promises = exile_vows_from_str("stdio rpath wpath cpath thread error"); + + exile_enable_policy(policy); + /* While args are invalid, it should never reach clone3 syscall handler, so it's irrelevant for + our test*/ + long ret = syscall(__NR_clone3, NULL, 0); + + if(ret == -1 && errno != ENOSYS) + { + LOG("clone3() was not allowed but did not return ENOSYS. It returned: %li, errno: %i\n", ret, errno); + return 1; + } + return 0; +} + struct dispatcher { char *name; @@ -670,6 +688,7 @@ struct dispatcher dispatchers[] = { { "launch", &test_launch}, { "launch-get", &test_launch_get}, { "vow_from_str", &test_vows_from_str}, + { "clone3_nosys", &test_clone3_nosys}, }; int main(int argc, char *argv[])