[uClibc] Re: ET_DYN patches made optional

Peter S. Mazinger ps.m at gmx.net
Fri Nov 21 15:44:28 UTC 2003


On Fri, 21 Nov 2003 pageexec at freemail.hu wrote:

New files according to the PaX Team's proposals
> > > > I have removed the crt0S.S file completely and integrated it into the 
> > > > main crt0.S.
> > > > It would ease porting to other archs.
> > > 
> > > Sorry for missing patch, here it comes.
> > I have added SCRT_FLAGS = -fPIC to be sure that it will be built as PIC.
> > Erik, if we can be sure that everywhere -fPIC (or -fpic) is used, then it 
> > can be removed.
Erik, this issue remains

> 
> the patch looks ok to me, you may want to simplify it a tiny bit
> by changing
> 
> #if (defined L_crt0 || defined L_Scrt0 ) || ! defined __UCLIBC_CTOR_DTOR__
> 
> to
> 
> #if defined L_crt0 || defined L_Scrt0 || ! defined __UCLIBC_CTOR_DTOR__
> 
> (there's no need for () )
done
> 
> on another note about your earlier patch with UCLIBC_PAX_LOADER: you
> should probably call it UCLIBC_PIE_SUPPORT or something like that as
> that's its real purpose, it's not specific to PaX. in fact, i would
> not make it an option at all, it should be standard as it is more like
> a bugfix than a feature (like it is in glibc/ld.so).
I have left the option in, it's the developers' decision, if they accept 
the ld.so part without ifdefs.

> 
> as for its dependency on FORCE_SHAREABLE_TEXT_SEGMENTS: i think
> you should turn UCLIBC_PAX_LOADER into merely enabling this option
> as well so that PaX users will know its for them, and leave the
> actual code changes in by default as suggested above.
changed.

The COMPLETELY_PIC requirement from FORCE_SHAREABLE_TEXT_SEGMENTS has to 
be removed (patch sent earlier), it's unused in the sources.

Thanks, Peter

-- 
Peter S. Mazinger <ps.m at gmx.net>   ID: 0xA5F059F2    NIC: IXUYHSKQLI
Key fingerprint = 92A4 31E1 56BC 3D5A 2D08  BB6E C389 975E A5F0 59F2

____________________________________________________________________
Miert fizetsz az internetert? Korlatlan, ingyenes internet hozzaferes a FreeStarttol.
Probald ki most! http://www.freestart.hu
-------------- next part --------------
--- uClibc-0.9.23/libc/sysdeps/linux/i386/crt0.S.mps	2003-11-21 10:51:56.000000000 +0100
+++ uClibc-0.9.23/libc/sysdeps/linux/i386/crt0.S	2003-11-21 11:13:02.000000000 +0100
@@ -18,6 +18,7 @@
 
 
 /*  Based on the code from GNU libc, but hacked up by John Beppu and Erik Andersen */
+/*  adapted by PaX Team for ET_DYN/PIE binaries */
 
 /*
     When we enter this piece of code, the program stack looks like this:
@@ -37,7 +38,7 @@
 
 	.global	_start
 	.type	_start,%function
-#if defined L_crt0 || ! defined __UCLIBC_CTOR_DTOR__
+#if defined L_crt0 || defined L_Scrt0 || ! defined __UCLIBC_CTOR_DTOR__
 	.type	__uClibc_main,%function
 #else
 	.weak	_init
@@ -74,10 +75,22 @@
 	pushl %ebp      /* callers %ebp (frame pointer) */
 	movl %esp,%ebp  /* mark callers stack frame as invalid */
 
-#if (defined L_crt1 || defined L_gcrt1 ) && defined __UCLIBC_CTOR_DTOR__
+#if defined L_Scrt0 || defined L_Scrt1
+	call .L0
+.L0:
+	pop %edx
+	addl $_GLOBAL_OFFSET_TABLE_+[.-.L0],%edx
+#endif
+
+#if ((defined L_crt1 || defined L_Scrt1 ) || defined L_gcrt1 ) && defined __UCLIBC_CTOR_DTOR__
 	/* Push .init and .fini arguments to __uClibc_start_main() on the stack */
+#ifdef L_Scrt1
+	pushl _fini at GOT(%edx)
+	pushl _init at GOT(%edx)
+#else
 	pushl $_fini
 	pushl $_init
+#endif
 
 	/* Push envp, argc, and argc arguments to __uClibc_start_main() on the stack */ 
 	pushl %eax	/* Environment pointer */
@@ -85,15 +98,23 @@
 	pushl %ecx	/* And the argument count */
 
 	/* Ok, now run uClibc's main() -- shouldn't return */
+#ifdef L_Scrt1
+	call *__uClibc_start_main at GOT(%edx)
+#else
 	call __uClibc_start_main
+#endif
 #else
 	/* Push envp, argc, and argc arguments to __uClibc_start_main() on the stack */ 
 	pushl %eax	/* Environment pointer */
 	pushl %ebx	/* Argument pointer */
 	pushl %ecx	/* And the argument count */
 
+#ifdef L_Scrt0
+	call *__uClibc_main at GOT(%edx)
+#else
 	call __uClibc_main
 #endif
+#endif
 
 	/* Crash if somehow `exit' returns anyways.  */
 	hlt
--- uClibc-0.9.23/libc/sysdeps/linux/i386/Makefile.mps	2003-11-21 11:21:04.000000000 +0100
+++ uClibc-0.9.23/libc/sysdeps/linux/i386/Makefile	2003-11-21 11:26:56.000000000 +0100
@@ -22,6 +22,10 @@
 
 CRT0_SRC = crt0.S
 CRT0_OBJ = crt0.o crt1.o gcrt1.o
+ifeq ($(strip $(UCLIBC_PIE_SUPPORT)),y)
+CRT0_OBJ += Scrt0.o Scrt1.o
+SCRT_FLAGS = -fPIC
+endif
 CRT0_DEPS=gmon-start.S
 CTOR_TARGETS=$(TOPDIR)lib/crti.o $(TOPDIR)lib/crtn.o
 
@@ -52,9 +56,16 @@
 ar-target: $(OBJS) $(CRT0_OBJ) $(CTOR_TARGETS)
 	$(AR) $(ARFLAGS) $(LIBC) $(OBJS)
 	cp $(CRT0_OBJ) $(TOPDIR)lib/
+ifeq ($(strip $(UCLIBC_PIE_SUPPORT)),y)
+ifeq ($(strip $(UCLIBC_CTOR_DTOR)),y)
+	$(RM) $(TOPDIR)lib/Scrt0.o
+else
+	mv $(TOPDIR)lib/Scrt0.o $(TOPDIR)lib/Scrt1.o
+endif
+endif
 
 $(CRT0_OBJ): $(CRT0_SRC)
-	$(CC) $(CFLAGS) -DL_$* $< -c -o $*.o
+	$(CC) $(CFLAGS) $(SCRT_FLAGS) -DL_$* $< -c -o $*.o
 	$(STRIPTOOL) -x -R .note -R .comment $*.o
 
 $(SOBJS): %.o : %.S
-------------- next part --------------
--- uClibc-0.9.23/extra/Configs/Config.in.pax	Wed Nov 19 14:59:04 2003
+++ uClibc-0.9.23/extra/Configs/Config.in	Wed Nov 19 15:26:01 2003
@@ -177,6 +177,20 @@
 	  little bit smaller and guarantee that no memory will be wasted by badly
 	  coded shared libraries.
 
+config UCLIBC_PIE_SUPPORT
+	bool "Support ET_DYN in shared library loader"
+	select FORCE_SHAREABLE_TEXT_SEGMENTS
+	default n
+	help
+	  If you answer Y here, the uClibc native shared library loader will
+	  support ET_DYN/PIE executables.
+	  It requires binutils-2.14.90.0.6 or later and the usage of the
+	  -pie option.
+	  More about ET_DYN/PIE binaries on <http://pageexec.virtualave.net/> .
+	  WARNING: This option also enables FORCE_SHAREABLE_TEXT_SEGMENTS, so all
+		libraries have to be built with -fPIC or -fpic, and all assembler
+		functions must be written as position independent code (PIC).
+
 config LDSO_LDD_SUPPORT
 	bool "Native shared library loader 'ldd' support"
 	depends on BUILD_UCLIBC_LDSO
--- uClibc-0.9.23/ldso/ldso/ldso.c.pax	Sat Oct  4 19:31:22 2003
+++ uClibc-0.9.23/ldso/ldso/ldso.c	Wed Nov 19 14:58:39 2003
@@ -371,6 +371,28 @@
 	app_tpnt = LD_MALLOC(sizeof(struct elf_resolve));
 	_dl_memset(app_tpnt, 0, sizeof(struct elf_resolve));
 
+#ifdef __UCLIBC_PIE_SUPPORT__
+	/* Find the runtime load address of the main executable, this may be
+         * different from what the ELF header says for ET_DYN/PIE executables.
+	 */
+	{
+		ElfW(Phdr) *ppnt;
+		int i;
+
+		ppnt = (ElfW(Phdr) *) auxvt[AT_PHDR].a_un.a_ptr;
+		for (i = 0; i < auxvt[AT_PHNUM].a_un.a_val; i++, ppnt++)
+			if (ppnt->p_type == PT_PHDR) {
+				app_tpnt->loadaddr = (ElfW(Addr)) (auxvt[AT_PHDR].a_un.a_val - ppnt->p_vaddr);
+				break;
+			}
+	}
+
+#ifdef __SUPPORT_LD_DEBUG_EARLY__
+	SEND_STDERR("app_tpnt->loadaddr=");
+	SEND_ADDRESS_STDERR(app_tpnt->loadaddr, 1);
+#endif
+#endif
+
 	/*
 	 * This is used by gdb to locate the chain of shared libraries that are currently loaded.
 	 */
@@ -407,7 +429,11 @@
 		ppnt = (ElfW(Phdr) *) auxvt[AT_PHDR].a_un.a_ptr;
 		for (i = 0; i < auxvt[AT_PHNUM].a_un.a_val; i++, ppnt++)
 			if (ppnt->p_type == PT_DYNAMIC) {
+#ifndef __UCLIBC_PIE_SUPPORT__
 				dpnt = (Elf32_Dyn *) ppnt->p_vaddr;
+#else
+				dpnt = (Elf32_Dyn *) (ppnt->p_vaddr + app_tpnt->loadaddr);
+#endif
 				while (dpnt->d_tag) {
 #if defined(__mips__)
 					if (dpnt->d_tag == DT_MIPS_GOTSYM)
@@ -501,8 +527,13 @@
 			ppnt = (ElfW(Phdr) *) auxvt[AT_PHDR].a_un.a_ptr;
 			for (i = 0; i < auxvt[AT_PHNUM].a_un.a_val; i++, ppnt++) {
 				if (ppnt->p_type == PT_LOAD && !(ppnt->p_flags & PF_W))
+#ifndef __UCLIBC_PIE_SUPPORT__
 					_dl_mprotect((void *) (ppnt->p_vaddr & PAGE_ALIGN),
 								 (ppnt->p_vaddr & ADDR_ALIGN) +
+#else
+					_dl_mprotect((void *) ((ppnt->p_vaddr + app_tpnt->loadaddr) & PAGE_ALIGN),
+								 ((ppnt->p_vaddr + app_tpnt->loadaddr) & ADDR_ALIGN) +
+#endif
 								 (unsigned long) ppnt->p_filesz,
 								 PROT_READ | PROT_WRITE | PROT_EXEC);
 			}
@@ -715,8 +746,13 @@
 	ppnt = (ElfW(Phdr) *) auxvt[AT_PHDR].a_un.a_ptr;
 	for (i = 0; i < auxvt[AT_PHNUM].a_un.a_val; i++, ppnt++) {
 		if (ppnt->p_type == PT_LOAD) {
+#ifndef __UCLIBC_PIE_SUPPORT__
 			if (ppnt->p_vaddr + ppnt->p_memsz > brk_addr)
 				brk_addr = ppnt->p_vaddr + ppnt->p_memsz;
+#else
+			if (ppnt->p_vaddr + app_tpnt->loadaddr + ppnt->p_memsz > brk_addr)
+				brk_addr = ppnt->p_vaddr + app_tpnt->loadaddr + ppnt->p_memsz;
+#endif
 		}
 		if (ppnt->p_type == PT_DYNAMIC) {
 #ifndef ALLOW_ZERO_PLTGOT
@@ -725,8 +761,13 @@
 				continue;
 #endif
 			/* OK, we have what we need - slip this one into the list. */
+#ifndef __UCLIBC_PIE_SUPPORT__
 			app_tpnt = _dl_add_elf_hash_table("", 0, 
 					app_tpnt->dynamic_info, ppnt->p_vaddr, ppnt->p_filesz);
+#else
+			app_tpnt = _dl_add_elf_hash_table("", (char *)app_tpnt->loadaddr,
+					app_tpnt->dynamic_info, ppnt->p_vaddr + app_tpnt->loadaddr, ppnt->p_filesz);
+#endif
 			_dl_loaded_modules->libtype = elf_executable;
 			_dl_loaded_modules->ppnt = (ElfW(Phdr) *) auxvt[AT_PHDR].a_un.a_ptr;
 			_dl_loaded_modules->n_phent = auxvt[AT_PHNUM].a_un.a_val;
@@ -735,7 +776,11 @@
 			rpnt->dyn = _dl_loaded_modules;
 			app_tpnt->usage_count++;
 			app_tpnt->symbol_scope = _dl_symbol_tables;
+#ifndef __UCLIBC_PIE_SUPPORT__
 			lpnt = (unsigned long *) (app_tpnt->dynamic_info[DT_PLTGOT]);
+#else
+			lpnt = (unsigned long *) (app_tpnt->dynamic_info[DT_PLTGOT] + app_tpnt->loadaddr);
+#endif
 #ifdef ALLOW_ZERO_PLTGOT
 			if (lpnt)
 #endif


More information about the uClibc mailing list