Commit aed51d81 authored by Guido van Rossum's avatar Guido van Rossum

SF patch 590294: os._execvpe security fix (Zack Weinberg).

1) Do not attempt to exec a file which does not exist
just to find out what error the operating system
returns. This is an exploitable race on all platforms
that support symbolic links.

2) Immediately re-raise the exception if we get an
error other than errno.ENOENT or errno.ENOTDIR. This
may need to be adapted for other platforms.

(As a security issue, this should be considered for 2.1
and 2.2 as well as 2.3.)
parent aaebdd6a
...@@ -319,8 +319,9 @@ def execvpe(file, args, env): ...@@ -319,8 +319,9 @@ def execvpe(file, args, env):
__all__.extend(["execl","execle","execlp","execlpe","execvp","execvpe"]) __all__.extend(["execl","execle","execlp","execlpe","execvp","execvpe"])
_notfound = None
def _execvpe(file, args, env=None): def _execvpe(file, args, env=None):
from errno import ENOENT, ENOTDIR
if env is not None: if env is not None:
func = execve func = execve
argrest = (args, env) argrest = (args, env)
...@@ -328,7 +329,7 @@ def _execvpe(file, args, env=None): ...@@ -328,7 +329,7 @@ def _execvpe(file, args, env=None):
func = execv func = execv
argrest = (args,) argrest = (args,)
env = environ env = environ
global _notfound
head, tail = path.split(file) head, tail = path.split(file)
if head: if head:
apply(func, (file,) + argrest) apply(func, (file,) + argrest)
...@@ -338,30 +339,14 @@ def _execvpe(file, args, env=None): ...@@ -338,30 +339,14 @@ def _execvpe(file, args, env=None):
else: else:
envpath = defpath envpath = defpath
PATH = envpath.split(pathsep) PATH = envpath.split(pathsep)
if not _notfound:
if sys.platform[:4] == 'beos':
# Process handling (fork, wait) under BeOS (up to 5.0)
# doesn't interoperate reliably with the thread interlocking
# that happens during an import. The actual error we need
# is the same on BeOS for posix.open() et al., ENOENT.
try: unlink('/_#.# ## #.#')
except error, _notfound: pass
else:
import tempfile
t = tempfile.mktemp()
# Exec a file that is guaranteed not to exist
try: execv(t, ('blah',))
except error, _notfound: pass
exc, arg = error, _notfound
for dir in PATH: for dir in PATH:
fullname = path.join(dir, file) fullname = path.join(dir, file)
try: try:
apply(func, (fullname,) + argrest) apply(func, (fullname,) + argrest)
except error, (errno, msg): except error, (errno, msg):
if errno != arg[0]: if errno != ENOENT and errno != ENOTDIR:
exc, arg = error, (errno, msg) raise
raise exc, arg raise error, (errno, msg)
# Change environ to automatically call putenv() if it exists # Change environ to automatically call putenv() if it exists
try: try:
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment