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 4d9128da54
,
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@gmail.com>
Sponsored by: The FreeBSD Foundation
MFC after: 3 days
This commit is contained in:
parent
5e7cdf1817
commit
630caa95d4
@ -81,6 +81,10 @@ extern struct r_debug r_debug; /* For GDB */
|
|||||||
extern int _thread_autoinit_dummy_decl;
|
extern int _thread_autoinit_dummy_decl;
|
||||||
extern void (*__cleanup)(void);
|
extern void (*__cleanup)(void);
|
||||||
|
|
||||||
|
struct dlerror_save {
|
||||||
|
int seen;
|
||||||
|
char *msg;
|
||||||
|
};
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* Function declarations.
|
* 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 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 int do_search_info(const Obj_Entry *obj, int, struct dl_serinfo *);
|
||||||
static bool donelist_check(DoneList *, const Obj_Entry *);
|
static bool donelist_check(DoneList *, const Obj_Entry *);
|
||||||
static void errmsg_restore(char *);
|
static void errmsg_restore(struct dlerror_save *);
|
||||||
static char *errmsg_save(void);
|
static struct dlerror_save *errmsg_save(void);
|
||||||
static void *fill_search_info(const char *, size_t, void *);
|
static void *fill_search_info(const char *, size_t, void *);
|
||||||
static char *find_library(const char *, const Obj_Entry *, int *);
|
static char *find_library(const char *, const Obj_Entry *, int *);
|
||||||
static const char *gethints(bool);
|
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.
|
* Return a dynamically-allocated copy of the current error message, if any.
|
||||||
*/
|
*/
|
||||||
static char *
|
static struct dlerror_save *
|
||||||
errmsg_save(void)
|
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.
|
* by errmsg_save(). The copy is freed.
|
||||||
*/
|
*/
|
||||||
static void
|
static void
|
||||||
errmsg_restore(char *saved_msg)
|
errmsg_restore(struct dlerror_save *saved_msg)
|
||||||
{
|
{
|
||||||
if (saved_msg == NULL)
|
if (saved_msg == NULL || saved_msg->seen == 1) {
|
||||||
_rtld_error("");
|
*lockinfo.dlerror_seen() = 1;
|
||||||
else {
|
} else {
|
||||||
_rtld_error("%s", saved_msg);
|
*lockinfo.dlerror_seen() = 0;
|
||||||
free(saved_msg);
|
strlcpy(lockinfo.dlerror_loc(), saved_msg->msg,
|
||||||
|
lockinfo.dlerror_loc_sz);
|
||||||
|
free(saved_msg->msg);
|
||||||
}
|
}
|
||||||
|
free(saved_msg);
|
||||||
}
|
}
|
||||||
|
|
||||||
static const char *
|
static const char *
|
||||||
@ -2736,7 +2749,7 @@ static void
|
|||||||
objlist_call_fini(Objlist *list, Obj_Entry *root, RtldLockState *lockstate)
|
objlist_call_fini(Objlist *list, Obj_Entry *root, RtldLockState *lockstate)
|
||||||
{
|
{
|
||||||
Objlist_Entry *elm;
|
Objlist_Entry *elm;
|
||||||
char *saved_msg;
|
struct dlerror_save *saved_msg;
|
||||||
Elf_Addr *fini_addr;
|
Elf_Addr *fini_addr;
|
||||||
int index;
|
int index;
|
||||||
|
|
||||||
@ -2812,7 +2825,7 @@ objlist_call_init(Objlist *list, RtldLockState *lockstate)
|
|||||||
{
|
{
|
||||||
Objlist_Entry *elm;
|
Objlist_Entry *elm;
|
||||||
Obj_Entry *obj;
|
Obj_Entry *obj;
|
||||||
char *saved_msg;
|
struct dlerror_save *saved_msg;
|
||||||
Elf_Addr *init_addr;
|
Elf_Addr *init_addr;
|
||||||
void (*reg)(void (*)(void));
|
void (*reg)(void (*)(void));
|
||||||
int index;
|
int index;
|
||||||
|
Loading…
Reference in New Issue
Block a user