summaryrefslogtreecommitdiff
path: root/ldso/dynlink.c
diff options
context:
space:
mode:
authorRich Felker <dalias@aerifal.cx>2026-05-05 20:34:14 -0400
committerRich Felker <dalias@aerifal.cx>2026-05-05 20:34:14 -0400
commit64f05291ff99ae407801ad7ab44cc4d7f6e0350f (patch)
tree8887f74e34b749a6df46da299e1a1700c1fd0e51 /ldso/dynlink.c
parentbb4b4102461acfbf77da759ca3a6deb555f3da3b (diff)
downloadmusl-64f05291ff99ae407801ad7ab44cc4d7f6e0350f.tar.gz
ldso: fix missing errno code when reporting relro mprotect failure
this code path potentially runs prior to stage 3, with thread-local storgae and thus errno unavailable. for this reason, commit 63c67053a3e42e9dff788de432f82ff07d4d772a removed the call to the mprotect function and replaced it with a __syscall operation that bypasses errno. however, this left the error message printing (which is only reachable in stage 3 and thus can safely access errno) with no error code for the %m format specifier to use. introduce a new set_errno function pointer that points to a no-op until stage 3. this is analogous to the error function pointer introduced in commit d16d7b10997e6f1c224c3de01b43868f0ce2cc3d.
Diffstat (limited to 'ldso/dynlink.c')
-rw-r--r--ldso/dynlink.c15
1 files changed, 15 insertions, 0 deletions
diff --git a/ldso/dynlink.c b/ldso/dynlink.c
index 715948f4..10471b23 100644
--- a/ldso/dynlink.c
+++ b/ldso/dynlink.c
@@ -41,6 +41,10 @@ static void error_impl(const char *, ...);
static void error_noop(const char *, ...);
static void (*error)(const char *, ...) = error_noop;
+static void set_errno_impl(int);
+static void set_errno_noop(int);
+static void (*set_errno)(int) = set_errno_noop;
+
#define MAXP2(a,b) (-(-(a)&-(b)))
#define ALIGN(x,y) ((x)+(y)-1 & -(y))
@@ -1424,6 +1428,7 @@ static void reloc_all(struct dso *p)
long ret = __syscall(SYS_mprotect, laddr(p, p->relro_start),
p->relro_end-p->relro_start, PROT_READ);
if (ret != 0 && ret != -ENOSYS) {
+ set_errno(-ret);
error("Error relocating %s: RELRO protection failed: %m",
p->name);
if (runtime) longjmp(*rtld_fail, 1);
@@ -1825,6 +1830,7 @@ void __dls3(size_t *sp, size_t *auxv)
/* Activate error handler function */
error = error_impl;
+ set_errno = set_errno_impl;
/* If the main program was already loaded by the kernel,
* AT_PHDR will point to some location other than the dynamic
@@ -2437,3 +2443,12 @@ static void error_impl(const char *fmt, ...)
static void error_noop(const char *fmt, ...)
{
}
+
+static void set_errno_impl(int e)
+{
+ errno = e;
+}
+
+static void set_errno_noop(int e)
+{
+}