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(a)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.
# 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