mailing list of musl libc
 help / color / mirror / code / Atom feed
* [musl] SIGSEGV with TEXTREL
@ 2020-09-25  3:50 Dominic Chen
  2020-09-25  9:37 ` Szabolcs Nagy
  0 siblings, 1 reply; 9+ messages in thread
From: Dominic Chen @ 2020-09-25  3:50 UTC (permalink / raw)
  To: musl

[-- Attachment #1: Type: text/plain, Size: 1124 bytes --]

Please CC me on replies.

I recently discovered that musl doesn't support DT/DF_TEXTREL in the
main executable, which can result in the dynamic loader crashing with
SIGSEGV and SEGV_ACCERR while processing relocations. I spent a few days
trying to fix this in the toolchain, but because it is a prototype based
on Clang/LLVM 4.0.0 that adds runtime instrumentation built using the
x64 large code model, so it's not easy to fix. Also, glibc does support
this behavior.

I ended up implementing support for this in musl itself (patch
attached), but given the discussion in the previous thread, "Static
linking is broken after creation of DT_TEXTREL," it seems like this
isn't acceptable due to overhead? I don't quite understand the concern,
because the loader needs to iterate again over the program headers only
if the program contains TEXTRELs, which is strictly an improvement, even
if the iteration itself is suboptimal. Alternatively, I'd suggest that
musl at least warns about unsupported TEXTRELs if present, because
asking application developers to debug a crashing ELF loader is quite a
high bar.

Thanks,

Dominic


[-- Attachment #2: musl-textrel.patch --]
[-- Type: text/plain, Size: 2064 bytes --]

diff --git a/ldso/dynlink.c b/ldso/dynlink.c
index d7726118..c7449df2 100644
--- a/ldso/dynlink.c
+++ b/ldso/dynlink.c
@@ -1326,10 +1326,32 @@ static void do_mips_relocs(struct dso *p, size_t *got)
 
 static void reloc_all(struct dso *p)
 {
+	unsigned char textrel = 0;
 	size_t dyn[DYN_CNT];
 	for (; p; p=p->next) {
 		if (p->relocated) continue;
 		decode_vec(p->dynv, dyn, DYN_CNT);
+
+		if ((dyn[0] & 1<<DT_TEXTREL) || (dyn[DT_FLAGS] & DF_TEXTREL)) {
+			size_t cnt = p->phnum;
+			Phdr *ph = p->phdr;
+			for (; cnt--; ph = (void *)((char *)ph + p->phentsize)) {
+				if (ph->p_type == PT_LOAD && !(ph->p_flags & PF_W)) {
+					unsigned prot = (((ph->p_flags&PF_R) ? PROT_READ : 0) |
+									((ph->p_flags&PF_X) ? PROT_EXEC : 0));
+					size_t start = ph->p_vaddr & -PAGE_SIZE,
+					       end = (ph->p_vaddr + ph->p_memsz + PAGE_SIZE-1) & -PAGE_SIZE;
+					if (mprotect(laddr(p, start), end - start, prot|PROT_WRITE)
+						&& errno != ENOSYS) {
+						error("Error relocating %s: TEXTREL unprotect failed: %m",
+						p->name);
+						if (runtime) longjmp(*rtld_fail, 1);
+					}
+					textrel = 1;
+				}
+			}
+		}
+
 		if (NEED_MIPS_GOT_RELOCS)
 			do_mips_relocs(p, laddr(p, dyn[DT_PLTGOT]));
 		do_relocs(p, laddr(p, dyn[DT_JMPREL]), dyn[DT_PLTRELSZ],
@@ -1345,6 +1367,25 @@ static void reloc_all(struct dso *p)
 			if (runtime) longjmp(*rtld_fail, 1);
 		}
 
+		if (textrel) {
+			size_t cnt = p->phnum;
+			Phdr *ph = p->phdr;
+			for (; cnt--; ph = (void *)((char *)ph + p->phentsize)) {
+				if (ph->p_type == PT_LOAD && !(ph->p_flags & PF_W)) {
+					unsigned prot = (((ph->p_flags&PF_R) ? PROT_READ : 0) |
+									((ph->p_flags&PF_X) ? PROT_EXEC : 0));
+					size_t start = ph->p_vaddr & -PAGE_SIZE,
+					       end = (ph->p_vaddr + ph->p_memsz + PAGE_SIZE-1) & -PAGE_SIZE;
+					if (mprotect(laddr(p, start), end - start, prot)
+						&& errno != ENOSYS) {
+						error("Error relocating %s: TEXTREL protect failed: %m",
+						p->name);
+						if (runtime) longjmp(*rtld_fail, 1);
+					}
+				}
+			}
+		}
+
 		p->relocated = 1;
 	}
 }

^ permalink raw reply	[flat|nested] 9+ messages in thread

end of thread, other threads:[~2020-09-26  9:10 UTC | newest]

Thread overview: 9+ messages (download: mbox.gz / follow: Atom feed)
-- links below jump to the message on this page --
2020-09-25  3:50 [musl] SIGSEGV with TEXTREL Dominic Chen
2020-09-25  9:37 ` Szabolcs Nagy
2020-09-25 18:58   ` Rich Felker
2020-09-25 20:13   ` Dominic Chen
2020-09-25 20:49     ` Markus Wichmann
2020-09-25 22:46     ` Rich Felker
2020-09-26  0:32       ` Dominic Chen
2020-09-26  4:14         ` Fangrui Song
2020-09-26  9:09           ` Szabolcs Nagy

Code repositories for project(s) associated with this public inbox

	https://git.vuxu.org/mirror/musl/

This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox;
as well as URLs for NNTP newsgroup(s).