From 9497a56f7158339b56421b932760851feb39e5ad Mon Sep 17 00:00:00 2001 From: Florian Weimer Date: Wed, 20 May 2020 19:38:35 +0200 Subject: [PATCH] open, open64: Eliminate dependency on ELF constructor ordering Another shared object may call open or open64 before the nosync ELF constructor has run. Relocation dependencies do not factor into ELF constructor ordering. --- open.c | 33 ++++++++++++++++----------------- 1 file changed, 16 insertions(+), 17 deletions(-) diff --git a/open.c b/open.c index 89c896d..f96f542 100644 --- a/open.c +++ b/open.c @@ -17,33 +17,32 @@ #include #include #include +#include #include #include +/* Avoid infinite recursion if called from dlsym(). The implementation + assumes that open is called before the process goes multi-threaded. */ static int dlsym_pending; #define OPEN(open) \ \ -static int (*real_ ## open)(const char *, int, ...); \ - \ int __nosync_ ## open(const char *path, int flags, mode_t mode) \ { \ - /* Avoid infinite recursion if called from dlsym(). */ \ - if (__builtin_expect(dlsym_pending, 0)) { \ - errno = ENOSYS; \ - return -1; \ + static int (*real)(const char *, int, ...); \ + int (*real_copy)(const char *, int, ...) \ + = __atomic_load_n(&real, __ATOMIC_RELAXED); \ + if (real_copy == NULL) { \ + if (dlsym_pending) { \ + errno = ENOSYS; \ + return -1; \ + } \ + dlsym_pending = 1; \ + real_copy = dlsym(RTLD_NEXT, #open); \ + dlsym_pending = 0; \ + __atomic_store_n(&real, real_copy, __ATOMIC_RELAXED); \ } \ - \ - return real_ ## open(path, flags & ~(O_SYNC | O_DSYNC), mode); \ -} \ - \ -__attribute__((constructor)) \ -static void \ -init_ ## open(void) \ -{ \ - dlsym_pending = 1; \ - real_ ## open = dlsym(RTLD_NEXT, #open); \ - dlsym_pending = 0; \ + return real_copy(path, flags & ~(O_SYNC | O_DSYNC), mode); \ } \ \ int open(const char *, int, ...) \