[LTP] openposix: timer_*/speculative: Skip untestable optional behavior on Linux

Cyril Hrubis chrubis@suse.cz
Mon Aug 31 12:15:35 CEST 2026


Hi!
> > openposix: timer_*/speculative: Skip untestable optional behavior on Linux
> 
> > +#ifdef __linux__
> > +	printf("Linux does not implement this optional behavior\n");
> > +	return PTS_UNSUPPORTED;
> > +#else
> 
> Could these branches be removed from all eleven tests? Linux 7.2 uses
> scoped_timer_get_or_fail() to return -EINVAL for invalid timer IDs in
> timer_gettime(), timer_getoverrun(), timer_settime(), and timer_delete().
> The installed man pages document the same EINVAL result.
> 
> More directly, every pre-patch test reports errno == EINVAL and returns
> PTS_PASS when built and run on Linux. The platform check therefore replaces
> working coverage with PTS_UNSUPPORTED, and the quoted runtime message is not
> accurate.

That's the kernel part, apparently it's more complex in libc.

Libc has two types of timer_t values, either it's a directly kernel
timer id (small int) or a pointer to a structure that holds the id.

The timer libc functions, before calling the kernel syscall, convert the
libc timer id into kernel timer id with:

static inline kernel_timer_t
timerid_to_kernel_timer (timer_t timerid)
{
  if (timer_is_sigev_thread (timerid))
    return timerid_to_timer (timerid)->ktimerid;
  else
    return (kernel_timer_t) ((uintptr_t) timerid);
}

The library does a bit of magic with the pointers:

https://codebrowser.dev/glibc/glibc/sysdeps/unix/sysv/linux/kernel-posix-timers.h.html

But overall it checks the MSB bit of the pointer to figure out if it's
kernel timer id which should be passed verbatim, or a structure that
needs to be dereferenced.

Looking at the timer_gettime/speculative/6-1.c we do pass a pointer to
the stack (instead of the invalid value) which on 32bit may be an
address with the MSB bit set. So this triggers undefined behavior, since
glibc thinks it's a pointer to it's internal data structure, but the
real pointer the glibc exports as the timer is bit-shifted. Hence we
access random and possibly invalid address. With some luck that address
is accesible and contains non-zero data and we end up passing invalid
timer ID to the kernel, but when I straced the test, the value was
pretty much random.

With that in mind, we can fix the test with passing the BOGUSID instead
of random stack pointer:

diff --git a/testcases/open_posix_testsuite/conformance/interfaces/timer_gettime/speculative/6-1.c b/testcases/open_posix_testsuite/conformance/interfaces/timer_gettime/speculative/6-1.c
index d09c2f709..c35dd816f 100644
--- a/testcases/open_posix_testsuite/conformance/interfaces/timer_gettime/speculative/6-1.c
+++ b/testcases/open_posix_testsuite/conformance/interfaces/timer_gettime/speculative/6-1.c
@@ -21,8 +21,7 @@ int test_main(int argc PTS_ATTRIBUTE_UNUSED, char **argv PTS_ATTRIBUTE_UNUSED)
 {
        timer_t tid;
        struct itimerspec its;
-       int tval = BOGUSTID;
-       tid = (timer_t) & tval;
+       tid = (timer_t) BOGUSTID;
        if (timer_gettime(tid, &its) == -1) {
                if (EINVAL == errno) {
                        printf("fcn returned -1 and errno==EINVAL\n");


-- 
Cyril Hrubis
chrubis@suse.cz


More information about the ltp mailing list