From mboxrd@z Thu Jan 1 00:00:00 1970 Received: from mailman by lists.gnu.org with tmda-scanned (Exim 4.43) id 1LdASV-0005xx-53 for qemu-devel@nongnu.org; Fri, 27 Feb 2009 16:41:27 -0500 Received: from exim by lists.gnu.org with spam-scanned (Exim 4.43) id 1LdASR-0005w4-Sk for qemu-devel@nongnu.org; Fri, 27 Feb 2009 16:41:26 -0500 Received: from [199.232.76.173] (port=41101 helo=monty-python.gnu.org) by lists.gnu.org with esmtp (Exim 4.43) id 1LdASR-0005w0-K5 for qemu-devel@nongnu.org; Fri, 27 Feb 2009 16:41:23 -0500 Received: from phong.sigbus.net ([65.49.35.42]:41180) by monty-python.gnu.org with esmtps (TLS-1.0:DHE_RSA_AES_256_CBC_SHA1:32) (Exim 4.60) (envelope-from ) id 1LdASQ-0001bE-SK for qemu-devel@nongnu.org; Fri, 27 Feb 2009 16:41:23 -0500 Received: from [192.168.0.3] (c-71-202-202-194.hsd1.ca.comcast.net [71.202.202.194]) by phong.sigbus.net (Postfix) with ESMTPSA id AF15495C0BB for ; Fri, 27 Feb 2009 13:41:18 -0800 (PST) From: Nolan Content-Type: text/plain Date: Fri, 27 Feb 2009 13:41:18 -0800 Message-Id: <1235770878.7115.98.camel@voxel> Mime-Version: 1.0 Content-Transfer-Encoding: 7bit Subject: [Qemu-devel] [PATCH] chroot and change user support Reply-To: qemu-devel@nongnu.org List-Id: qemu-devel.nongnu.org List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , To: qemu-devel@nongnu.org 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 Index: qemu-doc.texi =================================================================== --- qemu-doc.texi (revision 6629) +++ qemu-doc.texi (working copy) @@ -1158,6 +1158,14 @@ @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 Index: vl.c =================================================================== --- vl.c (revision 6629) +++ vl.c (working copy) @@ -52,6 +52,7 @@ #include #ifndef _WIN32 +#include #include #include #include @@ -4073,6 +4074,10 @@ #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" @@ -4189,6 +4194,8 @@ QEMU_OPTION_old_param, QEMU_OPTION_tb_size, QEMU_OPTION_incoming, + QEMU_OPTION_chroot, + QEMU_OPTION_runas, }; typedef struct QEMUOption { @@ -4318,6 +4325,8 @@ #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 }, }; @@ -4628,6 +4637,10 @@ 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); @@ -5278,6 +5291,12 @@ case QEMU_OPTION_incoming: incoming = optarg; break; + case QEMU_OPTION_chroot: + chroot_dir = optarg; + break; + case QEMU_OPTION_runas: + run_as = optarg; + break; } } } @@ -5732,7 +5751,6 @@ if (daemonize) { uint8_t status = 0; ssize_t len; - int fd; again1: len = write(fds[1], &status, 1); @@ -5746,14 +5764,49 @@ 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(); quit_timers(); net_cleanup();