Compare commits
No commits in common. "4824c6eaa9043878daaba7b3778338f5bf913f06" and "b2306299d5cba0fdb40c348cfc17d105078104e0" have entirely different histories.
4824c6eaa9
...
b2306299d5
309
exile.h
309
exile.h
@ -266,16 +266,6 @@ struct exile_path_policy
|
|||||||
#define EXILE_BPF_NOP \
|
#define EXILE_BPF_NOP \
|
||||||
BPF_STMT(BPF_JMP+BPF_JA,0)
|
BPF_STMT(BPF_JMP+BPF_JA,0)
|
||||||
|
|
||||||
/* A few more dirty markers to simplify array block initializers. We replace those
|
|
||||||
in append_syscall_to_bpf(). The k value is meaningless here and we don't expect
|
|
||||||
to ever have filter code actually wanting to jump that many steps forward. So
|
|
||||||
they serve as an special value we will replace with actual ones. */
|
|
||||||
#define EXILE_BPF_RETURN_MATCHING \
|
|
||||||
BPF_STMT(BPF_JMP+BPF_JA,1234)
|
|
||||||
|
|
||||||
#define EXILE_BPF_RETURN_NOT_MATCHING \
|
|
||||||
BPF_STMT(BPF_JMP+BPF_JA,5678)
|
|
||||||
|
|
||||||
#define EXILE_BPF_LOAD_SECCOMP_ARG(nr) \
|
#define EXILE_BPF_LOAD_SECCOMP_ARG(nr) \
|
||||||
BPF_STMT(BPF_LD+BPF_W+BPF_ABS, (offsetof(struct seccomp_data, args[nr])))
|
BPF_STMT(BPF_LD+BPF_W+BPF_ABS, (offsetof(struct seccomp_data, args[nr])))
|
||||||
|
|
||||||
@ -689,176 +679,198 @@ int exile_append_syscall_default_policy(struct exile_policy *exile_policy, unsig
|
|||||||
return exile_append_syscall_policy(exile_policy, EXILE_SYSCALL_MATCH_ALL, default_policy, NULL, 0);
|
return exile_append_syscall_policy(exile_policy, EXILE_SYSCALL_MATCH_ALL, default_policy, NULL, 0);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
struct exile_syscall_filter
|
|
||||||
{
|
|
||||||
uint64_t vowmask; /* Apply filter if this mask is set. 0 = ignore mask, apply always */
|
|
||||||
struct sock_filter filter;
|
|
||||||
int whenset; /* 1 = Filter should be added if vowmask is contained in pledge mask, otherwise won't be added. */
|
|
||||||
};
|
|
||||||
|
|
||||||
#define COUNT_EXILE_SYSCALL_FILTER(f) \
|
|
||||||
sizeof(f)/sizeof(f[0])
|
|
||||||
|
|
||||||
#define EXILE_SYSCALL_FILTER_LOAD_ARG(val) \
|
|
||||||
{ 0, EXILE_BPF_LOAD_SECCOMP_ARG(val), 0}
|
|
||||||
|
|
||||||
/* Returns, for the specific syscall, the correct sock_filter struct for the provided vow_promises
|
/* Returns, for the specific syscall, the correct sock_filter struct for the provided vow_promises
|
||||||
*
|
|
||||||
* Returns: 0 if none copied, otherwise the number of entries in "filter".
|
Returns: 0 if none copied, otherwise the number of entries in "filter".
|
||||||
*/
|
*/
|
||||||
|
|
||||||
static int get_vow_argfilter(long syscall, uint64_t vow_promises, struct sock_filter *filter , int *policy)
|
static int get_vow_argfilter(long syscall, uint64_t vow_promises, struct sock_filter *filter , int *policy)
|
||||||
{
|
{
|
||||||
|
|
||||||
/* How to read this:
|
/* How to read this:
|
||||||
* Keep in mind our default action is to deny, unless it's a syscall from a vow promise. Then it will be
|
* Keep in mind our default action is do deny, unless it's a syscall from an vow promise. Then it will be
|
||||||
* accepted if the argument values are good (if we care about them at all).
|
* accepted if the argument values are good (if we care about them at all).
|
||||||
* EXILE_BPF_MATCH() means the argument value is good, and the syscall can be accepted without further checks
|
* EXILE_BPF_MATCH() means the argument value is good, and the syscall can be accepted
|
||||||
* EXILE_BPF_NO_MATCH() means the syscall won't be allowed because the value is illegal
|
* EXILE_BPF_NO_MATCH() means the syscall won't be allowed because the value is illegal
|
||||||
*
|
|
||||||
* First field (vowmask): The mask to check
|
|
||||||
* Last field (whenset): If mask is set in vow_promises, then add this filter, otherwise don't.
|
|
||||||
*/
|
*/
|
||||||
|
struct sock_filter mmap_no_exec[] = {
|
||||||
|
EXILE_BPF_LOAD_SECCOMP_ARG(2),
|
||||||
|
EXILE_BPF_NO_MATCH(PROT_EXEC)
|
||||||
|
};
|
||||||
|
|
||||||
struct exile_syscall_filter mmap_filter[] = {
|
struct sock_filter ioctl_default[] = {
|
||||||
EXILE_SYSCALL_FILTER_LOAD_ARG(2),
|
EXILE_BPF_LOAD_SECCOMP_ARG(1),
|
||||||
{ EXILE_SYSCALL_VOW_PROT_EXEC, EXILE_BPF_NO_MATCH_SET(PROT_EXEC), 0},
|
EXILE_BPF_MATCH(FIONREAD),
|
||||||
|
EXILE_BPF_MATCH(FIONBIO),
|
||||||
|
EXILE_BPF_MATCH(FIOCLEX),
|
||||||
|
EXILE_BPF_CMP_EQ(FIONCLEX, EXILE_SYSCALL_EXIT_BPF_RETURN, EXILE_SYSCALL_EXIT_BPF_NO_MATCH)
|
||||||
|
};
|
||||||
|
|
||||||
|
/* open() and friends with read-only flags */
|
||||||
|
struct sock_filter open_rdonly[] = {
|
||||||
|
EXILE_BPF_LOAD_SECCOMP_ARG(1),
|
||||||
|
EXILE_BPF_NO_MATCH_SET(O_CREAT),
|
||||||
|
EXILE_BPF_NO_MATCH_SET(O_TMPFILE),
|
||||||
|
EXILE_BPF_NO_MATCH_SET(O_WRONLY),
|
||||||
|
EXILE_BPF_NO_MATCH_SET(O_RDWR),
|
||||||
|
EXILE_BPF_NO_MATCH_SET(O_APPEND),
|
||||||
|
};
|
||||||
|
|
||||||
|
struct sock_filter socket_filter[4] = {
|
||||||
|
EXILE_BPF_LOAD_SECCOMP_ARG(0),
|
||||||
|
EXILE_BPF_NOP,
|
||||||
|
EXILE_BPF_NOP,
|
||||||
|
EXILE_BPF_NOP
|
||||||
|
};
|
||||||
|
|
||||||
|
struct sock_filter setsockopt_filter[] = {
|
||||||
|
EXILE_BPF_LOAD_SECCOMP_ARG(2),
|
||||||
|
EXILE_BPF_NO_MATCH(SO_DEBUG),
|
||||||
|
EXILE_BPF_NO_MATCH(SO_SNDBUFFORCE)
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
||||||
struct exile_syscall_filter ioctl_filter[] = {
|
struct sock_filter clone_filter[] = {
|
||||||
EXILE_SYSCALL_FILTER_LOAD_ARG(1),
|
/* It's the first argument for x86_64 */
|
||||||
{ EXILE_SYSCALL_VOW_IOCTL, EXILE_BPF_RETURN_MATCHING, 1 },
|
EXILE_BPF_LOAD_SECCOMP_ARG(0),
|
||||||
{ EXILE_SYSCALL_VOW_STDIO, EXILE_BPF_MATCH(FIONREAD), 1},
|
EXILE_BPF_CMP_SET(CLONE_VM, 0, EXILE_SYSCALL_EXIT_BPF_NO_MATCH),
|
||||||
{ EXILE_SYSCALL_VOW_STDIO, EXILE_BPF_MATCH(FIONBIO), 1},
|
EXILE_BPF_CMP_SET(CLONE_THREAD, 0, EXILE_SYSCALL_EXIT_BPF_NO_MATCH),
|
||||||
{ EXILE_SYSCALL_VOW_STDIO, EXILE_BPF_MATCH(FIONREAD), 1},
|
EXILE_BPF_NO_MATCH_SET(CLONE_NEWCGROUP),
|
||||||
{ EXILE_SYSCALL_VOW_STDIO, EXILE_BPF_MATCH(FIOCLEX), 1},
|
EXILE_BPF_NO_MATCH_SET(CLONE_NEWIPC),
|
||||||
{ EXILE_SYSCALL_VOW_STDIO, EXILE_BPF_MATCH(FIONCLEX), 1},
|
EXILE_BPF_NO_MATCH_SET(CLONE_NEWNET),
|
||||||
{ EXILE_SYSCALL_VOW_STDIO, EXILE_BPF_RETURN_NOT_MATCHING, 1}
|
EXILE_BPF_NO_MATCH_SET(CLONE_NEWNS),
|
||||||
|
EXILE_BPF_NO_MATCH_SET(CLONE_NEWPID),
|
||||||
|
EXILE_BPF_NO_MATCH_SET(CLONE_NEWUSER),
|
||||||
|
EXILE_BPF_NO_MATCH_SET(CLONE_NEWUTS),
|
||||||
};
|
};
|
||||||
|
|
||||||
struct exile_syscall_filter open_filter[] = {
|
struct sock_filter prctl_default[] ={
|
||||||
EXILE_SYSCALL_FILTER_LOAD_ARG(1),
|
EXILE_BPF_LOAD_SECCOMP_ARG(0),
|
||||||
{ EXILE_SYSCALL_VOW_CPATH, EXILE_BPF_NO_MATCH_SET(O_CREAT), 0 },
|
EXILE_BPF_MATCH(PR_SET_NO_NEW_PRIVS),
|
||||||
{ EXILE_SYSCALL_VOW_WPATH, EXILE_BPF_NO_MATCH_SET(O_TMPFILE),0 },
|
EXILE_BPF_MATCH(PR_GET_NO_NEW_PRIVS),
|
||||||
{ EXILE_SYSCALL_VOW_WPATH, EXILE_BPF_NO_MATCH_SET(O_WRONLY),0 },
|
EXILE_BPF_MATCH(PR_GET_NAME),
|
||||||
{ EXILE_SYSCALL_VOW_WPATH, EXILE_BPF_NO_MATCH_SET(O_RDWR),0 },
|
EXILE_BPF_MATCH(PR_SET_NAME),
|
||||||
{ EXILE_SYSCALL_VOW_WPATH, EXILE_BPF_NO_MATCH_SET(O_APPEND),0 },
|
EXILE_BPF_CMP_EQ(PR_CAPBSET_READ, EXILE_SYSCALL_EXIT_BPF_RETURN, EXILE_SYSCALL_EXIT_BPF_NO_MATCH),
|
||||||
};
|
};
|
||||||
|
|
||||||
struct exile_syscall_filter socket_filter[] = {
|
|
||||||
EXILE_SYSCALL_FILTER_LOAD_ARG(0),
|
|
||||||
{ EXILE_SYSCALL_VOW_UNIX, EXILE_BPF_MATCH(AF_UNIX), 1 },
|
|
||||||
{ EXILE_SYSCALL_VOW_INET, EXILE_BPF_MATCH(AF_INET), 1 },
|
|
||||||
{ EXILE_SYSCALL_VOW_INET, EXILE_BPF_MATCH(AF_INET6), 1 },
|
|
||||||
{ 0, EXILE_BPF_RETURN_NOT_MATCHING, 0}
|
|
||||||
};
|
|
||||||
|
|
||||||
struct exile_syscall_filter setsockopt_filter[] = {
|
|
||||||
EXILE_SYSCALL_FILTER_LOAD_ARG(2),
|
|
||||||
{ 0, EXILE_BPF_NO_MATCH(SO_DEBUG), 0 },
|
|
||||||
{ 0, EXILE_BPF_NO_MATCH(SO_SNDBUFFORCE), 0 }
|
|
||||||
};
|
|
||||||
|
|
||||||
|
|
||||||
struct exile_syscall_filter clone_filter[] = {
|
|
||||||
/* It's the first (0) argument for x86_64 */
|
|
||||||
EXILE_SYSCALL_FILTER_LOAD_ARG(0),
|
|
||||||
{ EXILE_SYSCALL_VOW_CLONE, EXILE_BPF_RETURN_MATCHING, 1 },
|
|
||||||
{ EXILE_SYSCALL_VOW_THREAD, EXILE_BPF_CMP_SET(CLONE_VM, 0, EXILE_SYSCALL_EXIT_BPF_NO_MATCH), 1},
|
|
||||||
{ EXILE_SYSCALL_VOW_THREAD, EXILE_BPF_CMP_SET(CLONE_THREAD, 0, EXILE_SYSCALL_EXIT_BPF_NO_MATCH), 1},
|
|
||||||
{ 0, EXILE_BPF_NO_MATCH_SET(CLONE_NEWCGROUP), 0},
|
|
||||||
{ 0, EXILE_BPF_NO_MATCH_SET(CLONE_NEWIPC),0},
|
|
||||||
{ 0, EXILE_BPF_NO_MATCH_SET(CLONE_NEWNET),0},
|
|
||||||
{ 0, EXILE_BPF_NO_MATCH_SET(CLONE_NEWNS),0},
|
|
||||||
{ 0, EXILE_BPF_NO_MATCH_SET(CLONE_NEWPID),0},
|
|
||||||
{ 0, EXILE_BPF_NO_MATCH_SET(CLONE_NEWUSER),0},
|
|
||||||
{ 0, EXILE_BPF_NO_MATCH_SET(CLONE_NEWUTS),0},
|
|
||||||
};
|
|
||||||
|
|
||||||
|
|
||||||
struct exile_syscall_filter prctl_filter[] ={
|
|
||||||
EXILE_SYSCALL_FILTER_LOAD_ARG(0),
|
|
||||||
{ EXILE_SYSCALL_VOW_PRCTL, EXILE_BPF_RETURN_MATCHING, 1},
|
|
||||||
{ EXILE_SYSCALL_VOW_SECCOMP_INSTALL, EXILE_BPF_MATCH(PR_SET_SECCOMP), 1 },
|
|
||||||
{ EXILE_SYSCALL_VOW_STDIO, EXILE_BPF_MATCH(PR_SET_NO_NEW_PRIVS),1},
|
|
||||||
{ EXILE_SYSCALL_VOW_STDIO, EXILE_BPF_MATCH(PR_GET_NO_NEW_PRIVS),1},
|
|
||||||
{ EXILE_SYSCALL_VOW_STDIO, EXILE_BPF_MATCH(PR_GET_NAME),1},
|
|
||||||
{ EXILE_SYSCALL_VOW_STDIO, EXILE_BPF_MATCH(PR_SET_NAME),1},
|
|
||||||
{ EXILE_SYSCALL_VOW_STDIO, EXILE_BPF_MATCH(PR_CAPBSET_READ), 1},
|
|
||||||
{ 0, EXILE_BPF_RETURN_NOT_MATCHING, 0}
|
|
||||||
};
|
|
||||||
|
|
||||||
struct exile_syscall_filter *current_filter = NULL;
|
|
||||||
size_t current_count = 0;
|
|
||||||
|
|
||||||
*policy = EXILE_SYSCALL_ALLOW;
|
*policy = EXILE_SYSCALL_ALLOW;
|
||||||
|
int result = 0;
|
||||||
|
int current_filter_index = 1;
|
||||||
switch(syscall)
|
switch(syscall)
|
||||||
{
|
{
|
||||||
case EXILE_SYS(mmap):
|
case EXILE_SYS(mmap):
|
||||||
case EXILE_SYS(mprotect):
|
case EXILE_SYS(mprotect):
|
||||||
current_filter = mmap_filter;
|
if(vow_promises & EXILE_SYSCALL_VOW_PROT_EXEC)
|
||||||
current_count = COUNT_EXILE_SYSCALL_FILTER(mmap_filter);
|
{
|
||||||
|
/* If prot exec is allowed, there is no need to filter anything here */
|
||||||
|
result = 0;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
if(vow_promises & EXILE_SYSCALL_VOW_STDIO)
|
||||||
|
{
|
||||||
|
result = sizeof(mmap_no_exec)/sizeof(mmap_no_exec[0]);
|
||||||
|
memcpy(filter, mmap_no_exec, sizeof(mmap_no_exec));
|
||||||
|
}
|
||||||
break;
|
break;
|
||||||
case EXILE_SYS(ioctl):
|
case EXILE_SYS(ioctl):
|
||||||
current_filter = ioctl_filter;
|
if(vow_promises & EXILE_SYSCALL_VOW_IOCTL)
|
||||||
current_count = COUNT_EXILE_SYSCALL_FILTER(ioctl_filter);
|
{
|
||||||
|
result = 0;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
if(vow_promises & EXILE_SYSCALL_VOW_STDIO)
|
||||||
|
{
|
||||||
|
result = sizeof(ioctl_default)/sizeof(ioctl_default[0]);
|
||||||
|
memcpy(filter, ioctl_default, sizeof(ioctl_default));
|
||||||
|
}
|
||||||
break;
|
break;
|
||||||
case EXILE_SYS(open):
|
case EXILE_SYS(open):
|
||||||
case EXILE_SYS(openat):
|
case EXILE_SYS(openat):
|
||||||
case EXILE_SYS(open_by_handle_at):
|
case EXILE_SYS(open_by_handle_at):
|
||||||
|
/* TODO: This is still a mess with all those combinations.
|
||||||
|
We should think of something better */
|
||||||
if(syscall == EXILE_SYS(openat) || syscall == EXILE_SYS(open_by_handle_at))
|
if(syscall == EXILE_SYS(openat) || syscall == EXILE_SYS(open_by_handle_at))
|
||||||
{
|
{
|
||||||
/* for openat, it's the third arg */
|
/* for openat, it's the third arg */
|
||||||
open_filter[0] = (struct exile_syscall_filter) EXILE_SYSCALL_FILTER_LOAD_ARG(2);
|
open_rdonly[0].k = offsetof(struct seccomp_data, args[2]);
|
||||||
}
|
}
|
||||||
current_filter = open_filter;
|
/* The combination of those three implies no filtering of open args */
|
||||||
current_count = COUNT_EXILE_SYSCALL_FILTER(open_filter);
|
if((vow_promises & (EXILE_SYSCALL_VOW_CPATH|EXILE_SYSCALL_VOW_RPATH|EXILE_SYSCALL_VOW_WPATH)) == (EXILE_SYSCALL_VOW_CPATH|EXILE_SYSCALL_VOW_RPATH|EXILE_SYSCALL_VOW_WPATH))
|
||||||
|
{
|
||||||
|
result = 0;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
/* If cpath is legal, don't filter O_CREAT */
|
||||||
|
if(vow_promises & EXILE_SYSCALL_VOW_CPATH)
|
||||||
|
{
|
||||||
|
open_rdonly[1] = (struct sock_filter) EXILE_BPF_NOP;
|
||||||
|
}
|
||||||
|
if(vow_promises & EXILE_SYSCALL_VOW_WPATH)
|
||||||
|
{
|
||||||
|
open_rdonly[2] = (struct sock_filter) EXILE_BPF_NOP;
|
||||||
|
open_rdonly[3] = (struct sock_filter) EXILE_BPF_NOP;
|
||||||
|
open_rdonly[4] = (struct sock_filter) EXILE_BPF_NOP;
|
||||||
|
open_rdonly[5] = (struct sock_filter) EXILE_BPF_NOP;
|
||||||
|
}
|
||||||
|
result = sizeof(open_rdonly)/sizeof(open_rdonly[0]);
|
||||||
|
memcpy(filter, open_rdonly, sizeof(open_rdonly));
|
||||||
break;
|
break;
|
||||||
case EXILE_SYS(openat2):
|
case EXILE_SYS(openat2):
|
||||||
|
result = 0;
|
||||||
*policy = EXILE_SYSCALL_DENY_RET_ERROR;
|
*policy = EXILE_SYSCALL_DENY_RET_ERROR;
|
||||||
return 0;
|
|
||||||
break;
|
break;
|
||||||
case EXILE_SYS(socket):
|
case EXILE_SYS(socket):
|
||||||
current_filter = socket_filter;
|
if(vow_promises & EXILE_SYSCALL_VOW_UNIX)
|
||||||
current_count = COUNT_EXILE_SYSCALL_FILTER(socket_filter);
|
{
|
||||||
|
socket_filter[current_filter_index] = (struct sock_filter) EXILE_BPF_MATCH(AF_UNIX);
|
||||||
|
++current_filter_index;
|
||||||
|
}
|
||||||
|
if(vow_promises & EXILE_SYSCALL_VOW_INET)
|
||||||
|
{
|
||||||
|
socket_filter[current_filter_index] = (struct sock_filter) EXILE_BPF_MATCH(AF_INET);
|
||||||
|
++current_filter_index;
|
||||||
|
socket_filter[current_filter_index] = (struct sock_filter) EXILE_BPF_MATCH(AF_INET6);
|
||||||
|
++current_filter_index;
|
||||||
|
}
|
||||||
|
socket_filter[current_filter_index-1].jf = EXILE_SYSCALL_EXIT_BPF_NO_MATCH;
|
||||||
|
result = current_filter_index;
|
||||||
|
memcpy(filter, socket_filter, result * sizeof(struct sock_filter));
|
||||||
break;
|
break;
|
||||||
case EXILE_SYS(setsockopt):
|
case EXILE_SYS(setsockopt):
|
||||||
current_filter = setsockopt_filter;
|
result = sizeof(setsockopt_filter)/sizeof(setsockopt_filter[0]);
|
||||||
current_count = COUNT_EXILE_SYSCALL_FILTER(setsockopt_filter);
|
memcpy(filter, setsockopt_filter, sizeof(setsockopt_filter));
|
||||||
break;
|
break;
|
||||||
case EXILE_SYS(clone):
|
case EXILE_SYS(clone):
|
||||||
current_filter = clone_filter;
|
if(vow_promises & EXILE_SYSCALL_VOW_CLONE)
|
||||||
current_count = COUNT_EXILE_SYSCALL_FILTER(clone_filter);
|
{
|
||||||
|
result = 0;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
result = sizeof(clone_filter)/sizeof(clone_filter[0]);
|
||||||
|
memcpy(filter, clone_filter, sizeof(clone_filter));
|
||||||
break;
|
break;
|
||||||
case EXILE_SYS(clone3):
|
case EXILE_SYS(clone3):
|
||||||
if((vow_promises & EXILE_SYSCALL_VOW_CLONE) == 0)
|
if((vow_promises & EXILE_SYSCALL_VOW_CLONE) == 0)
|
||||||
{
|
{
|
||||||
|
result = 0;
|
||||||
*policy = EXILE_SYSCALL_DENY_RET_ERROR;
|
*policy = EXILE_SYSCALL_DENY_RET_ERROR;
|
||||||
return 0;
|
|
||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
case EXILE_SYS(prctl):
|
case EXILE_SYS(prctl):
|
||||||
current_filter = prctl_filter;
|
if(vow_promises & EXILE_SYSCALL_VOW_PRCTL)
|
||||||
current_count = COUNT_EXILE_SYSCALL_FILTER(prctl_filter);
|
{
|
||||||
|
result = 0;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
if(vow_promises & EXILE_SYSCALL_VOW_SECCOMP_INSTALL)
|
||||||
|
{
|
||||||
|
prctl_default[3] = (struct sock_filter) EXILE_BPF_MATCH(PR_SET_SECCOMP);
|
||||||
|
}
|
||||||
|
result = sizeof(prctl_default)/sizeof(prctl_default[0]);
|
||||||
|
memcpy(filter, prctl_default, sizeof(prctl_default));
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
return result;
|
||||||
int out_filter_index = 0;
|
|
||||||
for(size_t i = 0; i < current_count; i++)
|
|
||||||
{
|
|
||||||
struct exile_syscall_filter *c = ¤t_filter[i];
|
|
||||||
int set = 0;
|
|
||||||
if(c->vowmask & vow_promises)
|
|
||||||
{
|
|
||||||
set = 1;
|
|
||||||
}
|
|
||||||
if(c->whenset == set || c->vowmask == 0)
|
|
||||||
{
|
|
||||||
filter[out_filter_index++] = c->filter;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
return out_filter_index;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
int exile_append_vow_promises(struct exile_policy *policy, uint64_t vow_promises)
|
int exile_append_vow_promises(struct exile_policy *policy, uint64_t vow_promises)
|
||||||
@ -878,6 +890,7 @@ int exile_append_vow_promises(struct exile_policy *policy, uint64_t vow_promises
|
|||||||
EXILE_LOG_ERROR("Failed adding syscall policy from vow while processing %li\n", syscall);
|
EXILE_LOG_ERROR("Failed adding syscall policy from vow while processing %li\n", syscall);
|
||||||
return ret;
|
return ret;
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
int vow_policy = (vow_promises & EXILE_SYSCALL_VOW_DENY_ERROR) ? EXILE_SYSCALL_DENY_RET_ERROR : EXILE_SYSCALL_DENY_KILL_PROCESS;
|
int vow_policy = (vow_promises & EXILE_SYSCALL_VOW_DENY_ERROR) ? EXILE_SYSCALL_DENY_RET_ERROR : EXILE_SYSCALL_DENY_KILL_PROCESS;
|
||||||
@ -1323,38 +1336,26 @@ static void append_syscall_to_bpf(struct exile_syscall_policy *syscallpolicy, st
|
|||||||
filter[(*start_index)++] = syscall_check;
|
filter[(*start_index)++] = syscall_check;
|
||||||
--next_syscall_pc;
|
--next_syscall_pc;
|
||||||
|
|
||||||
struct sock_filter return_matching = EXILE_BPF_RETURN_MATCHING;
|
|
||||||
struct sock_filter return_not_matching = EXILE_BPF_RETURN_NOT_MATCHING;
|
|
||||||
|
|
||||||
for(size_t i = 0; i < syscallpolicy->argfilterscount; i++)
|
for(size_t i = 0; i < syscallpolicy->argfilterscount; i++)
|
||||||
{
|
{
|
||||||
filter[*start_index] = syscallpolicy->argfilters[i];
|
filter[*start_index] = syscallpolicy->argfilters[i];
|
||||||
struct sock_filter *current = &filter[*start_index];
|
|
||||||
__u8 jump_count_next_syscall = next_syscall_pc;
|
__u8 jump_count_next_syscall = next_syscall_pc;
|
||||||
__u8 jump_count_return = jump_count_next_syscall - 1;
|
__u8 jump_count_return = jump_count_next_syscall - 1;
|
||||||
if(current->jt == EXILE_SYSCALL_EXIT_BPF_NO_MATCH)
|
if(filter[*start_index].jt == EXILE_SYSCALL_EXIT_BPF_NO_MATCH)
|
||||||
{
|
{
|
||||||
current->jt = jump_count_next_syscall;
|
filter[*start_index].jt = jump_count_next_syscall;
|
||||||
}
|
}
|
||||||
if(current->jt == EXILE_SYSCALL_EXIT_BPF_RETURN)
|
if(filter[*start_index].jt == EXILE_SYSCALL_EXIT_BPF_RETURN)
|
||||||
{
|
{
|
||||||
current->jt = jump_count_return;
|
filter[*start_index].jt = jump_count_return;
|
||||||
}
|
}
|
||||||
if(current->jf == EXILE_SYSCALL_EXIT_BPF_NO_MATCH)
|
if(filter[*start_index].jf == EXILE_SYSCALL_EXIT_BPF_NO_MATCH)
|
||||||
{
|
{
|
||||||
current->jf = jump_count_next_syscall;
|
filter[*start_index].jf = jump_count_next_syscall;
|
||||||
}
|
}
|
||||||
if(current->jf == EXILE_SYSCALL_EXIT_BPF_RETURN)
|
if(filter[*start_index].jf == EXILE_SYSCALL_EXIT_BPF_RETURN)
|
||||||
{
|
{
|
||||||
current->jf = jump_count_return;
|
filter[*start_index].jf = jump_count_return;
|
||||||
}
|
|
||||||
if(current->code == return_matching.code && current->k == return_matching.k)
|
|
||||||
{
|
|
||||||
current->k = jump_count_return;
|
|
||||||
}
|
|
||||||
if(current->code == return_not_matching.code && current->k == return_not_matching.k)
|
|
||||||
{
|
|
||||||
current->k = jump_count_next_syscall;
|
|
||||||
}
|
}
|
||||||
--next_syscall_pc;
|
--next_syscall_pc;
|
||||||
++*start_index;
|
++*start_index;
|
||||||
@ -1546,18 +1547,18 @@ static int check_policy_sanity(struct exile_policy *policy)
|
|||||||
}
|
}
|
||||||
|
|
||||||
int can_use_landlock = exile_landlock_is_available();
|
int can_use_landlock = exile_landlock_is_available();
|
||||||
if(!can_use_landlock)
|
struct exile_path_policy *path_policy = policy->path_policies;
|
||||||
|
while(path_policy)
|
||||||
{
|
{
|
||||||
struct exile_path_policy *path_policy = policy->path_policies;
|
if(path_policy_needs_landlock(path_policy))
|
||||||
while(path_policy)
|
|
||||||
{
|
{
|
||||||
if(path_policy_needs_landlock(path_policy))
|
if(!can_use_landlock)
|
||||||
{
|
{
|
||||||
EXILE_LOG_ERROR("Error: A path policy needs landlock, but landlock is not available. Fallback not possible\n");
|
EXILE_LOG_ERROR("Error: A path policy needs landlock, but landlock is not available. Fallback not possible\n");
|
||||||
return -1;
|
return -1;
|
||||||
}
|
}
|
||||||
path_policy = path_policy->next;
|
|
||||||
}
|
}
|
||||||
|
path_policy = path_policy->next;
|
||||||
}
|
}
|
||||||
|
|
||||||
/* TODO: check if we have ALLOWED, but no default deny */
|
/* TODO: check if we have ALLOWED, but no default deny */
|
||||||
|
Loading…
Reference in New Issue
Block a user