|
From: Paul F. <pa...@so...> - 2026-03-02 20:00:18
|
https://sourceware.org/cgit/valgrind/commit/?id=7012c31a609e342be2d9ece38eda55a0cdddf20e commit 7012c31a609e342be2d9ece38eda55a0cdddf20e Author: Paul Floyd <pj...@wa...> Date: Mon Mar 2 20:15:32 2026 +0100 Bug 516748 - clock_nanosleep was also wrong clock_nanosleep returns 0 or an errno error code, not 0/-1 and it does not set errno. The code was copied and pasted from Linux which does return 0/-1. That means that the POST only needs a POST_MEM_WRITE for ARG4 if the remainder timespec pointer is not NULL and RES is EINTR. The error flag is not set so the syscall appears to have succeeded. Diff: --- .gitignore | 3 +- coregrind/m_syswrap/syswrap-freebsd.c | 2 +- memcheck/tests/freebsd/Makefile.am | 9 ++-- memcheck/tests/freebsd/clock_nanosleep1.c | 43 +++++++++++++++++++ memcheck/tests/freebsd/clock_nanosleep1.stderr.exp | 12 ++++++ memcheck/tests/freebsd/clock_nanosleep1.vgtest | 2 + memcheck/tests/freebsd/clock_nanosleep2.c | 48 ++++++++++++++++++++++ memcheck/tests/freebsd/clock_nanosleep2.vgtest | 2 + memcheck/tests/freebsd/clock_nanosleep_interrupt.c | 32 --------------- .../freebsd/clock_nanosleep_interrupt.stderr.exp | 7 ---- .../tests/freebsd/clock_nanosleep_interrupt.vgtest | 2 - 11 files changed, 115 insertions(+), 47 deletions(-) diff --git a/.gitignore b/.gitignore index 42581df318..8f9ba9ece7 100644 --- a/.gitignore +++ b/.gitignore @@ -1440,7 +1440,8 @@ /memcheck/tests/freebsd/capsicum /memcheck/tests/freebsd/chflags /memcheck/tests/freebsd/chmod_chown -/memcheck/tests/freebsd/clock_nanosleep_interrupt +/memcheck/tests/freebsd/clock_nanosleep1 +/memcheck/tests/freebsd/clock_nanosleep2 /memcheck/tests/freebsd/delete_sized_mismatch /memcheck/tests/freebsd/errno_aligned_allocs /memcheck/tests/freebsd/eventfd1 diff --git a/coregrind/m_syswrap/syswrap-freebsd.c b/coregrind/m_syswrap/syswrap-freebsd.c index c9a3939478..7dc778595d 100644 --- a/coregrind/m_syswrap/syswrap-freebsd.c +++ b/coregrind/m_syswrap/syswrap-freebsd.c @@ -2613,7 +2613,7 @@ PRE(sys_clock_nanosleep) POST(sys_clock_nanosleep) { - if (ARG4 != 0 && FAILURE && ERR == VKI_EINTR) { + if (ARG4 != 0 && RES == VKI_EINTR) { POST_MEM_WRITE( ARG4, sizeof(struct vki_timespec) ); } } diff --git a/memcheck/tests/freebsd/Makefile.am b/memcheck/tests/freebsd/Makefile.am index c59a02b798..ae0bd1e48b 100644 --- a/memcheck/tests/freebsd/Makefile.am +++ b/memcheck/tests/freebsd/Makefile.am @@ -35,8 +35,9 @@ EXTRA_DIST = \ chflags.stderr.exp-x86 \ chmod_chown.vgtest \ chmod_chown.stderr.exp \ - clock_nanosleep_interrupt.vgtest \ - clock_nanosleep_interrupt.stderr.exp \ + clock_nanosleep1.vgtest \ + clock_nanosleep1.stderr.exp \ + clock_nanosleep2.vgtest \ delete_sized_mismatch.vgtest \ delete_sized_mismatch.stderr.exp \ delete_sized_mismatch_xml.vgtest \ @@ -150,7 +151,7 @@ check_PROGRAMS = \ access aio aio_read aligned_alloc bug464476 bug470713 \ bug483786 \ capsicum chflags \ - chmod_chown clock_nanosleep_interrupt \ + chmod_chown clock_nanosleep1 clock_nanosleep2 \ delete_sized_mismatch errno_aligned_allocs \ extattr fbsd278566 \ fexecve \ @@ -233,7 +234,7 @@ endif access_CFLAGS = ${AM_CFLAGS} @FLAG_W_NO_UNINITIALIZED@ @FLAG_W_NO_USE_AFTER_FREE@ aligned_alloc_CFLAGS = ${AM_CFLAGS} @FLAG_W_NO_NON_POWER_OF_TWO_ALIGNMENT@ capsicum_CFLAGS = ${AM_CFLAGS} @FLAG_W_NO_UNINITIALIZED@ @FLAG_W_NO_USE_AFTER_FREE@ -clock_nanosleep_interrupt_CFLAGS = ${AM_CFLAGS} @FLAG_W_NO_ALLOC_SIZE@ +clock_nanosleep1_CFLAGS = ${AM_CFLAGS} @FLAG_W_NO_ALLOC_SIZE@ chflags_CFLAGS = ${AM_CFLAGS} @FLAG_W_NO_UNINITIALIZED@ @FLAG_W_NO_USE_AFTER_FREE@ chmod_chown_CFLAGS = ${AM_CFLAGS} @FLAG_W_NO_UNINITIALIZED@ @FLAG_W_NO_USE_AFTER_FREE@ delete_sized_mismatch_CXXFLAGS = ${AM_CXXFLAGS} --std=c++14 diff --git a/memcheck/tests/freebsd/clock_nanosleep1.c b/memcheck/tests/freebsd/clock_nanosleep1.c new file mode 100644 index 0000000000..14d13fa1d5 --- /dev/null +++ b/memcheck/tests/freebsd/clock_nanosleep1.c @@ -0,0 +1,43 @@ +#include <fcntl.h> +#include <signal.h> +#include <sys/time.h> +#include <unistd.h> +#include <stdlib.h> +#include <assert.h> +#include <errno.h> + +volatile int ticks = 0; +struct itimerval timert; +struct sigaction timer_action; + +void handle_alrm(int sig) { ticks++; } + +int main(int argc, char* argv[]) +{ + timer_action.sa_handler = handle_alrm; + sigemptyset(&timer_action.sa_mask); + timer_action.sa_flags = SA_RESTART; + + sigaction(SIGALRM, &timer_action, NULL); + + timert.it_interval.tv_sec = timert.it_value.tv_sec = 0; + timert.it_interval.tv_usec = timert.it_value.tv_usec = 100; + setitimer(ITIMER_REAL, &timert, NULL); + + struct timespec ts_initialized = {0, 1000000}; + int ret; + + ret = clock_nanosleep(CLOCK_MONOTONIC, 0, &ts_initialized, + NULL); + assert(ret == EINTR); + + struct timespec* too_small = malloc(1); + + ret = clock_nanosleep(CLOCK_MONOTONIC, 0, &ts_initialized, + too_small); + assert(ret == EINTR); + + ret = clock_nanosleep(CLOCK_MONOTONIC, TIMER_ABSTIME, NULL, + &ts_initialized); + assert(ret == EFAULT); +} diff --git a/memcheck/tests/freebsd/clock_nanosleep1.stderr.exp b/memcheck/tests/freebsd/clock_nanosleep1.stderr.exp new file mode 100644 index 0000000000..bd5566ef9f --- /dev/null +++ b/memcheck/tests/freebsd/clock_nanosleep1.stderr.exp @@ -0,0 +1,12 @@ +Syscall param clock_nanosleep(rmtp) points to unaddressable byte(s) + ... + by 0x........: main (clock_nanosleep1.c:36) + Address 0x........ is 0 bytes after a block of size 1 alloc'd + at 0x........: malloc (vg_replace_malloc.c:...) + by 0x........: main (clock_nanosleep1.c:34) + +Syscall param clock_nanosleep(rqtp) points to unaddressable byte(s) + ... + by 0x........: main (clock_nanosleep1.c:40) + Address 0x........ is not stack'd, malloc'd or (recently) free'd + diff --git a/memcheck/tests/freebsd/clock_nanosleep1.vgtest b/memcheck/tests/freebsd/clock_nanosleep1.vgtest new file mode 100644 index 0000000000..3d514bff7d --- /dev/null +++ b/memcheck/tests/freebsd/clock_nanosleep1.vgtest @@ -0,0 +1,2 @@ +prog: clock_nanosleep1 +vgopts: -q diff --git a/memcheck/tests/freebsd/clock_nanosleep2.c b/memcheck/tests/freebsd/clock_nanosleep2.c new file mode 100644 index 0000000000..ab22894f6b --- /dev/null +++ b/memcheck/tests/freebsd/clock_nanosleep2.c @@ -0,0 +1,48 @@ +#include <time.h> +#include <signal.h> +#include <unistd.h> +#include <stdio.h> +#include <string.h> +#include <errno.h> +#include <unistd.h> + +static void handler(int sig) { (void)sig; } + +int main(void) +{ + struct sigaction sa; + memset(&sa, 0, sizeof(sa)); + sa.sa_handler = handler; + sigaction(SIGUSR1, &sa, NULL); /* no SA_RESTART */ + + /* Child will interrupt us */ + if (fork() == 0) { + usleep(100000); /* 100ms */ + kill(getppid(), SIGUSR1); + _exit(0); + } + + struct timespec req = { .tv_sec = 2, .tv_nsec = 0 }; + struct timespec rem; + + int ret = clock_nanosleep(CLOCK_MONOTONIC, 0, &req, &rem); + + if (ret != EINTR) + { + printf("Unexpected return: %d\n", ret); + return 1; + } + + /* Force full struct read */ + volatile long sec = rem.tv_sec; + volatile long nsec = rem.tv_nsec; + + /* Trigger uninit read error if rem was not marked as initialised */ + if (sec || nsec) + { + return 1; + } + + return 0; +} + diff --git a/memcheck/tests/freebsd/clock_nanosleep2.vgtest b/memcheck/tests/freebsd/clock_nanosleep2.vgtest new file mode 100644 index 0000000000..c848fa34e1 --- /dev/null +++ b/memcheck/tests/freebsd/clock_nanosleep2.vgtest @@ -0,0 +1,2 @@ +prog: clock_nanosleep2 +vgopts: -q diff --git a/memcheck/tests/freebsd/clock_nanosleep_interrupt.c b/memcheck/tests/freebsd/clock_nanosleep_interrupt.c deleted file mode 100644 index 49f4a2814b..0000000000 --- a/memcheck/tests/freebsd/clock_nanosleep_interrupt.c +++ /dev/null @@ -1,32 +0,0 @@ -#include <fcntl.h> -#include <signal.h> -#include <stdio.h> -#include <sys/time.h> -#include <unistd.h> -#include <stdlib.h> - -volatile int ticks = 0; -struct itimerval timert; -struct sigaction timer_action; - -void handle_vtalrm(int sig) { ticks++; } - - -int main(int argc, char* argv[]) -{ - timer_action.sa_handler = handle_vtalrm; - sigemptyset(&timer_action.sa_mask); - timer_action.sa_flags = SA_RESTART; - - sigaction(SIGVTALRM, &timer_action, NULL); - - timert.it_interval.tv_sec = timert.it_value.tv_sec = 0; - timert.it_interval.tv_usec = timert.it_value.tv_usec = 500; - setitimer(ITIMER_VIRTUAL, &timert, NULL); - - struct timespec ts_initialized = {0, 1000000}; - struct timespec* too_small = malloc(1); - - clock_nanosleep(CLOCK_MONOTONIC, TIMER_ABSTIME, &ts_initialized, - too_small); -} diff --git a/memcheck/tests/freebsd/clock_nanosleep_interrupt.stderr.exp b/memcheck/tests/freebsd/clock_nanosleep_interrupt.stderr.exp deleted file mode 100644 index 1152ed2f10..0000000000 --- a/memcheck/tests/freebsd/clock_nanosleep_interrupt.stderr.exp +++ /dev/null @@ -1,7 +0,0 @@ -Syscall param clock_nanosleep(rmtp) points to unaddressable byte(s) - ... - by 0x........: main (clock_nanosleep_interrupt.c:30) - Address 0x........ is 0 bytes after a block of size 1 alloc'd - at 0x........: malloc (vg_replace_malloc.c:...) - by 0x........: main (clock_nanosleep_interrupt.c:28) - diff --git a/memcheck/tests/freebsd/clock_nanosleep_interrupt.vgtest b/memcheck/tests/freebsd/clock_nanosleep_interrupt.vgtest deleted file mode 100644 index c4b785d054..0000000000 --- a/memcheck/tests/freebsd/clock_nanosleep_interrupt.vgtest +++ /dev/null @@ -1,2 +0,0 @@ -prog: clock_nanosleep_interrupt -vgopts: -q |