[PATCH sandbox 1/4] push changing of user ID down into child process

[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]

 



When running interactive sandboxes, don't drop privileges in the
long running libvirt-sandbox-init-common process. This needs to
be privileged in order to sync, unmount and shutdown the guest
when the user command is finished. Push changing of user ID into
the child process, between fork & exec.

Signed-off-by: Daniel P. Berrange <berrange@xxxxxxxxxx>
---
 libvirt-sandbox/libvirt-sandbox-init-common.c | 60 +++++++++++++++------------
 1 file changed, 33 insertions(+), 27 deletions(-)

diff --git a/libvirt-sandbox/libvirt-sandbox-init-common.c b/libvirt-sandbox/libvirt-sandbox-init-common.c
index d35f760..760509f 100644
--- a/libvirt-sandbox/libvirt-sandbox-init-common.c
+++ b/libvirt-sandbox/libvirt-sandbox-init-common.c
@@ -390,30 +390,43 @@ static int change_user(const gchar *user,
     return 0;
 }
 
-static gboolean run_command(gboolean interactive, gchar **argv,
+static gboolean run_command(GVirSandboxConfig *config,
                             pid_t *child,
                             int *appin, int *appout, int *apperr)
 {
+    GVirSandboxConfigInteractive *iconfig = GVIR_SANDBOX_CONFIG_INTERACTIVE(config);
     int pid;
     int master = -1;
     int slave = -1;
     int pipein[2] = { -1, -1};
     int pipeout[2] = { -1, -1};
     int pipeerr[2] = { -1, -1};
+    gchar **appargv = gvir_sandbox_config_get_command(config);
+    gboolean wanttty = gvir_sandbox_config_interactive_get_tty(iconfig);
 
     if (debug)
         fprintf(stderr, "libvirt-sandbox-init-common: running command %s %d\n",
-                argv[0], interactive);
+                appargv[0], wanttty);
 
     *appin = *appout = -1;
 
-    if (interactive) {
+    if (wanttty) {
         if (openpty(&master, &slave, NULL, NULL, NULL) < 0) {
             fprintf(stderr, "Cannot setup slave for child: %s\n",
                     strerror(errno));
             goto error;
         }
 
+        if (!g_str_equal(gvir_sandbox_config_get_username(config), "root")) {
+            if (fchown(slave,
+                       gvir_sandbox_config_get_userid(config),
+                       gvir_sandbox_config_get_groupid(config)) < 0) {
+                fprintf(stderr, "Cannot make PTY available to user: %s\n",
+                        strerror(errno));
+                goto error;
+            }
+        }
+
         *appin = master;
         *appout = master;
         *apperr = master;
@@ -436,7 +449,13 @@ static gboolean run_command(gboolean interactive, gchar **argv,
     }
 
     if (pid == 0) {
-        if (interactive) {
+        if (change_user(gvir_sandbox_config_get_username(config),
+                        gvir_sandbox_config_get_userid(config),
+                        gvir_sandbox_config_get_groupid(config),
+                        gvir_sandbox_config_get_homedir(config)) < 0)
+            exit(EXIT_FAILURE);
+
+        if (wanttty) {
             close(master);
             close(STDIN_FILENO);
             close(STDOUT_FILENO);
@@ -469,24 +488,25 @@ static gboolean run_command(gboolean interactive, gchar **argv,
                 abort();
         }
 
-        execv(argv[0], argv);
-        fprintf(stderr, "Cannot execute '%s': %s\n", argv[0], strerror(errno));
+        execv(appargv[0], appargv);
+        fprintf(stderr, "Cannot execute '%s': %s\n", appargv[0], strerror(errno));
         exit(EXIT_FAILURE);
     }
 
-    if (interactive)
+    if (wanttty) {
         close(slave);
-    else {
+    } else {
         close(pipein[0]);
         close(pipeout[1]);
         close(pipeerr[1]);
     }
 
     *child = pid;
+    g_strfreev(appargv);
     return TRUE;
 
  error:
-    if (interactive) {
+    if (wanttty) {
         if (master != -1)
             close(master);
         if (slave != -1)
@@ -506,6 +526,7 @@ static gboolean run_command(gboolean interactive, gchar **argv,
             close(pipeerr[1]);
     }
     *appin = *appout = *apperr = -1;
+    g_strfreev(appargv);
     return FALSE;
 }
 
@@ -639,8 +660,7 @@ typedef enum {
     GVIR_SANDBOX_CONSOLE_STATE_RUNNING,
 } GVirSandboxConsoleState;
 
-static gboolean eventloop(gboolean interactive,
-                          gchar **appargv,
+static gboolean eventloop(GVirSandboxConfig *config,
                           int sigread,
                           int host)
 {
@@ -825,8 +845,7 @@ static gboolean eventloop(gboolean interactive,
                                     if (rx->buffer[0] == GVIR_SANDBOX_PROTOCOL_HANDSHAKE_SYNC) {
                                         if (debug)
                                             fprintf(stderr, "Running command\n");
-                                        if (!run_command(interactive,
-                                                         appargv,
+                                        if (!run_command(config,
                                                          &child,
                                                          &appin,
                                                          &appout,
@@ -1097,13 +1116,11 @@ static gboolean eventloop(gboolean interactive,
 static int
 run_interactive(GVirSandboxConfig *config)
 {
-    GVirSandboxConfigInteractive *iconfig = GVIR_SANDBOX_CONFIG_INTERACTIVE(config);
     int sigpipe[2] = { -1, -1 };
     int host = -1;
     int ret = -1;
     struct termios  rawattr;
     const char *devname;
-    gchar **command = NULL;
 
     if (pipe(sigpipe) < 0) {
         g_printerr(_("libvirt-sandbox-init-common: unable to create signal pipe: %s"),
@@ -1138,17 +1155,7 @@ run_interactive(GVirSandboxConfig *config)
     cfmakeraw(&rawattr);
     tcsetattr(host, TCSAFLUSH, &rawattr);
 
-
-
-    if (change_user(gvir_sandbox_config_get_username(config),
-                    gvir_sandbox_config_get_userid(config),
-                    gvir_sandbox_config_get_groupid(config),
-                    gvir_sandbox_config_get_homedir(config)) < 0)
-        goto cleanup;
-
-    command = gvir_sandbox_config_get_command(config);
-    if (!eventloop(gvir_sandbox_config_interactive_get_tty(iconfig),
-                   command,
+    if (!eventloop(config,
                    sigpipe[0],
                    host))
         goto cleanup;
@@ -1156,7 +1163,6 @@ run_interactive(GVirSandboxConfig *config)
     ret = 0;
 
  cleanup:
-    g_strfreev(command);
     signal(SIGCHLD, SIG_DFL);
 
     if (sigpipe[0] != -1)
-- 
2.4.3

--
libvir-list mailing list
libvir-list@xxxxxxxxxx
https://www.redhat.com/mailman/listinfo/libvir-list



[Index of Archives]     [Virt Tools]     [Libvirt Users]     [Lib OS Info]     [Fedora Users]     [Fedora Desktop]     [Fedora SELinux]     [Big List of Linux Books]     [Yosemite News]     [KDE Users]     [Fedora Tools]