File U_06-Add-rmdir_recursive.patch of Package slurm.31097
From: Tim Wickberg <tim@schedmd.com>
Date: Wed Oct 11 12:45:25 2023 -0600
Subject: [PATCH 6/19]Add rmdir_recursive().
Patch-mainline: Upstream
Git-repo: https://github.com/SchedMD/slurm
Git-commit: 2f4fc8aedf181f182fd9bbcdbf7950c602c6db24
References: bsc#1216207,CVE-2023-41914
Signed-off-by: Egbert Eich <eich@suse.de>
---
src/common/fd.c | 92 ++++++++++++++++++++++++++++++++++++++++++++++-
src/common/fd.h | 9 +++++
src/common/slurm_xlator.h | 1 +
3 files changed, 101 insertions(+), 1 deletion(-)
diff --git a/src/common/fd.c b/src/common/fd.c
index 09a386ecce..103fe441a2 100644
--- a/src/common/fd.c
+++ b/src/common/fd.c
@@ -35,6 +35,7 @@
* Refer to "fd.h" for documentation on public functions.
\*****************************************************************************/
+#include <dirent.h>
#include <assert.h>
#include <errno.h>
#include <fcntl.h>
@@ -53,7 +54,7 @@ strong_alias(fd_read_n, slurm_fd_read_n);
strong_alias(fd_write_n, slurm_fd_write_n);
strong_alias(fd_set_blocking, slurm_fd_set_blocking);
strong_alias(fd_set_nonblocking,slurm_fd_set_nonblocking);
-
+strong_alias(rmdir_recursive, slurm_rmdir_recursive);
static int fd_get_lock(int fd, int cmd, int type);
static pid_t fd_test_lock(int fd, int type);
@@ -237,3 +238,92 @@ extern int wait_fd_readable(int fd, int time_limit)
}
}
}
+
+static int _rmdir_recursive(int dirfd)
+{
+ int rc = 0;
+ DIR *dp;
+ struct dirent *ent;
+
+ if (!(dp = fdopendir(dirfd))) {
+ error("%s: can't open directory: %m", __func__);
+ return 1;
+ }
+
+ while ((ent = readdir(dp))) {
+ int childfd = -1;
+
+ /* skip special directories */
+ if (!strcmp(ent->d_name, ".") ||
+ !strcmp(ent->d_name, "..")) {
+ continue;
+ }
+
+ /* try to remove entry, first as a file, then as a directory */
+ if (unlinkat(dirfd, ent->d_name, 0) != -1) {
+ debug("%s: removed file `%s`", __func__, ent->d_name);
+ continue;
+ } else if (unlinkat(dirfd, ent->d_name, AT_REMOVEDIR) != -1) {
+ debug("%s: removed empty directory `%s`",
+ __func__, ent->d_name);
+ continue;
+ }
+
+ /* removal didn't work. assume it's a non-empty directory */
+ if ((childfd = openat(dirfd, ent->d_name,
+ (O_DIRECTORY | O_NOFOLLOW))) < 0) {
+ debug("%s: openat() failed for `%s`: %m",
+ __func__, ent->d_name);
+ rc++;
+ continue;
+ }
+
+ debug("%s: descending into directory `%s`",
+ __func__, ent->d_name);
+ rc += _rmdir_recursive(childfd);
+ (void) close(childfd);
+
+ if (unlinkat(dirfd, ent->d_name, AT_REMOVEDIR) != -1) {
+ debug("%s: removed now-empty directory `%s`",
+ __func__, ent->d_name);
+ } else {
+ debug("%s: unlinkat() failed for `%s`: %m",
+ __func__, ent->d_name);
+ rc++;
+ }
+ }
+ closedir(dp);
+
+ return rc;
+}
+
+extern int rmdir_recursive(const char *path, bool remove_top)
+{
+ int rc = 0;
+ int dirfd;
+
+ if ((dirfd = open(path, O_DIRECTORY | O_NOFOLLOW)) < 0) {
+ error("%s: could not open %s", __func__, path);
+ return 1;
+ }
+
+ rc = _rmdir_recursive(dirfd);
+ close(dirfd);
+
+ if (remove_top) {
+ if (rmdir(path) < 0) {
+ debug("%s: rmdir() failed for `%s`: %m",
+ __func__, path);
+ rc++;
+ } else {
+ debug("%s: removed now-empty top directory `%s`",
+ __func__, path);
+ }
+ }
+
+ if (rc)
+ error("%s: could not completely remove `%s`, %d files left",
+ __func__, path, rc);
+
+ return rc;
+}
diff --git a/src/common/fd.h b/src/common/fd.h
index 4505d6dce6..46f7b5b859 100644
--- a/src/common/fd.h
+++ b/src/common/fd.h
@@ -130,4 +130,13 @@ extern int wait_fd_readable(int fd, int time_limit);
/* Wait for a file descriptor to be readable (up to time_limit seconds).
* Return 0 when readable or -1 on error */
+/*
+ * Recursively remove a directory and all contents.
+ * Takes care not to follow any symlinks outside the target directory.
+ *
+ * Returns the number of files/directories it failed to remove,
+ * or 0 on success.
+ */
+extern int rmdir_recursive(const char *path, bool remove_top);
+
#endif /* !_FD_H */
diff --git a/src/common/slurm_xlator.h b/src/common/slurm_xlator.h
index 8f2516686a..832b1a0dad 100644
--- a/src/common/slurm_xlator.h
+++ b/src/common/slurm_xlator.h
@@ -115,6 +115,7 @@
#define fd_write_n slurm_fd_write_n
#define fd_set_blocking slurm_fd_set_blocking
#define fd_set_nonblocking slurm_fd_set_nonblocking
+#define rmdir_recursive slurm_rmdir_recursive
/* hostlist.[ch] functions */
#define hostlist_create slurm_hostlist_create