Bug report
Bug description:
test.test_posix.PosixTester._test_all_chown_common asserts that an
"unprivileged" process cannot change a file's group to gid 0:
if hasattr(os, 'getgroups'):
if 0 not in os.getgroups():
self.assertRaises(OSError, chown_func, first_param, -1, 0)
check_stat(uid, gid)
The guard uses only os.getgroups() (the supplementary groups). But the
kernel's permission check for changing a file's group accepts the group if it
is the process's effective/filesystem gid or one of the supplementary
groups (in_group_p() checks fsgid, which tracks egid). os.getgroups() does
not necessarily include the effective gid.
So when a process runs with effective gid 0 and a non-zero uid — common
in containers, user namespaces, and CI sandboxes — chown(file, -1, 0)
succeeds (the process is a member of group 0 via its egid), and the assertion
fails:
AssertionError: OSError not raised by chown
AssertionError: OSError not raised by lchown
The owner-changing assertions just above (chown(file, 0, 0) / (0, -1)) still
correctly raise, since changing the owner requires CAP_CHOWN, which such a
process does not have — so only the group-to-0 assertion is affected.
CPython versions tested on:
CPython main branch, 3.16, 3.15, 3.14
Operating systems tested on:
Linux
Linked PRs
Bug report
Bug description:
test.test_posix.PosixTester._test_all_chown_commonasserts that an"unprivileged" process cannot change a file's group to gid 0:
The guard uses only
os.getgroups()(the supplementary groups). But thekernel's permission check for changing a file's group accepts the group if it
is the process's effective/filesystem gid or one of the supplementary
groups (
in_group_p()checks fsgid, which tracks egid).os.getgroups()doesnot necessarily include the effective gid.
So when a process runs with effective gid 0 and a non-zero uid — common
in containers, user namespaces, and CI sandboxes —
chown(file, -1, 0)succeeds (the process is a member of group 0 via its egid), and the assertion
fails:
The owner-changing assertions just above (
chown(file, 0, 0)/(0, -1)) stillcorrectly raise, since changing the owner requires
CAP_CHOWN, which such aprocess does not have — so only the group-to-0 assertion is affected.
CPython versions tested on:
CPython main branch, 3.16, 3.15, 3.14
Operating systems tested on:
Linux
Linked PRs
_test_all_chown_commongroup-0 guard #151521