tags 479406 pending
thanks
Hi,
On Sun, Jul 19, 2009 at 08:58:49PM +0100, [email protected] wrote:
> 2009-07-18 21:26:56 +0200, Nicolas François:
> > Ping
>
> Sorry, forgot to reply to your earlier email.
No problem (it took me a year for the previous answer ;)
> > > Are there other su / login implementations which behave that way?
> [...]
>
> AFAICS, the "login" from util-linux (derived from BSD) and the
> one from NetBSD and OpenBSD at least do use the exec?p variants
> (from a quick look at there source code).
>
> The OpenSolaris one seems to be checking for that case (pw_shell
> being a shell script) explicitely and treats it specially:
>
> http://src.opensolaris.org/source/xref/onnv/onnv-gate/usr/src/cmd/login/login.c#2507
login is the easiest, su is more complex because the behavior of
"su -c <command>" must be defined in this case. So I will just make it as
"/bin/sh <shell> -c <command>"
I will commit and test the attached patch, which should fix it for both
login and su.
Best Regards,
--
Nekral
Index: libmisc/shell.c
===================================================================
--- libmisc/shell.c (révision 3031)
+++ libmisc/shell.c (copie de travail)
@@ -79,6 +80,15 @@
execle (file, arg, (char *) 0, envp);
err = errno;
+ if (access (file, R_OK|X_OK) == 0) {
+ /*
+ * Assume this is a shell script (with no shebang).
+ * Interpret it with /bin/sh
+ */
+ execle ("/bin/sh", "sh", file, (char *)0, envp);
+ err = errno;
+ }
+
/*
* Obviously something is really wrong - I can't figure out
* how to execute this stupid shell, so I might as well give
Index: src/su.c
===================================================================
--- src/su.c (révision 3031)
+++ src/su.c (copie de travail)
@@ -174,7 +174,41 @@
exit (1);
}
+/*
+ * execve_shell - Execute a shell with execve, or interpret it with
+ * /bin/sh
+ */
+void execve_shell (const char *shellstr, char *args[], char *const envp[])
+{
+ int err;
+ (void) execve (shellstr, (char **) args, envp);
+ err = errno;
+ if (access (shellstr, R_OK|X_OK) == 0) {
+ /*
+ * Assume this is a shell script (with no shebang).
+ * Interpret it with /bin/sh
+ */
+ size_t n_args = 0;
+ char **targs;
+ while (NULL != args[n_args]) {
+ n_args++;
+ }
+ targs = (char **) xmalloc ((n_args + 2) * sizeof (args[0]));
+ targs[0] = "sh";
+ targs[1] = xstrdup (shellstr);
+ targs[n_args+1] = NULL;
+ while (1 != n_args) {
+ targs[n_args] = args[n_args - 1];
+ n_args--;
+ }
+
+ (void) execve ("/bin/sh", targs, envp);
+ } else {
+ errno = err;
+ }
+}
+
#ifdef USE_PAM
/* Signal handler for parent process later */
static void catch_signals (unused int sig)
@@ -206,8 +240,9 @@
if (doshell) {
(void) shell (shellstr, (char *) args[0], envp);
} else {
- (void) execve (shellstr, (char **) args, envp);
+ execve_shell (shellstr, (char **) args, envp);
}
+
exit (errno == ENOENT ? E_CMD_NOTFOUND : E_CMD_NOEXEC);
} else if ((pid_t)-1 == child) {
(void) fprintf (stderr, "%s: Cannot fork user shell\n", Prog);
@@ -949,7 +984,7 @@
*/
argv[-1] = shellstr;
#ifndef USE_PAM
- (void) execve (shellstr, &argv[-1], environ);
+ execve_shell (shellstr, &argv[-1], environ);
err = errno;
(void) fputs (_("No shell\n"), stderr);
SYSLOG ((LOG_WARN, "Cannot execute %s", shellstr));