Commit d3f5c628 authored by Wayne Davison's avatar Wayne Davison

Avoid directory permission issues with --fake-super.

Fixes bug 7070.
parent 8b6ebde1
...@@ -1285,8 +1285,15 @@ static void recv_generator(char *fname, struct file_struct *file, int ndx, ...@@ -1285,8 +1285,15 @@ static void recv_generator(char *fname, struct file_struct *file, int ndx,
fnamecmp = fname; fnamecmp = fname;
if (is_dir) { if (is_dir) {
mode_t added_perms;
if (!implied_dirs && file->flags & FLAG_IMPLIED_DIR) if (!implied_dirs && file->flags & FLAG_IMPLIED_DIR)
goto cleanup; goto cleanup;
if (am_root < 0) {
/* For --fake-super, the dir must be useable by the copying
* user, just like it would be for root. */
added_perms = S_IRUSR|S_IWUSR|S_IXUSR;
} else
added_perms = 0;
if (is_dir < 0) { if (is_dir < 0) {
/* In inc_recurse mode we want to make sure any missing /* In inc_recurse mode we want to make sure any missing
* directories get created while we're still processing * directories get created while we're still processing
...@@ -1297,7 +1304,7 @@ static void recv_generator(char *fname, struct file_struct *file, int ndx, ...@@ -1297,7 +1304,7 @@ static void recv_generator(char *fname, struct file_struct *file, int ndx,
&& (S_ISDIR(sx.st.st_mode) && (S_ISDIR(sx.st.st_mode)
|| delete_item(fname, sx.st.st_mode, del_opts | DEL_FOR_DIR) != 0)) || delete_item(fname, sx.st.st_mode, del_opts | DEL_FOR_DIR) != 0))
goto cleanup; /* Any errors get reported later. */ goto cleanup; /* Any errors get reported later. */
if (do_mkdir(fname, file->mode & 0700) == 0) if (do_mkdir(fname, (file->mode|added_perms) & 0700) == 0)
file->flags |= FLAG_DIR_CREATED; file->flags |= FLAG_DIR_CREATED;
goto cleanup; goto cleanup;
} }
...@@ -1340,10 +1347,10 @@ static void recv_generator(char *fname, struct file_struct *file, int ndx, ...@@ -1340,10 +1347,10 @@ static void recv_generator(char *fname, struct file_struct *file, int ndx,
itemize(fnamecmp, file, ndx, statret, &sx, itemize(fnamecmp, file, ndx, statret, &sx,
statret ? ITEM_LOCAL_CHANGE : 0, 0, NULL); statret ? ITEM_LOCAL_CHANGE : 0, 0, NULL);
} }
if (real_ret != 0 && do_mkdir(fname,file->mode) < 0 && errno != EEXIST) { if (real_ret != 0 && do_mkdir(fname,file->mode|added_perms) < 0 && errno != EEXIST) {
if (!relative_paths || errno != ENOENT if (!relative_paths || errno != ENOENT
|| make_path(fname, MKP_DROP_NAME | MKP_SKIP_SLASH) < 0 || make_path(fname, MKP_DROP_NAME | MKP_SKIP_SLASH) < 0
|| (do_mkdir(fname, file->mode) < 0 && errno != EEXIST)) { || (do_mkdir(fname, file->mode|added_perms) < 0 && errno != EEXIST)) {
rsyserr(FERROR_XFER, errno, rsyserr(FERROR_XFER, errno,
"recv_generator: mkdir %s failed", "recv_generator: mkdir %s failed",
full_fname(fname)); full_fname(fname));
......
...@@ -24,6 +24,7 @@ ...@@ -24,6 +24,7 @@
extern int dry_run; extern int dry_run;
extern int do_xfers; extern int do_xfers;
extern int am_root;
extern int am_server; extern int am_server;
extern int inc_recurse; extern int inc_recurse;
extern int log_before_transfer; extern int log_before_transfer;
...@@ -173,15 +174,25 @@ int get_tmpname(char *fnametmp, const char *fname, BOOL make_unique) ...@@ -173,15 +174,25 @@ int get_tmpname(char *fnametmp, const char *fname, BOOL make_unique)
int open_tmpfile(char *fnametmp, const char *fname, struct file_struct *file) int open_tmpfile(char *fnametmp, const char *fname, struct file_struct *file)
{ {
int fd; int fd;
mode_t added_perms;
if (!get_tmpname(fnametmp, fname, False)) if (!get_tmpname(fnametmp, fname, False))
return -1; return -1;
if (am_root < 0) {
/* For --fake-super, the file must be useable by the copying
* user, just like it would be for root. */
added_perms = S_IRUSR|S_IWUSR;
} else {
/* For a normal copy, we need to be able to tweak things like xattrs. */
added_perms = S_IWUSR;
}
/* We initially set the perms without the setuid/setgid bits or group /* We initially set the perms without the setuid/setgid bits or group
* access to ensure that there is no race condition. They will be * access to ensure that there is no race condition. They will be
* correctly updated after the right owner and group info is set. * correctly updated after the right owner and group info is set.
* (Thanks to snabb@epipe.fi for pointing this out.) */ * (Thanks to snabb@epipe.fi for pointing this out.) */
fd = do_mkstemp(fnametmp, (file->mode & INITACCESSPERMS) | S_IWUSR); fd = do_mkstemp(fnametmp, (file->mode|added_perms) & INITACCESSPERMS);
#if 0 #if 0
/* In most cases parent directories will already exist because their /* In most cases parent directories will already exist because their
...@@ -191,7 +202,7 @@ int open_tmpfile(char *fnametmp, const char *fname, struct file_struct *file) ...@@ -191,7 +202,7 @@ int open_tmpfile(char *fnametmp, const char *fname, struct file_struct *file)
&& make_path(fnametmp, MKP_SKIP_SLASH | MKP_DROP_NAME) == 0) { && make_path(fnametmp, MKP_SKIP_SLASH | MKP_DROP_NAME) == 0) {
/* Get back to name with XXXXXX in it. */ /* Get back to name with XXXXXX in it. */
get_tmpname(fnametmp, fname, False); get_tmpname(fnametmp, fname, False);
fd = do_mkstemp(fnametmp, file->mode & INITACCESSPERMS); fd = do_mkstemp(fnametmp, (file->mode|added_perms) & INITACCESSPERMS);
} }
#endif #endif
......
...@@ -48,7 +48,8 @@ makepath "$chkdir/foo" ...@@ -48,7 +48,8 @@ makepath "$chkdir/foo"
echo wow >"$chkdir/file1" echo wow >"$chkdir/file1"
cp_touch "$fromdir/foo/file3" "$chkdir/foo" cp_touch "$fromdir/foo/file3" "$chkdir/foo"
files='foo file0 file1 file2 foo/file3 file4 foo/bar/file5' files='foo file0 file1 file2 foo/file3 file4 foo/bar foo/bar/file5'
uid_gid=`"$TOOLDIR/tls" "$fromdir/foo" | sed 's/^.* \([0-9][0-9]*\)\.\([0-9][0-9]*\) .*/\1:\2/'`
cd "$fromdir" cd "$fromdir"
...@@ -106,12 +107,35 @@ checkit "$RSYNC -aiX --fake-super --link-dest=../chk . ../to" "$chkdir" "$todir" ...@@ -106,12 +107,35 @@ checkit "$RSYNC -aiX --fake-super --link-dest=../chk . ../to" "$chkdir" "$todir"
cd "$todir" cd "$todir"
xls $files | diff $diffopt "$scratchdir/xattrs.txt" - xls $files | diff $diffopt "$scratchdir/xattrs.txt" -
sed -n -e '/\.\/file1$/d' -e '/^[^ ][^ ]* *[^ ][^ ]* *[^ ][^ ]* *1 /p' "$scratchdir/ls-to" >"$scratchdir/ls-diff" sed -n -e '/^[^ ][^ ]* *[^ ][^ ]* *[^ ][^ ]* *1 /p' "$scratchdir/ls-to" >"$scratchdir/ls-diff-all"
fgrep -v './file1' "$scratchdir/ls-diff-all" >"$scratchdir/ls-diff" || :
if [ -s "$scratchdir/ls-diff" ]; then if [ -s "$scratchdir/ls-diff" ]; then
echo "Missing hard links on:" echo "Missing hard links on:"
cat "$scratchdir/ls-diff" cat "$scratchdir/ls-diff"
exit 1 exit 1
fi fi
if [ ! -s "$scratchdir/ls-diff-all" ]; then
echo "Too many hard links on file1!"
exit 1
fi
cd "$chkdir"
chmod go-rwx . $files
xset user.nice 'this is nice, but different' file1
xset user.rsync.%stat "100000 0,0 $uid_gid" $files
xset user.rsync.%stat "40000 0,0 $uid_gid" foo foo/bar
xls $files >"$scratchdir/xattrs.txt"
cd "$fromdir"
rm -rf "$todir"
# When run by a non-root tester, this checks if no-user-perm files/dirs can be copied.
checkit "$RSYNC -aiX --fake-super --chmod=a= . ../to" "$chkdir" "$todir" # 2>"$scratchdir/errors.txt"
cd "$todir"
xls $files | diff $diffopt "$scratchdir/xattrs.txt" -
cd "$fromdir" cd "$fromdir"
rm -rf "$todir" "$chkdir" rm -rf "$todir" "$chkdir"
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment