From mboxrd@z Thu Jan 1 00:00:00 1970 Received: from mailman by lists.gnu.org with tmda-scanned (Exim 4.43) id 1LdAtw-0000Q6-SQ for qemu-devel@nongnu.org; Fri, 27 Feb 2009 17:09:48 -0500 Received: from exim by lists.gnu.org with spam-scanned (Exim 4.43) id 1LdAtv-0000O9-Q4 for qemu-devel@nongnu.org; Fri, 27 Feb 2009 17:09:48 -0500 Received: from [199.232.76.173] (port=44828 helo=monty-python.gnu.org) by lists.gnu.org with esmtp (Exim 4.43) id 1LdAtv-0000Np-Lw for qemu-devel@nongnu.org; Fri, 27 Feb 2009 17:09:47 -0500 Received: from savannah.gnu.org ([199.232.41.3]:49917 helo=sv.gnu.org) by monty-python.gnu.org with esmtps (TLS-1.0:RSA_AES_256_CBC_SHA1:32) (Exim 4.60) (envelope-from ) id 1LdAtu-00061Q-Vt for qemu-devel@nongnu.org; Fri, 27 Feb 2009 17:09:47 -0500 Received: from cvs.savannah.gnu.org ([199.232.41.69]) by sv.gnu.org with esmtp (Exim 4.63) (envelope-from ) id 1LdAtu-0001fB-1g for qemu-devel@nongnu.org; Fri, 27 Feb 2009 22:09:46 +0000 Received: from aliguori by cvs.savannah.gnu.org with local (Exim 4.69) (envelope-from ) id 1LdAtt-0001f7-QI for qemu-devel@nongnu.org; Fri, 27 Feb 2009 22:09:45 +0000 MIME-Version: 1.0 Errors-To: aliguori Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit From: Anthony Liguori Message-Id: Date: Fri, 27 Feb 2009 22:09:45 +0000 Subject: [Qemu-devel] [6652] chroot and change user support (Nolan) 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 Revision: 6652 http://svn.sv.gnu.org/viewvc/?view=rev&root=qemu&revision=6652 Author: aliguori Date: 2009-02-27 22:09:45 +0000 (Fri, 27 Feb 2009) Log Message: ----------- 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 Modified Paths: -------------- trunk/qemu-doc.texi trunk/vl.c Modified: trunk/qemu-doc.texi =================================================================== --- trunk/qemu-doc.texi 2009-02-27 20:14:29 UTC (rev 6651) +++ trunk/qemu-doc.texi 2009-02-27 22:09:45 UTC (rev 6652) @@ -1161,6 +1161,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 Modified: trunk/vl.c =================================================================== --- trunk/vl.c 2009-02-27 20:14:29 UTC (rev 6651) +++ trunk/vl.c 2009-02-27 22:09:45 UTC (rev 6652) @@ -52,6 +52,7 @@ #include #ifndef _WIN32 +#include #include #include #include @@ -4075,6 +4076,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" @@ -4192,6 +4197,8 @@ QEMU_OPTION_old_param, QEMU_OPTION_tb_size, QEMU_OPTION_incoming, + QEMU_OPTION_chroot, + QEMU_OPTION_runas, }; typedef struct QEMUOption { @@ -4322,6 +4329,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 }, }; @@ -4632,6 +4641,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); @@ -5287,6 +5300,12 @@ 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 @@ if (daemonize) { uint8_t status = 0; ssize_t len; - int fd; again1: len = write(fds[1], &status, 1); @@ -5753,14 +5771,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();