summaryrefslogtreecommitdiffstats
path: root/sys-utils/switch_root.c
diff options
context:
space:
mode:
authorPatrick Steinhardt2017-04-23 02:33:04 +0200
committerKarel Zak2017-04-26 11:23:50 +0200
commit85bfb519afcbccccb63849b1a348dde76ff6bb83 (patch)
treef0658d01ddbeae9813977c9c73ba034ab2cd8162 /sys-utils/switch_root.c
parentMerge branch '170415' of github.com:jwpi/util-linux (diff)
downloadkernel-qcow2-util-linux-85bfb519afcbccccb63849b1a348dde76ff6bb83.tar.gz
kernel-qcow2-util-linux-85bfb519afcbccccb63849b1a348dde76ff6bb83.tar.xz
kernel-qcow2-util-linux-85bfb519afcbccccb63849b1a348dde76ff6bb83.zip
switch_root: unlink files without _DIRENT_HAVE_D_TYPE
When _DIRENT_HAVE_D_TYPE is not defined, we need to always fstat the directory entry in order to determine whether it is a directory or not. If we determine that the file is indeed a directory on the same device, we proceed to recursively remove its contents as well. Otherwise, we simply skip removing the entry altogether. This logic is not entirely correct though. Note that we actually skip deletion of the entry if it is either not a directory or if it is not on the same device. The second condition is obviously correct here, as we do not want to delete files on other mounts here. But skipping deletion of the entry itself if it is not a directory is wrong. When _DIRENT_HAVE_D_TYPE is defined, this condition should never be triggered, as we have already determined that the entry is a directory. But if it is not, we will always do the fstat and check. Because of this, we will now skip deletion of all files which are not directories, which is wrong. Fix the issue by disentangling both conditions. We now first check whether we are still on the same device - if not, we skip recursive deletion as well as deletion of the directory entry. Afterwards, we check whether it is a directory - if so, we do delete its contents recursively. And finally, we will now unlink the entry disregarding whether it is a directory or not. Signed-off-by: Patrick Steinhardt <ps@pks.im>
Diffstat (limited to 'sys-utils/switch_root.c')
-rw-r--r--sys-utils/switch_root.c11
1 files changed, 7 insertions, 4 deletions
diff --git a/sys-utils/switch_root.c b/sys-utils/switch_root.c
index 6f5468fca..2b42ddf85 100644
--- a/sys-utils/switch_root.c
+++ b/sys-utils/switch_root.c
@@ -94,8 +94,12 @@ static int recursiveRemove(int fd)
continue;
}
- /* remove subdirectories if device is same as dir */
- if (S_ISDIR(sb.st_mode) && sb.st_dev == rb.st_dev) {
+ /* skip if device is not the same */
+ if (sb.st_dev != rb.st_dev)
+ continue;
+
+ /* remove subdirectories */
+ if (S_ISDIR(sb.st_mode)) {
int cfd;
cfd = openat(dfd, d->d_name, O_RDONLY);
@@ -104,8 +108,7 @@ static int recursiveRemove(int fd)
close(cfd);
}
isdir = 1;
- } else
- continue;
+ }
}
if (unlinkat(dfd, d->d_name, isdir ? AT_REMOVEDIR : 0))