diff options
author | aliguori <aliguori@c046a42c-6fe2-441c-8c8c-71466251a162> | 2009-02-27 22:09:45 +0000 |
---|---|---|
committer | aliguori <aliguori@c046a42c-6fe2-441c-8c8c-71466251a162> | 2009-02-27 22:09:45 +0000 |
commit | 0858532ea93e0890bf13556f4ef3dc25d7636233 (patch) | |
tree | bc6bb83d09f60293d7763f7d8ff608b8900b4036 | |
parent | 8290edda019cda3e97c5a127c29f17d73aded100 (diff) | |
download | hqemu-0858532ea93e0890bf13556f4ef3dc25d7636233.zip hqemu-0858532ea93e0890bf13556f4ef3dc25d7636233.tar.gz |
chroot and change user support (Nolan)
Resent with fixed formatting.
This patch adds two new command line options:
-chroot <dir>
-runas <user>
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 <nolan@sigbus.net>
Signed-off-by: Anthony Liguori <aliguori@us.ibm.com>
git-svn-id: svn://svn.savannah.nongnu.org/qemu/trunk@6652 c046a42c-6fe2-441c-8c8c-71466251a162
-rw-r--r-- | qemu-doc.texi | 8 | ||||
-rw-r--r-- | vl.c | 63 |
2 files changed, 66 insertions, 5 deletions
diff --git a/qemu-doc.texi b/qemu-doc.texi index 39a3a76..616de48 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 @@ -52,6 +52,7 @@ #include <zlib.h> #ifndef _WIN32 +#include <pwd.h> #include <sys/times.h> #include <sys/wait.h> #include <termios.h> @@ -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); + } + } + + 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); + close(fd); } main_loop(); |