summaryrefslogtreecommitdiff
path: root/src/select
diff options
context:
space:
mode:
authorRich Felker <dalias@aerifal.cx>2023-03-03 09:27:04 -0500
committerRich Felker <dalias@aerifal.cx>2023-03-03 09:52:52 -0500
commitb6811019e62a7561a4922f90e54b30ac306efe0b (patch)
tree964cd15c4e8fa86497b8b52d79fa00ef5c1e17ad /src/select
parent8949da7ab1c0dbf801e8bc78f0c0adc625020f75 (diff)
downloadmusl-b6811019e62a7561a4922f90e54b30ac306efe0b.tar.gz
poll: fix misuse of timespec type on 32-bit archs without poll syscall
this function was overlooked during the time64 transition, probably as a result of not having any time-related types in its application-side interface. however, for archs that lack the traditional poll syscall and have only ppoll, it used timespec as part of its interface with the kernel: the millisecond timeout was converted to a timespec to pass to SYS_ppoll. this is a type/ABI mismatch on 32-bit archs with legacy time32 syscalls. only one supported arch, or1k, is affected. all of the others either have SYS_poll, or are 64-bit. rather than using timespec, define a type locally to match what the kernel expects. the condition (SYS_ppoll_time64 == SYS_ppoll), comparable to conditions used elsewhere in timespec-handling code, evaluates true for "natively time64" 32-bit archs including x32, future riscv32, and all future 32-bit archs (via definitions in internal syscall.h). otherwise, the arch is either 64-bit or has syscalls that take the legacy type, and in either case "long" is correct. this fix is based on bug report and proposal by Alexey Izbyshev but with a different approach to the changes to minimize the contextual knowledge needed for a reader to understand the source file.
Diffstat (limited to 'src/select')
-rw-r--r--src/select/poll.c9
1 files changed, 7 insertions, 2 deletions
diff --git a/src/select/poll.c b/src/select/poll.c
index c84c8a99..7883dfab 100644
--- a/src/select/poll.c
+++ b/src/select/poll.c
@@ -8,8 +8,13 @@ int poll(struct pollfd *fds, nfds_t n, int timeout)
#ifdef SYS_poll
return syscall_cp(SYS_poll, fds, n, timeout);
#else
+#if SYS_ppoll_time64 == SYS_ppoll
+ typedef long long ppoll_ts_t[2];
+#else
+ typedef long ppoll_ts_t[2];
+#endif
return syscall_cp(SYS_ppoll, fds, n, timeout>=0 ?
- &((struct timespec){ .tv_sec = timeout/1000,
- .tv_nsec = timeout%1000*1000000 }) : 0, 0, _NSIG/8);
+ ((ppoll_ts_t){ timeout/1000, timeout%1000*1000000 }) : 0,
+ 0, _NSIG/8);
#endif
}