From 964efdfba9cf1d4f9a99afe6c965a7fd504319b4 Mon Sep 17 00:00:00 2001 From: Rob Clark Date: Sun, 6 Jun 2021 09:27:52 -0700 Subject: [PATCH] egl+libsync: Add check for valid fence-fd Debugging fd mix-ups (ie. where, possibly via close()ing the original fd, etc, you end up with something that is a valid fd but not a valid *fence* fd) can be difficult. Fortunately we can use the FILE_INFO ioctl, which will return an error if the fd is not a fence fd. For android, we instead use the libsync API, which does a similar thing on modern kernels, but has a fallback path for older android kernels. Note that the FILE_INFO ioctl has existed upstream since at least prior to destaging of sync_file. Signed-off-by: Rob Clark Reviewed-by: Emma Anholt Part-of: --- src/android_stub/sync_stub.cpp | 9 +++++++ src/egl/drivers/dri2/egl_dri2.c | 3 +++ src/util/libsync.h | 42 +++++++++++++++++++++++++++++++++ 3 files changed, 54 insertions(+) diff --git a/src/android_stub/sync_stub.cpp b/src/android_stub/sync_stub.cpp index 963d928a47f..3f5d5074276 100644 --- a/src/android_stub/sync_stub.cpp +++ b/src/android_stub/sync_stub.cpp @@ -17,4 +17,13 @@ int sync_merge(const char *name, int fd, int fd2) return 0; } +struct sync_file_info* sync_file_info(int32_t fd) +{ + return NULL; +} + +void sync_file_info_free(struct sync_file_info* info) +{ +} + } diff --git a/src/egl/drivers/dri2/egl_dri2.c b/src/egl/drivers/dri2/egl_dri2.c index c76684675cf..9e5a55a287c 100644 --- a/src/egl/drivers/dri2/egl_dri2.c +++ b/src/egl/drivers/dri2/egl_dri2.c @@ -62,6 +62,7 @@ #include "egl_dri2.h" #include "GL/mesa_glinterop.h" #include "loader/loader.h" +#include "util/libsync.h" #include "util/os_file.h" #include "util/u_atomic.h" #include "util/u_vector.h" @@ -3495,6 +3496,8 @@ dri2_dup_native_fence_fd(_EGLDisplay *disp, _EGLSync *sync) return EGL_NO_NATIVE_FENCE_FD_ANDROID; } + assert(sync_valid_fd(sync->SyncFd)); + return os_dupfd_cloexec(sync->SyncFd); } diff --git a/src/util/libsync.h b/src/util/libsync.h index 2e9f499200b..1c9303c174a 100644 --- a/src/util/libsync.h +++ b/src/util/libsync.h @@ -30,6 +30,7 @@ #include #include +#include #include #include #include @@ -46,6 +47,25 @@ extern "C" { * Android kernels. */ #include + +/** + * Check if the fd represents a valid fence-fd. + * + * The android variant of this debug helper is implemented on top of the + * system's libsync for compatibility with pre-4.7 android kernels. + */ +static inline bool +sync_valid_fd(int fd) +{ + /* sync_file_info() only available in SDK 26. */ +#if ANDROID_API_LEVEL >= 26 + struct sync_file_info *info = sync_file_info(fd); + if (!info) + return false; + sync_file_info_free(info); +#endif + return true; +} #else #ifndef SYNC_IOC_MERGE @@ -61,8 +81,20 @@ struct sync_merge_data { uint32_t flags; uint32_t pad; }; + +struct sync_file_info { + char name[32]; + int32_t status; + uint32_t flags; + uint32_t num_fences; + uint32_t pad; + + uint64_t sync_fence_info; +}; + #define SYNC_IOC_MAGIC '>' #define SYNC_IOC_MERGE _IOWR(SYNC_IOC_MAGIC, 3, struct sync_merge_data) +#define SYNC_IOC_FILE_INFO _IOWR(SYNC_IOC_MAGIC, 4, struct sync_file_info) #endif @@ -109,6 +141,16 @@ static inline int sync_merge(const char *name, int fd1, int fd2) return data.fence; } +/** + * Check if the fd represents a valid fence-fd. + */ +static inline bool +sync_valid_fd(int fd) +{ + struct sync_file_info info = {{0}}; + return ioctl(fd, SYNC_IOC_FILE_INFO, &info) >= 0; +} + #endif /* !ANDROID */ /* accumulate fd2 into fd1. If *fd1 is not a valid fd then dup fd2,