]> git.ipfire.org Git - thirdparty/valgrind.git/commitdiff
Add close_range(2) support
authorLubomir Rintel <lkundrak@v3.sk>
Mon, 4 Oct 2021 13:40:29 +0000 (15:40 +0200)
committerMark Wielaard <mark@klomp.org>
Tue, 12 Oct 2021 20:58:45 +0000 (22:58 +0200)
This is a system call introduced in Linux 5.9.

It's typically used to bulk-close file descriptors that a process inherited
without having desired so and doesn't want to pass them to its offspring
for security reasons. For this reason the sensible upper limit value tends
to be unknown and the users prefer to stay on the safe side by setting it
high.

This is a bit peculiar because, if unfiltered, the syscall could end up
closing descriptors Valgrind uses for its purposes, ending in no end of
mayhem and suffering.

This patch adjusts the upper bounds to a safe value and then skips over
the descriptor Valgrind uses by potentially calling the real system call
with sub-ranges that are safe to close.

The call can fail on negative ranges and bad flags -- we're dealing with
the first condition ourselves while letting the real call fail on bad
flags.

https://bugs.kde.org/show_bug.cgi?id=439090

15 files changed:
NEWS
coregrind/m_syswrap/priv_syswrap-linux.h
coregrind/m_syswrap/syswrap-amd64-linux.c
coregrind/m_syswrap/syswrap-arm-linux.c
coregrind/m_syswrap/syswrap-arm64-linux.c
coregrind/m_syswrap/syswrap-linux.c
coregrind/m_syswrap/syswrap-mips32-linux.c
coregrind/m_syswrap/syswrap-mips64-linux.c
coregrind/m_syswrap/syswrap-nanomips-linux.c
coregrind/m_syswrap/syswrap-ppc32-linux.c
coregrind/m_syswrap/syswrap-ppc64-linux.c
coregrind/m_syswrap/syswrap-s390x-linux.c
coregrind/m_syswrap/syswrap-x86-linux.c
include/vki/vki-linux.h
include/vki/vki-scnums-shared-linux.h

diff --git a/NEWS b/NEWS
index bd4458daefb36bde843118d63dcd55f1bf7b7a75..112758301306f6c1e331315f08824252632f2688 100644 (file)
--- a/NEWS
+++ b/NEWS
@@ -70,6 +70,7 @@ are not entered into bugzilla tend to get forgotten about or ignored.
         have debug information
 438871  unhandled instruction bytes: 0xF3 0x49 0xF 0x6F 0x9C 0x24 0x60 0x2 0x0 0x0
 439046  valgrind is unusably large when linked with lld
+439090  Implement close_range(2)
 439326  Valgrind 3.17.0 won't compile with Intel 2021 oneAPI compilers
 439590  glibc-2.34 breaks suppressions against obj:*/lib*/libc-2.*so*
 440670  unhandled ppc64le-linux syscall: 252 (statfs64) and 253 (fstatfs64)
index 110f7c832dbc1c90495fbbbe34cca06cf63f782c..baf362f112fac1e285a8d9c567040d50384f4cac 100644 (file)
@@ -320,6 +320,9 @@ DECL_TEMPLATE(linux, sys_io_uring_setup);
 DECL_TEMPLATE(linux, sys_io_uring_enter);
 DECL_TEMPLATE(linux, sys_io_uring_register);
 
+// Linux-specific (new in Linux 5.9)
+DECL_TEMPLATE(linux, sys_close_range);
+
 /* ---------------------------------------------------------------------
    Wrappers for sockets and ipc-ery.  These are split into standalone
    procedures because x86-linux hides them inside multiplexors
index 46d6b5bebd25854f4d0e8bcd54dbc980e305c042..5062324a1ef85bda5007619f7b93558e2daaa833 100644 (file)
@@ -875,6 +875,7 @@ static SyscallTableEntry syscall_table[] = {
    LINXY(__NR_io_uring_register, sys_io_uring_register), // 427
 
    GENX_(__NR_clone3,            sys_ni_syscall),        // 435
+   LINXY(__NR_close_range,       sys_close_range),       // 436
 
    LINX_(__NR_faccessat2,       sys_faccessat2),        // 439
 };
index 7f41b074916f6de84df4c78921ac455859e57fcf..556dd844b9564aa452641713fd80006cc7c96991 100644 (file)
@@ -1052,6 +1052,7 @@ static SyscallTableEntry syscall_main_table[] = {
    LINXY(__NR_io_uring_register, sys_io_uring_register), // 427
 
    GENX_(__NR_clone3,            sys_ni_syscall),        // 435
+   LINXY(__NR_close_range,       sys_close_range),       // 436
 
    LINX_(__NR_faccessat2,    sys_faccessat2),           // 439
 };
index 0d717f44be55c51145923549da6cb363673eee72..b8710772768a22fc12a5d029f7fc92faee8ad73e 100644 (file)
@@ -831,6 +831,7 @@ static SyscallTableEntry syscall_main_table[] = {
    LINXY(__NR_io_uring_register, sys_io_uring_register), // 427
 
    GENX_(__NR_clone3,            sys_ni_syscall),        // 435
+   LINXY(__NR_close_range,       sys_close_range),       // 436
 
    LINX_(__NR_faccessat2,        sys_faccessat2),        // 439
 };
index 818b11ff6e6c12dd92e55597d674975d22d61970..63dd1fb66e81b5bc11073f8f7cd42146463e389b 100644 (file)
@@ -13315,6 +13315,68 @@ PRE(sys_execveat)
 
 }
 
+PRE(sys_close_range)
+{
+   SysRes res = VG_(mk_SysRes_Success)(0);
+   unsigned int beg, end;
+   unsigned int last = ARG2;
+
+   FUSE_COMPATIBLE_MAY_BLOCK();
+   PRINT("sys_close_range ( %" FMT_REGWORD "u, %" FMT_REGWORD "u, %"
+         FMT_REGWORD "u )", ARG1, ARG2, ARG3);
+   PRE_REG_READ3(long, "close_range",
+                 unsigned int, first, unsigned int, last,
+                 unsigned int, flags);
+
+   if (ARG1 > last) {
+      SET_STATUS_Failure( VKI_EINVAL );
+      return;
+   }
+
+   if (last >= VG_(fd_hard_limit))
+      last = VG_(fd_hard_limit) - 1;
+
+   if (ARG1 > last) {
+      SET_STATUS_Success ( 0 );
+      return;
+   }
+
+   beg = end = ARG1;
+   do {
+      if (end > last
+         || (end == 2/*stderr*/ && VG_(debugLog_getLevel)() > 0)
+         || end == VG_(log_output_sink).fd
+         || end == VG_(xml_output_sink).fd) {
+         /* Split the range if it contains a file descriptor we're not
+          * supposed to close. */
+         if (end - 1 >= beg)
+             res = VG_(do_syscall3)(__NR_close_range, (UWord)beg, (UWord)end - 1, ARG3 );
+         beg = end + 1;
+      }
+   } while (end++ <= last);
+
+   /* If it failed along the way, it's presumably the flags being wrong. */
+   SET_STATUS_from_SysRes (res);
+}
+
+POST(sys_close_range)
+{
+   unsigned int fd;
+   unsigned int last = 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;
+
+   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)
+      ML_(record_fd_close)(fd);
+}
 
 #undef PRE
 #undef POST
index f957c6f583db73f6505bcf58a791486b2196ab20..f556e063f084637856ddc343aa510f2c44383b93 100644 (file)
@@ -1137,6 +1137,7 @@ static SyscallTableEntry syscall_main_table[] = {
    LINXY(__NR_io_uring_register,       sys_io_uring_register),       // 427
 
    GENX_(__NR_clone3,                  sys_ni_syscall),              // 435
+   LINXY(__NR_close_range,       sys_close_range),       // 436
 
    LINX_ (__NR_faccessat2,             sys_faccessat2),              // 439
 };
index 94f38366f0494f11a892cd36327fdaec9a729753..41a5404c559c4dffe3d0a89769422b6cf993d8b1 100644 (file)
@@ -816,6 +816,7 @@ static SyscallTableEntry syscall_main_table[] = {
    LINXY (__NR_io_uring_enter, sys_io_uring_enter),
    LINXY (__NR_io_uring_register, sys_io_uring_register),
    GENX_ (__NR_clone3, sys_ni_syscall),
+   LINXY (__NR_close_range, sys_close_range),
    LINX_ (__NR_faccessat2, sys_faccessat2),
 };
 
index 102c1555076c7ca8edbeb2466595a8f18db48449..f9d4b19f4af5dfe4ea059feb30791ed9f6927d24 100644 (file)
@@ -825,6 +825,7 @@ static SyscallTableEntry syscall_main_table[] = {
    LINXY (__NR_io_uring_enter,         sys_io_uring_enter),
    LINXY (__NR_io_uring_register,      sys_io_uring_register),
    GENX_ (__NR_clone3,                 sys_ni_syscall),
+   LINXY (__NR_close_range,            sys_close_range),
    LINX_ (__NR_faccessat2,             sys_faccessat2),
 };
 
index 7f9c9fa9bcea14e4e9bebe24995ae1eff46baecf..6263ab8451547e0288bc05c143c8dd6c64b6418b 100644 (file)
@@ -1055,6 +1055,7 @@ static SyscallTableEntry syscall_table[] = {
    LINXY(__NR_io_uring_register, sys_io_uring_register), // 427
 
    GENX_(__NR_clone3,            sys_ni_syscall),        // 435
+   LINXY(__NR_close_range,       sys_close_range),       // 436
 
    LINX_(__NR_faccessat2,        sys_faccessat2),       // 439
 };
index 43cde73271c34835abf7ce576d0b9730d743340b..a26b41c321fcbbec862e57c8a317bf4fa1b75ae3 100644 (file)
@@ -1024,6 +1024,7 @@ static SyscallTableEntry syscall_table[] = {
    LINXY(__NR_io_uring_register, sys_io_uring_register), // 427
 
    GENX_(__NR_clone3,            sys_ni_syscall),        // 435
+   LINXY(__NR_close_range,       sys_close_range),       // 436
 
    LINX_(__NR_faccessat2,        sys_faccessat2),       // 439
 };
index 5283c19fe49cd72d5694841d60e0e23de25ea1fb..5c9209859f2ff41b78ded02411d0807fbcf2e89c 100644 (file)
@@ -865,6 +865,7 @@ static SyscallTableEntry syscall_table[] = {
    LINXY(__NR_io_uring_register, sys_io_uring_register),              // 427
 
    GENX_(__NR_clone3, sys_ni_syscall),                                // 435
+   LINXY(__NR_close_range, sys_close_range),                          // 436
 
    LINX_(__NR_faccessat2,  sys_faccessat2),                           // 439
 };
index 418c769750f98eff505da02cd1a85ab125cc10a0..1d8f45d33a093d56ef0bf720b825277e439e7b7f 100644 (file)
@@ -1646,6 +1646,7 @@ static SyscallTableEntry syscall_table[] = {
    LINXY(__NR_io_uring_register, sys_io_uring_register),// 427
 
    GENX_(__NR_clone3,            sys_ni_syscall),       // 435
+   LINXY(__NR_close_range,       sys_close_range),      // 436
 
    LINX_(__NR_faccessat2,       sys_faccessat2),       // 439
 };
index 426d9db92f695c15cf67fb57057f2d5a32c2ea77..eb4e01b3374c8c5e9338131ae80facde59ae3e06 100644 (file)
@@ -5369,6 +5369,9 @@ struct vki_itimerspec64 {
 
 #define VKI_RLIM64_INFINITY (~0ULL)
 
+#define VKI_CLOSE_RANGE_UNSHARE (1U << 1)
+#define VKI_CLOSE_RANGE_CLOEXEC (1U << 2)
+
 /*--------------------------------------------------------------------*/
 /*--- end                                                          ---*/
 /*--------------------------------------------------------------------*/
index 6c70c9981d2650dc0b381590690804231bacfab2..fa63c7a9bc18c3cb74f77b45b86b6ef176e632ab 100644 (file)
@@ -40,6 +40,7 @@
 #define __NR_fspick            433
 
 #define __NR_clone3            435
+#define __NR_close_range       436
 
 #define __NR_faccessat2                439