Fix an infinite loop related to $_ when ksh is /bin/sh #90
Add this suggestion to a batch that can be applied as a single commit.
This suggestion is invalid because no changes were made to the code.
Suggestions cannot be applied while the pull request is closed.
Suggestions cannot be applied while viewing a subset of changes.
Only one suggestion per line can be applied in a batch.
Add this suggestion to a batch that can be applied as a single commit.
Applying suggestions on deleted lines is not supported.
You must change the existing code in this line in order to create a valid suggestion.
Outdated suggestions cannot be applied.
This suggestion has been applied or marked resolved.
Suggestions cannot be applied from pending reviews.
Suggestions cannot be applied on multi-line comments.
Suggestions cannot be applied while the pull request is queued to merge.
Suggestion cannot be applied right now. Please check back later.
An infinite loop can occur if ksh is the system's /bin/sh. The following explanation is mostly taken from Tomas Klacko's bug report on the old mailing list:
When ksh starts a binary, it sets its environment variable
$_
to "number/path/to/binary". Where "number" is the pid of the ksh process.The binary forks and the child executes a suid root shell script which begins with
#!/bin/sh
. For this bug to occur, ksh must be /bin/sh.The ksh process interpreting the suid shell script leaves the
$_
variable as not set (nv_getval(L_ARGNOD)
returnsNULL
) because the "number" from step 1 is not the pid of its parent process.Because
$_
is not set and the script is suid root, the following if condition is true in src/cmd/ksh93/sh/main.c, which results in the following code being executed:ksh/src/cmd/ksh93/sh/main.c
Lines 272 to 284 in f207cd5
When the
$SHELL
environment variable contains "/bin/sh"pathshell()
returns "/bin/sh". This becomes an infiniteloop of
/bin/sh /dev/fd/3
executing/bin/sh /dev/fd/3
./dev/fd/3 is the suid root script passed in via file descriptor 3.
The first /bin/sh in the loop is the
#!/bin/sh
from the suid script. The second and subsequent /bin/sh in the loop is from the$SHELL
environment variable.The bugfix does the following:
- In
get_lastarg()
, the check for if the "number" refers to the process id of the parent process is removed.- In
sh_main()
, prevent an infinite loop when$_
is not passed in from the environment.The reproducer is a C program that sets all the necessary conditions and triggers the infinite loop when ksh is /bin/sh:
Oracle applies this bugfix to their version of ksh:
https://github.com/oracle/solaris-userland/blob/master/components/ksh93/patches/190-17432413.patch