2
0
mirror of https://github.com/xcat2/confluent.git synced 2026-09-21 08:33:23 +00:00

Apply chown before chmod in syncfileclient permission handling

chown() clears the setuid bit of a file on Linux (and its setgid bit, if
the file is group-executable), even when run by root and even when the
owner/group are unchanged. Since the owner/group chown ran after the
permissions chmod, any syncfiles entry combining owner=/group= with a
setuid/setgid permissions= value silently lost the special bits.
This commit is contained in:
Markus Hilger
2026-08-04 04:24:30 +02:00
parent a806466f20
commit 9788d563aa
3 changed files with 22 additions and 4 deletions
@@ -301,6 +301,7 @@ def synchronize():
for fname in opts:
uid = -1
gid = -1
perms = None
for opt in opts[fname]:
if opt == 'owner':
try:
@@ -309,16 +310,21 @@ def synchronize():
try:
uid = opts[fname][opt]['id']
except KeyError:
raise Exception(f"Unable to map owner of {fname}")
raise Exception(f"Unable to map owner of {fname}")
elif opt == 'group':
try:
gid = grp.getgrnam(opts[fname][opt]['name']).gr_gid
except KeyError:
gid = opts[fname][opt]['id']
elif opt == 'permissions':
os.chmod(fname, int(opts[fname][opt], 8))
perms = int(opts[fname][opt], 8)
if uid != -1 or gid != -1:
# chown clears setuid (and setgid on a group-executable
# file), even for root, so it must happen before the
# chmod that applies them
os.chown(fname, uid, gid)
if perms is not None:
os.chmod(fname, perms)
return status
finally:
shutil.rmtree(tmpdir)
@@ -287,6 +287,7 @@ def synchronize():
for fname in opts:
uid = -1
gid = -1
perms = None
for opt in opts[fname]:
if opt == 'owner':
try:
@@ -299,9 +300,14 @@ def synchronize():
except KeyError:
gid = opts[fname][opt]['id']
elif opt == 'permissions':
os.chmod(fname, int(opts[fname][opt], 8))
perms = int(opts[fname][opt], 8)
if uid != -1 or gid != -1:
# chown clears setuid (and setgid on a group-executable
# file), even for root, so it must happen before the
# chmod that applies them
os.chown(fname, uid, gid)
if perms is not None:
os.chmod(fname, perms)
finally:
shutil.rmtree(tmpdir)
shutil.rmtree(appendoncedir)
@@ -287,6 +287,7 @@ def synchronize():
for fname in opts:
uid = -1
gid = -1
perms = None
for opt in opts[fname]:
if opt == 'owner':
try:
@@ -299,9 +300,14 @@ def synchronize():
except KeyError:
gid = opts[fname][opt]['id']
elif opt == 'permissions':
os.chmod(fname, int(opts[fname][opt], 8))
perms = int(opts[fname][opt], 8)
if uid != -1 or gid != -1:
# chown clears setuid (and setgid on a group-executable
# file), even for root, so it must happen before the
# chmod that applies them
os.chown(fname, uid, gid)
if perms is not None:
os.chmod(fname, perms)
finally:
shutil.rmtree(tmpdir)
shutil.rmtree(appendoncedir)