You can subscribe to this list here.
| 2002 |
Jan
|
Feb
|
Mar
|
Apr
|
May
|
Jun
|
Jul
|
Aug
|
Sep
(1) |
Oct
(122) |
Nov
(152) |
Dec
(69) |
|---|---|---|---|---|---|---|---|---|---|---|---|---|
| 2003 |
Jan
(6) |
Feb
(25) |
Mar
(73) |
Apr
(82) |
May
(24) |
Jun
(25) |
Jul
(10) |
Aug
(11) |
Sep
(10) |
Oct
(54) |
Nov
(203) |
Dec
(182) |
| 2004 |
Jan
(307) |
Feb
(305) |
Mar
(430) |
Apr
(312) |
May
(187) |
Jun
(342) |
Jul
(487) |
Aug
(637) |
Sep
(336) |
Oct
(373) |
Nov
(441) |
Dec
(210) |
| 2005 |
Jan
(385) |
Feb
(480) |
Mar
(636) |
Apr
(544) |
May
(679) |
Jun
(625) |
Jul
(810) |
Aug
(838) |
Sep
(634) |
Oct
(521) |
Nov
(965) |
Dec
(543) |
| 2006 |
Jan
(494) |
Feb
(431) |
Mar
(546) |
Apr
(411) |
May
(406) |
Jun
(322) |
Jul
(256) |
Aug
(401) |
Sep
(345) |
Oct
(542) |
Nov
(308) |
Dec
(481) |
| 2007 |
Jan
(427) |
Feb
(326) |
Mar
(367) |
Apr
(255) |
May
(244) |
Jun
(204) |
Jul
(223) |
Aug
(231) |
Sep
(354) |
Oct
(374) |
Nov
(497) |
Dec
(362) |
| 2008 |
Jan
(322) |
Feb
(482) |
Mar
(658) |
Apr
(422) |
May
(476) |
Jun
(396) |
Jul
(455) |
Aug
(267) |
Sep
(280) |
Oct
(253) |
Nov
(232) |
Dec
(304) |
| 2009 |
Jan
(486) |
Feb
(470) |
Mar
(458) |
Apr
(423) |
May
(696) |
Jun
(461) |
Jul
(551) |
Aug
(575) |
Sep
(134) |
Oct
(110) |
Nov
(157) |
Dec
(102) |
| 2010 |
Jan
(226) |
Feb
(86) |
Mar
(147) |
Apr
(117) |
May
(107) |
Jun
(203) |
Jul
(193) |
Aug
(238) |
Sep
(300) |
Oct
(246) |
Nov
(23) |
Dec
(75) |
| 2011 |
Jan
(133) |
Feb
(195) |
Mar
(315) |
Apr
(200) |
May
(267) |
Jun
(293) |
Jul
(353) |
Aug
(237) |
Sep
(278) |
Oct
(611) |
Nov
(274) |
Dec
(260) |
| 2012 |
Jan
(303) |
Feb
(391) |
Mar
(417) |
Apr
(441) |
May
(488) |
Jun
(655) |
Jul
(590) |
Aug
(610) |
Sep
(526) |
Oct
(478) |
Nov
(359) |
Dec
(372) |
| 2013 |
Jan
(467) |
Feb
(226) |
Mar
(391) |
Apr
(281) |
May
(299) |
Jun
(252) |
Jul
(311) |
Aug
(352) |
Sep
(481) |
Oct
(571) |
Nov
(222) |
Dec
(231) |
| 2014 |
Jan
(185) |
Feb
(329) |
Mar
(245) |
Apr
(238) |
May
(281) |
Jun
(399) |
Jul
(382) |
Aug
(500) |
Sep
(579) |
Oct
(435) |
Nov
(487) |
Dec
(256) |
| 2015 |
Jan
(338) |
Feb
(357) |
Mar
(330) |
Apr
(294) |
May
(191) |
Jun
(108) |
Jul
(142) |
Aug
(261) |
Sep
(190) |
Oct
(54) |
Nov
(83) |
Dec
(22) |
| 2016 |
Jan
(49) |
Feb
(89) |
Mar
(33) |
Apr
(50) |
May
(27) |
Jun
(34) |
Jul
(53) |
Aug
(53) |
Sep
(98) |
Oct
(206) |
Nov
(93) |
Dec
(53) |
| 2017 |
Jan
(65) |
Feb
(82) |
Mar
(102) |
Apr
(86) |
May
(187) |
Jun
(67) |
Jul
(23) |
Aug
(93) |
Sep
(65) |
Oct
(45) |
Nov
(35) |
Dec
(17) |
| 2018 |
Jan
(26) |
Feb
(35) |
Mar
(38) |
Apr
(32) |
May
(8) |
Jun
(43) |
Jul
(27) |
Aug
(30) |
Sep
(43) |
Oct
(42) |
Nov
(38) |
Dec
(67) |
| 2019 |
Jan
(32) |
Feb
(37) |
Mar
(53) |
Apr
(64) |
May
(49) |
Jun
(18) |
Jul
(14) |
Aug
(53) |
Sep
(25) |
Oct
(30) |
Nov
(49) |
Dec
(31) |
| 2020 |
Jan
(87) |
Feb
(45) |
Mar
(37) |
Apr
(51) |
May
(99) |
Jun
(36) |
Jul
(11) |
Aug
(14) |
Sep
(20) |
Oct
(24) |
Nov
(40) |
Dec
(23) |
| 2021 |
Jan
(14) |
Feb
(53) |
Mar
(85) |
Apr
(15) |
May
(19) |
Jun
(3) |
Jul
(14) |
Aug
(1) |
Sep
(57) |
Oct
(73) |
Nov
(56) |
Dec
(22) |
| 2022 |
Jan
(3) |
Feb
(22) |
Mar
(6) |
Apr
(55) |
May
(46) |
Jun
(39) |
Jul
(15) |
Aug
(9) |
Sep
(11) |
Oct
(34) |
Nov
(20) |
Dec
(36) |
| 2023 |
Jan
(79) |
Feb
(41) |
Mar
(99) |
Apr
(169) |
May
(48) |
Jun
(16) |
Jul
(16) |
Aug
(57) |
Sep
(83) |
Oct
(89) |
Nov
(97) |
Dec
(30) |
| 2024 |
Jan
(25) |
Feb
(73) |
Mar
(76) |
Apr
(122) |
May
(46) |
Jun
(44) |
Jul
(27) |
Aug
(30) |
Sep
(33) |
Oct
(67) |
Nov
(91) |
Dec
(70) |
| 2025 |
Jan
(44) |
Feb
(36) |
Mar
(85) |
Apr
(100) |
May
(138) |
Jun
(55) |
Jul
(107) |
Aug
(96) |
Sep
(151) |
Oct
(129) |
Nov
(102) |
Dec
(103) |
| 2026 |
Jan
(89) |
Feb
(83) |
Mar
(144) |
Apr
(118) |
May
|
Jun
|
Jul
|
Aug
|
Sep
|
Oct
|
Nov
|
Dec
|
|
From: Paul F. <pa...@so...> - 2026-04-27 06:46:56
|
https://sourceware.org/cgit/valgrind/commit/?id=31d5218709f6f68d6d1bb7ea6c894931a8aa4bd5 commit 31d5218709f6f68d6d1bb7ea6c894931a8aa4bd5 Author: Paul Floyd <pj...@wa...> Date: Mon Apr 27 08:45:40 2026 +0200 Darwin doc: describe apple pointer area and Massif woes Diff: --- docs/internals/Darwin-debug.txt | 7 ++++++- docs/internals/Darwin-notes.txt | 37 +++++++++++++++++++++++++++++++++++++ 2 files changed, 43 insertions(+), 1 deletion(-) diff --git a/docs/internals/Darwin-debug.txt b/docs/internals/Darwin-debug.txt index 705d6d57de..e753961c79 100644 --- a/docs/internals/Darwin-debug.txt +++ b/docs/internals/Darwin-debug.txt @@ -59,4 +59,9 @@ DYLD_SHARED_REGION gets set to "avoid" (but note that for macOS 11 Big Sur and later "avoid" is no longer an option). The Darwin callstack is a bit simpler to synthesise than the ones on -ELF platforms. There is no auxiliary vector (auxv) to construct. +ELF platforms. There is no auxiliary vector (auxv) to construct. However, +there is the "apple pointer area". At present we do not pass anything +that we get from the loader (and this is something of an omission). +Instead we just synthesise the small number of entries that we need. +Mostly these values are only used by dyld and for initialising the +system libs when they load. diff --git a/docs/internals/Darwin-notes.txt b/docs/internals/Darwin-notes.txt index 0cedd16981..0eb93fc921 100644 --- a/docs/internals/Darwin-notes.txt +++ b/docs/internals/Darwin-notes.txt @@ -71,6 +71,43 @@ means that I don't know which is the oldest version of macOS that will build Valgrind (as of December 2025). Somewhere between 10.8 (Darwin 12) and 10.12 (Darwin 16). +Massif on Darwin +~~~~~~~~~~~~~~~~ + +There is one fundamental difference in the architecture of Darwin +compared to the other ELF based systems. To start an ELF executable +ld.so is used. This is a minimalistic binary that just does the +loading and runtime link-editing of dependent shared libraries. +Darwin dyld does roughly the same thing except that it triggers +much more initialisation. Darwin does not have separate libraries +for the C and C++ standard libraries. Instead it has libSystem. +That is more like libc and libstdc++ and the Objective-C lib and +libcrypto and networking libs and about 30 other libs all bundled +into one. The result is that even before reaching "main()" a +Darwin guest will have performed vastly more allocations than +on an ELF system. For comparison, C++ Hello World on FreeBSD +does one allocation. On Darwin 22 it does 178 allocations. As +an aside, many of those are not deallocated, which also makes +a mess of all of the memcheck leak tests. + +All this means that the massif tests need very extensive use +of --ignore-fn for Darwin. There are hundreds of allocations +and the allocator functions seem to change frequently between +Darwin versions. For larger allocations, getting the name +of the allocation function is just a question of looking at +the failure diff. For small allocations the function may not +appear in the detailed reports but still cause a diff in +the allocation totals. In that case consider trying +- use --threshold=0.0 --detailed-freq=1 +- rerun the test outside of regtest (you can use the + .vgtest.log to get the full command line) +- if all else fails, run with --trace-malloc=yes to try to + find out which allocation function (malloc, calloc etc) + corresponds to the unaccounted size and then use gdb + and put a breakpoint on that allocation function. + +DHAT has similar issues but no --ignore-fn option (yet). + Valgrind-developer notes, todos re the MacOSX port ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ |
|
From: Paul F. <pa...@so...> - 2026-04-27 06:27:14
|
https://sourceware.org/cgit/valgrind/commit/?id=a7c65372bef5eccdace2444a48139aa8ecd0be43 commit a7c65372bef5eccdace2444a48139aa8ecd0be43 Author: Paul Floyd <pj...@wa...> Date: Mon Apr 27 08:26:27 2026 +0200 Darwin suppression: add a suppression for fork on macOS 13 Diff: --- darwin.supp | 7 +++++++ 1 file changed, 7 insertions(+) diff --git a/darwin.supp b/darwin.supp index cb6aeab48b..6c9a7606f7 100644 --- a/darwin.supp +++ b/darwin.supp @@ -984,3 +984,10 @@ fun:libSystem_initializer } +{ + macOS1300:fork + Memcheck:Addr4 + fun:xpc_atfork_child + fun:libSystem_atfork_child + fun:fork +} |
|
From: Paul F. <pa...@so...> - 2026-04-26 11:10:20
|
https://sourceware.org/cgit/valgrind/commit/?id=758bbcc0c5ce114dc1aa8119cdfb8598a69cd651 commit 758bbcc0c5ce114dc1aa8119cdfb8598a69cd651 Author: Paul Floyd <pj...@wa...> Date: Sun Apr 26 13:09:26 2026 +0200 Darwin regtest: add missing expected Diff: --- none/tests/scripts/shell.stderr.exp-darwin | 6 ++++++ 1 file changed, 6 insertions(+) diff --git a/none/tests/scripts/shell.stderr.exp-darwin b/none/tests/scripts/shell.stderr.exp-darwin new file mode 100644 index 0000000000..16726c6f44 --- /dev/null +++ b/none/tests/scripts/shell.stderr.exp-darwin @@ -0,0 +1,6 @@ +./shell: ./x86/: is a directory +./shell: ./shell.vgtest: Permission denied +./shell: ./shell_badinterp: /this/is/a/bogus/interpreter/name: bad interpreter: No such file or directory +./shell: ./shell_binaryfile: cannot execute binary file +./shell: ./shell_nosuchfile: No such file or directory +./shell: shell_nosuchfile: command not found |
|
From: Paul F. <pa...@so...> - 2026-04-26 11:09:23
|
https://sourceware.org/cgit/valgrind/commit/?id=e6388c9f70c2f3cc7c21e0253e635241286b2db1 commit e6388c9f70c2f3cc7c21e0253e635241286b2db1 Author: Paul Floyd <pj...@wa...> Date: Sun Apr 26 12:10:07 2026 +0200 Darwin syswrap: fixes for mach_msg2 Don't exclude macOS 13, fixes for the POST. Also add a suppression for this trap when it is called during initialisation. Diff: --- coregrind/m_syswrap/syswrap-darwin.c | 34 +++++++++++++++++++++++++--------- darwin.supp | 12 ++++++++++++ 2 files changed, 37 insertions(+), 9 deletions(-) diff --git a/coregrind/m_syswrap/syswrap-darwin.c b/coregrind/m_syswrap/syswrap-darwin.c index 4e3be2b15a..38304712da 100644 --- a/coregrind/m_syswrap/syswrap-darwin.c +++ b/coregrind/m_syswrap/syswrap-darwin.c @@ -7469,7 +7469,7 @@ POST(mach_make_memory_entry_64) Reply *reply = (Reply *)ARG1; if (reply->Head.msgh_bits & MACH_MSGH_BITS_COMPLEX) { - assign_port_name(reply->object.name, "memory-%p"); + record_named_port(tid, reply->object.name, MACH_PORT_RIGHT_SEND, "memory-%p"); PRINT("%s", name_for_port(reply->object.name)); } } @@ -9210,9 +9210,6 @@ PRE(mach_msg2) if (options & MACH_SEND_MSG && msgh_bits & MACH_SEND_TRAILER) { trailer_size = REQUESTED_TRAILER_SIZE(options); } -// FIXME: loads of issues on macOS 13 and no computer to test on -// disabled for now -#if DARWIN_VERS != DARWIN_13_00 if (options & MACH64_MSG_VECTOR) { mach_msg_vector_t *msgv = (mach_msg_vector_t *)mh; PRE_MEM_READ("mach_msg2(msgv)", (Addr)mh, sizeof(mach_msg_vector_t)); @@ -9240,7 +9237,6 @@ PRE(mach_msg2) PRE_MEM_WRITE("mach_msg2(msg)", (Addr)mh, size); } } -#endif // Assume call may block unless specified otherwise *flags |= SfMayBlock; @@ -9257,19 +9253,20 @@ PRE(mach_msg2) // no message sent, receive only CALL_PRE(mach_msg_receive); return; - } else if (msgh_local_port == vg_host_port) { + } else if (msgh_remote_port == vg_host_port) { // message sent to mach_host_self() CALL_PRE(mach_msg_host); + AFTER = POST_FN(mach_msg_host); return; - } else if (is_task_port(msgh_local_port)) { + } else if (is_task_port(msgh_remote_port)) { // message sent to a task CALL_PRE(mach_msg_task); return; - } else if (msgh_local_port == vg_bootstrap_port) { + } else if (msgh_remote_port == vg_bootstrap_port) { // message sent to bootstrap port CALL_PRE(mach_msg_bootstrap); return; - } else if (is_thread_port(msgh_local_port)) { + } else if (is_thread_port(msgh_remote_port)) { // message sent to one of this process's threads CALL_PRE(mach_msg_thread); return; @@ -9281,6 +9278,25 @@ PRE(mach_msg2) POST(mach_msg2) { +#define MACH_MSG2_UNSHIFT_LOW(x) ((x) & 0xffffffff) + mach_msg_header_t *mh = (mach_msg_header_t *)ARG1; + mach_msg_option64_t options = (mach_msg_option64_t)ARG2; + UWord rcv_size = MACH_MSG2_UNSHIFT_LOW(ARG7); +#undef MACH_MSG2_UNSHIFT_LOW + + if (options & MACH_RCV_MSG && RES == 0) { + if (options & MACH64_MSG_VECTOR) { + mach_msg_vector_t *msgv = (mach_msg_vector_t *)mh; + if (msgv->msgv_rcv_addr != 0) { + POST_MEM_WRITE((Addr)msgv->msgv_rcv_addr, msgv->msgv_rcv_size); + } else { + POST_MEM_WRITE((Addr)msgv->msgv_data, msgv->msgv_rcv_size); + } + } else { + POST_MEM_WRITE((Addr)mh, rcv_size); + } + } + // Call handler chosen by PRE(mach_msg2) if (AFTER) { (*AFTER)(tid, arrghs, status); diff --git a/darwin.supp b/darwin.supp index 9f8db09b9f..cb6aeab48b 100644 --- a/darwin.supp +++ b/darwin.supp @@ -972,3 +972,15 @@ fun:_ZL27_fetchInitializingClassListb } +{ + macOS1300:libSystem_initializer + Memcheck:Param + mach_msg2(msg) + fun:mach_msg2_trap + fun:mach_msg2_internal + fun:task_set_special_port + fun:_os_trace_create_debug_control_port + fun:_libtrace_init + fun:libSystem_initializer +} + |
|
From: Paul F. <pa...@so...> - 2026-04-26 05:39:48
|
https://sourceware.org/cgit/valgrind/commit/?id=ad9369a53c56691510678e8ed54103e55fdd3d5f commit ad9369a53c56691510678e8ed54103e55fdd3d5f Author: Paul Floyd <pj...@wa...> Date: Sun Apr 26 07:37:45 2026 +0200 Darwin regtest: re-enable none/tests/scripts/shell With a Darwin expected. I may need to add another expected for older versions of Darwin. Diff: --- none/tests/scripts/Makefile.am | 1 + none/tests/scripts/shell.vgtest | 2 +- 2 files changed, 2 insertions(+), 1 deletion(-) diff --git a/none/tests/scripts/Makefile.am b/none/tests/scripts/Makefile.am index 5102cc9381..aba7568ac4 100644 --- a/none/tests/scripts/Makefile.am +++ b/none/tests/scripts/Makefile.am @@ -16,6 +16,7 @@ EXTRA_DIST = \ shell.stderr.exp-dash4 \ shell.stdout.exp shell.stderr.exp-illumos shell.stderr.exp-freebsd \ shell.stderr.exp-solaris shell.stderr.exp-solaris-spawn \ + shell.stderr.exp-darwin \ shell2.vgtest shell2.stderr.exp shell2.stderr.exp-darwin19 \ shell2.stdout.exp \ shell3.vgtest shell3.stderr.exp shell3.stdout.exp \ diff --git a/none/tests/scripts/shell.vgtest b/none/tests/scripts/shell.vgtest index 47ce824e46..6deca1f01e 100644 --- a/none/tests/scripts/shell.vgtest +++ b/none/tests/scripts/shell.vgtest @@ -1,4 +1,4 @@ -prereq: ! ../../../tests/os_test darwin && rm -rf ./x86 && mkdir x86 +prereq: rm -rf ./x86 && mkdir x86 prog: shell stderr_filter: filter_shell_output vgopts: -q |
|
From: Paul F. <pa...@so...> - 2026-04-26 05:37:19
|
https://sourceware.org/cgit/valgrind/commit/?id=a10931c17a979e1b092cd2079cf2bf03d68f4793 commit a10931c17a979e1b092cd2079cf2bf03d68f4793 Author: Paul Floyd <pj...@wa...> Date: Sun Apr 26 07:36:02 2026 +0200 Darwin suppression: add another suppresion for startup allocations Diff: --- darwin.supp | 9 +++++++++ 1 file changed, 9 insertions(+) diff --git a/darwin.supp b/darwin.supp index 6c57ebb9ca..9f8db09b9f 100644 --- a/darwin.supp +++ b/darwin.supp @@ -963,3 +963,12 @@ ... fun:libSystem_atfork_child } + +{ + macOS1300:_fetchInitializingClassList(bool) + Memcheck:Leak + match-leak-kinds: reachable + fun:?alloc + fun:_ZL27_fetchInitializingClassListb +} + |
|
From: Paul F. <pa...@so...> - 2026-04-25 06:07:08
|
https://sourceware.org/cgit/valgrind/commit/?id=69a0bb7f8bb68fbed86d31236af6546b0edd9e53 commit 69a0bb7f8bb68fbed86d31236af6546b0edd9e53 Author: Paul Floyd <pj...@wa...> Date: Sat Apr 25 08:06:16 2026 +0200 Bump version to 3.28.0.GIT Diff: --- NEWS | 35 +++++++++++++++++++++++++++++++++++ configure.ac | 6 +++--- 2 files changed, 38 insertions(+), 3 deletions(-) diff --git a/NEWS b/NEWS index f8cd25de4b..50b8be88ba 100644 --- a/NEWS +++ b/NEWS @@ -1,3 +1,38 @@ +Release 3.28.0 (?? Oct 2026) +~~~~~~~~~~~~~~~~~~~~~~~~~~~~ + +This release supports X86/Linux, AMD64/Linux, ARM32/Linux, ARM64/Linux, +PPC32/Linux, PPC64BE/Linux, PPC64LE/Linux, S390X/Linux, MIPS32/Linux, +MIPS64/Linux, RISCV64/Linux, ARM/Android, ARM64/Android, MIPS32/Android, +X86/Android, X86/Solaris, AMD64/Solaris, X86/macOS, AMD64/macOS. +X86/FreeBSD, AMD64/FreeBSD and ARM64/FreeBSD. There is preliminary support +for nanoMIPS/Linux. macOS is supported up to version 13 Ventura (amd64 only). + +* ==================== CORE CHANGES =================== + +* ================== PLATFORM CHANGES ================= + +* ==================== TOOL CHANGES =================== + + +* ==================== FIXED BUGS ==================== + +The following bugs have been fixed or resolved. Note that "n-i-bz" +stands for "not in bugzilla" -- that is, a bug that was reported to us +but never got a bugzilla entry. We encourage you to file bugs in +bugzilla (https://bugs.kde.org/enter_bug.cgi?product=valgrind) rather +than mailing the developers (or mailing lists) directly -- bugs that +are not entered into bugzilla tend to get forgotten about or ignored. + +519223 Recognize ioctl(UFFDIO_*) operations + +To see details of a given bug, visit + https://bugs.kde.org/show_bug.cgi?id=XXXXXX +where XXXXXX is the bug number as listed above. + +(3.28.0.RC1: ?? Oct 2026) + + Release 3.27.0 (20 Apr 2026) ~~~~~~~~~~~~~~~~~~~~~~~~~~~~ diff --git a/configure.ac b/configure.ac index 4f62b19afc..39502a43ff 100644 --- a/configure.ac +++ b/configure.ac @@ -16,10 +16,10 @@ AC_PREREQ(2.69) # Also set the (expected/last) release date here. # Do not forget to rerun ./autogen.sh m4_define([v_major_ver], [3]) -m4_define([v_minor_ver], [27]) +m4_define([v_minor_ver], [28]) m4_define([v_micro_ver], [0]) -m4_define([v_suffix_ver], []) -m4_define([v_rel_date], ["20 Apr 2026"]) +m4_define([v_suffix_ver], [GIT]) +m4_define([v_rel_date], ["?? Oct 2026"]) m4_define([v_version], m4_if(v_suffix_ver, [], [v_major_ver.v_minor_ver.v_micro_ver], |
|
From: Martin C. <mc...@so...> - 2026-04-24 13:23:57
|
https://sourceware.org/cgit/valgrind/commit/?id=36f0e2fd8b43b57a3f661751ee9d496c51c5b727 commit 36f0e2fd8b43b57a3f661751ee9d496c51c5b727 Author: Martin Cermak <mc...@re...> Date: Fri Apr 24 13:21:05 2026 +0200 Recognize ioctl UFFDIO_* operations The userfaultfd* LTP testcases demonstrate how valgrind isn't aware of the ioctl UFFDIO_* operations. Teach Valgrind to recognize those per linux/fs/userfaultfd.c. https://bugs.kde.org/show_bug.cgi?id=519223 Diff: --- NEWS | 1 + coregrind/m_syswrap/syswrap-linux.c | 137 ++++++++++++++++++++++++++++++++++++ include/vki/vki-linux.h | 93 ++++++++++++++++++++++++ 3 files changed, 231 insertions(+) diff --git a/NEWS b/NEWS index f982eabf31..f8cd25de4b 100644 --- a/NEWS +++ b/NEWS @@ -170,6 +170,7 @@ are not entered into bugzilla tend to get forgotten about or ignored. 518609 Setting double verbose interferes with symbol loading (FreeBSD 16) 518778 Valgrind LTP testsuite fails to compile on Fedora 44+ 518951 LTP testcase fsconfig02 fails under Valgrind +519223 Recognize ioctl(UFFDIO_*) operations To see details of a given bug, visit https://bugs.kde.org/show_bug.cgi?id=XXXXXX diff --git a/coregrind/m_syswrap/syswrap-linux.c b/coregrind/m_syswrap/syswrap-linux.c index a1097c3167..f563e161bf 100644 --- a/coregrind/m_syswrap/syswrap-linux.c +++ b/coregrind/m_syswrap/syswrap-linux.c @@ -11054,6 +11054,97 @@ PRE(sys_ioctl) PRE_MEM_WRITE("ioctl(PROCMAP_QUERY)", (Addr)pq->build_id_addr, pq->build_id_size); break; } + case VKI_UFFDIO_API: { + struct vki_uffdio_api *ap = + (struct vki_uffdio_api *)(Addr)ARG3; + if (!ML_(safe_to_deref) (ap, sizeof(struct vki_uffdio_api))) + break; + PRE_FIELD_READ("ioctl(UFFDIO_API).api", ap->api); + PRE_FIELD_READ("ioctl(UFFDIO_API).features", ap->features); + PRE_MEM_WRITE("ioctl(UFFDIO_API)", (Addr)ap, sizeof(*ap)); + break; + } + case VKI_UFFDIO_REGISTER: { + struct vki_uffdio_register *ur = + (struct vki_uffdio_register *)(Addr)ARG3; + if (!ML_(safe_to_deref) (ur, sizeof(struct vki_uffdio_register))) + break; + PRE_FIELD_READ("ioctl(UFFDIO_REGISTER).mode", ur->mode); + PRE_FIELD_READ("ioctl(UFFDIO_REGISTER).range", ur->range); + PRE_MEM_WRITE("ioctl(UFFDIO_REGISTER)", (Addr)ur, sizeof(*ur)); + break; + } + case VKI_UFFDIO_UNREGISTER: + case VKI_UFFDIO_WAKE: { + struct vki_uffdio_range *rg = + (struct vki_uffdio_range *)(Addr)ARG3; + if (!ML_(safe_to_deref) (rg, sizeof(struct vki_uffdio_range))) + break; + PRE_FIELD_READ("ioctl(UFFDIO_UNREGISTER).start", rg->start); + PRE_FIELD_READ("ioctl(UFFDIO_UNREGISTER).len", rg->len); + break; + } + case VKI_UFFDIO_COPY: { + struct vki_uffdio_copy *uc = + (struct vki_uffdio_copy *)(Addr)ARG3; + if (!ML_(safe_to_deref) (uc, sizeof(struct vki_uffdio_copy))) + break; + PRE_FIELD_READ("ioctl(UFFDIO_COPY).dst", uc->dst); + PRE_FIELD_READ("ioctl(UFFDIO_COPY).src", uc->src); + PRE_FIELD_READ("ioctl(UFFDIO_COPY).len", uc->len); + PRE_FIELD_READ("ioctl(UFFDIO_COPY).mode", uc->mode); + PRE_MEM_WRITE("ioctl(UFFDIO_COPY)", (Addr)uc, sizeof(*uc)); + break; + } + case VKI_UFFDIO_ZEROPAGE: { + struct vki_uffdio_zeropage *zp = + (struct vki_uffdio_zeropage *)(Addr)ARG3; + if (!ML_(safe_to_deref) (zp, sizeof(struct vki_uffdio_zeropage))) + break; + PRE_FIELD_READ("ioctl(UFFDIO_REGISTER).range", zp->range); + PRE_FIELD_READ("ioctl(UFFDIO_REGISTER).mode", zp->mode); + break; + } + case VKI_UFFDIO_MOVE: { + struct vki_uffdio_move *mv = + (struct vki_uffdio_move *)(Addr)ARG3; + if (!ML_(safe_to_deref) (mv, sizeof(struct vki_uffdio_move))) + break; + PRE_FIELD_READ("ioctl(UFFDIO_MOVE).dst", mv->dst); + PRE_FIELD_READ("ioctl(UFFDIO_MOVE).src", mv->src); + PRE_FIELD_READ("ioctl(UFFDIO_MOVE).len", mv->len); + PRE_FIELD_READ("ioctl(UFFDIO_MOVE).mode", mv->mode); + PRE_MEM_WRITE("ioctl(UFFDIO_MOVE)", (Addr)mv, sizeof(*mv)); + break; + } + case VKI_UFFDIO_WRITEPROTECT: { + struct vki_uffdio_writeprotect *vp = + (struct vki_uffdio_writeprotect *)(Addr)ARG3; + if (!ML_(safe_to_deref) (vp, sizeof(struct vki_uffdio_writeprotect))) + break; + PRE_FIELD_READ("ioctl(UFFDIO_WRITEPROTECT).range", vp->range); + break; + } + case VKI_UFFDIO_CONTINUE: { + struct vki_uffdio_continue *vk = + (struct vki_uffdio_continue *)(Addr)ARG3; + if (!ML_(safe_to_deref) (vk, sizeof(struct vki_uffdio_continue))) + break; + PRE_FIELD_READ("ioctl(UFFDIO_CONTINUE).range", vk->range); + PRE_FIELD_READ("ioctl(UFFDIO_CONTINUE).mode", vk->mode); + PRE_MEM_WRITE("ioctl(UFFDIO_CONTINUE)", (Addr)vk, sizeof(*vk)); + break; + } + case VKI_UFFDIO_POISON: { + struct vki_uffdio_poison *po = + (struct vki_uffdio_poison *)(Addr)ARG3; + if (!ML_(safe_to_deref) (po, sizeof(struct vki_uffdio_poison))) + break; + PRE_FIELD_READ("ioctl(UFFDIO_POISON).range", po->range); + PRE_FIELD_READ("ioctl(UFFDIO_POISON).mode", po->mode); + PRE_MEM_WRITE("ioctl(UFFDIO_POISON)", (Addr)po, sizeof(*po)); + break; + } default: /* EVIOC* are variable length and return size written on success */ @@ -13226,6 +13317,52 @@ POST(sys_ioctl) POST_MEM_WRITE((Addr)pq, pq->size); break; } + case VKI_UFFDIO_API: { + struct vki_uffdio_api *ap = + (struct vki_uffdio_api *)(Addr)ARG3; + POST_FIELD_WRITE(ap->features); + POST_FIELD_WRITE(ap->ioctls); + break; + } + case VKI_UFFDIO_REGISTER: { + struct vki_uffdio_register *ur = + (struct vki_uffdio_register *)(Addr)ARG3; + POST_FIELD_WRITE(ur->ioctls); + break; + } + // case VKI_UFFDIO_UNREGISTER - no output members + // case VKI_UFFDIO_WAKE - no output members + case VKI_UFFDIO_COPY: { + struct vki_uffdio_copy *uc = + (struct vki_uffdio_copy *)(Addr)ARG3; + POST_FIELD_WRITE(uc->mode); + break; + } + case VKI_UFFDIO_ZEROPAGE: { + struct vki_uffdio_zeropage *zp = + (struct vki_uffdio_zeropage *)(Addr)ARG3; + POST_FIELD_WRITE(zp->mode); + break; + } + case VKI_UFFDIO_MOVE: { + struct vki_uffdio_move *mv = + (struct vki_uffdio_move *)(Addr)ARG3; + POST_FIELD_WRITE(mv->move); + break; + } + // case VKI_UFFDIO_WRITEPROTECT: no output members + case VKI_UFFDIO_CONTINUE: { + struct vki_uffdio_continue *vk = + (struct vki_uffdio_continue *)(Addr)ARG3; + POST_FIELD_WRITE(vk->mapped); + break; + } + case VKI_UFFDIO_POISON: { + struct vki_uffdio_poison *po = + (struct vki_uffdio_poison *)(Addr)ARG3; + POST_FIELD_WRITE(po->updated); + break; + } default: /* EVIOC* are variable length and return size written on success */ diff --git a/include/vki/vki-linux.h b/include/vki/vki-linux.h index 00e228a836..20e4ecd0c4 100644 --- a/include/vki/vki-linux.h +++ b/include/vki/vki-linux.h @@ -5680,6 +5680,99 @@ struct vki_lsm_ctx { __vki_u8 ctx[]; /* __counted_by(ctx_len); */ }; +//---------------------------------------------------------------------- +// From include/uapi/linux/userfaultfd.h +//---------------------------------------------------------------------- + +struct vki_uffdio_api { + __vki_u64 api; + __vki_u64 features; + __vki_u64 ioctls; +}; + +struct vki_uffdio_range { + __vki_u64 start; + __vki_u64 len; +}; + +struct vki_uffdio_register { + struct vki_uffdio_range range; + __vki_u64 mode; + __vki_u64 ioctls; +}; + +struct vki_uffdio_copy { + __vki_u64 dst; + __vki_u64 src; + __vki_u64 len; + __vki_u64 mode; + __vki_s64 copy; +}; + +struct vki_uffdio_zeropage { + struct vki_uffdio_range range; + __vki_u64 mode; + __vki_s64 zeropage; +}; + +struct vki_uffdio_move { + __vki_u64 dst; + __vki_u64 src; + __vki_u64 len; + __vki_u64 mode; + __vki_s64 move; +}; + +struct vki_uffdio_writeprotect { + struct vki_uffdio_range range; + __vki_u64 mode; +}; + +struct vki_uffdio_continue { + struct vki_uffdio_range range; + __vki_u64 mode; + __vki_s64 mapped; +}; + +struct vki_uffdio_poison { + struct vki_uffdio_range range; + __vki_u64 mode; + __vki_s64 updated; +}; + +#define _UFFDIO_REGISTER (0x00) +#define _UFFDIO_UNREGISTER (0x01) +#define _UFFDIO_WAKE (0x02) +#define _UFFDIO_COPY (0x03) +#define _UFFDIO_ZEROPAGE (0x04) +#define _UFFDIO_MOVE (0x05) +#define _UFFDIO_WRITEPROTECT (0x06) +#define _UFFDIO_CONTINUE (0x07) +#define _UFFDIO_POISON (0x08) +#define _UFFDIO_API (0x3F) + +#define VKI_UFFDIO 0xAA +#define VKI_UFFDIO_API _VKI_IOWR(VKI_UFFDIO, _UFFDIO_API, \ + struct vki_uffdio_api) +#define VKI_UFFDIO_REGISTER _VKI_IOWR(VKI_UFFDIO, _UFFDIO_REGISTER, \ + struct vki_uffdio_register) +#define VKI_UFFDIO_UNREGISTER _VKI_IOR(VKI_UFFDIO, _UFFDIO_UNREGISTER, \ + struct vki_uffdio_range) +#define VKI_UFFDIO_WAKE _VKI_IOR(VKI_UFFDIO, _UFFDIO_WAKE, \ + struct vki_uffdio_range) +#define VKI_UFFDIO_COPY _VKI_IOWR(VKI_UFFDIO, _UFFDIO_COPY, \ + struct vki_uffdio_copy) +#define VKI_UFFDIO_ZEROPAGE _VKI_IOWR(VKI_UFFDIO, _UFFDIO_ZEROPAGE, \ + struct vki_uffdio_zeropage) +#define VKI_UFFDIO_MOVE _VKI_IOWR(VKI_UFFDIO, _UFFDIO_MOVE, \ + struct vki_uffdio_move) +#define VKI_UFFDIO_WRITEPROTECT _VKI_IOWR(VKI_UFFDIO, _UFFDIO_WRITEPROTECT, \ + struct vki_uffdio_writeprotect) +#define VKI_UFFDIO_CONTINUE _VKI_IOWR(VKI_UFFDIO, _UFFDIO_CONTINUE, \ + struct vki_uffdio_continue) +#define VKI_UFFDIO_POISON _VKI_IOWR(VKI_UFFDIO, _UFFDIO_POISON, \ + struct vki_uffdio_poison) + /*--------------------------------------------------------------------*/ /*--- end ---*/ /*--------------------------------------------------------------------*/ |
|
From: Li W. <wan...@gm...> - 2026-04-24 01:56:55
|
Hi Petr, Reviewed-by: Li Wang <li...@li...> Tiny note: it would be appreciated if your replace all the reviewed-by with my new account in this patchset. -- Regards, Li Wang |
|
From: Martin C. <mc...@re...> - 2026-04-23 14:44:59
|
On Wed 2026-04-22 15:08 , Martin Cermak wrote:
> On Wed 2026-04-22 14:17 , Petr Vorel wrote:
> >
> >
> > > On 4/22/26 7:37 AM, Petr Vorel wrote:
> > > > > However, some of the testcases can be easily changed to use forked
> > > > > processes instead of threads. That's what this patch does. When
> > > > > client program forks, Valgrind forks too, and that allows for the needed
> > > > > parallelism to handle the page fault.
> > > > You understand process vs. threads more than me. But shouldn't mmap() use
> > > > MAP_SHARED instead of MAP_PRIVATE for those which aren't using /dev/userfaultfd?
> >
> > > The documentation for userfaultfd mentions threads. I'm afraid we'll
> > > lose vital coverage if we move to forked processes.
> >
> > +1, at least some tests would keep threads (not all userfaultfd tests would be
> > converted, but yes, that's why I suggested to use MAP_SHARED, which could be
> > similar to threads (yes, the difference between processes and threads in Linux
> > kernel is not that huge as both are created in clone(), it's mostly about what
> > is shared).
>
> My goal is to make at least part of these userfaultfd tests
> compatible with Valgrind. I've experimented with clone() and it
> seems like Valgrind has limited support for it. That said,
> adding another set of userfaultfd tests using fork() or clone()
> instead of threads might help. Some of such new tests will be
> "incompatible" with valgrind, but it might be a test coverage
> improvement.
Here is an ai-assisted patch that works for me:
>From 693f3015d39b39e2c263aac57c183e3e4cf7df4d Mon Sep 17 00:00:00 2001
From: Martin Cermak <mc...@re...>
Date: Thu, 23 Apr 2026 15:51:10 +0200
Subject: [PATCH] Provide Valgrind-compatible userfaultfd tests
The userfaultfd tests use threads. Threads are executed serially
in Valgrind, but parallelism is important for userfaultfd tests.
When a page fault happens in parent thread, kernel stops it, and
waits for the handler thread to handle the page fault. That said,
userfaultfd tests 01 - 06 stall in Valgrind.
This update comes with second set of userfaultfd tests 07 - 12.
These additional tests use fork() or clone(), thus a separate
process instead of threads. Support for clone() is also limited
in Valgrind. For that reason only tests 07, 09 and 10 are "Valgrind
compatible". But it's a test coverage improvement.
Valgrind can filter LTP tests on the per test binary basis. That's
why this update adds separate tests 07 - 12.
Assisted-by: Anthropic Claude
Reviewed-by: Martin Cermak <mc...@re...>
---
include/lapi/sched.h | 8 +
.../kernel/syscalls/userfaultfd/.gitignore | 6 +
.../kernel/syscalls/userfaultfd/Makefile | 3 +
.../syscalls/userfaultfd/userfaultfd07.c | 136 +++++++++++++++
.../syscalls/userfaultfd/userfaultfd08.c | 113 +++++++++++++
.../syscalls/userfaultfd/userfaultfd09.c | 141 ++++++++++++++++
.../syscalls/userfaultfd/userfaultfd10.c | 106 ++++++++++++
.../syscalls/userfaultfd/userfaultfd11.c | 140 ++++++++++++++++
.../syscalls/userfaultfd/userfaultfd12.c | 157 ++++++++++++++++++
9 files changed, 810 insertions(+)
create mode 100644 testcases/kernel/syscalls/userfaultfd/userfaultfd07.c
create mode 100644 testcases/kernel/syscalls/userfaultfd/userfaultfd08.c
create mode 100644 testcases/kernel/syscalls/userfaultfd/userfaultfd09.c
create mode 100644 testcases/kernel/syscalls/userfaultfd/userfaultfd10.c
create mode 100644 testcases/kernel/syscalls/userfaultfd/userfaultfd11.c
create mode 100644 testcases/kernel/syscalls/userfaultfd/userfaultfd12.c
diff --git a/include/lapi/sched.h b/include/lapi/sched.h
index 05b322c1c..b33de6657 100644
--- a/include/lapi/sched.h
+++ b/include/lapi/sched.h
@@ -121,6 +121,14 @@ static inline int getcpu(unsigned *cpu, unsigned *node)
# define CLONE_FS 0x00000200
#endif
+#ifndef CLONE_FILES
+# define CLONE_FILES 0x00000400
+#endif
+
+#ifndef CLONE_SIGHAND
+# define CLONE_SIGHAND 0x00000800
+#endif
+
#ifndef CLONE_PIDFD
# define CLONE_PIDFD 0x00001000
#endif
diff --git a/testcases/kernel/syscalls/userfaultfd/.gitignore b/testcases/kernel/syscalls/userfaultfd/.gitignore
index bc32fdf3b..59d28c6f3 100644
--- a/testcases/kernel/syscalls/userfaultfd/.gitignore
+++ b/testcases/kernel/syscalls/userfaultfd/.gitignore
@@ -4,3 +4,9 @@
/userfaultfd04
/userfaultfd05
/userfaultfd06
+/userfaultfd07
+/userfaultfd08
+/userfaultfd09
+/userfaultfd10
+/userfaultfd11
+/userfaultfd12
diff --git a/testcases/kernel/syscalls/userfaultfd/Makefile b/testcases/kernel/syscalls/userfaultfd/Makefile
index 3252e47df..e4ed56b4b 100644
--- a/testcases/kernel/syscalls/userfaultfd/Makefile
+++ b/testcases/kernel/syscalls/userfaultfd/Makefile
@@ -17,3 +17,6 @@ userfaultfd03: CFLAGS += -pthread
userfaultfd04: CFLAGS += -pthread
userfaultfd05: CFLAGS += -pthread
userfaultfd06: CFLAGS += -pthread
+# Tests 07-12: Valgrind-compatible variants using fork/clone
+# Tests 07, 09, 10: fork-based (no pthread needed)
+# Tests 08, 11, 12: clone-based (no pthread needed)
diff --git a/testcases/kernel/syscalls/userfaultfd/userfaultfd07.c b/testcases/kernel/syscalls/userfaultfd/userfaultfd07.c
new file mode 100644
index 000000000..bebf0e921
--- /dev/null
+++ b/testcases/kernel/syscalls/userfaultfd/userfaultfd07.c
@@ -0,0 +1,136 @@
+// SPDX-License-Identifier: GPL-2.0-or-later
+/*
+ * Copyright (c) 2019 SUSE LLC
+ * Author: Christian Amann <ca...@su...>
+ */
+
+/*\
+ * Force a pagefault event and handle it using :manpage:`userfaultfd(2)`
+ * from a different process (using fork instead of threads for Valgrind compatibility).
+ */
+
+#include <poll.h>
+#include "tst_test.h"
+#include "tst_safe_macros.h"
+#include "lapi/userfaultfd.h"
+
+#define BEFORE_5_11 1
+#define AFTER_5_11 2
+#define DESC(x) .flags = x, .desc = #x
+
+static struct tcase {
+ int flags;
+ const char *desc;
+ int kver;
+} tcases[] = {
+ { DESC(O_CLOEXEC | O_NONBLOCK) },
+ { DESC(O_CLOEXEC | O_NONBLOCK | UFFD_USER_MODE_ONLY), .kver = AFTER_5_11, },
+};
+
+static int page_size;
+static char *page;
+static void *copy_page;
+static int uffd;
+static int kver;
+
+static void setup(void)
+{
+ if (tst_kvercmp(5, 11, 0) >= 0)
+ kver = AFTER_5_11;
+ else
+ kver = BEFORE_5_11;
+}
+
+static void set_pages(void)
+{
+ page_size = sysconf(_SC_PAGE_SIZE);
+ page = SAFE_MMAP(NULL, page_size, PROT_READ | PROT_WRITE,
+ MAP_PRIVATE | MAP_ANONYMOUS, -1, 0);
+ copy_page = SAFE_MMAP(NULL, page_size, PROT_READ | PROT_WRITE,
+ MAP_PRIVATE | MAP_ANONYMOUS, -1, 0);
+}
+
+static void reset_pages(void)
+{
+ SAFE_MUNMAP(page, page_size);
+ SAFE_MUNMAP(copy_page, page_size);
+}
+
+static void *pagefault_handler(void)
+{
+ static struct uffd_msg msg;
+ struct uffdio_copy uffdio_copy = {};
+
+ struct pollfd pollfd;
+ int nready;
+
+ pollfd.fd = uffd;
+ pollfd.events = POLLIN;
+ nready = poll(&pollfd, 1, -1);
+ if (nready == -1)
+ tst_brk(TBROK | TERRNO, "Error on poll");
+
+ SAFE_READ(1, uffd, &msg, sizeof(msg));
+
+ if (msg.event != UFFD_EVENT_PAGEFAULT)
+ tst_brk(TBROK | TERRNO, "Received unexpected UFFD_EVENT %d", msg.event);
+
+ memset(copy_page, 'X', page_size);
+
+ uffdio_copy.src = (unsigned long) copy_page;
+
+ uffdio_copy.dst = (unsigned long) msg.arg.pagefault.address
+ & ~(page_size - 1);
+ uffdio_copy.len = page_size;
+ SAFE_IOCTL(uffd, UFFDIO_COPY, &uffdio_copy);
+
+ close(uffd);
+ return NULL;
+}
+
+static void run(unsigned int i)
+{
+ pid_t pid;
+ struct uffdio_api uffdio_api = {};
+ struct uffdio_register uffdio_register;
+ struct tcase *tc = &tcases[i];
+
+ if (tc->kver == AFTER_5_11 && kver == BEFORE_5_11)
+ tst_brk(TCONF, "%s requires kernel >= 5.11", tc->desc);
+
+ set_pages();
+
+ uffd = SAFE_USERFAULTFD(tc->flags, false);
+
+ uffdio_api.api = UFFD_API;
+ SAFE_IOCTL(uffd, UFFDIO_API, &uffdio_api);
+
+ uffdio_register.range.start = (unsigned long) page;
+ uffdio_register.range.len = page_size;
+ uffdio_register.mode = UFFDIO_REGISTER_MODE_MISSING;
+
+ SAFE_IOCTL(uffd, UFFDIO_REGISTER, &uffdio_register);
+
+ pid = SAFE_FORK();
+ if (pid == 0) {
+ pagefault_handler();
+ _exit(0);
+ }
+
+ char c = page[0xf];
+
+ if (c == 'X')
+ tst_res(TPASS, "Pagefault handled!");
+ else
+ tst_res(TFAIL, "Pagefault not handled!");
+
+ SAFE_WAITPID(pid, NULL, 0);
+ reset_pages();
+}
+
+static struct tst_test test = {
+ .setup = setup,
+ .test = run,
+ .tcnt = ARRAY_SIZE(tcases),
+ .forks_child = 1,
+};
diff --git a/testcases/kernel/syscalls/userfaultfd/userfaultfd08.c b/testcases/kernel/syscalls/userfaultfd/userfaultfd08.c
new file mode 100644
index 000000000..f6bde86cc
--- /dev/null
+++ b/testcases/kernel/syscalls/userfaultfd/userfaultfd08.c
@@ -0,0 +1,113 @@
+// SPDX-License-Identifier: GPL-2.0-or-later
+/*
+ * Copyright (c) 2025 SUSE LLC
+ * Author: Christian Amann <ca...@su...>
+ * Author: Ricardo Branco <rb...@su...>
+ */
+
+/*\
+ * Force a pagefault event and handle it using :manpage:`userfaultfd(2)`
+ * from a different process (using clone with CLONE_VM instead of threads
+ * for Valgrind compatibility) using UFFDIO_MOVE.
+ */
+
+#include "config.h"
+#include "tst_test.h"
+#include "tst_safe_macros.h"
+#include "tst_clone.h"
+#include "lapi/sched.h"
+#include "lapi/userfaultfd.h"
+
+#define CHILD_STACK_SIZE (1024 * 1024)
+
+static int page_size;
+static char *page;
+static void *move_page;
+static int uffd;
+static void *child_stack;
+
+static void set_pages(void)
+{
+ page_size = sysconf(_SC_PAGE_SIZE);
+ page = SAFE_MMAP(NULL, page_size, PROT_READ | PROT_WRITE,
+ MAP_PRIVATE | MAP_ANONYMOUS, -1, 0);
+ move_page = SAFE_MMAP(NULL, page_size, PROT_READ | PROT_WRITE,
+ MAP_PRIVATE | MAP_ANONYMOUS, -1, 0);
+}
+
+static void reset_pages(void)
+{
+ SAFE_MUNMAP(page, page_size);
+ /*
+ * After UFFDIO_MOVE, move_page is invalid and should not be unmapped.
+ * The kernel has already removed the mapping during the move operation.
+ */
+}
+
+static int pagefault_handler(void *arg LTP_ATTRIBUTE_UNUSED)
+{
+ struct uffd_msg msg;
+ struct uffdio_move uffdio_move = {};
+
+ SAFE_READ(1, uffd, &msg, sizeof(msg));
+
+ if (msg.event != UFFD_EVENT_PAGEFAULT)
+ tst_brk(TBROK | TERRNO, "Received unexpected UFFD_EVENT %d", msg.event);
+
+ memset(move_page, 'X', page_size);
+
+ uffdio_move.src = (unsigned long) move_page;
+
+ uffdio_move.dst = (unsigned long) msg.arg.pagefault.address
+ & ~(page_size - 1);
+ uffdio_move.len = page_size;
+ SAFE_IOCTL(uffd, UFFDIO_MOVE, &uffdio_move);
+
+ close(uffd);
+ return 0;
+}
+
+static void run(void)
+{
+ pid_t pid;
+ struct uffdio_api uffdio_api = {};
+ struct uffdio_register uffdio_register;
+
+ set_pages();
+
+ uffd = SAFE_USERFAULTFD(O_CLOEXEC, false);
+
+ uffdio_api.api = UFFD_API;
+ SAFE_IOCTL(uffd, UFFDIO_API, &uffdio_api);
+
+ uffdio_register.range.start = (unsigned long) page;
+ uffdio_register.range.len = page_size;
+ uffdio_register.mode = UFFDIO_REGISTER_MODE_MISSING;
+
+ SAFE_IOCTL(uffd, UFFDIO_REGISTER, &uffdio_register);
+
+ pid = ltp_clone(CLONE_VM | CLONE_FILES | CLONE_FS | CLONE_SIGHAND | SIGCHLD,
+ pagefault_handler, NULL, CHILD_STACK_SIZE, child_stack);
+ if (pid == -1)
+ tst_brk(TBROK | TERRNO, "ltp_clone failed");
+
+ char c = page[0xf];
+
+ if (c == 'X')
+ tst_res(TPASS, "Pagefault handled via UFFDIO_MOVE");
+ else
+ tst_res(TFAIL, "Pagefault not handled via UFFDIO_MOVE");
+
+ SAFE_WAITPID(pid, NULL, 0);
+ reset_pages();
+}
+
+static struct tst_test test = {
+ .test_all = run,
+ .min_kver = "6.8",
+ .forks_child = 1,
+ .bufs = (struct tst_buffers []) {
+ {&child_stack, .size = CHILD_STACK_SIZE},
+ {},
+ },
+};
diff --git a/testcases/kernel/syscalls/userfaultfd/userfaultfd09.c b/testcases/kernel/syscalls/userfaultfd/userfaultfd09.c
new file mode 100644
index 000000000..e1190a4ce
--- /dev/null
+++ b/testcases/kernel/syscalls/userfaultfd/userfaultfd09.c
@@ -0,0 +1,141 @@
+// SPDX-License-Identifier: GPL-2.0-or-later
+/*
+ * Copyright (c) 2025 SUSE LLC
+ * Author: Christian Amann <ca...@su...>
+ * Author: Ricardo Branco <rb...@su...>
+ */
+
+/*\
+ * Force a pagefault event and handle it using :manpage:`userfaultfd(2)`
+ * from a different process (using fork instead of threads for Valgrind compatibility)
+ * using /dev/userfaultfd instead of syscall, using USERFAULTFD_IOC_NEW ioctl to create
+ * the uffd & UFFDIO_COPY.
+ */
+
+#include "config.h"
+#include <poll.h>
+#include <unistd.h>
+#include "tst_test.h"
+#include "tst_safe_macros.h"
+#include "lapi/userfaultfd.h"
+
+static int page_size;
+static char *page;
+static void *copy_page;
+static int uffd;
+
+static void setup(void)
+{
+ if (access("/dev/userfaultfd", F_OK) != 0) {
+ int res = (tst_kvercmp(6, 1, 0) < 0) ? TCONF : TBROK;
+
+ tst_brk(res, "/dev/userfaultfd not found");
+ }
+}
+
+static int open_userfaultfd(int flags)
+{
+ int fd, fd2;
+
+ fd = SAFE_OPEN("/dev/userfaultfd", O_RDWR);
+
+ fd2 = SAFE_IOCTL(fd, USERFAULTFD_IOC_NEW, flags);
+
+ SAFE_CLOSE(fd);
+
+ return fd2;
+}
+
+static void set_pages(void)
+{
+ page_size = sysconf(_SC_PAGE_SIZE);
+ page = SAFE_MMAP(NULL, page_size, PROT_READ | PROT_WRITE,
+ MAP_PRIVATE | MAP_ANONYMOUS, -1, 0);
+ copy_page = SAFE_MMAP(NULL, page_size, PROT_READ | PROT_WRITE,
+ MAP_PRIVATE | MAP_ANONYMOUS, -1, 0);
+}
+
+static void reset_pages(void)
+{
+ SAFE_MUNMAP(page, page_size);
+ SAFE_MUNMAP(copy_page, page_size);
+}
+
+static void *pagefault_handler(void)
+{
+ static struct uffd_msg msg;
+ struct uffdio_copy uffdio_copy = {};
+
+ struct pollfd pollfd;
+ int nready;
+
+ pollfd.fd = uffd;
+ pollfd.events = POLLIN;
+ nready = poll(&pollfd, 1, -1);
+ if (nready == -1)
+ tst_brk(TBROK | TERRNO, "Error on poll");
+
+ SAFE_READ(1, uffd, &msg, sizeof(msg));
+
+ if (msg.event != UFFD_EVENT_PAGEFAULT)
+ tst_brk(TBROK | TERRNO, "Received unexpected UFFD_EVENT %d", msg.event);
+
+ memset(copy_page, 'X', page_size);
+
+ uffdio_copy.src = (unsigned long) copy_page;
+
+ uffdio_copy.dst = (unsigned long) msg.arg.pagefault.address
+ & ~(page_size - 1);
+ uffdio_copy.len = page_size;
+ SAFE_IOCTL(uffd, UFFDIO_COPY, &uffdio_copy);
+
+ close(uffd);
+ return NULL;
+}
+
+static void run(void)
+{
+ pid_t pid;
+ struct uffdio_api uffdio_api = {};
+ struct uffdio_register uffdio_register;
+
+ set_pages();
+
+ uffd = open_userfaultfd(O_CLOEXEC | O_NONBLOCK);
+
+ uffdio_api.api = UFFD_API;
+ SAFE_IOCTL(uffd, UFFDIO_API, &uffdio_api);
+
+ uffdio_register.range.start = (unsigned long) page;
+ uffdio_register.range.len = page_size;
+ uffdio_register.mode = UFFDIO_REGISTER_MODE_MISSING;
+
+ SAFE_IOCTL(uffd, UFFDIO_REGISTER, &uffdio_register);
+
+ pid = SAFE_FORK();
+ if (pid == 0) {
+ pagefault_handler();
+ _exit(0);
+ }
+
+ char c = page[0xf];
+
+ if (c == 'X')
+ tst_res(TPASS, "Pagefault handled via /dev/userfaultfd");
+ else
+ tst_res(TFAIL, "Pagefault not handled via /dev/userfaultfd");
+
+ SAFE_WAITPID(pid, NULL, 0);
+ reset_pages();
+}
+
+static struct tst_test test = {
+ .needs_root = 1,
+ .setup = setup,
+ .test_all = run,
+ .needs_kconfigs = (const char *[]) {
+ "CONFIG_USERFAULTFD=y",
+ NULL
+ },
+ .forks_child = 1,
+};
diff --git a/testcases/kernel/syscalls/userfaultfd/userfaultfd10.c b/testcases/kernel/syscalls/userfaultfd/userfaultfd10.c
new file mode 100644
index 000000000..8e9bd0b0c
--- /dev/null
+++ b/testcases/kernel/syscalls/userfaultfd/userfaultfd10.c
@@ -0,0 +1,106 @@
+// SPDX-License-Identifier: GPL-2.0-or-later
+/*
+ * Copyright (c) 2025 SUSE LLC
+ * Author: Christian Amann <ca...@su...>
+ * Author: Ricardo Branco <rb...@su...>
+ */
+
+/*\
+ * Force a pagefault event and handle it using :manpage:`userfaultfd(2)`
+ * from a different process (using fork instead of threads for Valgrind compatibility)
+ * using UFFDIO_ZEROPAGE.
+ */
+
+#include "config.h"
+#include <poll.h>
+#include "tst_test.h"
+#include "tst_safe_macros.h"
+#include "lapi/userfaultfd.h"
+
+static int page_size;
+static char *page;
+static int uffd;
+
+static void set_pages(void)
+{
+ page_size = sysconf(_SC_PAGE_SIZE);
+ page = SAFE_MMAP(NULL, page_size, PROT_READ | PROT_WRITE,
+ MAP_PRIVATE | MAP_ANONYMOUS, -1, 0);
+}
+
+static void reset_pages(void)
+{
+ SAFE_MUNMAP(page, page_size);
+}
+
+static void *pagefault_handler(void)
+{
+ static struct uffd_msg msg;
+ struct uffdio_zeropage uffdio_zeropage = {};
+
+ struct pollfd pollfd;
+ int nready;
+
+ pollfd.fd = uffd;
+ pollfd.events = POLLIN;
+ nready = poll(&pollfd, 1, -1);
+ if (nready == -1)
+ tst_brk(TBROK | TERRNO, "Error on poll");
+
+ SAFE_READ(1, uffd, &msg, sizeof(msg));
+
+ if (msg.event != UFFD_EVENT_PAGEFAULT)
+ tst_brk(TBROK | TERRNO, "Received unexpected UFFD_EVENT %d", msg.event);
+
+ uffdio_zeropage.range.start = msg.arg.pagefault.address
+ & ~(page_size - 1);
+ uffdio_zeropage.range.len = page_size;
+
+ SAFE_IOCTL(uffd, UFFDIO_ZEROPAGE, &uffdio_zeropage);
+
+ close(uffd);
+ return NULL;
+}
+
+static void run(void)
+{
+ pid_t pid;
+ struct uffdio_api uffdio_api = {};
+ struct uffdio_register uffdio_register;
+
+ set_pages();
+
+ uffd = SAFE_USERFAULTFD(O_CLOEXEC | O_NONBLOCK, false);
+
+ uffdio_api.api = UFFD_API;
+ SAFE_IOCTL(uffd, UFFDIO_API, &uffdio_api);
+
+ uffdio_register.range.start = (unsigned long) page;
+ uffdio_register.range.len = page_size;
+ uffdio_register.mode = UFFDIO_REGISTER_MODE_MISSING;
+
+ SAFE_IOCTL(uffd, UFFDIO_REGISTER, &uffdio_register);
+
+ pid = SAFE_FORK();
+ if (pid == 0) {
+ pagefault_handler();
+ _exit(0);
+ }
+
+ for (int i = 0; i < page_size; i++) {
+ if (page[i] != 0) {
+ tst_res(TFAIL, "page[%d]=0x%x not zero", i, page[i]);
+ return;
+ }
+ }
+
+ tst_res(TPASS, "Pagefault handled with UFFDIO_ZEROPAGE");
+
+ SAFE_WAITPID(pid, NULL, 0);
+ reset_pages();
+}
+
+static struct tst_test test = {
+ .test_all = run,
+ .forks_child = 1,
+};
diff --git a/testcases/kernel/syscalls/userfaultfd/userfaultfd11.c b/testcases/kernel/syscalls/userfaultfd/userfaultfd11.c
new file mode 100644
index 000000000..52590d117
--- /dev/null
+++ b/testcases/kernel/syscalls/userfaultfd/userfaultfd11.c
@@ -0,0 +1,140 @@
+// SPDX-License-Identifier: GPL-2.0-or-later
+/*
+ * Copyright (c) 2025 SUSE LLC
+ * Author: Christian Amann <ca...@su...>
+ * Author: Ricardo Branco <rb...@su...>
+ */
+
+/*\
+ * Force a pagefault event and handle it using :manpage:`userfaultfd(2)`
+ * from a different process (using clone with CLONE_VM instead of threads
+ * for Valgrind compatibility) testing UFFDIO_WRITEPROTECT_MODE_WP.
+ */
+
+#include "config.h"
+#include <poll.h>
+#include "tst_test.h"
+#include "tst_safe_macros.h"
+#include "lapi/sched.h"
+#include "lapi/userfaultfd.h"
+
+static int page_size;
+static char *page;
+static int uffd;
+static volatile int wp_fault_seen;
+
+static void set_pages(void)
+{
+ page_size = sysconf(_SC_PAGE_SIZE);
+ page = SAFE_MMAP(NULL, page_size, PROT_READ | PROT_WRITE,
+ MAP_PRIVATE | MAP_ANONYMOUS, -1, 0);
+
+ memset(page, 0, page_size);
+}
+
+static void reset_pages(void)
+{
+ SAFE_MUNMAP(page, page_size);
+}
+
+static void pagefault_handler(void)
+{
+ struct uffd_msg msg;
+ struct uffdio_writeprotect uffdio_writeprotect = {};
+
+ struct pollfd pollfd;
+ int nready;
+
+ pollfd.fd = uffd;
+ pollfd.events = POLLIN;
+ nready = poll(&pollfd, 1, -1);
+ if (nready == -1)
+ tst_brk(TBROK | TERRNO, "Error on poll");
+
+ SAFE_READ(1, uffd, &msg, sizeof(msg));
+
+ if (msg.event != UFFD_EVENT_PAGEFAULT)
+ tst_brk(TFAIL, "Received unexpected UFFD_EVENT %d", msg.event);
+
+ if (!(msg.arg.pagefault.flags & UFFD_PAGEFAULT_FLAG_WP) ||
+ !(msg.arg.pagefault.flags & UFFD_PAGEFAULT_FLAG_WRITE)) {
+ tst_brk(TFAIL,
+ "Expected WP+WRITE fault but flags=%lx",
+ (unsigned long)msg.arg.pagefault.flags);
+ }
+
+ /* While the WP fault is pending, the write must NOT be visible. */
+ if (page[0xf] != 0)
+ tst_brk(TFAIL,
+ "Write became visible while page was write-protected!");
+
+ wp_fault_seen = 1;
+
+ /* Resolve the fault by clearing WP so the writer can resume. */
+ uffdio_writeprotect.range.start = msg.arg.pagefault.address & ~(page_size - 1);
+ uffdio_writeprotect.range.len = page_size;
+
+ SAFE_IOCTL(uffd, UFFDIO_WRITEPROTECT, &uffdio_writeprotect);
+
+ close(uffd);
+}
+
+static void run(void)
+{
+ const struct tst_clone_args clone_args = {
+ .flags = CLONE_VM | CLONE_FILES | CLONE_FS | CLONE_SIGHAND,
+ .exit_signal = SIGCHLD,
+ };
+ pid_t pid;
+ struct uffdio_api uffdio_api;
+ struct uffdio_register uffdio_register;
+ struct uffdio_writeprotect uffdio_writeprotect;
+
+ set_pages();
+
+ uffd = SAFE_USERFAULTFD(O_CLOEXEC | O_NONBLOCK, false);
+
+ uffdio_api.api = UFFD_API;
+ uffdio_api.features = UFFD_FEATURE_PAGEFAULT_FLAG_WP;
+
+ SAFE_IOCTL(uffd, UFFDIO_API, &uffdio_api);
+
+ uffdio_register.range.start = (unsigned long) page;
+ uffdio_register.range.len = page_size;
+ uffdio_register.mode = UFFDIO_REGISTER_MODE_WP;
+
+ SAFE_IOCTL(uffd, UFFDIO_REGISTER, &uffdio_register);
+
+ uffdio_writeprotect.range.start = (unsigned long)page;
+ uffdio_writeprotect.range.len = page_size;
+ uffdio_writeprotect.mode = UFFDIO_WRITEPROTECT_MODE_WP;
+
+ SAFE_IOCTL(uffd, UFFDIO_WRITEPROTECT, &uffdio_writeprotect);
+
+ pid = SAFE_CLONE(&clone_args);
+ if (!pid) {
+ pagefault_handler();
+ _exit(0);
+ }
+
+ /* Try to write */
+ page[0xf] = 'W';
+
+ SAFE_WAITPID(pid, NULL, 0);
+ reset_pages();
+
+ if (wp_fault_seen)
+ tst_res(TPASS, "WRITEPROTECT pagefault handled!");
+ else
+ tst_res(TFAIL, "No WRITEPROTECT pagefault observed");
+}
+
+static struct tst_test test = {
+ .test_all = run,
+ .min_kver = "5.7",
+ .needs_kconfigs = (const char *[]) {
+ "CONFIG_HAVE_ARCH_USERFAULTFD_WP=y",
+ NULL
+ },
+ .forks_child = 1,
+};
diff --git a/testcases/kernel/syscalls/userfaultfd/userfaultfd12.c b/testcases/kernel/syscalls/userfaultfd/userfaultfd12.c
new file mode 100644
index 000000000..3fd4e3652
--- /dev/null
+++ b/testcases/kernel/syscalls/userfaultfd/userfaultfd12.c
@@ -0,0 +1,157 @@
+// SPDX-License-Identifier: GPL-2.0-or-later
+/*
+ * Copyright (c) 2026 SUSE LLC
+ * Author: Ricardo Branco <rb...@su...>
+ */
+
+/*\
+ * Force a pagefault event and handle it using :manpage:`userfaultfd(2)`
+ * from a different process (using clone with CLONE_VM instead of threads
+ * for Valgrind compatibility) testing UFFDIO_POISON.
+ */
+
+#include "config.h"
+#include <poll.h>
+#include <setjmp.h>
+#include <signal.h>
+#include <unistd.h>
+#include "tst_test.h"
+#include "tst_safe_macros.h"
+#include "tst_clone.h"
+#include "lapi/sched.h"
+#include "lapi/userfaultfd.h"
+
+#define CHILD_STACK_SIZE (1024 * 1024)
+
+static int page_size;
+static char *page;
+static int uffd;
+static int poison_fault_seen;
+static volatile int sigbus_seen;
+static sigjmp_buf jmpbuf;
+static void *child_stack;
+
+static void sigbus_handler(int sig)
+{
+ if (sig == SIGBUS) {
+ sigbus_seen = 1;
+ siglongjmp(jmpbuf, 1);
+ }
+}
+
+static void setup(void)
+{
+ struct sigaction sa = {};
+
+ sa.sa_handler = sigbus_handler;
+ sigemptyset(&sa.sa_mask);
+ SAFE_SIGACTION(SIGBUS, &sa, NULL);
+}
+
+static void set_pages(void)
+{
+ page_size = sysconf(_SC_PAGE_SIZE);
+ page = SAFE_MMAP(NULL, page_size, PROT_READ | PROT_WRITE,
+ MAP_PRIVATE | MAP_ANONYMOUS, -1, 0);
+}
+
+static void reset_pages(void)
+{
+ if (page) {
+ SAFE_MUNMAP(page, page_size);
+ page = NULL;
+ }
+}
+
+static int pagefault_handler(void *arg LTP_ATTRIBUTE_UNUSED)
+{
+ struct uffd_msg msg;
+ struct uffdio_poison uffdio_poison = {};
+ struct pollfd pollfd;
+ int nready;
+
+ pollfd.fd = uffd;
+ pollfd.events = POLLIN;
+ nready = poll(&pollfd, 1, -1);
+ if (nready == -1)
+ tst_brk(TBROK | TERRNO, "Error on poll");
+
+ SAFE_READ(1, uffd, &msg, sizeof(msg));
+
+ if (msg.event != UFFD_EVENT_PAGEFAULT)
+ tst_brk(TFAIL, "Received unexpected UFFD_EVENT %d", msg.event);
+
+ tst_atomic_store(1, &poison_fault_seen);
+
+ /* Poison the page that triggered the fault */
+ uffdio_poison.range.start = msg.arg.pagefault.address & ~(page_size - 1);
+ uffdio_poison.range.len = page_size;
+
+ SAFE_IOCTL(uffd, UFFDIO_POISON, &uffdio_poison);
+
+ close(uffd);
+ return 0;
+}
+
+static void run(void)
+{
+ pid_t pid;
+ struct uffdio_api uffdio_api = {};
+ struct uffdio_register uffdio_register;
+ char dummy;
+
+ poison_fault_seen = 0;
+ sigbus_seen = 0;
+ set_pages();
+
+ uffd = SAFE_USERFAULTFD(O_CLOEXEC | O_NONBLOCK, false);
+
+ uffdio_api.api = UFFD_API;
+ uffdio_api.features = UFFD_FEATURE_POISON;
+
+ SAFE_IOCTL(uffd, UFFDIO_API, &uffdio_api);
+
+ if (!(uffdio_api.features & UFFD_FEATURE_POISON))
+ tst_brk(TCONF, "UFFD_FEATURE_POISON not supported");
+
+ uffdio_register.range.start = (unsigned long) page;
+ uffdio_register.range.len = page_size;
+ uffdio_register.mode = UFFDIO_REGISTER_MODE_MISSING;
+
+ SAFE_IOCTL(uffd, UFFDIO_REGISTER, &uffdio_register);
+
+ pid = ltp_clone(CLONE_VM | CLONE_FILES | CLONE_FS | CLONE_SIGHAND | SIGCHLD,
+ pagefault_handler, NULL, CHILD_STACK_SIZE, child_stack);
+ if (pid == -1)
+ tst_brk(TBROK | TERRNO, "ltp_clone failed");
+
+ /* Try to read from the page: should trigger fault, get poisoned, then SIGBUS */
+ if (sigsetjmp(jmpbuf, 1) == 0) {
+ LTP_VAR_USED(dummy) = page[0];
+ }
+
+ SAFE_WAITPID(pid, NULL, 0);
+ reset_pages();
+
+ int poisoned = tst_atomic_load(&poison_fault_seen);
+
+ if (poisoned && sigbus_seen)
+ tst_res(TPASS, "POISON successfully triggered SIGBUS");
+ else if (poisoned && !sigbus_seen)
+ tst_res(TFAIL, "POISON fault seen but no SIGBUS received");
+ else if (!poisoned && sigbus_seen)
+ tst_res(TFAIL, "SIGBUS received but no poison fault seen");
+ else
+ tst_res(TFAIL, "No poison fault or SIGBUS observed");
+}
+
+static struct tst_test test = {
+ .test_all = run,
+ .setup = setup,
+ .cleanup = reset_pages,
+ .forks_child = 1,
+ .bufs = (struct tst_buffers []) {
+ {&child_stack, .size = CHILD_STACK_SIZE},
+ {},
+ },
+};
--
2.53.0
|
|
From: Petr V. <pv...@su...> - 2026-04-23 09:39:36
|
Hi, [ Cc valgrind-developers ML, which I should have done when sending the patchset ]. Kind regards, Petr > It'll be better for Valgrind developers to know, that test is skipped. > TCONF is not printed that often and because output of the message is > trimmed, it will not be that disruptive. > Signed-off-by: Petr Vorel <pv...@su...> > --- > New in v5 (it can be squashed, but I wanted to point this out and get Martin's ack). > doc/users/setup_tests.rst | 6 +++--- > lib/tst_test.c | 4 +--- > 2 files changed, 4 insertions(+), 6 deletions(-) > diff --git a/doc/users/setup_tests.rst b/doc/users/setup_tests.rst > index 491a5b003a..43573c8fb1 100644 > --- a/doc/users/setup_tests.rst > +++ b/doc/users/setup_tests.rst > @@ -43,9 +43,9 @@ users. > Shell language: ``TST_NEEDS_DEVICE=1``. > * - LTP_REPRODUCIBLE_OUTPUT > - - When set to ``1`` or ``y`` uppress printing TCONF, TINFO and TDEBUG > - messages and discards the actual content of the other messages printed > - by the test (suitable for a reproducible output). > + - When set to ``1`` or ``y`` uppress printing TINFO and TDEBUG messages > + and discards the actual content of the other messages printed by the > + test (suitable for a reproducible output). > * - LTP_SINGLE_FS_TYPE > - Specifies single filesystem to run the test on instead all supported > diff --git a/lib/tst_test.c b/lib/tst_test.c > index a0b55049ff..469a3f6b65 100644 > --- a/lib/tst_test.c > +++ b/lib/tst_test.c > @@ -306,8 +306,6 @@ static void print_result(const char *file, const int lineno, int ttype, > res = "TBROK"; > break; > case TCONF: > - if (reproducible_output) > - return; > res = "TCONF"; > break; > case TWARN: > @@ -675,7 +673,7 @@ static void print_help(void) > fprintf(stderr, "LTP_DEV Path to the block device to be used (for .needs_device)\n"); > fprintf(stderr, "LTP_DEV_FS_TYPE Filesystem used for testing (default: %s)\n", DEFAULT_FS_TYPE); > fprintf(stderr, "LTP_DEBUG Print debug messages (set 1(y) or 2)\n"); > - fprintf(stderr, "LTP_REPRODUCIBLE_OUTPUT Values 1 or y suppress printing TCONF, TINFO and TDEBUG messages and\n" > + fprintf(stderr, "LTP_REPRODUCIBLE_OUTPUT Values 1 or y suppress printing TINFO and TDEBUG messages and\n" > " discards the actual content of all other messages\n"); > fprintf(stderr, "LTP_SINGLE_FS_TYPE Specifies filesystem instead all supported (for .all_filesystems)\n"); > fprintf(stderr, "LTP_FORCE_SINGLE_FS_TYPE Testing only. The same as LTP_SINGLE_FS_TYPE but ignores test skiplist.\n"); |
|
From: Petr V. <pv...@su...> - 2026-04-23 09:38:51
|
Hi, [ Cc valgrind-developers ML, which I should have done when sending the patchset ]. Kind regards, Petr > LTP_REPRODUCIBLE_OUTPUT=1 environment variable was added in 5894abc5f to > help valgrind to use LTP for testing. It discards the actual content of > the messages printed by the test (removes everything after printing > TINFO/TPASS/TFAIL/... flag). > Later LTP_QUIET=1 was added which suppresses printing TCONF, TINFO, and > TDEBUG messages. > Valgrind project uses both variables but no need to handle them > separately. Therefore merge functionality of LTP_QUIET into > LTP_REPRODUCIBLE_OUTPUT. > LTP_QUIET was not even documented in HTML doc. > Also fix help description, because TWARN was not skipped, although doc > claimed to do. > Implements: https://github.com/linux-test-project/ltp/issues/1306 > Signed-off-by: Petr Vorel <pv...@su...> > --- > Changes v4->v5: > * Remove wrongly stated TWARN (error on code on master) > * Fix missing new lines in help (AI) > * Use single fprintf (Li) > doc/users/setup_tests.rst | 5 +++-- > lib/tst_test.c | 16 +++++----------- > 2 files changed, 8 insertions(+), 13 deletions(-) > diff --git a/doc/users/setup_tests.rst b/doc/users/setup_tests.rst > index 6f1d996e18..491a5b003a 100644 > --- a/doc/users/setup_tests.rst > +++ b/doc/users/setup_tests.rst > @@ -43,8 +43,9 @@ users. > Shell language: ``TST_NEEDS_DEVICE=1``. > * - LTP_REPRODUCIBLE_OUTPUT > - - When set to ``1`` or ``y`` discards the actual content of the messages > - printed by the test (suitable for a reproducible output). > + - When set to ``1`` or ``y`` uppress printing TCONF, TINFO and TDEBUG > + messages and discards the actual content of the other messages printed > + by the test (suitable for a reproducible output). > * - LTP_SINGLE_FS_TYPE > - Specifies single filesystem to run the test on instead all supported > diff --git a/lib/tst_test.c b/lib/tst_test.c > index 12f7489d4e..a0b55049ff 100644 > --- a/lib/tst_test.c > +++ b/lib/tst_test.c > @@ -68,7 +68,6 @@ static int iterations = 1; > static float duration = -1; > static float timeout_mul = -1; > static int reproducible_output; > -static int quiet_output; > struct context { > int32_t lib_pid; > @@ -307,7 +306,7 @@ static void print_result(const char *file, const int lineno, int ttype, > res = "TBROK"; > break; > case TCONF: > - if (quiet_output) > + if (reproducible_output) > return; > res = "TCONF"; > break; > @@ -315,12 +314,12 @@ static void print_result(const char *file, const int lineno, int ttype, > res = "TWARN"; > break; > case TINFO: > - if (quiet_output) > + if (reproducible_output) > return; > res = "TINFO"; > break; > case TDEBUG: > - if (quiet_output) > + if (reproducible_output) > return; > res = "TDEBUG"; > break; > @@ -676,8 +675,8 @@ static void print_help(void) > fprintf(stderr, "LTP_DEV Path to the block device to be used (for .needs_device)\n"); > fprintf(stderr, "LTP_DEV_FS_TYPE Filesystem used for testing (default: %s)\n", DEFAULT_FS_TYPE); > fprintf(stderr, "LTP_DEBUG Print debug messages (set 1(y) or 2)\n"); > - fprintf(stderr, "LTP_REPRODUCIBLE_OUTPUT Values 1 or y discard the actual content of the messages printed by the test\n"); > - fprintf(stderr, "LTP_QUIET Values 1 or y will suppress printing TCONF, TWARN, TINFO, and TDEBUG messages\n"); > + fprintf(stderr, "LTP_REPRODUCIBLE_OUTPUT Values 1 or y suppress printing TCONF, TINFO and TDEBUG messages and\n" > + " discards the actual content of all other messages\n"); > fprintf(stderr, "LTP_SINGLE_FS_TYPE Specifies filesystem instead all supported (for .all_filesystems)\n"); > fprintf(stderr, "LTP_FORCE_SINGLE_FS_TYPE Testing only. The same as LTP_SINGLE_FS_TYPE but ignores test skiplist.\n"); > fprintf(stderr, "LTP_TIMEOUT_MUL Timeout multiplier (must be a number >=1)\n"); > @@ -1398,7 +1397,6 @@ static void do_setup(int argc, char *argv[]) > { > char *tdebug_env = getenv("LTP_DEBUG"); > char *reproducible_env = getenv("LTP_REPRODUCIBLE_OUTPUT"); > - char *quiet_env = getenv("LTP_QUIET"); > if (!tst_test) > tst_brk(TBROK, "No tests to run"); > @@ -1429,10 +1427,6 @@ static void do_setup(int argc, char *argv[]) > (!strcmp(reproducible_env, "1") || !strcmp(reproducible_env, "y"))) > reproducible_output = 1; > - if (quiet_env && > - (!strcmp(quiet_env, "1") || !strcmp(quiet_env, "y"))) > - quiet_output = 1; > - > assert_test_fn(); > TCID = tcid = get_tcid(argv); |
|
From: Petr V. <pv...@su...> - 2026-04-22 13:41:50
|
Hi all, ... > Martin Cermak maintains the Linux Test Program (LTP) valgrind nit: s/Program/Project/ > integration, which checks our syscall wrappers work correctly. And he > makes sure newer linux syscalls are wrapped. Valgrind 3.27.0 adds > support for file_getattr, file_setattr, lsm_get_self_attr, > lsm_set_self_attr, lsm_list_modules. And corrects various syscall and > ioctl corner cases. Congrats to the new release. Kind regards, Petr |
|
From: Martin C. <mc...@re...> - 2026-04-22 13:09:02
|
On Wed 2026-04-22 14:17 , Petr Vorel wrote: > > > > On 4/22/26 7:37 AM, Petr Vorel wrote: > > > > However, some of the testcases can be easily changed to use forked > > > > processes instead of threads. That's what this patch does. When > > > > client program forks, Valgrind forks too, and that allows for the needed > > > > parallelism to handle the page fault. > > > You understand process vs. threads more than me. But shouldn't mmap() use > > > MAP_SHARED instead of MAP_PRIVATE for those which aren't using /dev/userfaultfd? > > > The documentation for userfaultfd mentions threads. I'm afraid we'll > > lose vital coverage if we move to forked processes. > > +1, at least some tests would keep threads (not all userfaultfd tests would be > converted, but yes, that's why I suggested to use MAP_SHARED, which could be > similar to threads (yes, the difference between processes and threads in Linux > kernel is not that huge as both are created in clone(), it's mostly about what > is shared). My goal is to make at least part of these userfaultfd tests compatible with Valgrind. I've experimented with clone() and it seems like Valgrind has limited support for it. That said, adding another set of userfaultfd tests using fork() or clone() instead of threads might help. Some of such new tests will be "incompatible" with valgrind, but it might be a test coverage improvement. m. |
|
From: Ricardo B. <rb...@su...> - 2026-04-22 12:42:24
|
On 4/22/26 2:17 PM, Petr Vorel wrote: >> Perhaps we should cover both? > What do you mean by "both"? > > Run test with both processes and threads e.g. via .test_variants? Yes. Best, R |
|
From: Mark W. <ma...@so...> - 2026-04-22 12:22:26
|
https://sourceware.org/cgit/valgrind/commit/?id=b62544e78b037b9a786814d047f41faf5f523e8d commit b62544e78b037b9a786814d047f41faf5f523e8d Author: Mark Wielaard <ma...@kl...> Date: Wed Apr 22 14:15:28 2026 +0200 Use SSizeT for VG_(readlink) result in VG_(realpath) VG_(readlink) returns a negative value if it fails. Which is checked for right after the call. But if SizeT is unsigned, so that check always fails. Use SSizeT instead for the result variable. Diff: --- coregrind/m_libcfile.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/coregrind/m_libcfile.c b/coregrind/m_libcfile.c index ef8bd9d7b7..2c5914d068 100644 --- a/coregrind/m_libcfile.c +++ b/coregrind/m_libcfile.c @@ -1865,7 +1865,7 @@ Bool VG_(realpath)(const HChar *path, HChar *resolved) } if (VKI_S_ISLNK(statbuf.mode)) { - SizeT link_len = VG_(readlink)(path, tmp, VKI_PATH_MAX); + SSizeT link_len = VG_(readlink)(path, tmp, VKI_PATH_MAX); if (link_len < 0) return False; tmp[link_len] = '\0'; |
|
From: Petr V. <pv...@su...> - 2026-04-22 12:17:55
|
> On 4/22/26 7:37 AM, Petr Vorel wrote: > > > However, some of the testcases can be easily changed to use forked > > > processes instead of threads. That's what this patch does. When > > > client program forks, Valgrind forks too, and that allows for the needed > > > parallelism to handle the page fault. > > You understand process vs. threads more than me. But shouldn't mmap() use > > MAP_SHARED instead of MAP_PRIVATE for those which aren't using /dev/userfaultfd? > The documentation for userfaultfd mentions threads. I'm afraid we'll > lose vital coverage if we move to forked processes. +1, at least some tests would keep threads (not all userfaultfd tests would be converted, but yes, that's why I suggested to use MAP_SHARED, which could be similar to threads (yes, the difference between processes and threads in Linux kernel is not that huge as both are created in clone(), it's mostly about what is shared). > Perhaps we should cover both? What do you mean by "both"? Run test with both processes and threads e.g. via .test_variants? Because combine MAP_SHARED | MAP_PRIVATE is not possible (mutually exclusive). > Also checkout UFFD_FEATURE_EVENT_FORK and the BUGS section for this in > userfaultfd(2). +1 > I have like 3 patches for userfaultfd that I'm afraid I'd have to rebase > then.\ Best, Yeah, that's life of an open source development. Kind regards, Petr > Ricardo |
|
From: Ricardo B. <rb...@su...> - 2026-04-22 07:54:43
|
On 4/22/26 7:37 AM, Petr Vorel wrote: >> However, some of the testcases can be easily changed to use forked >> processes instead of threads. That's what this patch does. When >> client program forks, Valgrind forks too, and that allows for the needed >> parallelism to handle the page fault. > You understand process vs. threads more than me. But shouldn't mmap() use > MAP_SHARED instead of MAP_PRIVATE for those which aren't using /dev/userfaultfd? The documentation for userfaultfd mentions threads. I'm afraid we'll lose vital coverage if we move to forked processes. Perhaps we should cover both? Also checkout UFFD_FEATURE_EVENT_FORK and the BUGS section for this in userfaultfd(2). I have like 3 patches for userfaultfd that I'm afraid I'd have to rebase then.\ Best, Ricardo |
|
From: Petr V. <pv...@su...> - 2026-04-22 05:37:29
|
Hi Martin, [ Cc Ricardo ] > Historically a page fault is handled in the linux kernel. The > userfaultfd mechanism [1] was introduced in Linux 4.3 (2015) to allow > custom handling page faults in userspace. It allows for custom page > fault handling strategies such as lazy loading, live migration of qemu > VMs, etc. With userfaultfd, kernel communicates with userspace via a > file descriptor (userfaultfd). Userfaultfd LTP tests cover this. > These tests set up a main thread and a page fault handler thread. Once > a page fault happens in the main thread, kernel stops it, and let's the > handler take care of the page fault. > This is a problem for Valgrind, because it serializes the threads > execution (using one "big mutex", VG_(acquire_BigLock)). Once kernel > stops the main thread, under valgrind, the handler thread doesn't have > a chance to handle the page fault. Valgrind stalls till the timeout > (adjustable via LTP_TIMEOUT_MUL ;) > However, some of the testcases can be easily changed to use forked > processes instead of threads. That's what this patch does. When > client program forks, Valgrind forks too, and that allows for the needed > parallelism to handle the page fault. You understand process vs. threads more than me. But shouldn't mmap() use MAP_SHARED instead of MAP_PRIVATE for those which aren't using /dev/userfaultfd? > This redesign can't be easily done with some of the tests, such as e.g. > userfaultfd02 where both the main thread and the handler thread need to > share the address space. That could be done via clone() and is proven What is the difference with userfaultfd02 then? > to work. But unfortunately there is another Valgrind limitation in clone > flags it supports, so this also isn't a practical way to go. > That said, this update tweaks userfaultfd01, userfaultfd03, and > userfaultfd04 in a way that they become "compatible" with Valgrind. > It's a test coverage improvement. Also doc should be updated (mentions thread). Please don't forget to add it next time: Signed-off-by: Martin Cermak <mc...@re...> > [1] https://www.kernel.org/doc/html/latest/admin-guide/mm/userfaultfd.html > --- > .../kernel/syscalls/userfaultfd/userfaultfd01.c | 13 +++++++++---- > .../kernel/syscalls/userfaultfd/userfaultfd03.c | 15 ++++++++++----- > .../kernel/syscalls/userfaultfd/userfaultfd04.c | 13 +++++++++---- > 3 files changed, 28 insertions(+), 13 deletions(-) > diff --git a/testcases/kernel/syscalls/userfaultfd/userfaultfd01.c b/testcases/kernel/syscalls/userfaultfd/userfaultfd01.c > index 7368d3863..c927cda95 100644 > --- a/testcases/kernel/syscalls/userfaultfd/userfaultfd01.c > +++ b/testcases/kernel/syscalls/userfaultfd/userfaultfd01.c > @@ -57,7 +57,7 @@ static void reset_pages(void) > SAFE_MUNMAP(copy_page, page_size); > } > -static void *handle_thread(void) > +static void *pagefault_handler(void) > { > static struct uffd_msg msg; > struct uffdio_copy uffdio_copy = {}; > @@ -91,7 +91,7 @@ static void *handle_thread(void) > static void run(unsigned int i) > { > - pthread_t thr; > + pid_t pid; > struct uffdio_api uffdio_api = {}; > struct uffdio_register uffdio_register; > struct tcase *tc = &tcases[i]; > @@ -112,7 +112,11 @@ static void run(unsigned int i) > SAFE_IOCTL(uffd, UFFDIO_REGISTER, &uffdio_register); > - SAFE_PTHREAD_CREATE(&thr, NULL, (void *) handle_thread, NULL); > + pid = SAFE_FORK(); > + if (pid == 0) { > + pagefault_handler(); > + _exit(0); > + } > char c = page[0xf]; > @@ -121,7 +125,7 @@ static void run(unsigned int i) > else > tst_res(TFAIL, "Pagefault not handled!"); > - SAFE_PTHREAD_JOIN(thr, NULL); > + SAFE_WAITPID(pid, NULL, 0); > reset_pages(); > } > @@ -129,4 +133,5 @@ static struct tst_test test = { > .setup = setup, > .test = run, > .tcnt = ARRAY_SIZE(tcases), > + .forks_child = 1, > }; > diff --git a/testcases/kernel/syscalls/userfaultfd/userfaultfd03.c b/testcases/kernel/syscalls/userfaultfd/userfaultfd03.c > index b65f39eca..f5d3be1ae 100644 > --- a/testcases/kernel/syscalls/userfaultfd/userfaultfd03.c > +++ b/testcases/kernel/syscalls/userfaultfd/userfaultfd03.c > @@ -61,7 +61,7 @@ static void reset_pages(void) > SAFE_MUNMAP(copy_page, page_size); > } > -static void *handle_thread(void) > +static void *pagefault_handler(void) > { > static struct uffd_msg msg; > struct uffdio_copy uffdio_copy = {}; > @@ -95,7 +95,7 @@ static void *handle_thread(void) > static void run(void) > { > - pthread_t thr; > + pid_t pid; > struct uffdio_api uffdio_api = {}; > struct uffdio_register uffdio_register; > @@ -112,7 +112,11 @@ static void run(void) > SAFE_IOCTL(uffd, UFFDIO_REGISTER, &uffdio_register); > - SAFE_PTHREAD_CREATE(&thr, NULL, (void *) handle_thread, NULL); > + pid = SAFE_FORK(); > + if (pid == 0) { > + pagefault_handler(); > + _exit(0); > + } > char c = page[0xf]; > @@ -121,7 +125,7 @@ static void run(void) > else > tst_res(TFAIL, "Pagefault not handled via /dev/userfaultfd"); > - SAFE_PTHREAD_JOIN(thr, NULL); > + SAFE_WAITPID(pid, NULL, 0); > reset_pages(); > } > @@ -132,5 +136,6 @@ static struct tst_test test = { > .needs_kconfigs = (const char *[]) { > "CONFIG_USERFAULTFD=y", > NULL > - } > + }, > + .forks_child = 1, > }; > diff --git a/testcases/kernel/syscalls/userfaultfd/userfaultfd04.c b/testcases/kernel/syscalls/userfaultfd/userfaultfd04.c > index 4eb811e45..13883a711 100644 > --- a/testcases/kernel/syscalls/userfaultfd/userfaultfd04.c > +++ b/testcases/kernel/syscalls/userfaultfd/userfaultfd04.c > @@ -33,7 +33,7 @@ static void reset_pages(void) > SAFE_MUNMAP(page, page_size); > } > -static void *handle_thread(void) > +static void *pagefault_handler(void) > { > static struct uffd_msg msg; > struct uffdio_zeropage uffdio_zeropage = {}; > @@ -64,7 +64,7 @@ static void *handle_thread(void) > static void run(void) > { > - pthread_t thr; > + pid_t pid; > struct uffdio_api uffdio_api = {}; > struct uffdio_register uffdio_register; > @@ -81,7 +81,11 @@ static void run(void) > SAFE_IOCTL(uffd, UFFDIO_REGISTER, &uffdio_register); > - SAFE_PTHREAD_CREATE(&thr, NULL, (void *) handle_thread, NULL); > + pid = SAFE_FORK(); > + if (pid == 0) { > + pagefault_handler(); > + _exit(0); > + } > for (int i = 0; i < page_size; i++) { > if (page[i] != 0) { > @@ -92,10 +96,11 @@ static void run(void) > tst_res(TPASS, "Pagefault handled with UFFDIO_ZEROPAGE"); > - SAFE_PTHREAD_JOIN(thr, NULL); > + SAFE_WAITPID(pid, NULL, 0); > reset_pages(); > } > static struct tst_test test = { > .test_all = run, > + .forks_child = 1, > }; |
|
From: Martin C. <mc...@re...> - 2026-04-21 15:24:43
|
Historically a page fault is handled in the linux kernel. The userfaultfd mechanism [1] was introduced in Linux 4.3 (2015) to allow custom handling page faults in userspace. It allows for custom page fault handling strategies such as lazy loading, live migration of qemu VMs, etc. With userfaultfd, kernel communicates with userspace via a file descriptor (userfaultfd). Userfaultfd LTP tests cover this. These tests set up a main thread and a page fault handler thread. Once a page fault happens in the main thread, kernel stops it, and let's the handler take care of the page fault. This is a problem for Valgrind, because it serializes the threads execution (using one "big mutex", VG_(acquire_BigLock)). Once kernel stops the main thread, under valgrind, the handler thread doesn't have a chance to handle the page fault. Valgrind stalls till the timeout (adjustable via LTP_TIMEOUT_MUL ;) However, some of the testcases can be easily changed to use forked processes instead of threads. That's what this patch does. When client program forks, Valgrind forks too, and that allows for the needed parallelism to handle the page fault. This redesign can't be easily done with some of the tests, such as e.g. userfaultfd02 where both the main thread and the handler thread need to share the address space. That could be done via clone() and is proven to work. But unfortunately there is another Valgrind limitation in clone flags it supports, so this also isn't a practical way to go. That said, this update tweaks userfaultfd01, userfaultfd03, and userfaultfd04 in a way that they become "compatible" with Valgrind. It's a test coverage improvement. [1] https://www.kernel.org/doc/html/latest/admin-guide/mm/userfaultfd.html --- .../kernel/syscalls/userfaultfd/userfaultfd01.c | 13 +++++++++---- .../kernel/syscalls/userfaultfd/userfaultfd03.c | 15 ++++++++++----- .../kernel/syscalls/userfaultfd/userfaultfd04.c | 13 +++++++++---- 3 files changed, 28 insertions(+), 13 deletions(-) diff --git a/testcases/kernel/syscalls/userfaultfd/userfaultfd01.c b/testcases/kernel/syscalls/userfaultfd/userfaultfd01.c index 7368d3863..c927cda95 100644 --- a/testcases/kernel/syscalls/userfaultfd/userfaultfd01.c +++ b/testcases/kernel/syscalls/userfaultfd/userfaultfd01.c @@ -57,7 +57,7 @@ static void reset_pages(void) SAFE_MUNMAP(copy_page, page_size); } -static void *handle_thread(void) +static void *pagefault_handler(void) { static struct uffd_msg msg; struct uffdio_copy uffdio_copy = {}; @@ -91,7 +91,7 @@ static void *handle_thread(void) static void run(unsigned int i) { - pthread_t thr; + pid_t pid; struct uffdio_api uffdio_api = {}; struct uffdio_register uffdio_register; struct tcase *tc = &tcases[i]; @@ -112,7 +112,11 @@ static void run(unsigned int i) SAFE_IOCTL(uffd, UFFDIO_REGISTER, &uffdio_register); - SAFE_PTHREAD_CREATE(&thr, NULL, (void *) handle_thread, NULL); + pid = SAFE_FORK(); + if (pid == 0) { + pagefault_handler(); + _exit(0); + } char c = page[0xf]; @@ -121,7 +125,7 @@ static void run(unsigned int i) else tst_res(TFAIL, "Pagefault not handled!"); - SAFE_PTHREAD_JOIN(thr, NULL); + SAFE_WAITPID(pid, NULL, 0); reset_pages(); } @@ -129,4 +133,5 @@ static struct tst_test test = { .setup = setup, .test = run, .tcnt = ARRAY_SIZE(tcases), + .forks_child = 1, }; diff --git a/testcases/kernel/syscalls/userfaultfd/userfaultfd03.c b/testcases/kernel/syscalls/userfaultfd/userfaultfd03.c index b65f39eca..f5d3be1ae 100644 --- a/testcases/kernel/syscalls/userfaultfd/userfaultfd03.c +++ b/testcases/kernel/syscalls/userfaultfd/userfaultfd03.c @@ -61,7 +61,7 @@ static void reset_pages(void) SAFE_MUNMAP(copy_page, page_size); } -static void *handle_thread(void) +static void *pagefault_handler(void) { static struct uffd_msg msg; struct uffdio_copy uffdio_copy = {}; @@ -95,7 +95,7 @@ static void *handle_thread(void) static void run(void) { - pthread_t thr; + pid_t pid; struct uffdio_api uffdio_api = {}; struct uffdio_register uffdio_register; @@ -112,7 +112,11 @@ static void run(void) SAFE_IOCTL(uffd, UFFDIO_REGISTER, &uffdio_register); - SAFE_PTHREAD_CREATE(&thr, NULL, (void *) handle_thread, NULL); + pid = SAFE_FORK(); + if (pid == 0) { + pagefault_handler(); + _exit(0); + } char c = page[0xf]; @@ -121,7 +125,7 @@ static void run(void) else tst_res(TFAIL, "Pagefault not handled via /dev/userfaultfd"); - SAFE_PTHREAD_JOIN(thr, NULL); + SAFE_WAITPID(pid, NULL, 0); reset_pages(); } @@ -132,5 +136,6 @@ static struct tst_test test = { .needs_kconfigs = (const char *[]) { "CONFIG_USERFAULTFD=y", NULL - } + }, + .forks_child = 1, }; diff --git a/testcases/kernel/syscalls/userfaultfd/userfaultfd04.c b/testcases/kernel/syscalls/userfaultfd/userfaultfd04.c index 4eb811e45..13883a711 100644 --- a/testcases/kernel/syscalls/userfaultfd/userfaultfd04.c +++ b/testcases/kernel/syscalls/userfaultfd/userfaultfd04.c @@ -33,7 +33,7 @@ static void reset_pages(void) SAFE_MUNMAP(page, page_size); } -static void *handle_thread(void) +static void *pagefault_handler(void) { static struct uffd_msg msg; struct uffdio_zeropage uffdio_zeropage = {}; @@ -64,7 +64,7 @@ static void *handle_thread(void) static void run(void) { - pthread_t thr; + pid_t pid; struct uffdio_api uffdio_api = {}; struct uffdio_register uffdio_register; @@ -81,7 +81,11 @@ static void run(void) SAFE_IOCTL(uffd, UFFDIO_REGISTER, &uffdio_register); - SAFE_PTHREAD_CREATE(&thr, NULL, (void *) handle_thread, NULL); + pid = SAFE_FORK(); + if (pid == 0) { + pagefault_handler(); + _exit(0); + } for (int i = 0; i < page_size; i++) { if (page[i] != 0) { @@ -92,10 +96,11 @@ static void run(void) tst_res(TPASS, "Pagefault handled with UFFDIO_ZEROPAGE"); - SAFE_PTHREAD_JOIN(thr, NULL); + SAFE_WAITPID(pid, NULL, 0); reset_pages(); } static struct tst_test test = { .test_all = run, + .forks_child = 1, }; -- 2.53.0 |
|
From: Mark W. <ma...@kl...> - 2026-04-21 00:32:48
|
We are pleased to announce a new release of Valgrind, version 3.27.0, available from https://valgrind.org/downloads/current.html This release brings two new options for helgrind (--show-events and --track-destroy), several new SSE4.1 instruction for x86 (32 bit), support for new s390x z/Architecture features from the 15th edition, integrated binutils objdump for s390x disassembly, support for new linux syscalls, address space manager support for tracking linux kernel lightweight guard pages, freebsd support for 16.0-CURRENT, macOS supported up to version 13 Ventura (Intel only), and new client requests macros (VALGRIND_REPLACES_MALLOC and VALGRIND_GET_TOOLNAME). See the release notes below for details of the changes. Our thanks to all those who contribute to Valgrind's development. This release represents a great deal of time, energy and effort on the part of many people. It was a busy release, with 494 commits by 12 people, fixing 62 bugs. Happy and productive debugging and profiling, -- The Valgrind Developers Release 3.27.0 (20 Apr 2026) ~~~~~~~~~~~~~~~~~~~~~~~~~~~~ This release supports X86/Linux, AMD64/Linux, ARM32/Linux, ARM64/Linux, PPC32/Linux, PPC64BE/Linux, PPC64LE/Linux, S390X/Linux, MIPS32/Linux, MIPS64/Linux, RISCV64/Linux, ARM/Android, ARM64/Android, MIPS32/Android, X86/Android, X86/Solaris, AMD64/Solaris, X86/macOS, AMD64/macOS. X86/FreeBSD, AMD64/FreeBSD and ARM64/FreeBSD. There is preliminary support for nanoMIPS/Linux. macOS is supported up to version 13 Ventura (amd64 only). * ==================== CORE CHANGES =================== * There are two new client requests - VALGRIND_REPLACES_MALLOC Returns 1 if the tool replaces malloc (e.g., memcheck). Returns 0 if the tool does not replace malloc (e.g., cachegrind and callgrind) or if the executable is not running under VALGRIND. - VALGRIND_GET_TOOLNAME Get the running tool name as a string. Takes two arguments, an input buffer pointer and the length of that buffer. Returns the required length (including terminating nul) for the tool name. Returns 0 and the contents supplied buffer are not modified if not running under Valgrind. See also the full description in the valgrind.h header file or the in The Client Request mechanism section of the Valgrind User Manual. * linux lightweight guard pages (madvise MADV_GUARD_INSTALL) supported glibc 2.42+ (with linux 6.13+) uses MADV_GUARD_INSTALL to setup stack guard pages. These lightweight guard pages are now supported under valgrind. By default, Valgrind can handle to up to 500 madvise guard pages. With thread heavy workloads the default value might not be sufficient. Use --max-guard-pages=N to provide a different limit. If --max-guard-pages is not set explicitly, then it will default to the --max-threads setting. * --num-callers now has a minimum value of 2. This is a breaking change. See https://bugs.kde.org/show_bug.cgi?id=515183#c13 for full details. * ================== PLATFORM CHANGES ================= * x86: Support for SSE4.1 instructions has been ported from AMD64 to (32bit) x86. This is ongoing work. Currently the following SSE4.1 instructions are supported BLENDPD BLENDPS BLENDVPD BLENDVPS MOVNTDQA MPSADBW PBLENDVB PBLENDW PCMPEQQ PINSRD PMAXSB PMAXSD PMAXUD PMAXUW PMINSB PMINSD PMINUD PMINUW PMULLD PTEST. Bug #518222 tracks further progress. * s390x: Machine models older than z196 are no longer supported. * s390x: Support new z/Architecture features from the 15th edition. In particular this enables running binaries compiled with `-march=arch15' or `-march=z17' and exploiting the new MSA extensions 10-13. * Support for the following macOS versions has been added 10.13 High Sierra (bug fixes) 10.14 Mojave 10.15 Catalina 11.0 Big Sur (Intel only) 12.0 Monterey (Intel only) 13.0 Ventura (Intel only, preliminary) * The Linux Test Project (LTP) v20260130 was integrated. New linux syscall wrappers for file_getattr, file_setattr, lsm_get_self_attr, lsm_set_self_attr, lsm_list_modules were added. * ==================== TOOL CHANGES =================== * Helgrind: - New debug option --show-events=0|1|2. Controls tracing of internal Helgrind synchronization, threading and memory events. At level 1, Helgrind prints a trace of its synchronization, threading and memory events. At level 2, additional memory events are also traced. The default value of 0 disables tracing. - New option --track-destroy=no|yes|all. Checks for missing pthread_mutex_destroy and pthread_rwlock_destroy calls. With yes, Helgrind warns when pthread_mutex_init or pthread_rwlock_init is called on the address of a live (undestroyed) lock. With all, Helgrind also reports undestroyed locks at process exit. --track-destroy does not track locks that use static initializers. * ==================== FIXED BUGS ==================== The following bugs have been fixed or resolved. Note that "n-i-bz" stands for "not in bugzilla" -- that is, a bug that was reported to us but never got a bugzilla entry. We encourage you to file bugs in bugzilla (https://bugs.kde.org/enter_bug.cgi?product=valgrind) rather than mailing the developers (or mailing lists) directly -- bugs that are not entered into bugzilla tend to get forgotten about or ignored. 126256 (fnop) vex x86->IR: unhandled instruction bytes: 0xD9 0xD0 0x31 0xC0 228343 none/tests/darwin/bug228343 fails on OS X 233298 MEMPOOL_FREE not reflected in heap summary 253436 vex amd64->IR: unhandled instruction bytes: 0xF2 0xA6 (repne cmps) 258140 Valgrind on OS X always reports some memory "still reachable" 390754 unhandled amd64-darwin syscall: unix:216 (open_dprotected_np) 406674 False positive when reading bitfield value on code compiled with clang 7.0 413369 unhandled amd64-darwin syscall: unix:151 (getpgid) 413410 unhandled amd64-darwin syscall: mach:50 (on macOS 10.15) 487055 memcheck/tests/x86-linux/scalar fails running in Docker 503238 s390x: Support miscellaneous-instruction-extensions facility 4 503239 s390x: Support vector-enhancements facility 3 503240 s390x: Support MSA extensions 10, 11, and 12 509562 s390x: Define minimum required machine model 510416 Missing syswraps for file_getattr and file_setattr 510563 Add missing syswraps for lsm_get_self_attr and lsm_set_self_attr 510864 Add SSE4.1 PMAXSD and PMINSD instructions support for 32-bit x86 511329 Darwin and FreeBSD: Move setting of carry flag out of ML_(do_syscall_for_client_WRK) 511461 Darwin 17 (MacOS X 10.13) memcheck issues 511713 Refactor syscall argument handling 511717 gdbserver (valgrind_read_memory) the 'impossible' happened: Killed by fatal signal (SIGSEGV) 511972 valgrind-3.26.0 tests fail to build on upcomig gcc-16: unrecognized command-line option '-Wno-alloc-size-larger-than=18446744073709551615' 512030 s390x: bfp-convert testcase fails 512037 malloc trace does not print free size or alignment 512291 Valgrind on Solaris should drop support for long gone /dev/crypto framework 512571 regtest problems with darwin dsymutil 512873 Add SSE4.1 min/max instructions for x86 32 bit 513257 Add missing syswraps for lsm_list_modules 513522 m_libcassert.c: 'ordered comparison of pointer with integer zero' compiler warning 513475 Add SSE4.1 PMULLD instruction for x86 32 bit 513598 Helgrind should detect locks without pthread_{rwlock,mutex}_destroy being called - Assertion 'lk->kind == LK_rdwr' failed. 514094 readlink("/proc/self/exe") overwrites buffer beyond its return value 514206 Assertion '!sr_isError(sr)' failed - mmap fd points to an open descriptor to a PCI device 514297 Track madvise MADV_GUARD_INSTALL in address space manager 514343 Add a valgrind.h macro VALGRIND_REPLACES_MALLOC 514596 Add SSE4.1 BLENDPD instruction for x86 32 bit 514613 Unclosed leak_summary/still_reachable tag in xml output 514659 ltp 20250930 vs linux 6.18.3 doesn't build 514762 Many "Bad file descriptor" messages when using --track-fds=yes and -d on systems without /proc 515183 Error occurred while executing the command `valgrind --num-callers=1 ./hello_world` 515265 Add SSE4.1 BLENDPS and PBLENDW instructions for x86 32 bit 516223 Add SSE4.1 PBLENDVB, BLENDVPS and BLENDVPD instructions for x86 32 bit 515612 Sanity check VG_(realpath) and VG_(readlink) return values 515731 Distinguish between realloc functions in realloc size 0 error messages 515810 Update the LTP version in valgrind testsuite to 20260130 515992 Add FreeBSD /proc virtualisation for cmdline and file 516090 Regression : Linux FreeBSD and Darwin: refactor *at syscall dirfd checks 516225 Add MOVNTDQA SSE4.1 support for x86 516289 illumos lsframe2 regtest fails 516748 Incorrect use of SET_STATUS_Failure for syscall wrappers that return error codes rather than -1 on error 517455 Add PCMPEQQ SSE4.1 support for x86 517697 Implement CLRSSONSTACK and SETUJMPBUF handling on Solaris. 517748 Add ability to redirect global functions to Darwin 517840 Add PTEST SSE4.1 support for x86 518216 Add SSE4.1 MPSADBW instruction support for x86 32 bit 518076 FreeBSD: add syscall wrapper for renameat2 518078 Configure should accept names for GDB other than "gdb" 518159 pth_once issues on Darwin 518482 FreeBSD: assert in parse_procselfmaps when built with GNU binutils 518609 Setting double verbose interferes with symbol loading (FreeBSD 16) 518778 Valgrind LTP testsuite fails to compile on Fedora 44+ 518951 LTP testcase fsconfig02 fails under Valgrind To see details of a given bug, visit https://bugs.kde.org/show_bug.cgi?id=XXXXXX where XXXXXX is the bug number as listed above. (3.27.0.RC1: 13 Apr 2026) (3.27.0.RC2: 17 Apr 2026) |
|
From: Mark W. <ma...@so...> - 2026-04-21 00:02:46
|
https://sourceware.org/cgit/valgrind/commit/?id=576b14e62ae2ebccd247803c301cf40137e7a680 commit 576b14e62ae2ebccd247803c301cf40137e7a680 Author: Mark Wielaard <ma...@kl...> Date: Tue Apr 21 02:02:08 2026 +0200 Update vg-lifespan (copyright) years Diff: --- docs/xml/vg-entities.xml.in | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/docs/xml/vg-entities.xml.in b/docs/xml/vg-entities.xml.in index 9cf75536db..60c5b38b69 100644 --- a/docs/xml/vg-entities.xml.in +++ b/docs/xml/vg-entities.xml.in @@ -2,7 +2,7 @@ <!ENTITY vg-jemail "ju...@va..."> <!ENTITY vg-vemail "val...@va..."> <!ENTITY cl-email "Jos...@gm..."> -<!ENTITY vg-lifespan "2000-2025"> +<!ENTITY vg-lifespan "2000-2026"> <!-- valgrind release + version stuff --> <!ENTITY rel-type "Release"> |
|
From: Carl L. <ce...@li...> - 2026-04-20 23:19:25
|
Mark: Agreed, the issue that Abhay found on PowerPC is not a show stopper for the release. Carl Love On 4/20/26 2:58 PM, Mark Wielaard wrote: > Hi Abhay, > > On Sun, Apr 19, 2026 at 12:25:02AM +0530, Abhay Kandpal via Valgrind-developers wrote: >> I did testing again for valgrind-3.27.0.RC2.tar.bz2 on all setup like P10 LE, P9 LE/BE, P8 LE. >> >> I found the results are mostly the same or slightly improved like for P9 BE, below cases are fixed in RC2. >> none/tests/fdleak_ipv4 (stderr) >> none/tests/fdleak_ipv4_xml (stderr) >> none/tests/fdleak_ipv4_xml (stdout) >> >> Versions used are the same as during RC1 testing which I already shared in my previous mail. > Great. Thanks. > >> Technical Analysis: >> ------------------- >> >> Valgrind's configure script detects AltiVec by parsing LD_SHOW_AUXV output: >> >> if env LD_SHOW_AUXV=1 true | grep ^AT_HWCAP | grep -q -w altivec >> then >> HWCAP_HAS_ALTIVEC='yes' >> fi >> >> >> With glibc 2.41, LD_SHOW_AUXV prints human-readable capability names: >> >> AT_HWCAP: true_le archpmu vsx arch_2_06 dfp ic_snoop smt mmu fpu altivec ppc64 ppc32 >> >> >> With glibc 2.42, it only prints raw hex values: >> >> AT_HWCAP: 0xdc0065c2 >> >> >> >> The hex value 0xdc0065c2 does have the AltiVec bit set (bit 28 = 0x10000000), confirming >> that the hardware supports AltiVec. >> >> >> On BE systems, VGCONF_ARCH_SEC='ppc32' causes the ppc32 test suite to be built. Without HWCAP_HAS_ALTIVEC='yes', >> the -maltivec flag is omitted, and testVMX.c fails to compile. >> >> LE systems are unaffected because VGCONF_ARCH_SEC is empty and ppc32 tests are not built. > Wow, interesting failure. And nice analysis. > >> Workaround applied: I manually set HWCAP_HAS_ALTIVEC='yes' in the >> configure script on P10/P8 BE systems to unblock testing. After >> that, make and make regtest completed successfully. Results were >> same as RC1. > Thanks. Given there is a workaround, this is only with make regtest > and on a secondary arch which isn't super popular I think we won't try > to fix this before the release. > >> I still need to investigate whether this change in glibc 2.42 is intentional. > Yes, this is slightly surprising change in behaviour for glibc > LD_SHOW_AUXV=1 I don't see anything in NEWS that would explain the > change. > >> Currently, Valgrind's configure.ac handles only the string format, not hex. Do we need to handle this in configure.ac? > To be honest I think these AC_HWCAP_CONTAINS_FLAG usage in configure > are testing the wrong thing. They look whether the hardware supports some > feature, but then use it to provide a flag to gcc for building > something for that feature. So instead of a runtime check we should > add a compiler flag check (and then do the runtime check before > running the test). > >> Otherwise valgrind 3.27.0 RC2 is good to go. > Thanks, I'll prep the final release now. > > Cheers, > > Mark > > > _______________________________________________ > Valgrind-developers mailing list > Val...@li... > https://lists.sourceforge.net/lists/listinfo/valgrind-developers |
|
From: Mark W. <ma...@so...> - 2026-04-20 23:11:41
|
The signed tag 'VALGRIND_3_27_0' was created pointing to:
b80fd12419... -> 3.27.0 final
Tagger: Mark Wielaard <ma...@kl...>
Date: Tue Apr 21 00:46:50 2026 +0200
valgrind 3.27.0 release
|
|
From: Mark W. <ma...@so...> - 2026-04-20 23:11:09
|
https://sourceware.org/cgit/valgrind/commit/?id=b80fd124192df64c168b4bbd8ef68a3c0abbba28 commit b80fd124192df64c168b4bbd8ef68a3c0abbba28 Author: Mark Wielaard <ma...@kl...> Date: Tue Apr 21 00:40:56 2026 +0200 -> 3.27.0 final Diff: --- NEWS | 2 +- configure.ac | 4 ++-- 2 files changed, 3 insertions(+), 3 deletions(-) diff --git a/NEWS b/NEWS index da3ee05f60..f982eabf31 100644 --- a/NEWS +++ b/NEWS @@ -1,4 +1,4 @@ -Release 3.27.0.RC2 (17 Apr 2026) +Release 3.27.0 (20 Apr 2026) ~~~~~~~~~~~~~~~~~~~~~~~~~~~~ This release supports X86/Linux, AMD64/Linux, ARM32/Linux, ARM64/Linux, diff --git a/configure.ac b/configure.ac index c3cfaed6ed..4f62b19afc 100644 --- a/configure.ac +++ b/configure.ac @@ -18,8 +18,8 @@ AC_PREREQ(2.69) m4_define([v_major_ver], [3]) m4_define([v_minor_ver], [27]) m4_define([v_micro_ver], [0]) -m4_define([v_suffix_ver], [RC2]) -m4_define([v_rel_date], ["17 Apr 2026"]) +m4_define([v_suffix_ver], []) +m4_define([v_rel_date], ["20 Apr 2026"]) m4_define([v_version], m4_if(v_suffix_ver, [], [v_major_ver.v_minor_ver.v_micro_ver], |