cef061bd68
Resolves: RHEL-1087,RHEL-18302,RHEL-22426,RHEL-2857,RHEL-5863,RHEL-5991
111 lines
4.2 KiB
Diff
111 lines
4.2 KiB
Diff
From c2665abd4cae74f262d9a522b94528841ad141d2 Mon Sep 17 00:00:00 2001
|
|
From: Lennart Poettering <lennart@poettering.net>
|
|
Date: Tue, 12 Oct 2021 15:53:27 +0200
|
|
Subject: [PATCH] fd-util: split out inner fallback loop of close_all_fds() as
|
|
close_all_fds_without_malloc()
|
|
|
|
(cherry picked from commit 11966552a88039869972ca4b450f622664bd1c5e)
|
|
|
|
Related: RHEL-18302
|
|
---
|
|
src/basic/fd-util.c | 63 +++++++++++++++++++++++++--------------------
|
|
src/basic/fd-util.h | 1 +
|
|
2 files changed, 36 insertions(+), 28 deletions(-)
|
|
|
|
diff --git a/src/basic/fd-util.c b/src/basic/fd-util.c
|
|
index 5d0df11d7e..7e4611dfda 100644
|
|
--- a/src/basic/fd-util.c
|
|
+++ b/src/basic/fd-util.c
|
|
@@ -213,44 +213,51 @@ static int get_max_fd(void) {
|
|
return (int) (m - 1);
|
|
}
|
|
|
|
-int close_all_fds(const int except[], size_t n_except) {
|
|
- _cleanup_closedir_ DIR *d = NULL;
|
|
- struct dirent *de;
|
|
- int r = 0;
|
|
+int close_all_fds_without_malloc(const int except[], size_t n_except) {
|
|
+ int max_fd, r = 0;
|
|
|
|
assert(n_except == 0 || except);
|
|
|
|
- d = opendir("/proc/self/fd");
|
|
- if (!d) {
|
|
- int fd, max_fd;
|
|
+ /* This is the inner fallback core of close_all_fds(). This never calls malloc() or opendir() or so
|
|
+ * and hence is safe to be called in signal handler context. Most users should call close_all_fds(),
|
|
+ * but when we assume we are called from signal handler context, then use this simpler call
|
|
+ * instead. */
|
|
|
|
- /* When /proc isn't available (for example in chroots) the fallback is brute forcing through
|
|
- * the fd table */
|
|
+ max_fd = get_max_fd();
|
|
+ if (max_fd < 0)
|
|
+ return max_fd;
|
|
|
|
- max_fd = get_max_fd();
|
|
- if (max_fd < 0)
|
|
- return max_fd;
|
|
+ /* Refuse to do the loop over more too many elements. It's better to fail immediately than to
|
|
+ * spin the CPU for a long time. */
|
|
+ if (max_fd > MAX_FD_LOOP_LIMIT)
|
|
+ return log_debug_errno(EPERM,
|
|
+ "Refusing to loop over %d potential fds.",
|
|
+ max_fd);
|
|
|
|
- /* Refuse to do the loop over more too many elements. It's better to fail immediately than to
|
|
- * spin the CPU for a long time. */
|
|
- if (max_fd > MAX_FD_LOOP_LIMIT)
|
|
- return log_debug_errno(EPERM,
|
|
- "/proc/self/fd is inaccessible. Refusing to loop over %d potential fds.",
|
|
- max_fd);
|
|
+ for (int fd = 3; fd >= 0; fd = fd < max_fd ? fd + 1 : -1) {
|
|
+ int q;
|
|
|
|
- for (fd = 3; fd >= 0; fd = fd < max_fd ? fd + 1 : -1) {
|
|
- int q;
|
|
+ if (fd_in_set(fd, except, n_except))
|
|
+ continue;
|
|
|
|
- if (fd_in_set(fd, except, n_except))
|
|
- continue;
|
|
+ q = close_nointr(fd);
|
|
+ if (q < 0 && q != -EBADF && r >= 0)
|
|
+ r = q;
|
|
+ }
|
|
|
|
- q = close_nointr(fd);
|
|
- if (q < 0 && q != -EBADF && r >= 0)
|
|
- r = q;
|
|
- }
|
|
+ return r;
|
|
+}
|
|
|
|
- return r;
|
|
- }
|
|
+int close_all_fds(const int except[], size_t n_except) {
|
|
+ _cleanup_closedir_ DIR *d = NULL;
|
|
+ struct dirent *de;
|
|
+ int r = 0;
|
|
+
|
|
+ assert(n_except == 0 || except);
|
|
+
|
|
+ d = opendir("/proc/self/fd");
|
|
+ if (!d)
|
|
+ return close_all_fds_without_malloc(except, n_except); /* ultimate fallback if /proc/ is not available */
|
|
|
|
FOREACH_DIRENT(de, d, return -errno) {
|
|
int fd = -1, q;
|
|
diff --git a/src/basic/fd-util.h b/src/basic/fd-util.h
|
|
index 8adc959da8..b2837d3588 100644
|
|
--- a/src/basic/fd-util.h
|
|
+++ b/src/basic/fd-util.h
|
|
@@ -54,6 +54,7 @@ int fd_nonblock(int fd, bool nonblock);
|
|
int fd_cloexec(int fd, bool cloexec);
|
|
|
|
int close_all_fds(const int except[], size_t n_except);
|
|
+int close_all_fds_without_malloc(const int except[], size_t n_except);
|
|
|
|
int same_fd(int a, int b);
|
|
|