]> git.ipfire.org Git - thirdparty/systemd.git/commitdiff
copy: only check for traversing mount points on directories
authorFilipe Brandenburger <filbranden@google.com>
Mon, 4 Jun 2018 21:23:14 +0000 (14:23 -0700)
committerLennart Poettering <lennart@poettering.net>
Thu, 7 Jun 2018 11:14:20 +0000 (13:14 +0200)
This fixes the copy routines on overlay filesystem, which typically
returns the underlying st_dev for files, symlinks, etc.

The value of st_dev is guaranteed to be the same for directories, so
checking it on directories only fixes this code on overlay filesystem
and still keeps it from traversing mount points (which was the original
intent.)

There's a small side effect here, by which regular (non-directory) files
with bind mounts will be copied by the new logic (while they were
skipped by the previous logic.)

Tested: ./build/test-copy with an overlay on /tmp.

Fixes: #9134
src/basic/copy.c

index 650de612b88c3b6dd27148ba2a849dd6e4fa88c7..6ed46241fccec29bbc837d6b5be6a7f6b2d1357b 100644 (file)
@@ -530,13 +530,12 @@ static int fd_copy_directory(
                         continue;
                 }
 
-                if (buf.st_dev != original_device)
-                        continue;
-
-                if (S_ISREG(buf.st_mode))
-                        q = fd_copy_regular(dirfd(d), de->d_name, &buf, fdt, de->d_name, override_uid, override_gid, copy_flags);
-                else if (S_ISDIR(buf.st_mode))
+                if (S_ISDIR(buf.st_mode)) {
+                        if (buf.st_dev != original_device)
+                                continue;
                         q = fd_copy_directory(dirfd(d), de->d_name, &buf, fdt, de->d_name, original_device, override_uid, override_gid, copy_flags);
+                } else if (S_ISREG(buf.st_mode))
+                        q = fd_copy_regular(dirfd(d), de->d_name, &buf, fdt, de->d_name, override_uid, override_gid, copy_flags);
                 else if (S_ISLNK(buf.st_mode))
                         q = fd_copy_symlink(dirfd(d), de->d_name, &buf, fdt, de->d_name, override_uid, override_gid, copy_flags);
                 else if (S_ISFIFO(buf.st_mode))