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@xxxxxxxxxx> --- 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. # 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 -- 2.5.5 -- libvir-list mailing list libvir-list@xxxxxxxxxx https://www.redhat.com/mailman/listinfo/libvir-list