From owner-dev-commits-src-branches@freebsd.org Fri Apr 23 11:15:05 2021 Return-Path: Delivered-To: dev-commits-src-branches@mailman.nyi.freebsd.org Received: from mx1.freebsd.org (mx1.freebsd.org [IPv6:2610:1c1:1:606c::19:1]) by mailman.nyi.freebsd.org (Postfix) with ESMTP id 723B85EE150; Fri, 23 Apr 2021 11:15:05 +0000 (UTC) (envelope-from git@FreeBSD.org) Received: from mxrelay.nyi.freebsd.org (mxrelay.nyi.freebsd.org [IPv6:2610:1c1:1:606c::19:3]) (using TLSv1.3 with cipher TLS_AES_256_GCM_SHA384 (256/256 bits) key-exchange X25519 server-signature RSA-PSS (4096 bits) server-digest SHA256 client-signature RSA-PSS (4096 bits) client-digest SHA256) (Client CN "mxrelay.nyi.freebsd.org", Issuer "R3" (verified OK)) by mx1.freebsd.org (Postfix) with ESMTPS id 4FRWsh6jtsz4X7l; Fri, 23 Apr 2021 11:15:04 +0000 (UTC) (envelope-from git@FreeBSD.org) Received: from gitrepo.freebsd.org (gitrepo.freebsd.org [IPv6:2610:1c1:1:6068::e6a:5]) (using TLSv1.3 with cipher TLS_AES_256_GCM_SHA384 (256/256 bits) key-exchange X25519 server-signature RSA-PSS (4096 bits) server-digest SHA256) (Client did not present a certificate) by mxrelay.nyi.freebsd.org (Postfix) with ESMTPS id 92D75450D; Fri, 23 Apr 2021 11:15:04 +0000 (UTC) (envelope-from git@FreeBSD.org) Received: from gitrepo.freebsd.org ([127.0.1.44]) by gitrepo.freebsd.org (8.16.1/8.16.1) with ESMTP id 13NBF42D013173; Fri, 23 Apr 2021 11:15:04 GMT (envelope-from git@gitrepo.freebsd.org) Received: (from git@localhost) by gitrepo.freebsd.org (8.16.1/8.16.1/Submit) id 13NBF4K4013172; Fri, 23 Apr 2021 11:15:04 GMT (envelope-from git) Date: Fri, 23 Apr 2021 11:15:04 GMT Message-Id: <202104231115.13NBF4K4013172@gitrepo.freebsd.org> To: src-committers@FreeBSD.org, dev-commits-src-all@FreeBSD.org, dev-commits-src-branches@FreeBSD.org From: Konstantin Belousov Subject: git: 7bbfb5d95932 - stable/13 - rtld: make dlerror() thread-local MIME-Version: 1.0 Content-Type: text/plain; charset=utf-8 Content-Transfer-Encoding: 8bit X-Git-Committer: kib X-Git-Repository: src X-Git-Refname: refs/heads/stable/13 X-Git-Reftype: branch X-Git-Commit: 7bbfb5d959329fe0c322c0b59c9268b75ddddace Auto-Submitted: auto-generated X-BeenThere: dev-commits-src-branches@freebsd.org X-Mailman-Version: 2.1.34 Precedence: list List-Id: Commits to the stable branches of the FreeBSD src repository List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , X-List-Received-Date: Fri, 23 Apr 2021 11:15:05 -0000 The branch stable/13 has been updated by kib: URL: https://cgit.FreeBSD.org/src/commit/?id=7bbfb5d959329fe0c322c0b59c9268b75ddddace commit 7bbfb5d959329fe0c322c0b59c9268b75ddddace Author: Konstantin Belousov AuthorDate: 2021-04-07 22:02:33 +0000 Commit: Konstantin Belousov CommitDate: 2021-04-23 11:14:08 +0000 rtld: make dlerror() thread-local (cherry picked from commit 4d9128da54f8f8e2a29190ffb18880c4f116a205) --- lib/libthr/thread/thr_private.h | 4 ++++ lib/libthr/thread/thr_rtld.c | 21 +++++++++++++++++++++ libexec/rtld-elf/rtld.c | 38 ++++++++++++++++++++------------------ libexec/rtld-elf/rtld_lock.c | 33 +++++++++++++++++++++++++++++++++ libexec/rtld-elf/rtld_lock.h | 7 ++++++- 5 files changed, 84 insertions(+), 19 deletions(-) diff --git a/lib/libthr/thread/thr_private.h b/lib/libthr/thread/thr_private.h index a1258940a896..a5bbc5997d30 100644 --- a/lib/libthr/thread/thr_private.h +++ b/lib/libthr/thread/thr_private.h @@ -577,6 +577,10 @@ struct pthread { /* pthread_set/get_name_np */ char *name; + + /* rtld thread-local dlerror message and seen control */ + char dlerror_msg[512]; + int dlerror_seen; }; #define THR_SHOULD_GC(thrd) \ diff --git a/lib/libthr/thread/thr_rtld.c b/lib/libthr/thread/thr_rtld.c index 5848fc6d5f61..1967ea14859d 100644 --- a/lib/libthr/thread/thr_rtld.c +++ b/lib/libthr/thread/thr_rtld.c @@ -189,6 +189,24 @@ _thr_rtld_clr_flag(int mask __unused) extern char _pli_rtli_version; char _pli_rtli_version; +static char * +_thr_dlerror_loc(void) +{ + struct pthread *curthread; + + curthread = _get_curthread(); + return (curthread->dlerror_msg); +} + +static int * +_thr_dlerror_seen(void) +{ + struct pthread *curthread; + + curthread = _get_curthread(); + return (&curthread->dlerror_seen); +} + void _thr_rtld_init(void) { @@ -221,6 +239,9 @@ _thr_rtld_init(void) li.thread_set_flag = _thr_rtld_set_flag; li.thread_clr_flag = _thr_rtld_clr_flag; li.at_fork = NULL; + li.dlerror_loc = _thr_dlerror_loc; + li.dlerror_loc_sz = sizeof(curthread->dlerror_msg); + li.dlerror_seen = _thr_dlerror_seen; /* * Preresolve the symbols needed for the fork interposer. We diff --git a/libexec/rtld-elf/rtld.c b/libexec/rtld-elf/rtld.c index 5e99b8db8ff7..d50774868908 100644 --- a/libexec/rtld-elf/rtld.c +++ b/libexec/rtld-elf/rtld.c @@ -195,7 +195,6 @@ int __sys_openat(int, const char *, int, ...); /* * Data declarations. */ -static char *error_message; /* Message for dlerror(), or NULL */ struct r_debug r_debug __exported; /* for GDB; */ static bool libmap_disable; /* Disable libmap */ static bool ld_loadfltr; /* Immediate filters processing */ @@ -441,6 +440,8 @@ _rtld(Elf_Addr *sp, func_ptr_type *exit_proc, Obj_Entry **objp) assert(aux_info[AT_BASE] != NULL); init_rtld((caddr_t) aux_info[AT_BASE]->a_un.a_ptr, aux_info); + dlerror_dflt_init(); + __progname = obj_rtld.path; argv0 = argv[0] != NULL ? argv[0] : "(null)"; environ = env; @@ -919,14 +920,14 @@ _rtld_bind(Obj_Entry *obj, Elf_Size reloff) void _rtld_error(const char *fmt, ...) { - static char buf[512]; - va_list ap; + va_list ap; - va_start(ap, fmt); - rtld_vsnprintf(buf, sizeof buf, fmt, ap); - error_message = buf; - va_end(ap); - LD_UTRACE(UTRACE_RTLD_ERROR, NULL, NULL, 0, 0, error_message); + va_start(ap, fmt); + rtld_vsnprintf(lockinfo.dlerror_loc(), lockinfo.dlerror_loc_sz, + fmt, ap); + va_end(ap); + *lockinfo.dlerror_seen() = 0; + LD_UTRACE(UTRACE_RTLD_ERROR, NULL, NULL, 0, 0, lockinfo.dlerror_loc()); } /* @@ -935,7 +936,7 @@ _rtld_error(const char *fmt, ...) static char * errmsg_save(void) { - return error_message == NULL ? NULL : xstrdup(error_message); + return (xstrdup(lockinfo.dlerror_loc())); } /* @@ -945,12 +946,12 @@ errmsg_save(void) static void errmsg_restore(char *saved_msg) { - if (saved_msg == NULL) - error_message = NULL; - else { - _rtld_error("%s", saved_msg); - free(saved_msg); - } + if (saved_msg == NULL) + _rtld_error(""); + else { + _rtld_error("%s", saved_msg); + free(saved_msg); + } } static const char * @@ -3369,9 +3370,10 @@ dlclose_locked(void *handle, RtldLockState *lockstate) char * dlerror(void) { - char *msg = error_message; - error_message = NULL; - return msg; + if (*(lockinfo.dlerror_seen()) != 0) + return (NULL); + *lockinfo.dlerror_seen() = 1; + return (lockinfo.dlerror_loc()); } /* diff --git a/libexec/rtld-elf/rtld_lock.c b/libexec/rtld-elf/rtld_lock.c index 4d54c687ee6f..94e931c2f760 100644 --- a/libexec/rtld-elf/rtld_lock.c +++ b/libexec/rtld-elf/rtld_lock.c @@ -59,6 +59,21 @@ void _rtld_thread_init(struct RtldLockInfo *) __exported; void _rtld_atfork_pre(int *) __exported; void _rtld_atfork_post(int *) __exported; +static char def_dlerror_msg[512]; +static int def_dlerror_seen_val; + +static char * +def_dlerror_loc(void) +{ + return (def_dlerror_msg); +} + +static int * +def_dlerror_seen(void) +{ + return (&def_dlerror_seen_val); +} + #define WAFLAG 0x1 /* A writer holds the lock */ #define RC_INCR 0x2 /* Adjusts count of readers desiring lock */ @@ -299,6 +314,14 @@ lock_restart_for_upgrade(RtldLockState *lockstate) } } +void +dlerror_dflt_init(void) +{ + lockinfo.dlerror_loc = def_dlerror_loc; + lockinfo.dlerror_loc_sz = sizeof(def_dlerror_msg); + lockinfo.dlerror_seen = def_dlerror_seen; +} + void lockdflt_init(void) { @@ -313,6 +336,9 @@ lockdflt_init(void) deflockinfo.thread_set_flag = def_thread_set_flag; deflockinfo.thread_clr_flag = def_thread_clr_flag; deflockinfo.at_fork = NULL; + deflockinfo.dlerror_loc = def_dlerror_loc; + deflockinfo.dlerror_loc_sz = sizeof(def_dlerror_msg); + deflockinfo.dlerror_seen = def_dlerror_seen; for (i = 0; i < RTLD_LOCK_CNT; i++) { rtld_locks[i].mask = (1 << i); @@ -404,6 +430,13 @@ _rtld_thread_init(struct RtldLockInfo *pli) lockinfo.thread_set_flag = pli->thread_set_flag; lockinfo.thread_clr_flag = pli->thread_clr_flag; lockinfo.at_fork = pli->at_fork; + if (lockinfo.rtli_version > RTLI_VERSION_ONE && pli != NULL) { + strlcpy(pli->dlerror_loc(), lockinfo.dlerror_loc(), + lockinfo.dlerror_loc_sz); + lockinfo.dlerror_loc = pli->dlerror_loc; + lockinfo.dlerror_loc_sz = pli->dlerror_loc_sz; + lockinfo.dlerror_seen = pli->dlerror_seen; + } /* restore thread locking state, this time with new locks */ thread_mask_clear(~0); diff --git a/libexec/rtld-elf/rtld_lock.h b/libexec/rtld-elf/rtld_lock.h index 7a61a1a525e2..fdbdc9917075 100644 --- a/libexec/rtld-elf/rtld_lock.h +++ b/libexec/rtld-elf/rtld_lock.h @@ -31,7 +31,7 @@ #define _RTLD_LOCK_H_ #define RTLI_VERSION_ONE 0x01 -#define RTLI_VERSION 0x01 +#define RTLI_VERSION 0x02 #define MAX_RTLD_LOCKS 8 @@ -46,6 +46,9 @@ struct RtldLockInfo int (*thread_set_flag)(int); int (*thread_clr_flag)(int); void (*at_fork)(void); + char *(*dlerror_loc)(void); + int *(*dlerror_seen)(void); + int dlerror_loc_sz; }; #if defined(IN_RTLD) || defined(PTHREAD_KERNEL) @@ -80,6 +83,8 @@ void lock_release(rtld_lock_t, RtldLockState *); void lock_upgrade(rtld_lock_t, RtldLockState *); void lock_restart_for_upgrade(RtldLockState *); +void dlerror_dflt_init(void); + #endif /* IN_RTLD */ #endif