Explorar o código

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.
Rich Felker %!s(int64=2) %!d(string=hai) anos
pai
achega
b6811019e6
Modificáronse 1 ficheiros con 7 adicións e 2 borrados
  1. 7 2
      src/select/poll.c

+ 7 - 2
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
 }