From: Paul Floyd Date: Fri, 2 May 2025 14:59:58 +0000 (+0200) Subject: FreeBSD close_range syscall X-Git-Url: http://git.ipfire.org/gitweb/gitweb.cgi?a=commitdiff_plain;h=8edc2fa6f8d70dbe10d634adff2513aa68143a22;p=thirdparty%2Fvalgrind.git FreeBSD close_range syscall Simplify the checking. No ned to test for reserved fds, and just split the close_range if debug output is enabled. Add a call to close_range with an upper bound of ~0U in the testcase. These changes will probably be the basis for fixing https://bugs.kde.org/show_bug.cgi?id=503641 --- diff --git a/coregrind/m_syswrap/syswrap-freebsd.c b/coregrind/m_syswrap/syswrap-freebsd.c index 7ea04fdbc..41cd07561 100644 --- a/coregrind/m_syswrap/syswrap-freebsd.c +++ b/coregrind/m_syswrap/syswrap-freebsd.c @@ -6615,10 +6615,8 @@ POST(sys___realpathat) // int close_range(u_int lowfd, u_int highfd, int flags); PRE(sys_close_range) { - SysRes res = VG_(mk_SysRes_Success)(0); - unsigned int lowfd = ARG1; - unsigned int fd_counter; // will count from lowfd to highfd - unsigned int highfd = ARG2; + UInt lowfd = ARG1; + UInt highfd = ARG2; /* on linux the may lock if futexes are used * there is a lock in the kernel but I assume it's just @@ -6642,46 +6640,48 @@ PRE(sys_close_range) return; } - fd_counter = lowfd; - do { - if (fd_counter > highfd - || (fd_counter == 2U/*stderr*/ && VG_(debugLog_getLevel)() > 0) - || fd_counter == VG_(log_output_sink).fd - || fd_counter == VG_(xml_output_sink).fd) { - /* Split the range if it contains a file descriptor we're not - * supposed to close. */ - if (fd_counter - 1 >= lowfd) { - res = VG_(do_syscall3)(__NR_close_range, (UWord)lowfd, (UWord)fd_counter - 1, ARG3 ); - } - lowfd = fd_counter + 1; - } - } while (fd_counter++ <= highfd); + vg_assert(VG_(log_output_sink).fd == -1 || + VG_(log_output_sink).fd >= VG_(fd_hard_limit)); + vg_assert(VG_(xml_output_sink).fd == -1 || + VG_(xml_output_sink).fd >= VG_(fd_hard_limit)); - /* If it failed along the way, it's presumably the flags being wrong. */ - SET_STATUS_from_SysRes (res); + if (VG_(debugLog_getLevel)() > 0 && + lowfd <= 2U && + highfd >= 2U && + lowfd != highfd) { + SysRes res = VG_(mk_SysRes_Success)(0); + if (lowfd <= 1U) { + res = VG_(do_syscall3)(__NR_close_range, lowfd, 1U, ARG3); + } + if (!sr_isError(res) && highfd >= 3U) { + res = VG_(do_syscall3)(__NR_close_range, 3U, highfd, ARG3); + } + /* If it failed along the way, it's presumably the flags being wrong. */ + SET_STATUS_from_SysRes (res); + } else { + SET_STATUS_from_SysRes(VG_(do_syscall3)(__NR_close_range, lowfd, highfd, ARG3)); + } } POST(sys_close_range) { - unsigned int fd; - unsigned int last = ARG2; + UInt fd; + UInt highfd = ARG2; if (!VG_(clo_track_fds) || (ARG3 & VKI_CLOSE_RANGE_CLOEXEC) != 0) return; - if (last >= VG_(fd_hard_limit)) - last = VG_(fd_hard_limit) - 1; + if (highfd >= VG_(fd_hard_limit)) + highfd = VG_(fd_hard_limit) - 1; /* If the close_range range is too wide, we don't want to loop through the whole range. */ - if (ARG2 == ~0U) - ML_(record_fd_close_range)(tid, ARG1); - else { - for (fd = ARG1; fd <= last; fd++) - if ((fd != 2/*stderr*/ || VG_(debugLog_getLevel)() == 0) - && fd != VG_(log_output_sink).fd - && fd != VG_(xml_output_sink).fd) + if (ARG2 >= VG_(fd_hard_limit)) { + ML_(record_fd_close_range)(tid, ARG1); + } else { + for (fd = ARG1; fd <= highfd; fd++) + if ((fd != 2/*stderr*/ || VG_(debugLog_getLevel)() == 0)) ML_(record_fd_close)(tid, fd); } } diff --git a/memcheck/tests/close_range.c b/memcheck/tests/close_range.c index 6d8b5a0ba..5c21e7f42 100644 --- a/memcheck/tests/close_range.c +++ b/memcheck/tests/close_range.c @@ -65,7 +65,7 @@ int main(void) errno = 0; // wrong order - close_range(fd3, fd1, 2); + close_range(fd3, fd1, 0); assert(errno = EINVAL); errno = 0; @@ -82,6 +82,9 @@ int main(void) close_range(3, rl.rlim_cur+1, 0); + int res = close_range(2U, ~0U, 0); + assert(res == 0); + { unsigned a; unsigned b; diff --git a/memcheck/tests/close_range.stderr.exp b/memcheck/tests/close_range.stderr.exp index 2f4d018f2..51dfcd40a 100644 --- a/memcheck/tests/close_range.stderr.exp +++ b/memcheck/tests/close_range.stderr.exp @@ -1,12 +1,12 @@ Syscall param close_range(lowfd) contains uninitialised byte(s) at 0x........: close_range (in /...libc...) - by 0x........: main (close_range.c:89) + by 0x........: main (close_range.c:92) Syscall param close_range(highfd) contains uninitialised byte(s) at 0x........: close_range (in /...libc...) - by 0x........: main (close_range.c:89) + by 0x........: main (close_range.c:92) Syscall param close_range(flags) contains uninitialised byte(s) at 0x........: close_range (in /...libc...) - by 0x........: main (close_range.c:89) + by 0x........: main (close_range.c:92)