chroot: Create all paths first, then mount
We mounted after creating dirs, this was potentially problematic for the next path policy to follow. Perform two passes on the path_policies list, first creates all dirs, second does the mounts.
This commit is contained in:
parent
3b61e90761
commit
a9e6b3ee67
85
exile.h
85
exile.h
@ -1092,28 +1092,39 @@ static int path_policy_needs_landlock(struct exile_path_policy *path_policy)
|
|||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/* TODO: we can do va_args */
|
||||||
|
char *concat_path(const char *first, const char *second)
|
||||||
|
{
|
||||||
|
char *result = (char *) calloc(1, PATH_MAX);
|
||||||
|
if(result == NULL)
|
||||||
|
{
|
||||||
|
EXILE_LOG_ERROR("exile: concat_path: calloc failed\n");
|
||||||
|
return NULL;
|
||||||
|
}
|
||||||
|
//TODO: We can strip multiple redundant slashes
|
||||||
|
int written = snprintf(result, PATH_MAX, "%s/%s", first, second);
|
||||||
|
if(written < 0)
|
||||||
|
{
|
||||||
|
EXILE_LOG_ERROR("exile: concat_path: Error during path concatination\n");
|
||||||
|
return NULL;
|
||||||
|
}
|
||||||
|
if(written >= PATH_MAX)
|
||||||
|
{
|
||||||
|
EXILE_LOG_ERROR("exile: mount_to_chroot: path concatination truncated\n");
|
||||||
|
return NULL;
|
||||||
|
}
|
||||||
|
return result;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
/* Helper to mount directories into the chroot path "chroot_target_path"
|
/* Helper to mount directories into the chroot path "chroot_target_path"
|
||||||
* Paths will be created if necessary
|
* Paths will be created if necessary
|
||||||
|
|
||||||
* @returns: 0 on sucess, -ERRNO on failure */
|
* @returns: 0 on sucess, -ERRNO on failure */
|
||||||
static int mount_to_chroot(const char *chroot_target_path, struct exile_path_policy *path_policy)
|
static int create_chroot_dirs(const char *chroot_target_path, struct exile_path_policy *path_policy)
|
||||||
{
|
{
|
||||||
while(path_policy != NULL)
|
while(path_policy != NULL)
|
||||||
{
|
{
|
||||||
|
|
||||||
char path_inside_chroot[PATH_MAX];
|
|
||||||
int written = snprintf(path_inside_chroot, sizeof(path_inside_chroot), "%s/%s", chroot_target_path, path_policy->path);
|
|
||||||
if(written < 0)
|
|
||||||
{
|
|
||||||
EXILE_LOG_ERROR("exile: mount_to_chroot: Error during path concatination\n");
|
|
||||||
return -EINVAL;
|
|
||||||
}
|
|
||||||
if(written >= PATH_MAX)
|
|
||||||
{
|
|
||||||
EXILE_LOG_ERROR("exile: mount_to_chroot: path concatination truncated\n");
|
|
||||||
return -EINVAL;
|
|
||||||
}
|
|
||||||
|
|
||||||
struct stat sb;
|
struct stat sb;
|
||||||
int ret = stat(path_policy->path, &sb);
|
int ret = stat(path_policy->path, &sb);
|
||||||
if(ret < 0)
|
if(ret < 0)
|
||||||
@ -1121,31 +1132,54 @@ static int mount_to_chroot(const char *chroot_target_path, struct exile_path_pol
|
|||||||
EXILE_LOG_ERROR("mount_to_chroot(): stat failed\n");
|
EXILE_LOG_ERROR("mount_to_chroot(): stat failed\n");
|
||||||
return ret;
|
return ret;
|
||||||
}
|
}
|
||||||
|
|
||||||
int baseisfile = 0;
|
int baseisfile = 0;
|
||||||
if(S_ISREG(sb.st_mode))
|
if(S_ISREG(sb.st_mode))
|
||||||
{
|
{
|
||||||
baseisfile = 1;
|
baseisfile = 1;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
char *path_inside_chroot = concat_path(chroot_target_path, path_policy->path);
|
||||||
|
if(path_inside_chroot == NULL)
|
||||||
|
{
|
||||||
|
return 1;
|
||||||
|
}
|
||||||
|
|
||||||
ret = mkpath(path_inside_chroot, 0700, baseisfile);
|
ret = mkpath(path_inside_chroot, 0700, baseisfile);
|
||||||
if(ret < 0)
|
if(ret < 0)
|
||||||
{
|
{
|
||||||
EXILE_LOG_ERROR("Error creating directory structure while mounting paths to chroot. %s\n", strerror(errno));
|
EXILE_LOG_ERROR("Error creating directory structure while mounting paths to chroot. %s\n", strerror(errno));
|
||||||
|
free(path_inside_chroot);
|
||||||
return ret;
|
return ret;
|
||||||
}
|
}
|
||||||
|
path_policy = path_policy->next;
|
||||||
|
free(path_inside_chroot);
|
||||||
|
}
|
||||||
|
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
static int perform_mounts(const char *chroot_target_path, struct exile_path_policy *path_policy)
|
||||||
|
{
|
||||||
|
while(path_policy != NULL)
|
||||||
|
{
|
||||||
int mount_flags = get_policy_mount_flags(path_policy);
|
int mount_flags = get_policy_mount_flags(path_policy);
|
||||||
|
|
||||||
|
char *path_inside_chroot = concat_path(chroot_target_path, path_policy->path);
|
||||||
|
if(path_inside_chroot == NULL)
|
||||||
|
{
|
||||||
|
return 1;
|
||||||
|
}
|
||||||
//all we do is bind mounts
|
//all we do is bind mounts
|
||||||
mount_flags |= MS_BIND;
|
mount_flags |= MS_BIND;
|
||||||
|
|
||||||
|
|
||||||
if(path_policy->policy & EXILE_FS_ALLOW_ALL_READ || path_policy->policy & EXILE_FS_ALLOW_ALL_WRITE)
|
if(path_policy->policy & EXILE_FS_ALLOW_ALL_READ || path_policy->policy & EXILE_FS_ALLOW_ALL_WRITE)
|
||||||
{
|
{
|
||||||
ret = mount(path_policy->path, path_inside_chroot, NULL, mount_flags, NULL);
|
int ret = mount(path_policy->path, path_inside_chroot, NULL, mount_flags, NULL);
|
||||||
if(ret < 0 )
|
if(ret < 0 )
|
||||||
{
|
{
|
||||||
EXILE_LOG_ERROR("Error: Failed to mount %s to %s: %s\n", path_policy->path, path_inside_chroot, strerror(errno));
|
EXILE_LOG_ERROR("Error: Failed to mount %s to %s: %s\n", path_policy->path, path_inside_chroot, strerror(errno));
|
||||||
|
free(path_inside_chroot);
|
||||||
return ret;
|
return ret;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -1154,15 +1188,18 @@ static int mount_to_chroot(const char *chroot_target_path, struct exile_path_pol
|
|||||||
if(ret < 0 )
|
if(ret < 0 )
|
||||||
{
|
{
|
||||||
EXILE_LOG_ERROR("Error: Failed to remount %s: %s\n", path_inside_chroot, strerror(errno));
|
EXILE_LOG_ERROR("Error: Failed to remount %s: %s\n", path_inside_chroot, strerror(errno));
|
||||||
|
free(path_inside_chroot);
|
||||||
return ret;
|
return ret;
|
||||||
}
|
}
|
||||||
|
path_policy = path_policy->next;
|
||||||
|
free(path_inside_chroot);
|
||||||
}
|
}
|
||||||
path_policy = path_policy->next;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* Frees the memory taken by a exile_policy object
|
* Frees the memory taken by a exile_policy object
|
||||||
*/
|
*/
|
||||||
@ -1767,11 +1804,17 @@ int exile_enable_policy(struct exile_policy *policy)
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
if(mount_to_chroot(policy->chroot_target_path, policy->path_policies) < 0)
|
if(create_chroot_dirs(policy->chroot_target_path, policy->path_policies) < 0)
|
||||||
{
|
{
|
||||||
EXILE_LOG_ERROR("mount_to_chroot: bind mounting of path policies failed\n");
|
EXILE_LOG_ERROR("mount_to_chroot: bind mounting of path policies failed\n");
|
||||||
return -1;
|
return -1;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if(perform_mounts(policy->chroot_target_path, policy->path_policies) < 0)
|
||||||
|
{
|
||||||
|
EXILE_LOG_ERROR("perform_mounts: Failed to remount\n");
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
if(*policy->chroot_target_path != '\0')
|
if(*policy->chroot_target_path != '\0')
|
||||||
|
Loading…
Reference in New Issue
Block a user