Skip to content

Commit

Permalink
rsyslog: add patch for issue 5158 (#10989)
Browse files Browse the repository at this point in the history
  • Loading branch information
anphel31 authored Jan 30, 2025
1 parent 63f3442 commit 9e039e7
Show file tree
Hide file tree
Showing 2 changed files with 191 additions and 1 deletion.
185 changes: 185 additions & 0 deletions SPECS/rsyslog/issue5158.patch
Original file line number Diff line number Diff line change
@@ -0,0 +1,185 @@
From a2e87cc6ae847ec3de21cae3dc4c3e24b306bd71 Mon Sep 17 00:00:00 2001
From: Rainer Gerhards <[email protected]>
Date: Tue, 26 Sep 2023 14:38:44 +0200
Subject: [PATCH] fix startup issue on modern systemd systems

close all unneeded file descriptors. Not doing this has some
security implications. Traditionally, we do this by iterating
over all possible file descriptor values. This is fairly compatible,
because we need no OS-specific method. However, modern systemd configs
tend to not limit the number of fds, so there are potentially 2^30(*)
fds to close. While this is OKish, it takes some time and makes
systemd think that rsyslog did not properly start up.

We have now solved this by using the /proc filesystem to obtain our
currently open fds. This works for Linux, as well as Cygwin, NetBSD,
FreeBDS and MacOS. Where not available,and close_range() is available
on the (build) platform, we try to use it. If that fails as well, we
fall back to the traditional method. In our opionion, this fallback
is unproblematic, as on these platforms there is no systemd and in
almost all cases a decent number of fds to close.

Very special thanks go out to Brennan Kinney, who clearly described
the issue to us on github and also provided ample ways to solve it.
What we did is just implement what we think is the best fit from
rsyslog's PoV.

(*) Some details below on the number of potentially to close fds.
This is directly from a github posting from Brennan Kinney.
Just to clarify, by default since systemd v240 (2018Q4), that
should be `1024:524288` limit. As in the soft limit is the expected
`1024`.

The problem is other software shipping misconfiguration in systemd
services that overrides this to something silly like
`LimitNOFILE=infinity`.
- Which will map to the sysctl `fs.nr_open` (_a value systemd
v240 also raises from `2^20` to 2^30`, some distro like Debian are
known to opt-out via patch for the `fs.nr_open` change_).
- With the biggest issue there being that the soft limit was also
set to `infinity` instead of their software requesting to raise
the soft limit to a higher value that the hard limit permits.
`infinity` isn't at all sane though.
- The known source of this misconfiguration is container software such
as Docker and `containerd` (_which would often sync with the
systemd `.service` config from the Docker daemon `dockerd.service`_).

closes https://github.com/rsyslog/rsyslog/issues/5158

---
configure.ac | 4 +--
tools/rsyslogd.c | 68 +++++++++++++++++++++++++++++++++++++++++++-----
2 files changed, 63 insertions(+), 9 deletions(-)

diff --git a/configure.ac b/configure.ac
index 247a155a1..95ce0287e 100644
--- a/configure.ac
+++ b/configure.ac
@@ -200,7 +200,7 @@ AC_CHECK_HEADERS([malloc.h],[],[],[
#endif
]
])
-AC_CHECK_HEADERS([fcntl.h locale.h netdb.h netinet/in.h paths.h stddef.h stdlib.h string.h sys/file.h sys/ioctl.h sys/param.h sys/socket.h sys/time.h sys/stat.h unistd.h utmp.h utmpx.h sys/epoll.h sys/prctl.h sys/select.h getopt.h])
+AC_CHECK_HEADERS([fcntl.h locale.h netdb.h netinet/in.h paths.h stddef.h stdlib.h string.h sys/file.h sys/ioctl.h sys/param.h sys/socket.h sys/time.h sys/stat.h unistd.h utmp.h utmpx.h sys/epoll.h sys/prctl.h sys/select.h getopt.h linux/close_range.h])

# Checks for typedefs, structures, and compiler characteristics.
AC_C_CONST
@@ -233,7 +233,7 @@ AC_TYPE_SIGNAL
AC_FUNC_STAT
AC_FUNC_STRERROR_R
AC_FUNC_VPRINTF
-AC_CHECK_FUNCS([flock recvmmsg basename alarm clock_gettime gethostbyname gethostname gettimeofday localtime_r memset mkdir regcomp select setsid socket strcasecmp strchr strdup strerror strndup strnlen strrchr strstr strtol strtoul uname ttyname_r getline malloc_trim prctl epoll_create epoll_create1 fdatasync syscall lseek64 asprintf])
+AC_CHECK_FUNCS([flock recvmmsg basename alarm clock_gettime gethostbyname gethostname gettimeofday localtime_r memset mkdir regcomp select setsid socket strcasecmp strchr strdup strerror strndup strnlen strrchr strstr strtol strtoul uname ttyname_r getline malloc_trim prctl epoll_create epoll_create1 fdatasync syscall lseek64 asprintf close_range])
AC_CHECK_FUNC([setns], [AC_DEFINE([HAVE_SETNS], [1], [Define if setns exists.])])
AC_CHECK_TYPES([off64_t])

diff --git a/tools/rsyslogd.c b/tools/rsyslogd.c
index 6b8aa93a9..0c6e4cdec 100644
--- a/tools/rsyslogd.c
+++ b/tools/rsyslogd.c
@@ -3,7 +3,7 @@
* because it was either written from scratch by me (rgerhards) or
* contributors who agreed to ASL 2.0.
*
- * Copyright 2004-2019 Rainer Gerhards and Adiscon
+ * Copyright 2004-2023 Rainer Gerhards and Adiscon
*
* This file is part of rsyslog.
*
@@ -27,6 +27,7 @@
#include <stdlib.h>
#include <sys/types.h>
#include <sys/wait.h>
+#include <dirent.h>
#include <unistd.h>
#include <errno.h>
#ifdef ENABLE_LIBLOGGING_STDLOG
@@ -37,6 +38,9 @@
#ifdef HAVE_LIBSYSTEMD
# include <systemd/sd-daemon.h>
#endif
+#if defined(HAVE_LINUX_CLOSE_RANGE_H)
+# include <linux/close_range.h>
+#endif

#include "rsyslog.h"
#include "wti.h"
@@ -339,6 +343,36 @@ finalize_it:
RETiRet;
}

+
+
+/* note: this function is specific to OS'es which provide
+ * the ability to read open file descriptors via /proc.
+ * returns 0 - success, something else otherwise
+ */
+static int
+close_unneeded_open_files(const char *const procdir,
+ const int beginClose, const int parentPipeFD)
+{
+ DIR *dir;
+ struct dirent *entry;
+
+ dir = opendir(procdir);
+ if (dir == NULL) {
+ dbgprintf("closes unneeded files: opendir failed for %s\n", procdir);
+ return 1;
+ }
+
+ while ((entry = readdir(dir)) != NULL) {
+ const int fd = atoi(entry->d_name);
+ if(fd >= beginClose && (((fd != dbgGetDbglogFd()) && (fd != parentPipeFD)))) {
+ close(fd);
+ }
+ }
+
+ closedir(dir);
+ return 0;
+}
+
/* prepares the background processes (if auto-backbrounding) for
* operation.
*/
@@ -384,12 +418,32 @@ prepareBackground(const int parentPipeFD)
}
#endif

- /* close unnecessary open files */
- const int endClose = getdtablesize();
- close(0);
- for(int i = beginClose ; i <= endClose ; ++i) {
- if((i != dbgGetDbglogFd()) && (i != parentPipeFD)) {
- aix_close_it(i); /* AIXPORT */
+ /* close unnecessary open files - first try to use /proc file system,
+ * if that is not possible iterate through all potentially open file
+ * descriptors. This can be lenghty, but in practice /proc should work
+ * for almost all current systems, and the fallback is primarily for
+ * Solaris and AIX, where we do expect a decent max numbers of fds.
+ */
+ close(0); /* always close stdin, we do not need it */
+
+ /* try Linux, Cygwin, NetBSD */
+ if(close_unneeded_open_files("/proc/self/fd", beginClose, parentPipeFD) != 0) {
+ /* try MacOS, FreeBSD */
+ if(close_unneeded_open_files("/proc/fd", beginClose, parentPipeFD) != 0) {
+ /* did not work out, so let's close everything... */
+ const int endClose = getdtablesize();
+# if defined(HAVE_CLOSE_RANGE)
+ if(close_range(beginClose, endClose, 0) != 0) {
+ dbgprintf("errno %d after close_range(), fallback to loop\n", errno);
+# endif
+ for(int i = beginClose ; i <= endClose ; ++i) {
+ if((i != dbgGetDbglogFd()) && (i != parentPipeFD)) {
+ aix_close_it(i); /* AIXPORT */
+ }
+ }
+# if defined(HAVE_CLOSE_RANGE)
+ }
+# endif
}
}
seedRandomNumberForChild();
--
2.33.8

7 changes: 6 additions & 1 deletion SPECS/rsyslog/rsyslog.spec
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,7 @@
Summary: Rocket-fast system for log processing
Name: rsyslog
Version: 8.2204.1
Release: 3%{?dist}
Release: 4%{?dist}
License: GPLv3+ AND ASL 2.0
Vendor: Microsoft Corporation
Distribution: Mariner
Expand All @@ -16,6 +16,7 @@ Source3: rsyslog.conf
# Upstream only publishes built docs for base_version.0
Source4: https://www.rsyslog.com/files/download/rsyslog/%{name}-doc-%{base_version}.0.tar.gz
Source5: rsyslog.logrotate
Patch0: issue5158.patch
BuildRequires: autogen
BuildRequires: curl-devel
BuildRequires: gnutls-devel
Expand Down Expand Up @@ -66,6 +67,7 @@ HTML documentation for %{name}
%prep
# Unpack the code source tarball
%setup -q
%patch 0 -p1
# Unpack the documentation tarball in the folder created above
%setup -q -a 4 -T -D
# Remove documentation sources
Expand Down Expand Up @@ -175,6 +177,9 @@ fi
%doc %{_docdir}/%{name}/html

%changelog
* Fri Nov 08 2024 Andrew Phelps <[email protected]> - 8.2204.1-4
- Add patch to fix upstream issue #5158

* Wed Oct 12 2022 Nan Liu <[email protected]> - 8.2204.1-3
- Add rsyslog configuration file to /etc/logrotate.d

Expand Down

0 comments on commit 9e039e7

Please sign in to comment.