From 06ea9aed58c6372b4138d3668ef0f93465ab70d0 Mon Sep 17 00:00:00 2001 From: "L. E. Segovia" Date: Mon, 1 Apr 2024 23:55:01 -0300 Subject: [PATCH] glib/gthread-posix: Block futex_time64 usage on Android API level < 30 This syscall is seccomp blocked on all lower API levels: https://github.com/aosp-mirror/platform_bionic/commit/ee7bc3002dc3127faac110167d28912eb0e86a20 --- glib/gthread-posix.c | 12 ++++++++++-- glib/gthreadprivate.h | 34 +++++++++++++++++++++++++++++++++- 2 files changed, 43 insertions(+), 3 deletions(-) diff --git a/glib/gthread-posix.c b/glib/gthread-posix.c index ad4c006fd..a8cd6314e 100644 --- a/glib/gthread-posix.c +++ b/glib/gthread-posix.c @@ -1605,12 +1605,16 @@ g_cond_wait_until (GCond *cond, * To get around this problem we * a) check if `futex_time64` is available, which only exists on 32-bit * platforms and always uses 64-bit `time_t`. - * b) otherwise (or if that returns `ENOSYS`), we call the normal `futex` + * b) if `futex_time64` is available, but the Android runtime's API level + * is < 30, `futex_time64` is blocked by seccomp and using it will cause + * the app to be terminated. Skip to c). + * https://android-review.googlesource.com/c/platform/bionic/+/1094758 + * c) otherwise (or if that returns `ENOSYS`), we call the normal `futex` * syscall with the `struct timespec` used by the kernel. By default, we * use `__kernel_long_t` for both its fields, which is equivalent to * `__kernel_old_time_t` and is available in the kernel headers for a * longer time. - * c) With very old headers (~2.6.x), `__kernel_long_t` is not available, and + * d) With very old headers (~2.6.x), `__kernel_long_t` is not available, and * we use an older definition that uses `__kernel_time_t` and `long`. * * Also some 32-bit systems do not define `__NR_futex` at all and only @@ -1621,7 +1625,11 @@ g_cond_wait_until (GCond *cond, g_mutex_unlock (mutex); #ifdef __NR_futex_time64 +#if defined(__BIONIC__) + if (__builtin_available (android 30, *)) { +#else { +#endif struct { gint64 tv_sec; diff --git a/glib/gthreadprivate.h b/glib/gthreadprivate.h index 61dfdae34..e2e322763 100644 --- a/glib/gthreadprivate.h +++ b/glib/gthreadprivate.h @@ -64,10 +64,41 @@ struct _GRealThread * with the normal `futex` syscall. This can happen if newer kernel headers * are used than the kernel that is actually running. * + * The `futex_time64` syscall is also skipped in favour of `futex` if the + * Android runtime’s API level is lower than 30, as it’s blocked by seccomp + * there and using it will cause the app to be terminated: + * https://android-review.googlesource.com/c/platform/bionic/+/1094758 + * https://github.com/aosp-mirror/platform_bionic/commit/ee7bc3002dc3127faac110167d28912eb0e86a20 + * * This must not be called with a timeout parameter as that differs * in size between the two syscall variants! */ #if defined(__NR_futex) && defined(__NR_futex_time64) +#if defined(__BIONIC__) +#define g_futex_simple(uaddr, futex_op, ...) \ + G_STMT_START \ + { \ + int res = 0; \ + if (__builtin_available (android 30, *)) \ + { \ + res = syscall (__NR_futex_time64, uaddr, (gsize) futex_op, __VA_ARGS__); \ + if (res < 0 && errno == ENOSYS) \ + { \ + errno = saved_errno; \ + res = syscall (__NR_futex, uaddr, (gsize) futex_op, __VA_ARGS__); \ + } \ + } \ + else \ + { \ + res = syscall (__NR_futex, uaddr, (gsize) futex_op, __VA_ARGS__); \ + } \ + if (res < 0 && errno == EAGAIN) \ + { \ + errno = saved_errno; \ + } \ + } \ + G_STMT_END +#else #define g_futex_simple(uaddr, futex_op, ...) \ G_STMT_START \ { \ @@ -84,6 +115,7 @@ struct _GRealThread } \ } \ G_STMT_END +#endif /* defined(__BIONIC__) */ #elif defined(__NR_futex_time64) #define g_futex_simple(uaddr, futex_op, ...) \ G_STMT_START \ @@ -109,7 +141,7 @@ struct _GRealThread } \ G_STMT_END #else /* !defined(__NR_futex) && !defined(__NR_futex_time64) */ -#error "Neither __NR_futex nor __NR_futex_time64 are defined but were found by meson" +#error "Neither __NR_futex nor __NR_futex_time64 are available" #endif /* defined(__NR_futex) && defined(__NR_futex_time64) */ #endif