qemu-devel.nongnu.org archive mirror
 help / color / mirror / Atom feed
* [Qemu-devel] [PATCH] chroot and change user support
@ 2009-02-20 23:05 Nolan
  0 siblings, 0 replies; 2+ messages in thread
From: Nolan @ 2009-02-20 23:05 UTC (permalink / raw)
  To: qemu-devel

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>

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 <zlib.h>
 
 #ifndef _WIN32
+#include <pwd.h>
 #include <sys/times.h>
 #include <sys/wait.h>
 #include <termios.h>
@@ -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();

^ permalink raw reply	[flat|nested] 2+ messages in thread

* [Qemu-devel] [PATCH] chroot and change user support
@ 2009-02-27 21:41 Nolan
  0 siblings, 0 replies; 2+ messages in thread
From: Nolan @ 2009-02-27 21:41 UTC (permalink / raw)
  To: qemu-devel

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>

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 <zlib.h>
 
 #ifndef _WIN32
+#include <pwd.h>
 #include <sys/times.h>
 #include <sys/wait.h>
 #include <termios.h>
@@ -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();

^ permalink raw reply	[flat|nested] 2+ messages in thread

end of thread, other threads:[~2009-02-27 21:41 UTC | newest]

Thread overview: 2+ messages (download: mbox.gz follow: Atom feed
-- links below jump to the message on this page --
2009-02-20 23:05 [Qemu-devel] [PATCH] chroot and change user support Nolan
  -- strict thread matches above, loose matches on Subject: below --
2009-02-27 21:41 Nolan

This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox;
as well as URLs for NNTP newsgroup(s).