Package: rsync
Version: 3.2.7-1
Severity: normal
X-Debbugs-Cc: [email protected]
Dear Maintainer,
I found a regression in rrsync, which came with the change from Perl (Bullseye)
to Python (Bookworm), and would like to propose a bug fix.
* What led up to the situation?
I am using backupninja to create local backups from a remote server. With
Bullseye, I had to use the following line in the configuration file to make it
work with rrsync:
include = .
backupninja converts this to the command
rsync <arguments> user@remoteserver:/./ /localbackupdir/
to read the complete subdirectory defined by rrsync (see below) and store it in
the local backup directory.
authorized_keys on the remote server:
command="/usr/bin/rrsync -ro /path/to/restricted/source/",restrict ssh-rsa
...
Starting with Bookworm, rrsync breaks the backup process with the error "unsafe
arg":
(Output of die('unsafe arg:', orig_arg, [arg, real_arg]) )
unsafe arg: /./, [/path/to/restricted/source/., /path/to/restricted/source]
Note that arg is not equal to real_arg, since the trailing "/./" of the
original argument (orig_arg) is not completely stripped from arg.
* What exactly did you do (or not do) that was effective (or ineffective)?
I found that in rrsync, there is a directory argument check that is too
restrictive to work with above (valid) string:
rrsync 3.2.7 (as in Bookworm):
https://salsa.debian.org/debian/rsync/-/blob/debian/3.2.7-1/support/rrsync?ref_type=tags#L309
ret = [ ]
for arg in got:
if args.dir != '/' and arg != '.' and (typ == 3 or (typ == 2 and not
am_sender)):
arg_has_trailing_slash = arg.endswith('/')
if arg_has_trailing_slash:
arg = arg[:-1]
else:
arg_has_trailing_slash_dot = arg.endswith('/.')
if arg_has_trailing_slash_dot:
arg = arg[:-2]
real_arg = os.path.realpath(arg)
if arg != real_arg and not real_arg.startswith(args.dir_slash):
die('unsafe arg:', orig_arg, [arg, real_arg])
if arg_has_trailing_slash:
arg += '/'
elif arg_has_trailing_slash_dot:
arg += '/.'
if opt == 'arg' and arg.startswith(args.dir_slash):
arg = arg[args.dir_slash_len:]
if arg == '':
arg = '.'
ret.append(arg)
After a small patch, the code seems still valid for me, but allowing a trailing
"/" after a trailing "/.", therefore allowing a trailing "/./".
My proposed patch:
ret = [ ]
for arg in got:
if args.dir != '/' and arg != '.' and (typ == 3 or (typ == 2 and not
am_sender)):
1. arg_has_trailing_slash = arg.endswith('/')
if arg_has_trailing_slash:
arg = arg[:-1]
2. arg_has_trailing_slash_dot = arg.endswith('/.')
if arg_has_trailing_slash_dot:
arg = arg[:-2]
3. real_arg = os.path.realpath(arg)
if arg != real_arg and not real_arg.startswith(args.dir_slash):
die('unsafe arg:', orig_arg, [arg, real_arg])
4. if arg_has_trailing_slash_dot:
arg += '/.'
5. if arg_has_trailing_slash:
arg += '/'
if opt == 'arg' and arg.startswith(args.dir_slash):
arg = arg[args.dir_slash_len:]
if arg == '':
arg = '.'
ret.append(arg)
1. Trailing "/" is removed.
2. Trailing "/." is removed.
3. Directory is checked.
4. Trailing "/." is appended again.
5. Trailing "/" is appended again.
Please check carefully, I am not familiar with the Python language.
* What was the outcome of this action?
The check in line 320 (
https://salsa.debian.org/debian/rsync/-/blob/debian/3.2.7-1/support/rrsync?ref_type=tags#L320
) does not fail, which is the intended result.
Thank you in advance.
-- System Information:
Debian Release: 12.1
APT prefers stable-updates
APT policy: (500, 'stable-updates'), (500, 'stable-security'), (500, 'stable')
Architecture: amd64 (x86_64)
Foreign Architectures: i386
Kernel: Linux 6.1.0-10-amd64 (SMP w/8 CPU threads; PREEMPT)
Kernel taint flags: TAINT_WARN, TAINT_OOT_MODULE, TAINT_UNSIGNED_MODULE
Locale: LANG=en_US.UTF-8, LC_CTYPE=de_DE.UTF-8 (charmap=UTF-8),
LANGUAGE=en_US:en
Shell: /bin/sh linked to /usr/bin/dash
Init: systemd (via /run/systemd/system)
LSM: AppArmor: enabled
Versions of packages rsync depends on:
ii init-system-helpers 1.65.2
ii libacl1 2.3.1-3
ii libc6 2.36-9+deb12u1
ii liblz4-1 1.9.4-1
ii libpopt0 1.19+dfsg-1
ii libssl3 3.0.9-1
ii libxxhash0 0.8.1-1
ii libzstd1 1.5.4+dfsg2-5
ii lsb-base 11.6
ii sysvinit-utils [lsb-base] 3.06-4
ii zlib1g 1:1.2.13.dfsg-1
rsync recommends no packages.
Versions of packages rsync suggests:
ii openssh-client 1:9.2p1-2
ii openssh-server 1:9.2p1-2
ii python3 3.11.2-1+b1
pn python3-braceexpand <none>
-- no debconf information