From b9ed79c99a35f91e438edd96eb37fe4f43002e70 Mon Sep 17 00:00:00 2001 From: Jade Lovelace Date: Sat, 10 Aug 2024 01:10:35 -0700 Subject: libutil: deal with Linux systems that do not implement close_range Seems a little bit Rich that musl does not implement close_range because they suspect that the system call itself is a bad idea, so they uhhhh are considering not implementing a wrapper. Let's just fix the problem at hand by writing our own wrapper. Change-Id: I1f8e5858e4561d58a5450503d9c4585aded2b216 --- meson.build | 5 +++++ src/libutil/file-descriptor.cc | 16 ++++++++++++++-- 2 files changed, 19 insertions(+), 2 deletions(-) diff --git a/meson.build b/meson.build index 4e2f713ce..41bfe6722 100644 --- a/meson.build +++ b/meson.build @@ -417,6 +417,11 @@ check_funcs = [ 'strsignal', 'sysconf', ] +if target_machine.kernel() in ['linux', 'freebsd'] + # musl does not have close_range as of 2024-08-10 + # patch: https://www.openwall.com/lists/musl/2024/08/01/9 + check_funcs += [ 'close_range' ] +endif foreach funcspec : check_funcs define_name = 'HAVE_' + funcspec.underscorify().to_upper() define_value = cxx.has_function(funcspec).to_int() diff --git a/src/libutil/file-descriptor.cc b/src/libutil/file-descriptor.cc index 4807869f9..f95d7b321 100644 --- a/src/libutil/file-descriptor.cc +++ b/src/libutil/file-descriptor.cc @@ -223,15 +223,27 @@ void closeExtraFDs() constexpr int MAX_KEPT_FD = 2; static_assert(std::max({STDIN_FILENO, STDOUT_FILENO, STDERR_FILENO}) == MAX_KEPT_FD); -#if __linux__ + // Both Linux and FreeBSD support close_range. +#if __linux__ || __FreeBSD__ + auto closeRange = [](unsigned int first, unsigned int last, int flags) -> int { + // musl does not have close_range as of 2024-08-10 + // patch: https://www.openwall.com/lists/musl/2024/08/01/9 +#ifdef HAVE_CLOSE_RANGE + return close_range(first, last, flags); +#else + return syscall(SYS_close_range, first, last, flags); +#endif + }; // first try to close_range everything we don't care about. if this // returns an error with these parameters we're running on a kernel // that does not implement close_range (i.e. pre 5.9) and fall back // to the old method. we should remove that though, in some future. - if (close_range(3, ~0U, 0) == 0) { + if (closeRange(3, ~0U, 0) == 0) { return; } +#endif +#if __linux__ try { for (auto & s : readDirectory("/proc/self/fd")) { auto fd = std::stoi(s.name); -- cgit v1.2.3