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

Cedric Bosdonnat cbosdonnat at suse.com
Mon Sep 7 11:24:14 UTC 2015


On Fri, 2015-09-04 at 12:40 +0100, Daniel P. Berrange wrote:
> 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 at redhat.com>
> ---
>  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)

ACK

--
Cedric




More information about the libvir-list mailing list