Use new qssb_append_*_syscall functions, remove old fields

This commit is contained in:
Albert S. 2021-08-11 20:54:40 +02:00
parent 68694723fe
commit fa06287b13
2 changed files with 39 additions and 58 deletions

79
qssb.h
View File

@ -212,8 +212,6 @@ struct qssb_policy
/* Bind mounts all paths in path_policies into the chroot and applies /* Bind mounts all paths in path_policies into the chroot and applies
non-landlock policies */ non-landlock policies */
int mount_path_policies_to_chroot; int mount_path_policies_to_chroot;
int *blacklisted_syscalls;
int *whitelisted_syscalls;
char chroot_target_path[PATH_MAX]; char chroot_target_path[PATH_MAX];
const char *chdir_path; const char *chdir_path;
@ -283,7 +281,6 @@ int qssb_append_denied_syscalls(struct qssb_policy *qssb_policy, int *syscalls,
struct qssb_policy *qssb_init_policy() struct qssb_policy *qssb_init_policy()
{ {
struct qssb_policy *result = (struct qssb_policy *) calloc(1, sizeof(struct qssb_policy)); struct qssb_policy *result = (struct qssb_policy *) calloc(1, sizeof(struct qssb_policy));
result->blacklisted_syscalls = default_blacklisted_syscals;
result->drop_caps = 1; result->drop_caps = 1;
result->not_dumpable = 1; result->not_dumpable = 1;
result->no_new_privs = 1; result->no_new_privs = 1;
@ -632,13 +629,13 @@ static int drop_caps()
/* /*
* Enables the per_syscall seccomp action for system calls * Enables the per_syscall seccomp action for system calls
* *
* syscalls: array of system calls numbers. -1 must be the last entry. * syscalls: array of system calls numbers.
* per_syscall: action to apply for each system call * per_syscall: action to apply for each system call
* default_action: the default action at the end * default_action: the default action at the end
* *
* @returns: 0 on success, -1 on error * @returns: 0 on success, -1 on error
*/ */
static int seccomp_enable(int *syscalls, unsigned int per_syscall, unsigned int default_action) static int seccomp_enable(int *syscalls, size_t n, unsigned int per_syscall, unsigned int default_action)
{ {
struct sock_filter filter[1024] = struct sock_filter filter[1024] =
{ {
@ -646,15 +643,13 @@ static int seccomp_enable(int *syscalls, unsigned int per_syscall, unsigned int
}; };
unsigned short int current_filter_index = 1; unsigned short int current_filter_index = 1;
while(*syscalls >= 0) for(size_t i = 0; i < n; i++)
{ {
unsigned int sysc = (unsigned int) *syscalls; unsigned int sysc = (unsigned int) syscalls[i];
struct sock_filter syscall = BPF_JUMP(BPF_JMP+BPF_JEQ+BPF_K, sysc, 0, 1); struct sock_filter syscall = BPF_JUMP(BPF_JMP+BPF_JEQ+BPF_K, sysc, 0, 1);
struct sock_filter action = BPF_STMT(BPF_RET+BPF_K, per_syscall); struct sock_filter action = BPF_STMT(BPF_RET+BPF_K, per_syscall);
filter[current_filter_index++] = syscall; filter[current_filter_index++] = syscall;
filter[current_filter_index++] = action; filter[current_filter_index++] = action;
++syscalls;
} }
struct sock_filter da = BPF_STMT(BPF_RET+BPF_K, default_action); struct sock_filter da = BPF_STMT(BPF_RET+BPF_K, default_action);
@ -678,21 +673,21 @@ static int seccomp_enable(int *syscalls, unsigned int per_syscall, unsigned int
/* /*
* Blacklists the specified systemcalls. * Blacklists the specified systemcalls.
* *
* syscalls: array of system calls numbers. -1 must be the last entry. * syscalls: array of system calls numbers.
*/ */
static int seccomp_enable_blacklist(int *syscalls) static int seccomp_enable_blacklist(int *syscalls, size_t n)
{ {
return seccomp_enable(syscalls, SECCOMP_RET_KILL, SECCOMP_RET_ALLOW); return seccomp_enable(syscalls, n, SECCOMP_RET_KILL, SECCOMP_RET_ALLOW);
} }
/* /*
* Whitelists the specified systemcalls. * Whitelists the specified systemcalls.
* *
* syscalls: array of system calls numbers. -1 must be the last entry. * syscalls: array of system calls numbers.
*/ */
static int seccomp_enable_whitelist(int *syscalls) static int seccomp_enable_whitelist(int *syscalls, size_t n)
{ {
return seccomp_enable(syscalls, SECCOMP_RET_ALLOW, SECCOMP_RET_KILL); return seccomp_enable(syscalls, n, SECCOMP_RET_ALLOW, SECCOMP_RET_KILL);
} }
#if HAVE_LANDLOCK == 1 #if HAVE_LANDLOCK == 1
@ -814,9 +809,9 @@ static int landlock_prepare_ruleset(struct qssb_path_policy *policies)
/* Checks for illogical or dangerous combinations */ /* Checks for illogical or dangerous combinations */
static int check_policy_sanity(struct qssb_policy *policy) static int check_policy_sanity(struct qssb_policy *policy)
{ {
if(policy->blacklisted_syscalls != NULL && policy->whitelisted_syscalls != NULL) if(policy->denied_syscalls.used > 0 && policy->allowed_syscalls.used > 0)
{ {
QSSB_LOG_ERROR("Error: Cannot mix blacklisted and whitelisted systemcalls\n"); QSSB_LOG_ERROR("Error: Cannot mix allowed and denied systemcalls in policy\n");
return -EINVAL; return -EINVAL;
} }
@ -836,7 +831,7 @@ static int check_policy_sanity(struct qssb_policy *policy)
if(policy->no_new_privs != 1) if(policy->no_new_privs != 1)
{ {
if(policy->blacklisted_syscalls != NULL || policy->whitelisted_syscalls != NULL) if(policy->allowed_syscalls.used > 0 || policy->denied_syscalls.used > 0)
{ {
QSSB_LOG_ERROR("no_new_privs = 1 is required for seccomp filtering!\n"); QSSB_LOG_ERROR("no_new_privs = 1 is required for seccomp filtering!\n");
return -1; return -1;
@ -902,37 +897,15 @@ static int enable_no_fs(struct qssb_policy *policy)
return -1; return -1;
} }
if(policy->whitelisted_syscalls == NULL) if(policy->allowed_syscalls.used == 0)
{ {
if(policy->blacklisted_syscalls == NULL) size_t fs_access_syscalls_count = sizeof(fs_access_syscalls)/sizeof(fs_access_syscalls[0]);
{
policy->blacklisted_syscalls = fs_access_syscalls;
}
else
{
size_t nbl = 0;
size_t nfs = sizeof(fs_access_syscalls)/sizeof(fs_access_syscalls[0]);
int *tmp = policy->blacklisted_syscalls;
while(*tmp != -1)
{
++nbl;
++tmp;
}
size_t n = (nbl + nfs) + 1;
tmp = (int *) calloc(n, sizeof(int));
int *tmp_begin = tmp;
if(tmp == NULL)
{
QSSB_LOG_ERROR("Failed to expand blacklisted syscall array\n");
return -1;
}
memcpy(tmp, policy->blacklisted_syscalls, nbl*sizeof(int));
tmp+=nbl;
memcpy(tmp, fs_access_syscalls, nfs*sizeof(int));
tmp+=(nfs+1);
*tmp = -1;
policy->blacklisted_syscalls = tmp_begin; int ret = qssb_append_denied_syscalls(policy, fs_access_syscalls, fs_access_syscalls_count);
if(ret != 0)
{
QSSB_LOG_ERROR("Failed to add system calls to blacklist\n");
return -1;
} }
} }
return 0; return 0;
@ -1085,18 +1058,22 @@ int qssb_enable_policy(struct qssb_policy *policy)
close(landlock_ruleset_fd); close(landlock_ruleset_fd);
#endif #endif
if(policy->whitelisted_syscalls != NULL) if(policy->allowed_syscalls.used > 0)
{ {
if(seccomp_enable_whitelist(policy->whitelisted_syscalls) <0) int *syscalls = (int *)policy->allowed_syscalls.data;
size_t n = policy->allowed_syscalls.used / sizeof(int);
if(seccomp_enable_whitelist(syscalls, n) < 0)
{ {
QSSB_LOG_ERROR("seccomp_enable_whitelist failed\n"); QSSB_LOG_ERROR("seccomp_enable_whitelist failed\n");
return -1; return -1;
} }
} }
if(policy->blacklisted_syscalls != NULL) if(policy->denied_syscalls.used > 0)
{ {
if(seccomp_enable_blacklist(policy->blacklisted_syscalls) <0) int *syscalls = (int *)policy->denied_syscalls.data;
size_t n = policy->denied_syscalls.used / sizeof(int);
if(seccomp_enable_blacklist(syscalls, n) < 0)
{ {
QSSB_LOG_ERROR("seccomp_enable_blacklist failed\n"); QSSB_LOG_ERROR("seccomp_enable_blacklist failed\n");
return -1; return -1;

18
test.c
View File

@ -15,9 +15,11 @@ int test_default_main(int argc, char *argv[])
int test_both_syscalls(int argc, char *argv[]) int test_both_syscalls(int argc, char *argv[])
{ {
struct qssb_policy *policy = qssb_init_policy(); struct qssb_policy *policy = qssb_init_policy();
int bla[] = { 1,2,3}; int syscalls[] = {1,2,3};
policy->blacklisted_syscalls = &bla;
policy->whitelisted_syscalls = &bla; qssb_append_denied_syscalls(policy, syscalls, 3);
qssb_append_allowed_syscalls(policy, syscalls, 3);
int ret = qssb_enable_policy(policy); int ret = qssb_enable_policy(policy);
if(ret != 0) if(ret != 0)
{ {
@ -29,8 +31,9 @@ int test_both_syscalls(int argc, char *argv[])
int test_seccomp_blacklisted(int argc, char *argv[]) int test_seccomp_blacklisted(int argc, char *argv[])
{ {
struct qssb_policy *policy = qssb_init_policy(); struct qssb_policy *policy = qssb_init_policy();
int blacklisted[] = { QSSB_SYS(getuid) };
policy->blacklisted_syscalls = blacklisted; qssb_append_denied_syscall(policy, QSSB_SYS(getuid));
int ret = qssb_enable_policy(policy); int ret = qssb_enable_policy(policy);
uid_t pid = geteuid(); uid_t pid = geteuid();
pid = getuid(); pid = getuid();
@ -40,8 +43,9 @@ int test_seccomp_blacklisted(int argc, char *argv[])
int test_seccomp_blacklisted_call_permitted(int argc, char *argv[]) int test_seccomp_blacklisted_call_permitted(int argc, char *argv[])
{ {
struct qssb_policy *policy = qssb_init_policy(); struct qssb_policy *policy = qssb_init_policy();
int blacklisted[] = { QSSB_SYS(getuid) };
policy->blacklisted_syscalls = blacklisted; qssb_append_denied_syscall(policy, QSSB_SYS(getuid));
int ret = qssb_enable_policy(policy); int ret = qssb_enable_policy(policy);
//geteuid is not blacklisted, so must succeed //geteuid is not blacklisted, so must succeed
uid_t pid = geteuid(); uid_t pid = geteuid();