]> git.ipfire.org Git - thirdparty/systemd.git/commitdiff
shared/copy: rewind dir fd before using it for cleanup 29677/head
authorZbigniew Jędrzejewski-Szmek <zbyszek@in.waw.pl>
Mon, 23 Oct 2023 12:06:32 +0000 (14:06 +0200)
committerZbigniew Jędrzejewski-Szmek <zbyszek@in.waw.pl>
Tue, 24 Oct 2023 11:37:10 +0000 (13:37 +0200)
This seems to be the only place where rm_rf_children() is called with a
possibly used fd, which is then passed through to rm_rf_children_impl().

This also fixes #29606.
(Tested on Fedora rawhide with kernel 6.5.6-300.fc39.x86_64.)

src/shared/copy.c
src/shared/rm-rf.h

index a2740857e9a3906f8432e9a3372c73244c6e7ef2..c0e30cdc278f520c2184e674a3f5789c28591ca0 100644 (file)
@@ -638,6 +638,10 @@ static void hardlink_context_destroy(HardlinkContext *c) {
          * _cleanup_() so that we really delete this, even on failure. */
 
         if (c->dir_fd >= 0) {
+                /* <dir_fd> might be have already been used for reading, so we need to rewind it. */
+                if (lseek(c->dir_fd, 0, SEEK_SET) < 0)
+                        log_debug_errno(errno, "Failed to lseek on file descriptor, ignoring: %m");
+
                 r = rm_rf_children(TAKE_FD(c->dir_fd), REMOVE_PHYSICAL, NULL); /* consumes dir_fd in all cases, even on failure */
                 if (r < 0)
                         log_debug_errno(r, "Failed to remove hardlink store (%s) contents, ignoring: %m", c->subdir);
index 9d93692e0a6e531123d078365a7efbb89b4d5947..6e52bbb41d4c198dc526b917ded2ff9a44b75912 100644 (file)
@@ -25,6 +25,8 @@ int fstatat_harder(int dfd,
                 int fstatat_flags,
                 RemoveFlags remove_flags);
 
+/* Note: directory file descriptors passed to the functions below must be
+ * positioned at the beginning. If the fd was already used for reading, rewind it. */
 int rm_rf_children(int fd, RemoveFlags flags, const struct stat *root_dev);
 int rm_rf_child(int fd, const char *name, RemoveFlags flags);
 int rm_rf_at(int dir_fd, const char *path, RemoveFlags flags);