From 64f05291ff99ae407801ad7ab44cc4d7f6e0350f Mon Sep 17 00:00:00 2001 From: Rich Felker Date: Tue, 5 May 2026 20:34:14 -0400 Subject: 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. --- ldso/dynlink.c | 15 +++++++++++++++ 1 file changed, 15 insertions(+) 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) +{ +} -- cgit v1.2.1