From: kettenis Date: Fri, 21 May 2021 16:52:42 +0000 (+0000) Subject: The implementation of the FUTEX_WAIT option in futex(2) is subtly broken. X-Git-Url: http://artulab.com/gitweb/?a=commitdiff_plain;h=173afbac0719ddb7b5184b7ab35c6fc25d91b757;p=openbsd The implementation of the FUTEX_WAIT option in futex(2) is subtly broken. Unfortunately libc and libpthread rely on the broken behaviour. Adjust the code in those libraries such that it works with both the old and the proposed new behaviour. The kernel changes that fix the issue will be committed in a week or so to give those who do their own builds a chance to update these libraries before we make the change. ok mpi@, deraadt@ --- diff --git a/lib/libc/thread/synch.h b/lib/libc/thread/synch.h index aaeb965956a..91b5001c515 100644 --- a/lib/libc/thread/synch.h +++ b/lib/libc/thread/synch.h @@ -1,4 +1,4 @@ -/* $OpenBSD: synch.h,v 1.5 2020/07/06 13:33:06 pirofti Exp $ */ +/* $OpenBSD: synch.h,v 1.6 2021/05/21 16:52:42 kettenis Exp $ */ /* * Copyright (c) 2017 Martin Pieuchot * @@ -29,12 +29,17 @@ static inline int _twait(volatile uint32_t *p, int val, clockid_t clockid, const struct timespec *abs) { struct timespec rel; + int error; - if (abs == NULL) - return futex(p, FUTEX_WAIT_PRIVATE, val, NULL, NULL); + if (abs == NULL) { + error = futex(p, FUTEX_WAIT_PRIVATE, val, NULL, NULL); + if (error == -1) + error = errno; + return error; + } if (abs->tv_nsec >= 1000000000 || WRAP(clock_gettime)(clockid, &rel)) - return (EINVAL); + return EINVAL; rel.tv_sec = abs->tv_sec - rel.tv_sec; if ((rel.tv_nsec = abs->tv_nsec - rel.tv_nsec) < 0) { @@ -42,9 +47,12 @@ _twait(volatile uint32_t *p, int val, clockid_t clockid, const struct timespec * rel.tv_nsec += 1000000000; } if (rel.tv_sec < 0) - return (ETIMEDOUT); + return ETIMEDOUT; - return futex(p, FUTEX_WAIT_PRIVATE, val, &rel, NULL); + error = futex(p, FUTEX_WAIT_PRIVATE, val, &rel, NULL); + if (error == -1) + error = errno; + return error; } static inline int diff --git a/lib/librthread/synch.h b/lib/librthread/synch.h index 381ed1b1749..e5c623e87a0 100644 --- a/lib/librthread/synch.h +++ b/lib/librthread/synch.h @@ -1,4 +1,4 @@ -/* $OpenBSD: synch.h,v 1.6 2019/10/24 12:32:18 sthen Exp $ */ +/* $OpenBSD: synch.h,v 1.7 2021/05/21 16:52:42 kettenis Exp $ */ /* * Copyright (c) 2017 Martin Pieuchot * @@ -36,12 +36,17 @@ static inline int _twait(volatile uint32_t *p, int val, clockid_t clockid, const struct timespec *abs) { struct timespec rel; + int error; - if (abs == NULL) - return futex(p, FUTEX_WAIT, val, NULL, NULL); + if (abs == NULL) { + error = futex(p, FUTEX_WAIT, val, NULL, NULL); + if (error == -1) + error = errno; + return error; + } if (abs->tv_nsec >= 1000000000 || clock_gettime(clockid, &rel)) - return (EINVAL); + return EINVAL; rel.tv_sec = abs->tv_sec - rel.tv_sec; if ((rel.tv_nsec = abs->tv_nsec - rel.tv_nsec) < 0) { @@ -49,9 +54,12 @@ _twait(volatile uint32_t *p, int val, clockid_t clockid, const struct timespec * rel.tv_nsec += 1000000000; } if (rel.tv_sec < 0) - return (ETIMEDOUT); + return ETIMEDOUT; - return futex(p, FUTEX_WAIT, val, &rel, NULL); + error = futex(p, FUTEX_WAIT, val, &rel, NULL); + if (error == -1) + error = errno; + return error; } static inline int