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
This commit is contained in:
aliguori 2009-02-27 22:09:45 +00:00
parent 8290edda01
commit 0858532ea9
2 changed files with 66 additions and 5 deletions

View File

@ -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

63
vl.c
View File

@ -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);
}
}
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();