git: 630caa95d461 - main - rtld: preserve the 'seen' state of the dlerror message in errmsg_save()

Konstantin Belousov kib at FreeBSD.org
Mon May 10 23:48:29 UTC 2021


The branch main has been updated by kib:

URL: https://cgit.FreeBSD.org/src/commit/?id=630caa95d46191220dd457c2ae2d06460cb4f71b

commit 630caa95d46191220dd457c2ae2d06460cb4f71b
Author:     Konstantin Belousov <kib at FreeBSD.org>
AuthorDate: 2021-05-10 19:02:19 +0000
Commit:     Konstantin Belousov <kib at FreeBSD.org>
CommitDate: 2021-05-10 23:47:00 +0000

    rtld: preserve the 'seen' state of the dlerror message in errmsg_save()
    
    rtld preserves its current error message around calls to user init/fini
    lists, to not override original error with potential secondary errors
    caused by user code recursing into rtld.  After 4d9128da54f8f8e2a29190,
    the preservation of the string itself is not enough, the 'seen'
    indicator must be preserved as well.  Otherwise, since new code does not
    clear string (it cannot), call to _rtld_error() from errmsg_restore()
    revived whatever message was consumed last.
    
    Change errmsg_save() to return structure recording both 'seen' indicator
    and the message, if any.
    
    PR:     255698
    Reported by:    Eugene M. Kim <astralblue at gmail.com>
    Sponsored by:   The FreeBSD Foundation
    MFC after:      3 days
---
 libexec/rtld-elf/rtld.c | 37 +++++++++++++++++++++++++------------
 1 file changed, 25 insertions(+), 12 deletions(-)

diff --git a/libexec/rtld-elf/rtld.c b/libexec/rtld-elf/rtld.c
index fce455a0ee79..75c502e8cc85 100644
--- a/libexec/rtld-elf/rtld.c
+++ b/libexec/rtld-elf/rtld.c
@@ -81,6 +81,10 @@ extern struct r_debug r_debug; /* For GDB */
 extern int _thread_autoinit_dummy_decl;
 extern void (*__cleanup)(void);
 
+struct dlerror_save {
+	int seen;
+	char *msg;
+};
 
 /*
  * Function declarations.
@@ -100,8 +104,8 @@ static Obj_Entry *dlopen_object(const char *name, int fd, Obj_Entry *refobj,
 static Obj_Entry *do_load_object(int, const char *, char *, struct stat *, int);
 static int do_search_info(const Obj_Entry *obj, int, struct dl_serinfo *);
 static bool donelist_check(DoneList *, const Obj_Entry *);
-static void errmsg_restore(char *);
-static char *errmsg_save(void);
+static void errmsg_restore(struct dlerror_save *);
+static struct dlerror_save *errmsg_save(void);
 static void *fill_search_info(const char *, size_t, void *);
 static char *find_library(const char *, const Obj_Entry *, int *);
 static const char *gethints(bool);
@@ -941,10 +945,16 @@ _rtld_error(const char *fmt, ...)
 /*
  * Return a dynamically-allocated copy of the current error message, if any.
  */
-static char *
+static struct dlerror_save *
 errmsg_save(void)
 {
-	return (xstrdup(lockinfo.dlerror_loc()));
+	struct dlerror_save *res;
+
+	res = xmalloc(sizeof(*res));
+	res->seen = *lockinfo.dlerror_seen();
+	if (res->seen == 0)
+		res->msg = xstrdup(lockinfo.dlerror_loc());
+	return (res);
 }
 
 /*
@@ -952,14 +962,17 @@ errmsg_save(void)
  * by errmsg_save().  The copy is freed.
  */
 static void
-errmsg_restore(char *saved_msg)
+errmsg_restore(struct dlerror_save *saved_msg)
 {
-	if (saved_msg == NULL)
-		_rtld_error("");
-	else {
-		_rtld_error("%s", saved_msg);
-		free(saved_msg);
+	if (saved_msg == NULL || saved_msg->seen == 1) {
+		*lockinfo.dlerror_seen() = 1;
+	} else {
+		*lockinfo.dlerror_seen() = 0;
+		strlcpy(lockinfo.dlerror_loc(), saved_msg->msg,
+		    lockinfo.dlerror_loc_sz);
+		free(saved_msg->msg);
 	}
+	free(saved_msg);
 }
 
 static const char *
@@ -2736,7 +2749,7 @@ static void
 objlist_call_fini(Objlist *list, Obj_Entry *root, RtldLockState *lockstate)
 {
     Objlist_Entry *elm;
-    char *saved_msg;
+    struct dlerror_save *saved_msg;
     Elf_Addr *fini_addr;
     int index;
 
@@ -2812,7 +2825,7 @@ objlist_call_init(Objlist *list, RtldLockState *lockstate)
 {
     Objlist_Entry *elm;
     Obj_Entry *obj;
-    char *saved_msg;
+    struct dlerror_save *saved_msg;
     Elf_Addr *init_addr;
     void (*reg)(void (*)(void));
     int index;


More information about the dev-commits-src-all mailing list