Commit 04028db1 authored by Colin Walters's avatar Colin Walters

[SECURITY] Use fsuid to lookup bind mount paths and chroot target

Otherise, the user can access otherwise inaccessible directories like
this:

$ linux-user-chroot --mount-bind /root/.virsh ~/mnt / /bin/sh

Also, we should check the accessibility of the chroot target; this is
much harder to exploit because you'd need an executable inside the
chroot that can be run.
Reported-by: 's avatarMarc Deslauriers <marc.deslauriers@canonical.com>
Reported-by: Allison Karlitskaya's avatarRyan Lortie <desrt@desrt.ca>
Reviewed-by: 's avatarMarc Deslauriers <marc.deslauriers@canonical.com>
Signed-off-by: Colin Walters's avatarColin Walters <walters@verbum.org>
parent c4388a62
......@@ -38,6 +38,7 @@
#include <stdlib.h>
#include <sys/types.h>
#include <sys/prctl.h>
#include <sys/fsuid.h>
#include <sys/mount.h>
#include <sys/syscall.h>
#include <sys/wait.h>
......@@ -110,6 +111,28 @@ reverse_mount_list (MountSpec *mount)
return prev;
}
/**
* fsuid_chdir:
* @uid: User id we should use
* @path: Path string
*
* Like chdir() except we use the filesystem privileges of @uid.
*/
static int
fsuid_chdir (uid_t uid,
const char *path)
{
int errsv;
int ret;
/* Note we don't check errors here because we can't, basically */
(void) setfsuid (uid);
ret = chdir (path);
errsv = errno;
(void) setfsuid (0);
errno = errsv;
return ret;
}
int
main (int argc,
char **argv)
......@@ -330,7 +353,9 @@ main (int argc,
}
else if (bind_mount_iter->type == MOUNT_SPEC_BIND)
{
if (mount (bind_mount_iter->source, dest,
if (fsuid_chdir (ruid, bind_mount_iter->source) < 0)
fatal ("Couldn't chdir to bind mount source");
if (mount (".", dest,
NULL, MS_BIND | MS_PRIVATE, NULL) < 0)
fatal_errno ("mount (MS_BIND)");
}
......@@ -345,10 +370,10 @@ main (int argc,
free (dest);
}
if (chdir (chroot_dir) < 0)
if (fsuid_chdir (ruid, chroot_dir) < 0)
fatal_errno ("chdir");
if (mount (chroot_dir, chroot_dir, NULL, MS_BIND | MS_PRIVATE, NULL) < 0)
if (mount (".", ".", NULL, MS_BIND | MS_PRIVATE, NULL) < 0)
fatal_errno ("mount (MS_BIND)");
/* Only move if we're not actually just using / */
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment