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.
/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
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) );
}
}
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 \
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 \
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
--- /dev/null
+#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);
+}
--- /dev/null
+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
+
--- /dev/null
+prog: clock_nanosleep1
+vgopts: -q
--- /dev/null
+#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;
+}
+
--- /dev/null
+prog: clock_nanosleep2
+vgopts: -q
+++ /dev/null
-#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);
-}
+++ /dev/null
-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)
-
+++ /dev/null
-prog: clock_nanosleep_interrupt
-vgopts: -q