Skip to content

Commit eb16397

Browse files
encukouvstinner
andauthored
[3.9] gh-107902: gh-108948: Don't test setting suid/sgid/sticky on systems that don't support them (GH-108368) (GH-109697) (#125576)
On FreeBSD, regular users cannot set the sticky bit. Skip the test if chmod() fails with EFTYPE error. Co-authored-by: Victor Stinner <[email protected]>
1 parent be988e8 commit eb16397

File tree

1 file changed

+39
-15
lines changed

1 file changed

+39
-15
lines changed

Lib/test/test_tarfile.py

+39-15
Original file line numberDiff line numberDiff line change
@@ -1,3 +1,4 @@
1+
import errno
12
import sys
23
import os
34
import io
@@ -3651,34 +3652,55 @@ def test_modes(self):
36513652
arc.add('read_group_only', mode='?---r-----')
36523653
arc.add('no_bits', mode='?---------')
36533654
arc.add('dir/', mode='?---rwsrwt')
3655+
arc.add('dir_all_bits/', mode='?rwsrwsrwt')
36543656

3655-
# On some systems, setting the sticky bit is a no-op.
3656-
# Check if that's the case.
3657+
# On some systems, setting the uid, gid, and/or sticky bit is a no-ops.
3658+
# Check which bits we can set, so we can compare tarfile machinery to
3659+
# a simple chmod.
36573660
tmp_filename = os.path.join(TEMPDIR, "tmp.file")
36583661
with open(tmp_filename, 'w'):
36593662
pass
3660-
os.chmod(tmp_filename, os.stat(tmp_filename).st_mode | stat.S_ISVTX)
3661-
have_sticky_files = (os.stat(tmp_filename).st_mode & stat.S_ISVTX)
3662-
os.unlink(tmp_filename)
3663+
try:
3664+
new_mode = (os.stat(tmp_filename).st_mode
3665+
| stat.S_ISVTX | stat.S_ISGID | stat.S_ISUID)
3666+
try:
3667+
os.chmod(tmp_filename, new_mode)
3668+
except OSError as exc:
3669+
if exc.errno == getattr(errno, "EFTYPE", 0):
3670+
# gh-108948: On FreeBSD, regular users cannot set
3671+
# the sticky bit.
3672+
self.skipTest("chmod() failed with EFTYPE: "
3673+
"regular users cannot set sticky bit")
3674+
else:
3675+
raise
3676+
3677+
got_mode = os.stat(tmp_filename).st_mode
3678+
_t_file = 't' if (got_mode & stat.S_ISVTX) else 'x'
3679+
_suid_file = 's' if (got_mode & stat.S_ISUID) else 'x'
3680+
_sgid_file = 's' if (got_mode & stat.S_ISGID) else 'x'
3681+
finally:
3682+
os.unlink(tmp_filename)
36633683

36643684
os.mkdir(tmp_filename)
3665-
os.chmod(tmp_filename, os.stat(tmp_filename).st_mode | stat.S_ISVTX)
3666-
have_sticky_dirs = (os.stat(tmp_filename).st_mode & stat.S_ISVTX)
3685+
new_mode = (os.stat(tmp_filename).st_mode
3686+
| stat.S_ISVTX | stat.S_ISGID | stat.S_ISUID)
3687+
os.chmod(tmp_filename, new_mode)
3688+
got_mode = os.stat(tmp_filename).st_mode
3689+
_t_dir = 't' if (got_mode & stat.S_ISVTX) else 'x'
3690+
_suid_dir = 's' if (got_mode & stat.S_ISUID) else 'x'
3691+
_sgid_dir = 's' if (got_mode & stat.S_ISGID) else 'x'
36673692
os.rmdir(tmp_filename)
36683693

36693694
with self.check_context(arc.open(), 'fully_trusted'):
3670-
if have_sticky_files:
3671-
self.expect_file('all_bits', mode='?rwsrwsrwt')
3672-
else:
3673-
self.expect_file('all_bits', mode='?rwsrwsrwx')
3695+
self.expect_file('all_bits',
3696+
mode=f'?rw{_suid_file}rw{_sgid_file}rw{_t_file}')
36743697
self.expect_file('perm_bits', mode='?rwxrwxrwx')
36753698
self.expect_file('exec_group_other', mode='?rw-rwxrwx')
36763699
self.expect_file('read_group_only', mode='?---r-----')
36773700
self.expect_file('no_bits', mode='?---------')
3678-
if have_sticky_dirs:
3679-
self.expect_file('dir/', mode='?---rwsrwt')
3680-
else:
3681-
self.expect_file('dir/', mode='?---rwsrwx')
3701+
self.expect_file('dir/', mode=f'?---rw{_sgid_dir}rw{_t_dir}')
3702+
self.expect_file('dir_all_bits/',
3703+
mode=f'?rw{_suid_dir}rw{_sgid_dir}rw{_t_dir}')
36823704

36833705
with self.check_context(arc.open(), 'tar'):
36843706
self.expect_file('all_bits', mode='?rwxr-xr-x')
@@ -3687,6 +3709,7 @@ def test_modes(self):
36873709
self.expect_file('read_group_only', mode='?---r-----')
36883710
self.expect_file('no_bits', mode='?---------')
36893711
self.expect_file('dir/', mode='?---r-xr-x')
3712+
self.expect_file('dir_all_bits/', mode='?rwxr-xr-x')
36903713

36913714
with self.check_context(arc.open(), 'data'):
36923715
normal_dir_mode = stat.filemode(stat.S_IMODE(
@@ -3697,6 +3720,7 @@ def test_modes(self):
36973720
self.expect_file('read_group_only', mode='?rw-r-----')
36983721
self.expect_file('no_bits', mode='?rw-------')
36993722
self.expect_file('dir/', mode=normal_dir_mode)
3723+
self.expect_file('dir_all_bits/', mode=normal_dir_mode)
37003724

37013725
def test_pipe(self):
37023726
# Test handling of a special file

0 commit comments

Comments
 (0)