From e3b84b105e632731352776fd619bbbea4d223b35 Mon Sep 17 00:00:00 2001 From: =?utf8?q?Zbigniew=20J=C4=99drzejewski-Szmek?= Date: Mon, 23 Oct 2023 14:06:32 +0200 Subject: [PATCH] shared/copy: rewind dir fd before using it for cleanup 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 | 4 ++++ src/shared/rm-rf.h | 2 ++ 2 files changed, 6 insertions(+) diff --git a/src/shared/copy.c b/src/shared/copy.c index a2740857e9a..c0e30cdc278 100644 --- a/src/shared/copy.c +++ b/src/shared/copy.c @@ -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) { + /* 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); diff --git a/src/shared/rm-rf.h b/src/shared/rm-rf.h index 9d93692e0a6..6e52bbb41d4 100644 --- a/src/shared/rm-rf.h +++ b/src/shared/rm-rf.h @@ -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); -- 2.47.3