Commit 0858532ea93e0890bf13556f4ef3dc25d7636233
1 parent
8290edda
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
Showing
2 changed files
with
66 additions
and
5 deletions
qemu-doc.texi
@@ -1161,6 +1161,14 @@ character to Control-t. | @@ -1161,6 +1161,14 @@ character to Control-t. | ||
1161 | @item -echr 20 | 1161 | @item -echr 20 |
1162 | @end table | 1162 | @end table |
1163 | 1163 | ||
1164 | +@item -chroot dir | ||
1165 | +Immediately before starting guest execution, chroot to the specified | ||
1166 | +directory. Especially useful in combination with -runas. | ||
1167 | + | ||
1168 | +@item -runas user | ||
1169 | +Immediately before starting guest execution, drop root privileges, switching | ||
1170 | +to the specified user. | ||
1171 | + | ||
1164 | @end table | 1172 | @end table |
1165 | 1173 | ||
1166 | @c man end | 1174 | @c man end |
vl.c
@@ -52,6 +52,7 @@ | @@ -52,6 +52,7 @@ | ||
52 | #include <zlib.h> | 52 | #include <zlib.h> |
53 | 53 | ||
54 | #ifndef _WIN32 | 54 | #ifndef _WIN32 |
55 | +#include <pwd.h> | ||
55 | #include <sys/times.h> | 56 | #include <sys/times.h> |
56 | #include <sys/wait.h> | 57 | #include <sys/wait.h> |
57 | #include <termios.h> | 58 | #include <termios.h> |
@@ -4075,6 +4076,10 @@ static void help(int exitcode) | @@ -4075,6 +4076,10 @@ static void help(int exitcode) | ||
4075 | #endif | 4076 | #endif |
4076 | "-tb-size n set TB size\n" | 4077 | "-tb-size n set TB size\n" |
4077 | "-incoming p prepare for incoming migration, listen on port p\n" | 4078 | "-incoming p prepare for incoming migration, listen on port p\n" |
4079 | +#ifndef _WIN32 | ||
4080 | + "-chroot dir Chroot to dir just before starting the VM.\n" | ||
4081 | + "-runas user Change to user id user just before starting the VM.\n" | ||
4082 | +#endif | ||
4078 | "\n" | 4083 | "\n" |
4079 | "During emulation, the following keys are useful:\n" | 4084 | "During emulation, the following keys are useful:\n" |
4080 | "ctrl-alt-f toggle full screen\n" | 4085 | "ctrl-alt-f toggle full screen\n" |
@@ -4192,6 +4197,8 @@ enum { | @@ -4192,6 +4197,8 @@ enum { | ||
4192 | QEMU_OPTION_old_param, | 4197 | QEMU_OPTION_old_param, |
4193 | QEMU_OPTION_tb_size, | 4198 | QEMU_OPTION_tb_size, |
4194 | QEMU_OPTION_incoming, | 4199 | QEMU_OPTION_incoming, |
4200 | + QEMU_OPTION_chroot, | ||
4201 | + QEMU_OPTION_runas, | ||
4195 | }; | 4202 | }; |
4196 | 4203 | ||
4197 | typedef struct QEMUOption { | 4204 | typedef struct QEMUOption { |
@@ -4322,6 +4329,8 @@ static const QEMUOption qemu_options[] = { | @@ -4322,6 +4329,8 @@ static const QEMUOption qemu_options[] = { | ||
4322 | #endif | 4329 | #endif |
4323 | { "tb-size", HAS_ARG, QEMU_OPTION_tb_size }, | 4330 | { "tb-size", HAS_ARG, QEMU_OPTION_tb_size }, |
4324 | { "incoming", HAS_ARG, QEMU_OPTION_incoming }, | 4331 | { "incoming", HAS_ARG, QEMU_OPTION_incoming }, |
4332 | + { "chroot", HAS_ARG, QEMU_OPTION_chroot }, | ||
4333 | + { "runas", HAS_ARG, QEMU_OPTION_runas }, | ||
4325 | { NULL }, | 4334 | { NULL }, |
4326 | }; | 4335 | }; |
4327 | 4336 | ||
@@ -4632,6 +4641,10 @@ int main(int argc, char **argv, char **envp) | @@ -4632,6 +4641,10 @@ int main(int argc, char **argv, char **envp) | ||
4632 | const char *pid_file = NULL; | 4641 | const char *pid_file = NULL; |
4633 | int autostart; | 4642 | int autostart; |
4634 | const char *incoming = NULL; | 4643 | const char *incoming = NULL; |
4644 | + int fd; | ||
4645 | + struct passwd *pwd; | ||
4646 | + const char *chroot_dir = NULL; | ||
4647 | + const char *run_as = NULL; | ||
4635 | 4648 | ||
4636 | qemu_cache_utils_init(envp); | 4649 | qemu_cache_utils_init(envp); |
4637 | 4650 | ||
@@ -5287,6 +5300,12 @@ int main(int argc, char **argv, char **envp) | @@ -5287,6 +5300,12 @@ int main(int argc, char **argv, char **envp) | ||
5287 | case QEMU_OPTION_incoming: | 5300 | case QEMU_OPTION_incoming: |
5288 | incoming = optarg; | 5301 | incoming = optarg; |
5289 | break; | 5302 | break; |
5303 | + case QEMU_OPTION_chroot: | ||
5304 | + chroot_dir = optarg; | ||
5305 | + break; | ||
5306 | + case QEMU_OPTION_runas: | ||
5307 | + run_as = optarg; | ||
5308 | + break; | ||
5290 | } | 5309 | } |
5291 | } | 5310 | } |
5292 | } | 5311 | } |
@@ -5739,7 +5758,6 @@ int main(int argc, char **argv, char **envp) | @@ -5739,7 +5758,6 @@ int main(int argc, char **argv, char **envp) | ||
5739 | if (daemonize) { | 5758 | if (daemonize) { |
5740 | uint8_t status = 0; | 5759 | uint8_t status = 0; |
5741 | ssize_t len; | 5760 | ssize_t len; |
5742 | - int fd; | ||
5743 | 5761 | ||
5744 | again1: | 5762 | again1: |
5745 | len = write(fds[1], &status, 1); | 5763 | len = write(fds[1], &status, 1); |
@@ -5753,12 +5771,47 @@ int main(int argc, char **argv, char **envp) | @@ -5753,12 +5771,47 @@ int main(int argc, char **argv, char **envp) | ||
5753 | TFR(fd = open("/dev/null", O_RDWR)); | 5771 | TFR(fd = open("/dev/null", O_RDWR)); |
5754 | if (fd == -1) | 5772 | if (fd == -1) |
5755 | exit(1); | 5773 | exit(1); |
5774 | + } | ||
5756 | 5775 | ||
5757 | - dup2(fd, 0); | ||
5758 | - dup2(fd, 1); | ||
5759 | - dup2(fd, 2); | 5776 | +#ifndef _WIN32 |
5777 | + if (run_as) { | ||
5778 | + pwd = getpwnam(run_as); | ||
5779 | + if (!pwd) { | ||
5780 | + fprintf(stderr, "User \"%s\" doesn't exist\n", run_as); | ||
5781 | + exit(1); | ||
5782 | + } | ||
5783 | + } | ||
5784 | + | ||
5785 | + if (chroot_dir) { | ||
5786 | + if (chroot(chroot_dir) < 0) { | ||
5787 | + fprintf(stderr, "chroot failed\n"); | ||
5788 | + exit(1); | ||
5789 | + } | ||
5790 | + chdir("/"); | ||
5791 | + } | ||
5792 | + | ||
5793 | + if (run_as) { | ||
5794 | + if (setgid(pwd->pw_gid) < 0) { | ||
5795 | + fprintf(stderr, "Failed to setgid(%d)\n", pwd->pw_gid); | ||
5796 | + exit(1); | ||
5797 | + } | ||
5798 | + if (setuid(pwd->pw_uid) < 0) { | ||
5799 | + fprintf(stderr, "Failed to setuid(%d)\n", pwd->pw_uid); | ||
5800 | + exit(1); | ||
5801 | + } | ||
5802 | + if (setuid(0) != -1) { | ||
5803 | + fprintf(stderr, "Dropping privileges failed\n"); | ||
5804 | + exit(1); | ||
5805 | + } | ||
5806 | + } | ||
5807 | +#endif | ||
5808 | + | ||
5809 | + if (daemonize) { | ||
5810 | + dup2(fd, 0); | ||
5811 | + dup2(fd, 1); | ||
5812 | + dup2(fd, 2); | ||
5760 | 5813 | ||
5761 | - close(fd); | 5814 | + close(fd); |
5762 | } | 5815 | } |
5763 | 5816 | ||
5764 | main_loop(); | 5817 | main_loop(); |