Project

General

Profile

Bug #500

set-uid script with -p in magic number gets Exec format error

Added by Roland Mainz about 9 years ago. Updated about 9 years ago.

Status:
New
Priority:
Normal
Assignee:
-
Category:
cmd - userland programs
Start date:
2010-12-10
Due date:
% Done:

0%

Estimated time:
Difficulty:
Tags:

Description

[Originally filed as http://bugs.opensolaris.org/bugdatabase/view_bug.do?bug_id=6934836]
The following script, when run as a set-uid script, fails to execute,
reporting an "Exec format error" instead:

$ cat ok.ksh
#!/bin/ksh -p

print "okay"
$

This is odd because ksh -p is documented as doing nothing more than suppressing the processing of the user's $HOME/.profile and using
/etc/suid_profile instead of the ENV variable. Nothing in available ksh93 documentation suggests that -p is incompatible with set-uid scripts.

Work Around

Remove the options from the #! line and use a "set" line instead to set the same options. For instance, the following line:

#!/usr/bin/ksh -p

can be replaced by these lines:

#!/usr/bin/ksh
set -p

Does not seem to have anything to do with the "-p" option specifically. The script fails in exactly the same way if we use any options, "-x", "-v", etc.

The difference between the way a suid script is executed and a regular one is that in case of a suid script, the script to be executed is passed as a /dev/fd parameter to close the "replace script between exec and open by shell" hole (usr/src/uts/common/exec/shbin/shbin.c). This, with ksh93, seems to have a problem only if there are options specified on the command line.

The program below demonstrates this:

$ cat testexec.c
#include <stdio.h>
#include <fcntl.h>
#include <unistd.h>

int
main() {
int fd = -1;
char devfd32;
char *script = "/tmp/ok.ksh";

fd = open(script, O_RDONLY);
sprintf(devfd, "/dev/fd/%d", fd);
execl("/usr/bin/sparcv9/ksh93", "ksh", "-v", devfd, NULL);
//execl("/usr/bin/sparcv9/ksh93", "ksh", "-v", script, NULL);
//execl("/usr/bin/bash", "bash", "-v", devfd, NULL);
//execl("/usr/bin/sparcv9/ksh93", "ksh", devfd, NULL);
perror("exec failed");
}
$ ./testexec
/usr/bin/ksh: /usr/bin/ksh: cannot execute [Exec format error]

This fails irrespective of whether the script is suid or not. And the other commented execl() lines in the source (using the script directly instead of the /dev/fd path, bash with command line options and the devfd path, or ksh93 without command line options) all work perfectly.
A few interesting twists:

$ cp testexec kshexec
$ ./kshexec
okay

(Renaming the script to something starting with 'ksh' makes it start working.)

$ SHELL=/bin/ksh ./testexec
ksh: ksh: cannot execute [Exec format error]
$ SHELL=/bin/bash ./testexec
/usr/bin/ksh: /usr/bin/ksh: cannot execute binary file

(Though we are invoking ksh93 directly, it does an exec of itself when we use /dev/fd/XX scripts where it ends up using the SHELL environment variable.)
The culprit seems to be the code below:

<lib/libshell/common/sh/init.c>
1216 shp->st.dolv=argv+(argc-1)-shp->st.dolc;
1217 shp->st.dolv0 = argv0;

Here, we are overwriting one of the arguments of argv (because shp->st.dolv indexes into the argv vector).

In this particular case, argv which originally looked like this:

ksh, -v, /dev/fd/3

ends up looking like this:

ksh, ksh, /dev/fd/3

We then pass the mangled argv to execv():

<lib/libshell/common/sh/main.c>

298 /* exec to change $0 for ps */
299 execv(pathshell(),av);

As a consequence, ksh tries to load the ksh binary as a shell script and fails with an "Exec format" error.


Files

patch.diff.txt (1.77 KB) patch.diff.txt Prototype patch Roland Mainz, 2010-12-10 02:23 PM
sun_solaris_cr_6934836_set-uid_script_with_-p_in_magic_number_gets_exec_format_error.sh.txt (7.43 KB) sun_solaris_cr_6934836_set-uid_script_with_-p_in_magic_number_gets_exec_format_error.sh.txt Testsuite module to test for this bug Roland Mainz, 2010-12-10 02:25 PM

Also available in: Atom PDF