From 08bfbd43594b7642de0d2487550f36b0ee1eceba Mon Sep 17 00:00:00 2001 From: Konstantin Belousov Date: Sat, 10 Apr 2021 15:32:24 +0300 Subject: [PATCH] rtld: workaround for broken ABI Right now, libthr does not initialize RtldLockInfo.rtli_version when calling _rtld_thread_init(), which makes versioning the interface troublesome. Add a workaround: if the calling object of _rtld_thread_init() exports the "_pli_rtli_version" symbol, then consider rtli_version initialized. Otherwise, forcibly set it to RTLI_VERSION_ONE, currently defined as RTLI_VERSION. Export "_pli_rtli_version" from libthr and properly initialize rtli_version. Sponsored by: The FreeBSD Foundation MFC after: 1 week Differential revision: https://reviews.freebsd.org/D29633 --- lib/libthr/pthread.map | 3 +++ lib/libthr/thread/thr_rtld.c | 8 ++++++++ libexec/rtld-elf/rtld_lock.c | 17 ++++++++++++++++- libexec/rtld-elf/rtld_lock.h | 4 +++- 4 files changed, 30 insertions(+), 2 deletions(-) diff --git a/lib/libthr/pthread.map b/lib/libthr/pthread.map index 232d65084ba9..15195ce0847b 100644 --- a/lib/libthr/pthread.map +++ b/lib/libthr/pthread.map @@ -296,6 +296,9 @@ FBSDprivate_1.0 { _thread_size_key; _thread_state_running; _thread_state_zoombie; + + /* ABI bug workaround, indicate that pli->rtli_version is valid */ + _pli_rtli_version; }; FBSD_1.1 { diff --git a/lib/libthr/thread/thr_rtld.c b/lib/libthr/thread/thr_rtld.c index 291ca17e2068..5848fc6d5f61 100644 --- a/lib/libthr/thread/thr_rtld.c +++ b/lib/libthr/thread/thr_rtld.c @@ -182,6 +182,13 @@ _thr_rtld_clr_flag(int mask __unused) return (0); } +/* + * ABI bug workaround: This symbol must be present for rtld to accept + * RTLI_VERSION from RtldLockInfo + */ +extern char _pli_rtli_version; +char _pli_rtli_version; + void _thr_rtld_init(void) { @@ -205,6 +212,7 @@ _thr_rtld_init(void) mprotect(NULL, 0, 0); _rtld_get_stack_prot(); + li.rtli_version = RTLI_VERSION; li.lock_create = _thr_rtld_lock_create; li.lock_destroy = _thr_rtld_lock_destroy; li.rlock_acquire = _thr_rtld_rlock_acquire; diff --git a/libexec/rtld-elf/rtld_lock.c b/libexec/rtld-elf/rtld_lock.c index d94bd1a283e9..4d54c687ee6f 100644 --- a/libexec/rtld-elf/rtld_lock.c +++ b/libexec/rtld-elf/rtld_lock.c @@ -344,8 +344,23 @@ lockdflt_init(void) void _rtld_thread_init(struct RtldLockInfo *pli) { - int flags, i; + const Obj_Entry *obj; + SymLook req; void *locks[RTLD_LOCK_CNT]; + int flags, i, res; + + if (pli == NULL) { + lockinfo.rtli_version = RTLI_VERSION; + } else { + lockinfo.rtli_version = RTLI_VERSION_ONE; + obj = obj_from_addr(pli->lock_create); + if (obj != NULL) { + symlook_init(&req, "_pli_rtli_version"); + res = symlook_obj(&req, obj); + if (res == 0) + lockinfo.rtli_version = pli->rtli_version; + } + } /* disable all locking while this function is running */ flags = thread_mask_set(~0); diff --git a/libexec/rtld-elf/rtld_lock.h b/libexec/rtld-elf/rtld_lock.h index ecc733a06e44..7a61a1a525e2 100644 --- a/libexec/rtld-elf/rtld_lock.h +++ b/libexec/rtld-elf/rtld_lock.h @@ -30,7 +30,9 @@ #ifndef _RTLD_LOCK_H_ #define _RTLD_LOCK_H_ -#define RTLI_VERSION 0x01 +#define RTLI_VERSION_ONE 0x01 +#define RTLI_VERSION 0x01 + #define MAX_RTLD_LOCKS 8 struct RtldLockInfo