Skip to content

Commit

Permalink
core/openrc: use close_range in start-stop-daemon
Browse files Browse the repository at this point in the history
[ commit 76c4c51f8e4cdd27fbc76ecd2439d01260cadfd4 ]

upstream: OpenRC/openrc#645
  • Loading branch information
ncopa authored and akodanev committed Sep 6, 2023
1 parent 517687e commit bc47813
Show file tree
Hide file tree
Showing 2 changed files with 312 additions and 1 deletion.
4 changes: 3 additions & 1 deletion core/openrc/APKBUILD
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,7 @@
pkgname=openrc
pkgver=0.48
_ver=${pkgver/_git*/}
pkgrel=0
pkgrel=1
pkgdesc="OpenRC dependency-based init system"
url="https://github.com/OpenRC/openrc"
arch="all"
Expand Down Expand Up @@ -35,6 +35,7 @@ source="$pkgname-$pkgver.tar.gz::https://github.com/OpenRC/openrc/archive/$pkgve
supervise-daemon-defaults.patch
sysctl-readme.patch
cloexec_fds.patch
openrc.logrotate
hostname.initd
Expand Down Expand Up @@ -186,6 +187,7 @@ c67c0a1c87f44a6fde0a7634fcdff0683a821eef5183a4f3e1ef850d04dd7f6c23ec0a72b4a76d9f
475f4ea63b9b5d7eb9c623e96b6cc3d3072abcb7194d0045b84e0688836c8514fccfc68b0eae0b4bee60878cdea8042c3ce7e48406ee7a2f0e4a3e128a153468 0008-bootmisc-switch-wipe_tmp-setting-to-no-by-default.patch
1323a8476580f7b56a9cf1b24b26b10da76c5916cf23d7dab01f08a3261751341dfe01d1ed884df8e6ea17ff6a52021cc40fb3101e99b77d4ae7f3f61ee330e8 supervise-daemon-defaults.patch
903ff555275a67ff08da91badb55d9fa6c6a2901e8ef09ca8366bd74d69757491c8336347f04551268ecf053c8ae974f50decd869926894dd94e382008e3e925 sysctl-readme.patch
fc4cc4bd37dbf9978345564bf68349abeb59be252fc9e2fa649af6be2b96eb3b3f8e35a23f84b4377af5c5a25b667f95b76b3acc6861cfabe73462dde54d8e29 cloexec_fds.patch
12bb6354e808fbf47bbab963de55ee7901738b4a912659982c57ef2777fff9a670e867fcb8ec316a76b151032c92dc89a950d7d1d835ef53f753a8f3b41d2cec openrc.logrotate
26858b0b91d5e9910a74915d94639d778489457c96d68086d9a755ab1a7dae64c6d69f20db72d4f7e4a6055a88405ea3a988aa73818fc996c09fd4f21c13437a hostname.initd
28c212de6ef0d1c03d4eb27f985ff75f4f96be5f4ebcef95519e4b82d388434ddad435de0527183d1d23536292acb07094e57038fe5c79e8fa79559785d713c2 modules.initd
Expand Down
309 changes: 309 additions & 0 deletions core/openrc/cloexec_fds.patch
Original file line number Diff line number Diff line change
@@ -0,0 +1,309 @@
From 90744198869f4adf349ee7dba3cc13ad66907d46 Mon Sep 17 00:00:00 2001
From: Natanael Copa <[email protected]>
Date: Wed, 30 Aug 2023 11:33:37 +0200
Subject: [PATCH 1/4] supervise-daemon: rename HAVE_CLOSE_RANGE_EXEC to
HAVE_CLOSE_RANGE

Use HAVE_CLOSE_RANGE to tell if system provides a close_range(2)
wrapper, which better explains the purpose.

Add a compat inline which returns -1 if close_range is unavailable.
---
meson.build | 5 ++---
src/supervise-daemon/supervise-daemon.c | 16 +++++++++++++---
2 files changed, 15 insertions(+), 6 deletions(-)

diff --git a/meson.build b/meson.build
index 73cb9778..d04171b3 100644
--- a/meson.build
+++ b/meson.build
@@ -198,9 +198,8 @@ endif
if cc.has_function('closefrom', prefix: '#define _GNU_SOURCE\n#include <unistd.h>')
add_project_arguments('-DHAVE_CLOSEFROM', language: 'c')
endif
-if cc.has_function('close_range', prefix: '#define _GNU_SOURCE\n#include <unistd.h>') and \
- cc.has_header_symbol('unistd.h', 'CLOSE_RANGE_CLOEXEC', prefix: '#define _GNU_SOURCE')
- add_project_arguments('-DHAVE_CLOSE_RANGE_CLOEXEC', language: 'c')
+if cc.has_function('close_range', prefix: '#define _GNU_SOURCE\n#include <unistd.h>')
+ add_project_arguments('-DHAVE_CLOSE_RANGE', language: 'c')
endif

if cc.has_function('strlcpy', prefix: '#define _GNU_SOURCE\n#include <string.h>')
diff --git a/src/supervise-daemon/supervise-daemon.c b/src/supervise-daemon/supervise-daemon.c
index 836a1ec7..e36d0314 100644
--- a/src/supervise-daemon/supervise-daemon.c
+++ b/src/supervise-daemon/supervise-daemon.c
@@ -22,7 +22,7 @@
#define ONE_SECOND 1000000000
#define ONE_MS 1000000

-#ifdef HAVE_CLOSE_RANGE_CLOEXEC
+#ifdef HAVE_CLOSE_RANGE
/* For close_range() */
# define _GNU_SOURCE
#endif
@@ -203,6 +203,18 @@ static inline int ioprio_set(int which RC_UNUSED, int who RC_UNUSED,
}
#endif

+#ifndef CLOSE_RANGE_CLOEXEC
+# define CLOSE_RANGE_CLOEXEC (1U << 2)
+#endif
+#ifndef HAVE_CLOSE_RANGE
+static inline int close_range(int first RC_UNUSED,
+ int last RC_UNUSED,
+ unsigned int flags RC_UNUSED)
+{
+ return -1;
+}
+#endif
+
static void cleanup(void)
{
free(changeuser);
@@ -570,9 +582,7 @@ RC_NORETURN static void child_process(char *exec, char **argv)
if (redirect_stderr || rc_yesno(getenv("EINFO_QUIET")))
dup2(stderr_fd, STDERR_FILENO);

-#ifdef HAVE_CLOSE_RANGE_CLOEXEC
if (close_range(3, UINT_MAX, CLOSE_RANGE_CLOEXEC) < 0)
-#endif
for (i = getdtablesize() - 1; i >= 3; --i)
fcntl(i, F_SETFD, FD_CLOEXEC);
cmdline = make_cmdline(argv);
--
2.42.0


From 004ad356e948056c58119b9656937b4ff9bb1b8f Mon Sep 17 00:00:00 2001
From: Natanael Copa <[email protected]>
Date: Wed, 30 Aug 2023 13:17:07 +0200
Subject: [PATCH 2/4] misc: add cloexec_fds_from() helper function

Move logic to set file descriptors to a cloexec_fds_from() function in
misc.c so it can be shared by both supervisor-daemon and
start-stop-daemon, and hide the details behind.
---
src/shared/misc.c | 27 +++++++++++++++++++++++++
src/shared/misc.h | 2 ++
src/supervise-daemon/supervise-daemon.c | 22 ++------------------
3 files changed, 31 insertions(+), 20 deletions(-)

diff --git a/src/shared/misc.c b/src/shared/misc.c
index c987ce8c..429407d4 100644
--- a/src/shared/misc.c
+++ b/src/shared/misc.c
@@ -15,6 +15,11 @@
* except according to the terms contained in the LICENSE file.
*/

+#ifdef HAVE_CLOSE_RANGE
+/* For close_range() */
+# define _GNU_SOURCE
+#endif
+
#include <ctype.h>
#include <errno.h>
#include <fcntl.h>
@@ -500,3 +505,25 @@ pid_t get_pid(const char *applet,const char *pidfile)

return pid;
}
+
+#ifndef HAVE_CLOSE_RANGE
+static inline int close_range(int first RC_UNUSED,
+ int last RC_UNUSED,
+ unsigned int flags RC_UNUSED)
+{
+ return -1;
+}
+#endif
+#ifndef CLOSE_RANGE_CLOEXEC
+# define CLOSE_RANGE_CLOEXEC (1U << 2)
+#endif
+
+void
+cloexec_fds_from(int first)
+{
+ int i;
+ if (close_range(first, UINT_MAX, CLOSE_RANGE_CLOEXEC) < 0) {
+ for (i = getdtablesize() - 1; i >= first; --i)
+ fcntl(i, F_SETFD, FD_CLOEXEC);
+ }
+}
diff --git a/src/shared/misc.h b/src/shared/misc.h
index f4ab25ad..b158a786 100644
--- a/src/shared/misc.h
+++ b/src/shared/misc.h
@@ -73,4 +73,6 @@ void from_time_t(char *time_string, time_t tv);
time_t to_time_t(char *timestring);
pid_t get_pid(const char *applet, const char *pidfile);

+void cloexec_fds_from(int);
+
#endif
diff --git a/src/supervise-daemon/supervise-daemon.c b/src/supervise-daemon/supervise-daemon.c
index e36d0314..f0f298d2 100644
--- a/src/supervise-daemon/supervise-daemon.c
+++ b/src/supervise-daemon/supervise-daemon.c
@@ -22,11 +22,6 @@
#define ONE_SECOND 1000000000
#define ONE_MS 1000000

-#ifdef HAVE_CLOSE_RANGE
-/* For close_range() */
-# define _GNU_SOURCE
-#endif
-
#include <errno.h>
#include <fcntl.h>
#include <getopt.h>
@@ -203,18 +198,6 @@ static inline int ioprio_set(int which RC_UNUSED, int who RC_UNUSED,
}
#endif

-#ifndef CLOSE_RANGE_CLOEXEC
-# define CLOSE_RANGE_CLOEXEC (1U << 2)
-#endif
-#ifndef HAVE_CLOSE_RANGE
-static inline int close_range(int first RC_UNUSED,
- int last RC_UNUSED,
- unsigned int flags RC_UNUSED)
-{
- return -1;
-}
-#endif
-
static void cleanup(void)
{
free(changeuser);
@@ -582,9 +565,8 @@ RC_NORETURN static void child_process(char *exec, char **argv)
if (redirect_stderr || rc_yesno(getenv("EINFO_QUIET")))
dup2(stderr_fd, STDERR_FILENO);

- if (close_range(3, UINT_MAX, CLOSE_RANGE_CLOEXEC) < 0)
- for (i = getdtablesize() - 1; i >= 3; --i)
- fcntl(i, F_SETFD, FD_CLOEXEC);
+ cloexec_fds_from(3);
+
cmdline = make_cmdline(argv);
syslog(LOG_INFO, "Child command line: %s", cmdline);
free(cmdline);
--
2.42.0


From 1c22d40a329982a6e3e9307625790f40080d3c16 Mon Sep 17 00:00:00 2001
From: Natanael Copa <[email protected]>
Date: Wed, 30 Aug 2023 13:20:16 +0200
Subject: [PATCH 3/4] start-stop-daemon: set fds to CLOEXEC instead of closing

Set file descriptors to CLOEXEC instead of closing them before exec,
similar to what we do in supervise-daemon.

Use the share cloexec_fds_from() helper for this.

closefrom() is no longer used so remove the test.
---
meson.build | 3 ---
src/start-stop-daemon/start-stop-daemon.c | 7 +------
2 files changed, 1 insertion(+), 9 deletions(-)

diff --git a/meson.build b/meson.build
index d04171b3..ec970494 100644
--- a/meson.build
+++ b/meson.build
@@ -195,9 +195,6 @@ if cc.compiles(malloc_attribute_test, name : 'malloc attribute with arguments')
add_project_arguments('-DHAVE_MALLOC_EXTENDED_ATTRIBUTE', language: 'c')
endif

-if cc.has_function('closefrom', prefix: '#define _GNU_SOURCE\n#include <unistd.h>')
- add_project_arguments('-DHAVE_CLOSEFROM', language: 'c')
-endif
if cc.has_function('close_range', prefix: '#define _GNU_SOURCE\n#include <unistd.h>')
add_project_arguments('-DHAVE_CLOSE_RANGE', language: 'c')
endif
diff --git a/src/start-stop-daemon/start-stop-daemon.c b/src/start-stop-daemon/start-stop-daemon.c
index ef6f454e..3e4a19a1 100644
--- a/src/start-stop-daemon/start-stop-daemon.c
+++ b/src/start-stop-daemon/start-stop-daemon.c
@@ -1098,12 +1098,7 @@ int main(int argc, char **argv)
|| rc_yesno(getenv("EINFO_QUIET")))
dup2(stderr_fd, STDERR_FILENO);

-#ifdef HAVE_CLOSEFROM
- closefrom(3);
-#else
- for (i = getdtablesize() - 1; i >= 3; --i)
- close(i);
-#endif
+ cloexec_fds_from(3);

if (scheduler != NULL) {
int scheduler_index;
--
2.42.0


From 56758ae2fd54c66c38ff6b0bb02c1370402eaa63 Mon Sep 17 00:00:00 2001
From: Natanael Copa <[email protected]>
Date: Wed, 30 Aug 2023 13:34:23 +0200
Subject: [PATCH 4/4] misc: add syscall fallback for close_range for musl libc

Add fallback for the close_range syscall wrapper. This is needed for
musl libc, which currently does not have a close_range wrapper.
---
meson.build | 2 ++
src/shared/misc.c | 8 ++++++++
2 files changed, 10 insertions(+)

diff --git a/meson.build b/meson.build
index ec970494..fea86408 100644
--- a/meson.build
+++ b/meson.build
@@ -197,6 +197,8 @@ endif

if cc.has_function('close_range', prefix: '#define _GNU_SOURCE\n#include <unistd.h>')
add_project_arguments('-DHAVE_CLOSE_RANGE', language: 'c')
+elif cc.has_header('linux/close_range.h')
+ add_project_arguments('-DHAVE_LINUX_CLOSE_RANGE_H', language: 'c')
endif

if cc.has_function('strlcpy', prefix: '#define _GNU_SOURCE\n#include <string.h>')
diff --git a/src/shared/misc.c b/src/shared/misc.c
index 429407d4..27665d8d 100644
--- a/src/shared/misc.c
+++ b/src/shared/misc.c
@@ -24,6 +24,9 @@
#include <errno.h>
#include <fcntl.h>
#include <limits.h>
+#ifdef HAVE_LINUX_CLOSE_RANGE_H
+# include <linux/close_range.h>
+#endif
#include <signal.h>
#include <stdio.h>
#include <stdlib.h>
@@ -31,6 +34,7 @@
#include <sys/file.h>
#include <sys/time.h>
#ifdef __linux__
+# include <sys/syscall.h> /* for close_range */
# include <sys/sysinfo.h>
#endif
#include <sys/types.h>
@@ -511,7 +515,11 @@ static inline int close_range(int first RC_UNUSED,
int last RC_UNUSED,
unsigned int flags RC_UNUSED)
{
+#ifdef SYS_close_range
+ return syscall(SYS_close_range, first, last, flags);
+#else
return -1;
+#endif
}
#endif
#ifndef CLOSE_RANGE_CLOEXEC
--
2.42.0

0 comments on commit bc47813

Please sign in to comment.