From 0858532ea93e0890bf13556f4ef3dc25d7636233 Mon Sep 17 00:00:00 2001 From: aliguori Date: Fri, 27 Feb 2009 22:09:45 +0000 Subject: [PATCH] chroot and change user support (Nolan) Resent with fixed formatting. This patch adds two new command line options: -chroot -runas This is useful for running qemu as an unprivileged user in a chroot jail. To avoid having to populate the jail, chrooting happens right before the start of guest execution. Signed-off-by: Nolan Leake Signed-off-by: Anthony Liguori git-svn-id: svn://svn.savannah.nongnu.org/qemu/trunk@6652 c046a42c-6fe2-441c-8c8c-71466251a162 --- qemu-doc.texi | 8 +++++++ vl.c | 63 +++++++++++++++++++++++++++++++++++++++++++++++---- 2 files changed, 66 insertions(+), 5 deletions(-) diff --git a/qemu-doc.texi b/qemu-doc.texi index 39a3a76ca4..616de48c0c 100644 --- a/qemu-doc.texi +++ b/qemu-doc.texi @@ -1161,6 +1161,14 @@ character to Control-t. @item -echr 20 @end table +@item -chroot dir +Immediately before starting guest execution, chroot to the specified +directory. Especially useful in combination with -runas. + +@item -runas user +Immediately before starting guest execution, drop root privileges, switching +to the specified user. + @end table @c man end diff --git a/vl.c b/vl.c index 224c811757..8e59cd8d74 100644 --- a/vl.c +++ b/vl.c @@ -52,6 +52,7 @@ #include #ifndef _WIN32 +#include #include #include #include @@ -4075,6 +4076,10 @@ static void help(int exitcode) #endif "-tb-size n set TB size\n" "-incoming p prepare for incoming migration, listen on port p\n" +#ifndef _WIN32 + "-chroot dir Chroot to dir just before starting the VM.\n" + "-runas user Change to user id user just before starting the VM.\n" +#endif "\n" "During emulation, the following keys are useful:\n" "ctrl-alt-f toggle full screen\n" @@ -4192,6 +4197,8 @@ enum { QEMU_OPTION_old_param, QEMU_OPTION_tb_size, QEMU_OPTION_incoming, + QEMU_OPTION_chroot, + QEMU_OPTION_runas, }; typedef struct QEMUOption { @@ -4322,6 +4329,8 @@ static const QEMUOption qemu_options[] = { #endif { "tb-size", HAS_ARG, QEMU_OPTION_tb_size }, { "incoming", HAS_ARG, QEMU_OPTION_incoming }, + { "chroot", HAS_ARG, QEMU_OPTION_chroot }, + { "runas", HAS_ARG, QEMU_OPTION_runas }, { NULL }, }; @@ -4632,6 +4641,10 @@ int main(int argc, char **argv, char **envp) const char *pid_file = NULL; int autostart; const char *incoming = NULL; + int fd; + struct passwd *pwd; + const char *chroot_dir = NULL; + const char *run_as = NULL; qemu_cache_utils_init(envp); @@ -5287,6 +5300,12 @@ int main(int argc, char **argv, char **envp) case QEMU_OPTION_incoming: incoming = optarg; break; + case QEMU_OPTION_chroot: + chroot_dir = optarg; + break; + case QEMU_OPTION_runas: + run_as = optarg; + break; } } } @@ -5739,7 +5758,6 @@ int main(int argc, char **argv, char **envp) if (daemonize) { uint8_t status = 0; ssize_t len; - int fd; again1: len = write(fds[1], &status, 1); @@ -5753,12 +5771,47 @@ int main(int argc, char **argv, char **envp) TFR(fd = open("/dev/null", O_RDWR)); if (fd == -1) exit(1); + } - dup2(fd, 0); - dup2(fd, 1); - dup2(fd, 2); +#ifndef _WIN32 + if (run_as) { + pwd = getpwnam(run_as); + if (!pwd) { + fprintf(stderr, "User \"%s\" doesn't exist\n", run_as); + exit(1); + } + } - close(fd); + if (chroot_dir) { + if (chroot(chroot_dir) < 0) { + fprintf(stderr, "chroot failed\n"); + exit(1); + } + chdir("/"); + } + + if (run_as) { + if (setgid(pwd->pw_gid) < 0) { + fprintf(stderr, "Failed to setgid(%d)\n", pwd->pw_gid); + exit(1); + } + if (setuid(pwd->pw_uid) < 0) { + fprintf(stderr, "Failed to setuid(%d)\n", pwd->pw_uid); + exit(1); + } + if (setuid(0) != -1) { + fprintf(stderr, "Dropping privileges failed\n"); + exit(1); + } + } +#endif + + if (daemonize) { + dup2(fd, 0); + dup2(fd, 1); + dup2(fd, 2); + + close(fd); } main_loop();