|
|
@ -3680,13 +3680,15 @@ class ExternalContext(object):
|
|
|
|
os.dup2(fd, stdfd)
|
|
|
|
os.dup2(fd, stdfd)
|
|
|
|
os.close(fd)
|
|
|
|
os.close(fd)
|
|
|
|
|
|
|
|
|
|
|
|
def _setup_stdio(self):
|
|
|
|
def _preserve_tty_fp(self):
|
|
|
|
# #481: when stderr is a TTY due to being started via
|
|
|
|
"""
|
|
|
|
# tty_create_child()/hybrid_tty_create_child(), and some privilege
|
|
|
|
#481: when stderr is a TTY due to being started via tty_create_child()
|
|
|
|
# escalation tool like prehistoric versions of sudo exec this process
|
|
|
|
or hybrid_tty_create_child(), and some privilege escalation tool like
|
|
|
|
# over the top of itself, there is nothing left to keep the slave PTY
|
|
|
|
prehistoric versions of sudo exec this process over the top of itself,
|
|
|
|
# open after we replace our stdio. Therefore if stderr is a TTY, keep
|
|
|
|
there is nothing left to keep the slave PTY open after we replace our
|
|
|
|
# around a permanent dup() to avoid receiving SIGHUP.
|
|
|
|
stdio. Therefore if stderr is a TTY, keep around a permanent dup() to
|
|
|
|
|
|
|
|
avoid receiving SIGHUP.
|
|
|
|
|
|
|
|
"""
|
|
|
|
try:
|
|
|
|
try:
|
|
|
|
if os.isatty(2):
|
|
|
|
if os.isatty(2):
|
|
|
|
self.reserve_tty_fp = os.fdopen(os.dup(2), 'r+b', 0)
|
|
|
|
self.reserve_tty_fp = os.fdopen(os.dup(2), 'r+b', 0)
|
|
|
@ -3694,6 +3696,8 @@ class ExternalContext(object):
|
|
|
|
except OSError:
|
|
|
|
except OSError:
|
|
|
|
pass
|
|
|
|
pass
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
def _setup_stdio(self):
|
|
|
|
|
|
|
|
self._preserve_tty_fp()
|
|
|
|
# When sys.stdout was opened by the runtime, overwriting it will not
|
|
|
|
# When sys.stdout was opened by the runtime, overwriting it will not
|
|
|
|
# close FD 1. However when forking from a child that previously used
|
|
|
|
# close FD 1. However when forking from a child that previously used
|
|
|
|
# fdopen(), overwriting it /will/ close FD 1. So we must swallow the
|
|
|
|
# fdopen(), overwriting it /will/ close FD 1. So we must swallow the
|
|
|
|