1From e5499a3cac1e823c3e0697e8667e952317b70cc8 Mon Sep 17 00:00:00 2001
2From: Alistair Francis <alistair.francis@wdc.com>
3Date: Thu, 4 Mar 2021 12:10:11 -0500
4Subject: [PATCH] Fixup support for io_pgetevents_time64 syscall
5
6This is a fixup for the original commit 5b5e2985f355c8e99c196d9ce5d02c15bebadfbc
7"Add support for io_pgetevents_time64 syscall" that didn't correctly
8work for 32-bit architecutres with a 64-bit time_t that aren't RISC-V.
9
10For a full discussion of the issue see:
11https://github.com/openssl/openssl/commit/5b5e2985f355c8e99c196d9ce5d02c15bebadfbc
12
13Signed-off-by: Alistair Francis <alistair.francis@wdc.com>
14
15Reviewed-by: Tomas Mraz <tomas@openssl.org>
16Reviewed-by: Paul Dale <pauli@openssl.org>
17(Merged from https://github.com/openssl/openssl/pull/14432)
18---
19 engines/e_afalg.c | 55 ++++++++++++++++++++++++++++++++++++-----------
20 1 file changed, 42 insertions(+), 13 deletions(-)
21
22diff --git a/engines/e_afalg.c b/engines/e_afalg.c
23index 9480d7c24b..4e9d67db2d 100644
24--- a/engines/e_afalg.c
25+++ b/engines/e_afalg.c
26@@ -124,27 +124,56 @@ static ossl_inline int io_read(aio_context_t ctx, long n, struct iocb **iocb)
27     return syscall(__NR_io_submit, ctx, n, iocb);
28 }
29
30+/* A version of 'struct timespec' with 32-bit time_t and nanoseconds.  */
31+struct __timespec32
32+{
33+  __kernel_long_t tv_sec;
34+  __kernel_long_t tv_nsec;
35+};
36+
37 static ossl_inline int io_getevents(aio_context_t ctx, long min, long max,
38                                struct io_event *events,
39                                struct timespec *timeout)
40 {
41+#if defined(__NR_io_pgetevents_time64)
42+    /* Check if we are a 32-bit architecture with a 64-bit time_t */
43+    if (sizeof(*timeout) != sizeof(struct __timespec32)) {
44+        int ret = syscall(__NR_io_pgetevents_time64, ctx, min, max, events,
45+                          timeout, NULL);
46+        if (ret == 0 || errno != ENOSYS)
47+            return ret;
48+    }
49+#endif
50+
51 #if defined(__NR_io_getevents)
52-    return syscall(__NR_io_getevents, ctx, min, max, events, timeout);
53-#elif defined(__NR_io_pgetevents_time64)
54-    /* Let's only support the 64 suffix syscalls for 64-bit time_t.
55-     * This simplifies the code for us as we don't need to use a 64-bit
56-     * version of timespec with a 32-bit time_t and handle converting
57-     * between 64-bit and 32-bit times and check for overflows.
58-     */
59-    if (sizeof(timeout->tv_sec) == 8)
60-        return syscall(__NR_io_pgetevents_time64, ctx, min, max, events, timeout, NULL);
61+    if (sizeof(*timeout) == sizeof(struct __timespec32))
62+        /*
63+         * time_t matches our architecture length, we can just use
64+         * __NR_io_getevents
65+         */
66+        return syscall(__NR_io_getevents, ctx, min, max, events, timeout);
67     else {
68-        errno = ENOSYS;
69-        return -1;
70+        /*
71+         * We don't have __NR_io_pgetevents_time64, but we are using a
72+         * 64-bit time_t on a 32-bit architecture. If we can fit the
73+         * timeout value in a 32-bit time_t, then let's do that
74+         * and then use the __NR_io_getevents syscall.
75+         */
76+        if (timeout && timeout->tv_sec == (long)timeout->tv_sec) {
77+            struct __timespec32 ts32;
78+
79+            ts32.tv_sec = (__kernel_long_t) timeout->tv_sec;
80+            ts32.tv_nsec = (__kernel_long_t) timeout->tv_nsec;
81+
82+            return syscall(__NR_io_getevents, ctx, min, max, events, ts32);
83+        } else {
84+            return syscall(__NR_io_getevents, ctx, min, max, events, NULL);
85+        }
86     }
87-#else
88-# error "We require either the io_getevents syscall or __NR_io_pgetevents_time64."
89 #endif
90+
91+    errno = ENOSYS;
92+    return -1;
93 }
94
95 static void afalg_waitfd_cleanup(ASYNC_WAIT_CTX *ctx, const void *key,
96--
972.25.1
98
99