Begin low-level seccomp arg filter interface
Squashed: test: Adjust existing to new API with arg filters test: Add tests for low-level seccomp args filter API test: Add seccomp_filter_mixed() test: Switch to syscall() everywhere append_syscall_to_bpf(): Apply EXILE_SYSCALL_EXIT_BPF_NO_MATCH also for sock_filter.jt
This commit is contained in:
parent
48deab0dde
commit
15a6850023
174
exile.h
174
exile.h
@ -673,33 +673,24 @@ struct exile_path_policy
|
|||||||
struct exile_path_policy *next;
|
struct exile_path_policy *next;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
/* Special values */
|
||||||
struct exile_allocated_entry
|
|
||||||
{
|
|
||||||
void *data; /* the actual data */
|
|
||||||
size_t size; /* number of bytes allocated for data */
|
|
||||||
size_t used; /* number of bytes in use */
|
|
||||||
};
|
|
||||||
|
|
||||||
/* Special value */
|
|
||||||
#define EXILE_SYSCALL_MATCH_ALL -1
|
#define EXILE_SYSCALL_MATCH_ALL -1
|
||||||
|
#define EXILE_SYSCALL_EXIT_BPF_NO_MATCH 255 //exit the bpf filter, not matching policy
|
||||||
|
|
||||||
#define EXILE_SYSCALL_ALLOW 1
|
#define EXILE_SYSCALL_ALLOW 1
|
||||||
#define EXILE_SYSCALL_DENY_KILL_PROCESS 2
|
#define EXILE_SYSCALL_DENY_KILL_PROCESS 2
|
||||||
#define EXILE_SYSCALL_DENY_RET_ERROR 3
|
#define EXILE_SYSCALL_DENY_RET_ERROR 3
|
||||||
|
|
||||||
|
#define EXILE_ARGFILTERS_COUNT 60
|
||||||
struct exile_syscall_policy
|
struct exile_syscall_policy
|
||||||
{
|
{
|
||||||
struct exile_allocated_entry syscall;
|
struct sock_filter argfilters[EXILE_ARGFILTERS_COUNT];
|
||||||
|
size_t argfilterscount;
|
||||||
|
long syscall;
|
||||||
unsigned int policy;
|
unsigned int policy;
|
||||||
struct exile_syscall_policy *next;
|
struct exile_syscall_policy *next;
|
||||||
};
|
};
|
||||||
|
|
||||||
/* Number of bytes to grow the buffer in exile_allocated_entry with */
|
|
||||||
#define EXILE_ENTRY_ALLOC_SIZE 32
|
|
||||||
|
|
||||||
|
|
||||||
/* Policy tells exile what to do */
|
/* Policy tells exile what to do */
|
||||||
struct exile_policy
|
struct exile_policy
|
||||||
{
|
{
|
||||||
@ -727,86 +718,32 @@ struct exile_policy
|
|||||||
|
|
||||||
};
|
};
|
||||||
|
|
||||||
static int exile_entry_append(struct exile_allocated_entry *entry, void *data, size_t bytes)
|
|
||||||
{
|
|
||||||
size_t remaining = entry->size - entry->used;
|
|
||||||
if(remaining < bytes)
|
|
||||||
{
|
|
||||||
size_t expandval = EXILE_ENTRY_ALLOC_SIZE > bytes ? EXILE_ENTRY_ALLOC_SIZE : bytes;
|
|
||||||
size_t sizenew = 0;
|
|
||||||
if(__builtin_add_overflow(entry->size, expandval, &sizenew))
|
|
||||||
{
|
|
||||||
EXILE_LOG_ERROR("overflow in exile_entry_append\n");
|
|
||||||
return -EINVAL;
|
|
||||||
}
|
|
||||||
int *datanew = (int *) realloc(entry->data, sizenew);
|
|
||||||
if(datanew == NULL)
|
|
||||||
{
|
|
||||||
EXILE_LOG_ERROR("failed to resize array: %s\n", strerror(errno));
|
|
||||||
return -1;
|
|
||||||
}
|
|
||||||
entry->size = sizenew;
|
|
||||||
entry->data = datanew;
|
|
||||||
}
|
|
||||||
uint8_t *target = (uint8_t *) entry->data;
|
|
||||||
memcpy(target + entry->used, data, bytes);
|
|
||||||
entry->used = entry->used + bytes;
|
|
||||||
return 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
static int exile_append_syscall(struct exile_allocated_entry *entry, long *syscalls, size_t n)
|
|
||||||
{
|
|
||||||
size_t bytes = 0;
|
|
||||||
if(__builtin_mul_overflow(n, sizeof(long), &bytes))
|
|
||||||
{
|
|
||||||
EXILE_LOG_ERROR("Overflow while trying to add system calls\n");
|
|
||||||
return -EINVAL;
|
|
||||||
}
|
|
||||||
return exile_entry_append(entry, syscalls, bytes);
|
|
||||||
}
|
|
||||||
|
|
||||||
static int is_valid_syscall_policy(unsigned int policy)
|
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;
|
||||||
}
|
}
|
||||||
|
|
||||||
static void get_syscall_array(struct exile_syscall_policy *policy, long **syscall, size_t *n)
|
int exile_append_syscall_policy(struct exile_policy *exile_policy, long syscall, unsigned int syscall_policy, struct sock_filter *argfilters, size_t n)
|
||||||
{
|
{
|
||||||
*syscall = (long *) policy->syscall.data;
|
|
||||||
*n = policy->syscall.used / sizeof(long);
|
|
||||||
}
|
|
||||||
|
|
||||||
int exile_append_syscalls_policy(struct exile_policy *exile_policy, unsigned int syscall_policy, long *syscalls, size_t n)
|
|
||||||
{
|
|
||||||
/* Check whether we already have this policy. If so, merge new entries to the existing ones */
|
|
||||||
struct exile_syscall_policy *current_policy = exile_policy->syscall_policies;
|
|
||||||
while(current_policy)
|
|
||||||
{
|
|
||||||
if(current_policy->policy == syscall_policy)
|
|
||||||
{
|
|
||||||
return exile_append_syscall(¤t_policy->syscall, syscalls, n);
|
|
||||||
}
|
|
||||||
current_policy = current_policy->next;
|
|
||||||
}
|
|
||||||
|
|
||||||
/* We don't so we create a new policy */
|
|
||||||
struct exile_syscall_policy *newpolicy = (struct exile_syscall_policy *) calloc(1, sizeof(struct exile_syscall_policy));
|
struct exile_syscall_policy *newpolicy = (struct exile_syscall_policy *) calloc(1, sizeof(struct exile_syscall_policy));
|
||||||
if(newpolicy == NULL)
|
if(newpolicy == NULL)
|
||||||
{
|
{
|
||||||
EXILE_LOG_ERROR("Failed to allocate memory for syscall policy\n");
|
EXILE_LOG_ERROR("Failed to allocate memory for syscall policy\n");
|
||||||
return -1;
|
return -1;
|
||||||
}
|
}
|
||||||
|
newpolicy->policy = syscall_policy;
|
||||||
int ret = exile_append_syscall(&newpolicy->syscall, syscalls, n);
|
newpolicy->syscall = syscall;
|
||||||
if(ret != 0)
|
newpolicy->argfilterscount = n;
|
||||||
|
if(n > EXILE_ARGFILTERS_COUNT)
|
||||||
{
|
{
|
||||||
free(newpolicy);
|
EXILE_LOG_ERROR("Too many argfilters supplied\n");
|
||||||
EXILE_LOG_ERROR("Failed to append syscall\n");
|
|
||||||
return -1;
|
return -1;
|
||||||
}
|
}
|
||||||
|
for(size_t i = 0; i < n; i++)
|
||||||
|
{
|
||||||
|
newpolicy->argfilters[i] = argfilters[i];
|
||||||
|
}
|
||||||
newpolicy->next = NULL;
|
newpolicy->next = NULL;
|
||||||
newpolicy->policy = syscall_policy;
|
|
||||||
|
|
||||||
*(exile_policy->syscall_policies_tail) = newpolicy;
|
*(exile_policy->syscall_policies_tail) = newpolicy;
|
||||||
exile_policy->syscall_policies_tail = &(newpolicy->next);
|
exile_policy->syscall_policies_tail = &(newpolicy->next);
|
||||||
@ -815,14 +752,10 @@ int exile_append_syscalls_policy(struct exile_policy *exile_policy, unsigned int
|
|||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
int exile_append_syscall_policy(struct exile_policy *exile_policy, unsigned int syscall_policy, long syscall)
|
|
||||||
{
|
|
||||||
return exile_append_syscalls_policy(exile_policy, syscall_policy, &syscall, 1);
|
|
||||||
}
|
|
||||||
|
|
||||||
int exile_append_syscall_default_policy(struct exile_policy *exile_policy, unsigned int default_policy)
|
int exile_append_syscall_default_policy(struct exile_policy *exile_policy, unsigned int default_policy)
|
||||||
{
|
{
|
||||||
return exile_append_syscall_policy(exile_policy, default_policy, EXILE_SYSCALL_MATCH_ALL);
|
return exile_append_syscall_policy(exile_policy, EXILE_SYSCALL_MATCH_ALL, default_policy, NULL, 0);
|
||||||
}
|
}
|
||||||
|
|
||||||
static void get_group_syscalls(uint64_t mask, long *syscalls, size_t *n)
|
static void get_group_syscalls(uint64_t mask, long *syscalls, size_t *n)
|
||||||
@ -856,8 +789,17 @@ int exile_append_group_syscall_policy(struct exile_policy *exile_policy, unsigne
|
|||||||
EXILE_LOG_ERROR("Error: No syscalls found for group mask\n");
|
EXILE_LOG_ERROR("Error: No syscalls found for group mask\n");
|
||||||
return -EINVAL;
|
return -EINVAL;
|
||||||
}
|
}
|
||||||
|
for(size_t i = 0; i < n; i++)
|
||||||
|
{
|
||||||
|
int ret = exile_append_syscall_policy(exile_policy, syscalls[i], syscall_policy, NULL, 0);
|
||||||
|
if(ret != 0)
|
||||||
|
{
|
||||||
|
EXILE_LOG_ERROR("Error: Failed while trying to append group policy\n");
|
||||||
|
return ret;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
return exile_append_syscalls_policy(exile_policy, syscall_policy, syscalls, n);
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Creates the default policy
|
/* Creates the default policy
|
||||||
@ -1240,8 +1182,9 @@ static int drop_caps()
|
|||||||
|
|
||||||
|
|
||||||
|
|
||||||
static void append_syscalls_to_bpf(long *syscalls, size_t n, unsigned int action, struct sock_filter *filter, unsigned short int *start_index)
|
static void append_syscall_to_bpf(struct exile_syscall_policy *syscallpolicy, struct sock_filter *filter, unsigned short int *start_index)
|
||||||
{
|
{
|
||||||
|
unsigned int action = syscallpolicy->policy;
|
||||||
if(action == EXILE_SYSCALL_ALLOW)
|
if(action == EXILE_SYSCALL_ALLOW)
|
||||||
{
|
{
|
||||||
action = SECCOMP_RET_ALLOW;
|
action = SECCOMP_RET_ALLOW;
|
||||||
@ -1254,18 +1197,45 @@ static void append_syscalls_to_bpf(long *syscalls, size_t n, unsigned int action
|
|||||||
{
|
{
|
||||||
action = SECCOMP_RET_ERRNO|EACCES;
|
action = SECCOMP_RET_ERRNO|EACCES;
|
||||||
}
|
}
|
||||||
for(size_t i = 0; i < n; i++)
|
long syscall = syscallpolicy->syscall;
|
||||||
{
|
|
||||||
long syscall = syscalls[i];
|
struct sock_filter syscall_load = BPF_STMT(BPF_LD+BPF_W+BPF_ABS, offsetof(struct seccomp_data, nr));
|
||||||
|
filter[(*start_index)++] = syscall_load;
|
||||||
if(syscall != EXILE_SYSCALL_MATCH_ALL)
|
if(syscall != EXILE_SYSCALL_MATCH_ALL)
|
||||||
{
|
{
|
||||||
struct sock_filter syscall_check = BPF_JUMP(BPF_JMP+BPF_JEQ+BPF_K, (unsigned int) syscall, 0, 1);
|
/* How many steps forward to jump when we don't match. This is either the last statement,
|
||||||
|
* i. e. the default action or the next syscall policy */
|
||||||
|
__u8 next_syscall_pc = 1;
|
||||||
|
if(__builtin_add_overflow(next_syscall_pc, syscallpolicy->argfilterscount, &next_syscall_pc))
|
||||||
|
{
|
||||||
|
EXILE_LOG_ERROR("Error: Overflow while trying to calculate jump offset\n");
|
||||||
|
/* TODO: Return error */
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
struct sock_filter syscall_check = BPF_JUMP(BPF_JMP+BPF_JEQ+BPF_K, (unsigned int) syscall, 0, next_syscall_pc);
|
||||||
filter[(*start_index)++] = syscall_check;
|
filter[(*start_index)++] = syscall_check;
|
||||||
|
--next_syscall_pc;
|
||||||
|
|
||||||
|
for(size_t i = 0; i < syscallpolicy->argfilterscount; i++)
|
||||||
|
{
|
||||||
|
filter[*start_index] = syscallpolicy->argfilters[i];
|
||||||
|
__u8 jump_count = next_syscall_pc;
|
||||||
|
if(filter[*start_index].jt == EXILE_SYSCALL_EXIT_BPF_NO_MATCH)
|
||||||
|
{
|
||||||
|
filter[*start_index].jt = jump_count;
|
||||||
|
}
|
||||||
|
if(filter[*start_index].jf == EXILE_SYSCALL_EXIT_BPF_NO_MATCH)
|
||||||
|
{
|
||||||
|
filter[*start_index].jf = jump_count;
|
||||||
|
}
|
||||||
|
--next_syscall_pc;
|
||||||
|
++*start_index;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
struct sock_filter syscall_action = BPF_STMT(BPF_RET+BPF_K, action);
|
struct sock_filter syscall_action = BPF_STMT(BPF_RET+BPF_K, action);
|
||||||
/* TODO: we can do better than adding this below every jump */
|
/* TODO: we can do better than adding this below every jump */
|
||||||
filter[(*start_index)++] = syscall_action;
|
filter[(*start_index)++] = syscall_action;
|
||||||
}
|
|
||||||
}
|
}
|
||||||
/*
|
/*
|
||||||
* Enables the seccomp policy
|
* Enables the seccomp policy
|
||||||
@ -1297,21 +1267,8 @@ static int exile_enable_syscall_policy(struct exile_policy *policy)
|
|||||||
EXILE_LOG_ERROR("invalid syscall policy specified\n");
|
EXILE_LOG_ERROR("invalid syscall policy specified\n");
|
||||||
return -1;
|
return -1;
|
||||||
}
|
}
|
||||||
long *syscalls = NULL;
|
/* TODO: reintroduce overflow checks */
|
||||||
size_t n = 0;
|
append_syscall_to_bpf(current_policy, filter, ¤t_filter_index);
|
||||||
get_syscall_array(current_policy, &syscalls, &n);
|
|
||||||
unsigned short int newsize;
|
|
||||||
if(__builtin_add_overflow(current_filter_index, n, &newsize))
|
|
||||||
{
|
|
||||||
EXILE_LOG_ERROR("Overflow when trying to add new system calls\n");
|
|
||||||
return -EINVAL;
|
|
||||||
}
|
|
||||||
if(newsize > (sizeof(filter)/sizeof(filter[0]))-1)
|
|
||||||
{
|
|
||||||
EXILE_LOG_ERROR("Too many system calls added\n");
|
|
||||||
return -EINVAL;
|
|
||||||
}
|
|
||||||
append_syscalls_to_bpf(syscalls, n, current_policy->policy, filter, ¤t_filter_index);
|
|
||||||
current_policy = current_policy->next;
|
current_policy = current_policy->next;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -1504,10 +1461,7 @@ static int check_policy_sanity(struct exile_policy *policy)
|
|||||||
int last_policy = 0;
|
int last_policy = 0;
|
||||||
while(syscall_policy)
|
while(syscall_policy)
|
||||||
{
|
{
|
||||||
long *syscall;
|
if(syscall_policy->syscall == EXILE_SYSCALL_MATCH_ALL)
|
||||||
size_t n = 0;
|
|
||||||
get_syscall_array(syscall_policy, &syscall, &n);
|
|
||||||
if(syscall[n-1] == EXILE_SYSCALL_MATCH_ALL)
|
|
||||||
{
|
{
|
||||||
last_match_all = i;
|
last_match_all = i;
|
||||||
match_all_policy = syscall_policy->policy;
|
match_all_policy = syscall_policy->policy;
|
||||||
|
131
test.c
131
test.c
@ -87,13 +87,13 @@ static int test_successful_exit(int (*f)())
|
|||||||
static int do_test_seccomp_blacklisted()
|
static int do_test_seccomp_blacklisted()
|
||||||
{
|
{
|
||||||
struct exile_policy *policy = exile_init_policy();
|
struct exile_policy *policy = exile_init_policy();
|
||||||
exile_append_syscall_policy(policy, EXILE_SYSCALL_DENY_KILL_PROCESS, EXILE_SYS(getuid));
|
exile_append_syscall_policy(policy,EXILE_SYS(getuid), EXILE_SYSCALL_DENY_KILL_PROCESS, NULL, 0);
|
||||||
exile_append_syscall_default_policy(policy, EXILE_SYSCALL_ALLOW);
|
exile_append_syscall_default_policy(policy, EXILE_SYSCALL_ALLOW);
|
||||||
|
|
||||||
xexile_enable_policy(policy);
|
xexile_enable_policy(policy);
|
||||||
|
|
||||||
uid_t pid = geteuid();
|
uid_t pid = syscall(EXILE_SYS(geteuid));
|
||||||
pid = getuid();
|
pid = syscall(EXILE_SYS(getuid));
|
||||||
return 0;
|
return 0;
|
||||||
|
|
||||||
|
|
||||||
@ -108,12 +108,12 @@ static int do_test_seccomp_blacklisted_call_permitted()
|
|||||||
{
|
{
|
||||||
struct exile_policy *policy = exile_init_policy();
|
struct exile_policy *policy = exile_init_policy();
|
||||||
|
|
||||||
exile_append_syscall_policy(policy, EXILE_SYSCALL_DENY_KILL_PROCESS, EXILE_SYS(getuid));
|
exile_append_syscall_policy(policy, EXILE_SYS(getuid), EXILE_SYSCALL_DENY_KILL_PROCESS, NULL, 0);
|
||||||
exile_append_syscall_default_policy(policy, EXILE_SYSCALL_ALLOW);
|
exile_append_syscall_default_policy(policy, EXILE_SYSCALL_ALLOW);
|
||||||
|
|
||||||
xexile_enable_policy(policy);
|
xexile_enable_policy(policy);
|
||||||
//geteuid is not blacklisted, so must succeed
|
//geteuid is not blacklisted, so must succeed
|
||||||
uid_t pid = geteuid();
|
uid_t pid = syscall(EXILE_SYS(geteuid));
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -127,7 +127,7 @@ static int do_test_seccomp_x32_kill()
|
|||||||
{
|
{
|
||||||
struct exile_policy *policy = exile_init_policy();
|
struct exile_policy *policy = exile_init_policy();
|
||||||
|
|
||||||
exile_append_syscall_policy(policy, EXILE_SYSCALL_DENY_KILL_PROCESS, EXILE_SYS(getuid));
|
exile_append_syscall_policy(policy, EXILE_SYS(getuid), EXILE_SYSCALL_DENY_KILL_PROCESS, NULL, 0);
|
||||||
exile_append_syscall_default_policy(policy, EXILE_SYSCALL_ALLOW);
|
exile_append_syscall_default_policy(policy, EXILE_SYSCALL_ALLOW);
|
||||||
|
|
||||||
xexile_enable_policy(policy);
|
xexile_enable_policy(policy);
|
||||||
@ -148,7 +148,7 @@ int test_seccomp_require_last_matchall()
|
|||||||
{
|
{
|
||||||
struct exile_policy *policy = exile_init_policy();
|
struct exile_policy *policy = exile_init_policy();
|
||||||
|
|
||||||
exile_append_syscall_policy(policy, EXILE_SYSCALL_DENY_KILL_PROCESS, EXILE_SYS(getuid));
|
exile_append_syscall_policy(policy, EXILE_SYS(getuid), EXILE_SYSCALL_DENY_KILL_PROCESS, NULL, 0);
|
||||||
|
|
||||||
int status = exile_enable_policy(policy);
|
int status = exile_enable_policy(policy);
|
||||||
if(status == 0)
|
if(status == 0)
|
||||||
@ -163,13 +163,13 @@ static int do_test_seccomp_errno()
|
|||||||
{
|
{
|
||||||
struct exile_policy *policy = exile_init_policy();
|
struct exile_policy *policy = exile_init_policy();
|
||||||
|
|
||||||
exile_append_syscall_policy(policy, EXILE_SYSCALL_DENY_RET_ERROR, EXILE_SYS(close));
|
exile_append_syscall_policy(policy, EXILE_SYS(close),EXILE_SYSCALL_DENY_RET_ERROR, NULL, 0);
|
||||||
exile_append_syscall_default_policy(policy, EXILE_SYSCALL_ALLOW);
|
exile_append_syscall_default_policy(policy, EXILE_SYSCALL_ALLOW);
|
||||||
|
|
||||||
xexile_enable_policy(policy);
|
xexile_enable_policy(policy);
|
||||||
uid_t id = getuid();
|
uid_t id = syscall(EXILE_SYS(getuid));
|
||||||
|
|
||||||
int fd = close(0);
|
int fd = syscall(EXILE_SYS(close), 0);
|
||||||
printf("close() return code: %i, errno: %s\n", fd, strerror(errno));
|
printf("close() return code: %i, errno: %s\n", fd, strerror(errno));
|
||||||
return fd == -1 ? 0 : 1;
|
return fd == -1 ? 0 : 1;
|
||||||
}
|
}
|
||||||
@ -185,7 +185,11 @@ static int test_seccomp_group()
|
|||||||
{
|
{
|
||||||
struct exile_policy *policy = exile_init_policy();
|
struct exile_policy *policy = exile_init_policy();
|
||||||
|
|
||||||
exile_append_group_syscall_policy(policy, EXILE_SYSCALL_DENY_RET_ERROR, EXILE_SYSCGROUP_SOCKET);
|
if(exile_append_group_syscall_policy(policy, EXILE_SYSCALL_DENY_RET_ERROR, EXILE_SYSCGROUP_SOCKET) != 0)
|
||||||
|
{
|
||||||
|
printf("nothing added\n");
|
||||||
|
return 1;
|
||||||
|
}
|
||||||
exile_append_syscall_default_policy(policy, EXILE_SYSCALL_ALLOW);
|
exile_append_syscall_default_policy(policy, EXILE_SYSCALL_ALLOW);
|
||||||
|
|
||||||
xexile_enable_policy(policy);
|
xexile_enable_policy(policy);
|
||||||
@ -193,7 +197,107 @@ static int test_seccomp_group()
|
|||||||
int s = socket(AF_INET,SOCK_STREAM,0);
|
int s = socket(AF_INET,SOCK_STREAM,0);
|
||||||
if(s != -1)
|
if(s != -1)
|
||||||
{
|
{
|
||||||
printf("Failed: socket was expected to return error\n");
|
printf("Failed: socket was expected to return error, but returned %i\n", s);
|
||||||
|
return 1;
|
||||||
|
}
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
int test_seccomp_argfilter_allowed()
|
||||||
|
{
|
||||||
|
struct exile_policy *policy = exile_init_policy();
|
||||||
|
|
||||||
|
struct sock_filter argfilter[2] =
|
||||||
|
{
|
||||||
|
BPF_STMT(BPF_LD+BPF_W+BPF_ABS, (offsetof(struct seccomp_data, args[1]))),
|
||||||
|
BPF_JUMP(BPF_JMP+BPF_JSET+BPF_K, O_WRONLY, 0, EXILE_SYSCALL_EXIT_BPF_NO_MATCH)
|
||||||
|
};
|
||||||
|
|
||||||
|
exile_append_syscall_policy(policy, EXILE_SYS(open),EXILE_SYSCALL_DENY_RET_ERROR, argfilter, 2);
|
||||||
|
exile_append_syscall_default_policy(policy, EXILE_SYSCALL_ALLOW);
|
||||||
|
xexile_enable_policy(policy);
|
||||||
|
|
||||||
|
|
||||||
|
char *t = "/dev/random";
|
||||||
|
int ret = (int) syscall(EXILE_SYS(open),t, O_RDONLY);
|
||||||
|
|
||||||
|
if(ret == -1)
|
||||||
|
{
|
||||||
|
printf("Failed: open was expected to succeed, but returned %i\n", ret);
|
||||||
|
return 1;
|
||||||
|
}
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
int test_seccomp_argfilter_filtered()
|
||||||
|
{
|
||||||
|
struct exile_policy *policy = exile_init_policy();
|
||||||
|
|
||||||
|
struct sock_filter argfilter[2] =
|
||||||
|
{
|
||||||
|
BPF_STMT(BPF_LD+BPF_W+BPF_ABS, (offsetof(struct seccomp_data, args[1]))),
|
||||||
|
BPF_JUMP(BPF_JMP+BPF_JSET+BPF_K, O_WRONLY, 0, EXILE_SYSCALL_EXIT_BPF_NO_MATCH)
|
||||||
|
};
|
||||||
|
|
||||||
|
exile_append_syscall_policy(policy, EXILE_SYS(open),EXILE_SYSCALL_DENY_RET_ERROR, argfilter, 2);
|
||||||
|
exile_append_syscall_default_policy(policy, EXILE_SYSCALL_ALLOW);
|
||||||
|
xexile_enable_policy(policy);
|
||||||
|
|
||||||
|
char *t = "/dev/random";
|
||||||
|
int ret = (int) syscall(EXILE_SYS(open),t, O_WRONLY);
|
||||||
|
|
||||||
|
if(ret != -1)
|
||||||
|
{
|
||||||
|
printf("Failed: open was expected to fail, but returned %i\n", ret);
|
||||||
|
return 1;
|
||||||
|
}
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
int test_seccomp_argfilter_mixed()
|
||||||
|
{
|
||||||
|
struct exile_policy *policy = exile_init_policy();
|
||||||
|
|
||||||
|
struct sock_filter argfilter[2] =
|
||||||
|
{
|
||||||
|
BPF_STMT(BPF_LD+BPF_W+BPF_ABS, (offsetof(struct seccomp_data, args[1]))),
|
||||||
|
BPF_JUMP(BPF_JMP+BPF_JSET+BPF_K, O_WRONLY, 0, EXILE_SYSCALL_EXIT_BPF_NO_MATCH)
|
||||||
|
};
|
||||||
|
|
||||||
|
exile_append_syscall_policy(policy, EXILE_SYS(stat),EXILE_SYSCALL_DENY_RET_ERROR, NULL,0);
|
||||||
|
exile_append_syscall_policy(policy, EXILE_SYS(open),EXILE_SYSCALL_DENY_RET_ERROR, argfilter, 2);
|
||||||
|
exile_append_syscall_policy(policy, EXILE_SYS(getpid),EXILE_SYSCALL_DENY_RET_ERROR, NULL, 0);
|
||||||
|
|
||||||
|
exile_append_syscall_default_policy(policy, EXILE_SYSCALL_ALLOW);
|
||||||
|
xexile_enable_policy(policy);
|
||||||
|
|
||||||
|
struct stat statbuf;
|
||||||
|
int s = (int) syscall(EXILE_SYS(stat), "/dev/urandom", &statbuf);
|
||||||
|
if(s != -1)
|
||||||
|
{
|
||||||
|
printf("Failed: stat was expected to fail, but returned %i\n", s);
|
||||||
|
return 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
pid_t p = (pid_t) syscall(EXILE_SYS(getpid));
|
||||||
|
if(p != -1)
|
||||||
|
{
|
||||||
|
printf("Failed: getpid was expected to fail, but returned %i\n", p);
|
||||||
|
return 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
char *t = "/dev/random";
|
||||||
|
int ret = (int) syscall(EXILE_SYS(open),t, O_WRONLY);
|
||||||
|
if(ret != -1)
|
||||||
|
{
|
||||||
|
printf("Failed: open was expected to fail, but returned %i\n", ret);
|
||||||
|
return 1;
|
||||||
|
}
|
||||||
|
ret = (int) syscall(EXILE_SYS(open), t, O_RDONLY);
|
||||||
|
if(ret == -1)
|
||||||
|
{
|
||||||
|
printf("Failed: open with O_RDONLY was expected to succeed, but returned %i\n", ret);
|
||||||
return 1;
|
return 1;
|
||||||
}
|
}
|
||||||
return 0;
|
return 0;
|
||||||
@ -300,6 +404,9 @@ struct dispatcher dispatchers[] = {
|
|||||||
{ "seccomp-require-last-matchall", &test_seccomp_require_last_matchall},
|
{ "seccomp-require-last-matchall", &test_seccomp_require_last_matchall},
|
||||||
{ "seccomp-errno", &test_seccomp_errno},
|
{ "seccomp-errno", &test_seccomp_errno},
|
||||||
{ "seccomp-group", &test_seccomp_group},
|
{ "seccomp-group", &test_seccomp_group},
|
||||||
|
{ "seccomp-argfilter-allowed", &test_seccomp_argfilter_allowed},
|
||||||
|
{ "seccomp-argfilter-filtered", &test_seccomp_argfilter_filtered},
|
||||||
|
{ "seccomp-argfilter-mixed", &test_seccomp_argfilter_mixed},
|
||||||
{ "landlock", &test_landlock},
|
{ "landlock", &test_landlock},
|
||||||
{ "landlock-deny-write", &test_landlock_deny_write },
|
{ "landlock-deny-write", &test_landlock_deny_write },
|
||||||
{ "no_fs", &test_nofs},
|
{ "no_fs", &test_nofs},
|
||||||
|
Loading…
Reference in New Issue
Block a user