From b2c27072b05777fe8dc6d32791de1e4eff044ebb Mon Sep 17 00:00:00 2001 From: Mark Wielaard Date: Wed, 24 Sep 2025 23:16:29 +0200 Subject: [PATCH] Deal with linux arches that don't have getdents, only getdents64 Not all linux arches have getdents, some newer arches (arm64 and riscv64) only implement getdents64. So only use the function filter_valgrind_fds_from_getdents_with_refill on linux with __NR_getdents. Also move the getdents_filter testcase under none/tests/linux and only use getdents64. Fixes: e8e4066c3a01 ("Filter Valgrind FDs from getdents syscalls") https://bugs.kde.org/show_bug.cgi?id=331311 --- coregrind/m_syswrap/syswrap-generic.c | 15 +++++++++++++++ none/tests/Makefile.am | 2 -- none/tests/linux/Makefile.am | 2 ++ none/tests/{ => linux}/getdents_filter.c | 15 +++++++++------ none/tests/{ => linux}/getdents_filter.stderr.exp | 0 none/tests/{ => linux}/getdents_filter.stdout.exp | 0 none/tests/{ => linux}/getdents_filter.vgtest | 0 7 files changed, 26 insertions(+), 8 deletions(-) rename none/tests/{ => linux}/getdents_filter.c (92%) rename none/tests/{ => linux}/getdents_filter.stderr.exp (100%) rename none/tests/{ => linux}/getdents_filter.stdout.exp (100%) rename none/tests/{ => linux}/getdents_filter.vgtest (100%) diff --git a/coregrind/m_syswrap/syswrap-generic.c b/coregrind/m_syswrap/syswrap-generic.c index 33b58f5a5e..3786e9cd89 100644 --- a/coregrind/m_syswrap/syswrap-generic.c +++ b/coregrind/m_syswrap/syswrap-generic.c @@ -4045,6 +4045,10 @@ static Bool should_keep_fd_entry(const HChar *name) return True; } +/* Make sure we really need the proc filtering using (32bit) getdents, + which not every linux arch implements. */ +#if defined(VGO_linux) && defined(__NR_getdents) + /* Filter and compact dirent entries */ static SizeT filter_dirent_entries(struct vki_dirent *dirp, SizeT orig_size) { @@ -4067,6 +4071,7 @@ static SizeT filter_dirent_entries(struct vki_dirent *dirp, SizeT orig_size) return new_size; } +#endif /* defined(VGO_linux) && defined(__NR_getdents) */ /* Filter and compact dirent64 entries */ static SizeT filter_dirent64_entries(struct vki_dirent64 *dirp, SizeT orig_size) @@ -4091,6 +4096,10 @@ static SizeT filter_dirent64_entries(struct vki_dirent64 *dirp, SizeT orig_size) return new_size; } +/* Make sure we really need the proc filtering using (32bit) getdents, + which not every linux arch implements. */ +#if defined(VGO_linux) && defined(__NR_getdents) + /* Filter out Valgrind's internal file descriptors from getdents results with refill capability. When entries are filtered out, attempts to read more entries to avoid empty results. Returns filtered size on success, or -1 if retry syscall failed. */ @@ -4119,6 +4128,7 @@ static SizeT filter_valgrind_fds_from_getdents_with_refill(Int fd, struct vki_di return new_size; } +#endif /* defined(VGO_linux) && defined(__NR_getdents) */ /* Filter out Valgrind's internal file descriptors from getdents64 results with refill capability. Same logic as getdents version but for 64-bit dirent structures. @@ -4155,6 +4165,10 @@ POST(sys_getdents) if (RES > 0) { SizeT result_size = RES; + /* Make sure we really need the proc filtering using (32bit) getdents, + which not every linux arch implements. */ +#if defined(VGO_linux) && defined(__NR_getdents) + /* Only filter Valgrind FDs when listing /proc/PID/fd or /proc/PID/fdinfo directories */ if (is_proc_fd_directory(ARG1)) { SizeT filtered_size = filter_valgrind_fds_from_getdents_with_refill(ARG1, (struct vki_dirent *)ARG2, RES, ARG3, status); @@ -4166,6 +4180,7 @@ POST(sys_getdents) if (result_size != RES) SET_STATUS_Success(result_size); } +#endif /* defined(VGO_linux) && defined(__NR_getdents) */ POST_MEM_WRITE( ARG2, result_size ); } diff --git a/none/tests/Makefile.am b/none/tests/Makefile.am index ccdd85e53e..716ce000d3 100644 --- a/none/tests/Makefile.am +++ b/none/tests/Makefile.am @@ -172,7 +172,6 @@ EXTRA_DIST = \ floored.stderr.exp floored.stdout.exp floored.vgtest \ fork.stderr.exp fork.stdout.exp fork.vgtest \ fucomip.stderr.exp fucomip.vgtest \ - getdents_filter.stderr.exp getdents_filter.stdout.exp getdents_filter.vgtest \ gxx304.stderr.exp gxx304.vgtest \ ifunc.stderr.exp ifunc.stdout.exp ifunc.vgtest \ ioctl_moans.stderr.exp ioctl_moans.vgtest \ @@ -292,7 +291,6 @@ check_PROGRAMS = \ fdleak_fcntl fdleak_ipv4 fdleak_open fdleak_pipe \ fdleak_socketpair \ floored fork fucomip \ - getdents_filter \ ioctl_moans \ libvex_test \ libvexmultiarch_test \ diff --git a/none/tests/linux/Makefile.am b/none/tests/linux/Makefile.am index 7bfcedc862..55426e2b26 100644 --- a/none/tests/linux/Makefile.am +++ b/none/tests/linux/Makefile.am @@ -10,6 +10,7 @@ EXTRA_DIST = \ bug498317.stderr.exp bug498317.supp bug498317.vgtest \ bug506910.stderr.exp bug506910.vgtest \ clonev.stdout.exp clonev.stderr.exp clonev.vgtest \ + getdents_filter.stderr.exp getdents_filter.stdout.exp getdents_filter.vgtest \ membarrier.stderr.exp membarrier.vgtest \ mremap.stderr.exp mremap.stderr.exp-glibc27 mremap.stdout.exp \ mremap.vgtest \ @@ -28,6 +29,7 @@ check_PROGRAMS = \ brk-overflow2 \ bug498317 \ clonev \ + getdents_filter \ mremap \ mremap2 \ mremap3 \ diff --git a/none/tests/getdents_filter.c b/none/tests/linux/getdents_filter.c similarity index 92% rename from none/tests/getdents_filter.c rename to none/tests/linux/getdents_filter.c index d508cdde0f..361659f51d 100644 --- a/none/tests/getdents_filter.c +++ b/none/tests/linux/getdents_filter.c @@ -13,10 +13,11 @@ #include #include -struct linux_dirent { - unsigned long d_ino; - off_t d_off; +struct linux_dirent64 { + ino64_t d_ino; + off64_t d_off; unsigned short d_reclen; + unsigned char d_type; char d_name[]; }; @@ -67,7 +68,7 @@ static void test_retry_logic_with_small_buffer(void) int fd; char buf[SMALL_BUF_SIZE]; long nread; - struct linux_dirent *d; + struct linux_dirent64 *d; printf("retry_test_start\n"); @@ -83,7 +84,9 @@ static void test_retry_logic_with_small_buffer(void) * may return only Valgrind FDs, which will trigger the retry mechanism. */ for (;;) { - nread = syscall(SYS_getdents, fd, buf, SMALL_BUF_SIZE); + /* Note, using getdents64 since some linux arches don't implement + the 32bit getdents. */ + nread = syscall(SYS_getdents64, fd, buf, SMALL_BUF_SIZE); if (nread == -1) { printf("retry_test_error\n"); @@ -97,7 +100,7 @@ static void test_retry_logic_with_small_buffer(void) /* Print client FD entries found in this buffer (excluding . and ..) */ for (size_t bpos = 0; bpos < nread;) { - d = (struct linux_dirent *)(buf + bpos); + d = (struct linux_dirent64 *)(buf + bpos); if (strcmp(d->d_name, ".") != 0 && strcmp(d->d_name, "..") != 0) { char *endptr; long fd_num = strtol(d->d_name, &endptr, 10); diff --git a/none/tests/getdents_filter.stderr.exp b/none/tests/linux/getdents_filter.stderr.exp similarity index 100% rename from none/tests/getdents_filter.stderr.exp rename to none/tests/linux/getdents_filter.stderr.exp diff --git a/none/tests/getdents_filter.stdout.exp b/none/tests/linux/getdents_filter.stdout.exp similarity index 100% rename from none/tests/getdents_filter.stdout.exp rename to none/tests/linux/getdents_filter.stdout.exp diff --git a/none/tests/getdents_filter.vgtest b/none/tests/linux/getdents_filter.vgtest similarity index 100% rename from none/tests/getdents_filter.vgtest rename to none/tests/linux/getdents_filter.vgtest -- 2.47.3