diff options
author | Colin Walters <walters@verbum.org> | 2015-09-05 09:20:58 -0400 |
---|---|---|
committer | Colin Walters <walters@verbum.org> | 2015-09-05 09:20:58 -0400 |
commit | 4b9efbfb1fd3c543e7808af90bc8e9730c1ba6e9 (patch) | |
tree | decfd7785a840587b47feee3af46a8eb4622a57f | |
parent | ab5eea42d2a182c7c9a5807ccbc3a7bd254d1865 (diff) | |
download | linux-user-chroot-4b9efbfb1fd3c543e7808af90bc8e9730c1ba6e9.tar.gz |
Add --mount-devapi optionmore-restriction-options
By default, we had supported `--mount-bind /dev /dev` to get
access to devices. But in many cases, build systems and the
like will want to avoid exposing host physical devices.
For example, if I'm building something locally, I don't want the
makefile etc. to be able to access `/dev/dri`.
-rw-r--r-- | Makefile-user-chroot.am | 1 | ||||
-rw-r--r-- | src/cleanup.h | 38 | ||||
-rw-r--r-- | src/linux-user-chroot.c | 25 | ||||
-rw-r--r-- | src/setup-dev.c | 89 | ||||
-rw-r--r-- | src/setup-dev.h | 24 |
5 files changed, 176 insertions, 1 deletions
diff --git a/Makefile-user-chroot.am b/Makefile-user-chroot.am index 5d0504f..29b6682 100644 --- a/Makefile-user-chroot.am +++ b/Makefile-user-chroot.am @@ -19,6 +19,7 @@ bin_PROGRAMS += linux-user-chroot linux_user_chroot_SOURCES = \ src/setup-seccomp.c \ + src/setup-dev.c \ src/linux-user-chroot.c \ $(NULL) diff --git a/src/cleanup.h b/src/cleanup.h new file mode 100644 index 0000000..070dcf9 --- /dev/null +++ b/src/cleanup.h @@ -0,0 +1,38 @@ +/* -*- mode: c; tab-width: 2; indent-tabs-mode: nil -*- + * + * linux-user-chroot: A setuid program that allows non-root users to safely chroot(2) + * + * Copyright 2015 Colin Walters <walters@verbum.org> + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it would be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software Foundation, + * Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + */ + +#pragma once + +#include <assert.h> + +static inline void +cleanup_close_fdp (int *fdp) +{ + int fd; + + assert (fdp); + + fd = *fdp; + if (fd != -1) + (void) close (fd); +} + +#define _cleanup_fd_close_ __attribute__((cleanup(cleanup_close_fdp))) diff --git a/src/linux-user-chroot.c b/src/linux-user-chroot.c index 87d85b0..dada947 100644 --- a/src/linux-user-chroot.c +++ b/src/linux-user-chroot.c @@ -48,6 +48,7 @@ #include <sched.h> #include "setup-seccomp.h" +#include "setup-dev.h" #ifndef PR_SET_NO_NEW_PRIVS #define PR_SET_NO_NEW_PRIVS 38 @@ -91,7 +92,8 @@ fatal_errno (const char *message) typedef enum { MOUNT_SPEC_BIND, MOUNT_SPEC_READONLY, - MOUNT_SPEC_PROCFS + MOUNT_SPEC_PROCFS, + MOUNT_SPEC_DEVAPI } MountSpecType; typedef struct _MountSpec MountSpec; @@ -254,6 +256,22 @@ main (int argc, bind_mounts = mount; after_mount_arg_index += 2; } + else if (strcmp (arg, "--mount-devapi") == 0) + { + MountSpec *mount; + + if ((argc - after_mount_arg_index) < 2) + fatal ("--mount-devapi takes one argument"); + + mount = malloc (sizeof (MountSpec)); + mount->type = MOUNT_SPEC_DEVAPI; + mount->source = NULL; + mount->dest = argv[after_mount_arg_index+1]; + mount->next = bind_mounts; + + bind_mounts = mount; + after_mount_arg_index += 2; + } else if (strcmp (arg, "--unshare-ipc") == 0) { unshare_ipc = 1; @@ -394,6 +412,11 @@ main (int argc, "proc", MS_MGC_VAL | MS_PRIVATE, NULL) < 0) fatal_errno ("mount (\"proc\")"); } + else if (bind_mount_iter->type == MOUNT_SPEC_DEVAPI) + { + if (setup_dev (dest) < 0) + fatal_errno ("setting up devapi"); + } else assert (0); free (dest); diff --git a/src/setup-dev.c b/src/setup-dev.c new file mode 100644 index 0000000..e46c98d --- /dev/null +++ b/src/setup-dev.c @@ -0,0 +1,89 @@ +/* + * Copyright (C) 2015 Colin Walters <walters@verbum.org> + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; either + * version 2 of the License, or (at your option) any later version. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with this library. If not, see <http://www.gnu.org/licenses/>. + * + */ + +#include "config.h" +/* Core libc/linux-headers stuff */ +#define _GNU_SOURCE +#include <unistd.h> +#include <stdio.h> +#include <fcntl.h> +#include <errno.h> +#include <stdarg.h> +#include <string.h> +#include <assert.h> +#include <stdlib.h> +#include <stdarg.h> +#include <sys/types.h> +#include <sys/stat.h> +#include <sys/prctl.h> +#include <sys/fsuid.h> +#include <sys/mount.h> +#include <sys/syscall.h> +#include <sys/wait.h> +#include <sys/socket.h> +#include <sys/utsname.h> +#include <sched.h> + +#include "setup-dev.h" +#include "cleanup.h" + +#define N_ELEMENTS(arr) (sizeof (arr) / sizeof ((arr)[0])) + +int +setup_dev (const char *dest_devdir) +{ + _cleanup_fd_close_ int src_fd = -1; + _cleanup_fd_close_ int dest_fd = -1; + struct stat stbuf; + unsigned int i; + static const char *const devnodes[] = { "null", "zero", "full", "random", "urandom", "tty" }; + + src_fd = openat (AT_FDCWD, "/dev", O_RDONLY | O_NONBLOCK | O_DIRECTORY | O_CLOEXEC | O_NOCTTY); + if (src_fd == -1) + return -1; + + if (mount ("tmpfs", dest_devdir, + "tmpfs", MS_MGC_VAL | MS_PRIVATE | MS_NOSUID, "mode=0755") < 0) + return -1; + + dest_fd = openat (AT_FDCWD, dest_devdir, O_RDONLY | O_NONBLOCK | O_DIRECTORY | O_CLOEXEC | O_NOCTTY); + if (dest_fd == -1) + return -1; + + for (i = 0; i < N_ELEMENTS (devnodes); i++) + { + const char *nodename = devnodes[i]; + + if (fstatat (src_fd, nodename, &stbuf, 0) == -1) + return -1; + if (mknodat (dest_fd, nodename, stbuf.st_mode, stbuf.st_rdev) != 0) + return -1; + if (fchmodat (dest_fd, nodename, stbuf.st_mode, 0) != 0) + return -1; + } + + if (symlinkat ("/proc/self/fd/0", dest_fd, "stdin") < 0) + return -1; + if (symlinkat ("/proc/self/fd/1", dest_fd, "stdout") < 0) + return -1; + if (symlinkat ("/proc/self/fd/2", dest_fd, "stderr") < 0) + return -1; + + return 0; +} + diff --git a/src/setup-dev.h b/src/setup-dev.h new file mode 100644 index 0000000..48e7668 --- /dev/null +++ b/src/setup-dev.h @@ -0,0 +1,24 @@ +/* -*- mode: c; tab-width: 2; indent-tabs-mode: nil -*- + * + * linux-user-chroot: A setuid program that allows non-root users to safely chroot(2) + * + * Copyright 2015 Colin Walters <walters@verbum.org> + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it would be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software Foundation, + * Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + */ + +#pragma once + +int setup_dev (const char *dest); |