[linux-user-chroot] [SECURITY] Use fsuid to lookup bind mount paths and chroot target
- From: Colin Walters <walters src gnome org>
- To: commits-list gnome org
- Cc:
- Subject: [linux-user-chroot] [SECURITY] Use fsuid to lookup bind mount paths and chroot target
- Date: Sun, 24 Feb 2013 16:03:26 +0000 (UTC)
commit 04028db1d9f7909f4c86d9b4d4a8640e65fd11f1
Author: Colin Walters <walters verbum org>
Date: Sun Feb 24 08:33:31 2013 -0500
[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: Marc Deslauriers <marc deslauriers canonical com>
Reported-by: Ryan Lortie <desrt desrt ca>
Reviewed-by: Marc Deslauriers <marc deslauriers canonical com>
Signed-off-by: Colin Walters <walters verbum org>
src/linux-user-chroot.c | 31 ++++++++++++++++++++++++++++---
1 files changed, 28 insertions(+), 3 deletions(-)
---
diff --git a/src/linux-user-chroot.c b/src/linux-user-chroot.c
index ac542ad..6cac578 100644
--- a/src/linux-user-chroot.c
+++ b/src/linux-user-chroot.c
@@ -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 / */
[
Date Prev][
Date Next] [
Thread Prev][
Thread Next]
[
Thread Index]
[
Date Index]
[
Author Index]