Introduce flags indicating errors to catch non-checked return codes

Certain functions can fail before we execute exile_enable_policy().

While the return code should be checked, it's easily forgotten. For
most users, checking just the exile_enable_policy() return code
should suffice.

exile_append_path_policies(): Add check whether a path exists. If not,
set the error flag.

This also allows an early exit, allowing to cleanly handle the case
when a path does not exist. Previously, this was only caught
during activation, and a failure there is generally undefined.
This commit is contained in:
Albert S. 2022-01-08 16:39:12 +01:00
parent fd4dfb12f0
commit 3780509078
2 changed files with 35 additions and 0 deletions

22
exile.h
View File

@ -328,6 +328,11 @@ is thus up to the default policy */
#define EXILE_ARGFILTERS_COUNT 60 #define EXILE_ARGFILTERS_COUNT 60
#define EXILE_FLAG_ADD_PATH_POLICY_FAIL (1u<<1)
#define EXILE_FLAG_ADD_SYSCALL_POLICY_FAIL (1u<<2)
struct exile_syscall_policy struct exile_syscall_policy
{ {
struct sock_filter argfilters[EXILE_ARGFILTERS_COUNT]; struct sock_filter argfilters[EXILE_ARGFILTERS_COUNT];
@ -364,6 +369,7 @@ struct exile_policy
struct exile_syscall_policy *syscall_policies; struct exile_syscall_policy *syscall_policies;
struct exile_syscall_policy **syscall_policies_tail; struct exile_syscall_policy **syscall_policies_tail;
uint32_t exile_flags;
}; };
@ -662,6 +668,7 @@ int exile_append_syscall_policy(struct exile_policy *exile_policy, long syscall,
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");
exile_policy->exile_flags |= EXILE_FLAG_ADD_SYSCALL_POLICY_FAIL;
return -1; return -1;
} }
newpolicy->policy = syscall_policy; newpolicy->policy = syscall_policy;
@ -670,6 +677,7 @@ int exile_append_syscall_policy(struct exile_policy *exile_policy, long syscall,
if(n > EXILE_ARGFILTERS_COUNT) if(n > EXILE_ARGFILTERS_COUNT)
{ {
EXILE_LOG_ERROR("Too many argfilters supplied\n"); EXILE_LOG_ERROR("Too many argfilters supplied\n");
exile_policy->exile_flags |= EXILE_FLAG_ADD_SYSCALL_POLICY_FAIL;
return -1; return -1;
} }
for(size_t i = 0; i < n; i++) for(size_t i = 0; i < n; i++)
@ -939,10 +947,19 @@ int exile_append_path_policies(struct exile_policy *exile_policy, unsigned int p
path = va_arg(args, char*); path = va_arg(args, char*);
while(path != NULL) while(path != NULL)
{ {
int fd = open(path, O_PATH);
if(fd == -1)
{
EXILE_LOG_ERROR("Failed to open the specified path: %s\n", strerror(errno));
exile_policy->exile_flags |= EXILE_FLAG_ADD_PATH_POLICY_FAIL;
return -1;
}
close(fd);
struct exile_path_policy *newpolicy = (struct exile_path_policy *) calloc(1, sizeof(struct exile_path_policy)); struct exile_path_policy *newpolicy = (struct exile_path_policy *) calloc(1, sizeof(struct exile_path_policy));
if(newpolicy == NULL) if(newpolicy == NULL)
{ {
EXILE_LOG_ERROR("Failed to allocate memory for path policy\n"); EXILE_LOG_ERROR("Failed to allocate memory for path policy\n");
exile_policy->exile_flags |= EXILE_FLAG_ADD_PATH_POLICY_FAIL;
return -1; return -1;
} }
newpolicy->path = path; newpolicy->path = path;
@ -1763,6 +1780,11 @@ static int enable_no_fs(struct exile_policy *policy)
*/ */
int exile_enable_policy(struct exile_policy *policy) int exile_enable_policy(struct exile_policy *policy)
{ {
if((policy->exile_flags & EXILE_FLAG_ADD_PATH_POLICY_FAIL) || (policy->exile_flags & EXILE_FLAG_ADD_SYSCALL_POLICY_FAIL))
{
EXILE_LOG_ERROR("Error: At least one syscall or path policy was not successfully added!\n");
return -1;
}
if(check_policy_sanity(policy) != 0) if(check_policy_sanity(policy) != 0)
{ {
EXILE_LOG_ERROR("Error: Policy sanity check failed. Cannot apply policy!\n"); EXILE_LOG_ERROR("Error: Policy sanity check failed. Cannot apply policy!\n");

13
test.c
View File

@ -530,6 +530,18 @@ int test_mkpath()
return 0; return 0;
} }
int test_fail_flags()
{
struct exile_policy *policy = exile_init_policy();
exile_append_path_policy(policy, EXILE_FS_ALLOW_ALL_READ, "/nosuchpathexists");
int ret = exile_enable_policy(policy);
if(ret == 0)
{
fprintf(stderr, "Failed: A path that does not exist should have set the error flag %i\n", ret);
return 1;
}
return 0;
}
struct dispatcher struct dispatcher
{ {
@ -554,6 +566,7 @@ struct dispatcher dispatchers[] = {
{ "no_fs", &test_nofs}, { "no_fs", &test_nofs},
{ "no_new_fds", &test_no_new_fds}, { "no_new_fds", &test_no_new_fds},
{ "mkpath", &test_mkpath}, { "mkpath", &test_mkpath},
{ "failflags", &test_fail_flags},
}; };
int main(int argc, char *argv[]) int main(int argc, char *argv[])