Introduce EXILE_SYSCALL_DENY_RET_NOSYS for syscalls like clone3()
clone3() is used more and more, but we cannot filter it. We can either allow it fully or return ENONYS. Some libraries perform fallbacks to the older clone() in that case, which we can filter again.
Этот коммит содержится в:
родитель
bbbdfc44da
Коммит
bd3641981c
12
exile.c
12
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;
|
||||
}
|
||||
|
||||
/*
|
||||
|
2
exile.h
2
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)
|
||||
|
19
test.c
19
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[])
|
||||
|
Загрузка…
Ссылка в новой задаче
Block a user