[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