Don't allow salt.utils.files.fopen() to open stdin/stdout/stderr

It's like crossing the streams. h/t @garethgreenaway
This commit is contained in:
Erik Johnson 2018-02-27 18:13:08 -06:00
parent adc8950bbe
commit fe1527a3c4
No known key found for this signature in database
GPG key ID: 5E5583C437808F3F
2 changed files with 41 additions and 0 deletions

View file

@ -328,6 +328,17 @@ def fopen(*args, **kwargs):
NB! We still have small race condition between open and fcntl.
'''
if six.PY3:
try:
# Don't permit stdin/stdout/stderr to be opened. The boolean False
# and True are treated by Python 3's open() as file descriptors 0
# and 1, respectively.
if args[0] in (0, 1, 2):
raise TypeError(
'{0} is not a permitted file descriptor'.format(args[0])
)
except IndexError:
pass
binary = None
# ensure 'binary' mode is always used on Windows in Python 2
if ((six.PY2 and salt.utils.platform.is_windows() and 'binary' not in kwargs) or

View file

@ -11,6 +11,7 @@ import tempfile
# Import Salt libs
import salt.utils.files
from salt.ext import six
# Import Salt Testing libs
from tests.support.paths import TMP
@ -69,3 +70,32 @@ class FilesUtilTestCase(TestCase):
)
finally:
shutil.rmtree(tmp)
@skipIf(not six.PY3, 'This test only applies to Python 3')
def test_fopen_with_disallowed_fds(self):
'''
This is safe to have as a unit test since we aren't going to actually
try to read or write. We want to ensure that we are raising a
TypeError. Python 3's open() builtin will treat the booleans as file
descriptor numbers and try to open stdin/stdout. We also want to test
fd 2 which is stderr.
'''
for invalid_fn in (False, True, 0, 1, 2):
try:
with salt.utils.files.fopen(invalid_fn):
pass
except TypeError:
# This is expected. We aren't using an assertRaises here
# because we want to ensure that if we did somehow open the
# filehandle, that it doesn't remain open.
pass
else:
# We probably won't even get this far if we actually opened
# stdin/stdout as a file descriptor. It is likely to cause the
# integration suite to die since, news flash, closing
# stdin/stdout/stderr is usually not a wise thing to do in the
# middle of a program's execution.
self.fail(
'fopen() should have been prevented from opening a file '
'using {0} as the filename'.format(invalid_fn)
)