From 22daaea39f1cc5f7391f0a5cd84576ffb58c2860 Mon Sep 17 00:00:00 2001 From: Rich Felker Date: Fri, 9 Aug 2019 15:26:23 -0400 Subject: [PATCH] add time64 redirect for, and redirecting implementation of, dlsym if symbols are being redirected to provide the new time64 ABI, dlsym must perform matching redirections; otherwise, it would poke a hole in the magic and return pointers to functions that are not safe to call from a caller using time64 types. rather than duplicating a table of redirections, use the time64 symbols present in libc's symbol table to derive the decision for whether a particular symbol needs to be redirected. --- include/dlfcn.h | 4 ++++ ldso/dynlink.c | 27 +++++++++++++++++++++++++++ 2 files changed, 31 insertions(+) diff --git a/include/dlfcn.h b/include/dlfcn.h index 78fb0733..13ab71dd 100644 --- a/include/dlfcn.h +++ b/include/dlfcn.h @@ -35,6 +35,10 @@ int dladdr(const void *, Dl_info *); int dlinfo(void *, int, void *); #endif +#if _REDIR_TIME64 +__REDIR(dlsym, __dlsym_time64); +#endif + #ifdef __cplusplus } #endif diff --git a/ldso/dynlink.c b/ldso/dynlink.c index 7ac0bf75..7810356b 100644 --- a/ldso/dynlink.c +++ b/ldso/dynlink.c @@ -2237,6 +2237,33 @@ hidden void *__dlsym(void *restrict p, const char *restrict s, void *restrict ra return res; } +hidden void *__dlsym_redir_time64(void *restrict p, const char *restrict s, void *restrict ra) +{ +#if _REDIR_TIME64 + const char *suffix, *suffix2 = ""; + char redir[36]; + + /* Map the symbol name to a time64 version of itself according to the + * pattern used for naming the redirected time64 symbols. */ + size_t l = strnlen(s, sizeof redir); + if (l<4 || l==sizeof redir) goto no_redir; + if (s[l-2]=='_' && s[l-1]=='r') { + l -= 2; + suffix2 = s+l; + } + if (l<4) goto no_redir; + if (!strcmp(s+l-4, "time")) suffix = "64"; + else suffix = "_time64"; + + /* Use the presence of the remapped symbol name in libc to determine + * whether it's one that requires time64 redirection; replace if so. */ + snprintf(redir, sizeof redir, "__%.*s%s%s", (int)l, s, suffix, suffix2); + if (find_sym(&ldso, redir, 1).sym) s = redir; +no_redir: +#endif + return __dlsym(p, s, ra); +} + int dl_iterate_phdr(int(*callback)(struct dl_phdr_info *info, size_t size, void *data), void *data) { struct dso *current;