rrsync: deny copy-unsafe-links in restricted dirs; flock fallback

Deny --copy-unsafe-links inside a restricted (non-"/") rrsync directory (it
dereferences a symlink pointing outside the tree and copies the referent
out -- exfiltration), and don't abort the run when flock() is unavailable.

Test: rrsync-copy-unsafe-links-denied.
(cherry picked from commit beaae13ff25d5a8f4435010e0531116fb1d00742)
This commit is contained in:
Andrew Tridgell committed 2026-06-15 15:26:15 +10:00
1 parent 055d0c3a06
commit 0e0803f859
1 file changed
+11 -3
+11 -3
View File
@@ -182,6 +182,7 @@ def main():
if args.dir != '/':
global short_disabled
short_disabled += short_disabled_subdir
long_opts['copy-unsafe-links'] = -1
short_no_arg_re = short_no_arg
short_with_num_re = short_with_num
@@ -333,13 +334,20 @@ def validated_arg(opt, arg, typ=3, wild=False):
def lock_or_die(dirname):
import fcntl
import fcntl, errno
global lock_handle
lock_handle = os.open(dirname, os.O_RDONLY)
try:
fcntl.flock(lock_handle, fcntl.LOCK_EX | fcntl.LOCK_NB)
except:
die('Another instance of rrsync is already accessing this directory.')
except OSError as e:
if e.errno in (errno.EWOULDBLOCK, errno.EAGAIN, errno.EACCES):
die('Another instance of rrsync is already accessing this directory.')
# flock() is unavailable on this fd/platform -- e.g. Solaris returns
# EBADF for flock() on a directory fd. The single-run lock is a
# best-effort convenience (cf. -no-lock), not a security control, so
# proceed without it rather than abort every transfer.
os.close(lock_handle)
lock_handle = None
def die(*msg):