[libvirt] [PATCH 12/17] virt-login-shell: change way we request a login shell

John Ferlan jferlan at redhat.com
Wed Apr 27 18:46:24 UTC 2016



On 04/14/2016 11:22 AM, Daniel P. Berrange wrote:
> Currently we request a login shell by passing the -l argument
> to the shell. This is either hardcoded, or required to be
> specified by the user in the virt-login-shell.conf file.
> 
> The standard way for login programs to request a shell run
> as a login shell is to modify the argv passed to execve()
> so that argv[0] contains the relative shell filename
> prefixed with a zero. eg instead of doing
> 
>   const char **shellargs = ["/bin/bash", "-l", NULL];
>   execve(shellargs[0], shellargs, env);
> 
> We should be doing
> 
>   const char **shellargs = ["-bash", NULL];
>   execve("/bin/bash", shellargs, env);
> 
> Signed-off-by: Daniel P. Berrange <berrange at redhat.com>
> ---
>  tools/virt-login-shell.c    | 27 ++++++++++++++++++++++-----
>  tools/virt-login-shell.conf |  6 +++++-
>  tools/virt-login-shell.pod  |  2 +-
>  3 files changed, 28 insertions(+), 7 deletions(-)
> 
> diff --git a/tools/virt-login-shell.c b/tools/virt-login-shell.c
> index 34a8836..1ca58ee 100644
> --- a/tools/virt-login-shell.c
> +++ b/tools/virt-login-shell.c
> @@ -111,7 +111,7 @@ static int virLoginShellGetShellArgv(virConfPtr conf,
>  
>      p = virConfGetValue(conf, "shell");
>      if (!p) {
> -        len = 2; /* /bin/sh -l */
> +        len = 1; /* /bin/sh */
>      } else if (p->type == VIR_CONF_LIST) {
>          /* Calc length and check items */
>          for (len = 0, pp = p->list; pp; len++, pp = pp->next) {
> @@ -136,8 +136,6 @@ static int virLoginShellGetShellArgv(virConfPtr conf,
>      if (!p) {
>          if (VIR_STRDUP(shargv[i++], "/bin/sh") < 0)
>              goto error;
> -        if (VIR_STRDUP(shargv[i++], "-l") < 0)
> -            goto error;
>      } else if (p->type == VIR_CONF_LIST) {
>          for (pp = p->list; pp; pp = pp->next) {
>              if (VIR_STRDUP(shargv[i++], pp->str) < 0)
> @@ -200,6 +198,7 @@ main(int argc, char **argv)
>      char *name = NULL;
>      char **shargv = NULL;
>      size_t shargvlen = 0;
> +    char *shcmd = NULL;
>      virSecurityModelPtr secmodel = NULL;
>      virSecurityLabelPtr seclabel = NULL;
>      virDomainPtr dom = NULL;
> @@ -214,6 +213,7 @@ main(int argc, char **argv)
>      int openmax;
>      size_t i;
>      const char *cmdstr = NULL;
> +    char *tmp;
>  
>      struct option opt[] = {
>          {"help", no_argument, NULL, 'h'},
> @@ -356,6 +356,22 @@ main(int argc, char **argv)
>          shargv[shargvlen] = NULL;
>      }
>  
> +    /* We need to modify the first elementin shargv
> +     * so that it has the relative filename and has
> +     * a leading '-' to indicate it is a login shell
> +     */
> +    shcmd = shargv[0];
> +    if (shcmd[0] != '/') {
> +        virReportSystemError(errno,
> +                             _("Shell '%s' should have absolute path"),
> +                             shcmd);
> +        goto cleanup;
> +    }
> +    tmp = strrchr(shcmd, '/');
> +    if (VIR_STRDUP(shargv[0], tmp) < 0)
> +        goto cleanup;
> +    shargv[0][0] = '-';
> +
>      /* A fork is required to create new process in correct pid namespace.  */
>      if ((cpid = virFork()) < 0)
>          goto cleanup;
> @@ -367,9 +383,9 @@ main(int argc, char **argv)
>              tmpfd = i;
>              VIR_MASS_CLOSE(tmpfd);
>          }
> -        if (execv(shargv[0], (char *const*) shargv) < 0) {
> +        if (execv(shcmd, (char *const*) shargv) < 0) {
>              virReportSystemError(errno, _("Unable to exec shell %s"),
> -                                 shargv[0]);
> +                                 shcmd);
>              virDispatchError(NULL);
>              return errno == ENOENT ? EXIT_ENOENT : EXIT_CANNOT_INVOKE;
>          }
> @@ -388,6 +404,7 @@ main(int argc, char **argv)
>      if (conn)
>          virConnectClose(conn);
>      virStringFreeList(shargv);
> +    VIR_FREE(shcmd);
>      VIR_FREE(name);
>      VIR_FREE(homedir);
>      VIR_FREE(seclabel);
> diff --git a/tools/virt-login-shell.conf b/tools/virt-login-shell.conf
> index 835fd3f..67ca1cc 100644
> --- a/tools/virt-login-shell.conf
> +++ b/tools/virt-login-shell.conf
> @@ -8,7 +8,11 @@
>  # container.  Shell commands must be a list of commands/options separated by
>  # comma and delimited by square brackets. Defaults to: /bin/sh -l.

Need to adjust the "Defaults to:", right?


ACK w/ that.

John
>  # Modify and uncomment the following to modify the login shell.
> -# shell = [ "/bin/sh",  "-l" ]
> +#
> +# shell = [ "/bin/bash" ]
> +#
> +# Note there is no need to pass a '--login' / '-l' argument since
> +# virt-login-shell will always request a login shell
>  
>  # allowed_users specifies the user names of all users that are allowed to
>  # execute virt-login-shell.  You can specify the users as a comma
> diff --git a/tools/virt-login-shell.pod b/tools/virt-login-shell.pod
> index 56861f7..99eeed8 100644
> --- a/tools/virt-login-shell.pod
> +++ b/tools/virt-login-shell.pod
> @@ -39,7 +39,7 @@ By default, virt-login-shell will execute the /bin/sh program for the user.
>  You can modify this behaviour by defining the shell variable in
>  /etc/libvirt/virt-login-shell.conf.
>  
> -eg.  shell = [ "/bin/ksh", "--login"]
> +eg.  shell = [ "/bin/bash" ]
>  
>  By default no users are allowed to use virt-login-shell, if you want to allow
>  certain users to use virt-login-shell, you need to modify the allowed_users
> 




More information about the libvir-list mailing list