Use new qssb_append_*_syscall functions, remove old fields
This commit is contained in:
parent
68694723fe
commit
fa06287b13
79
qssb.h
79
qssb.h
@ -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
18
test.c
@ -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();
|
||||||
|
Loading…
Reference in New Issue
Block a user