Follow @Openwall on Twitter for new release announcements and other news
[<prev] [next>] [<thread-prev] [thread-next>] [day] [month] [year] [list]
Date: Sun, 5 Apr 2015 18:55:33 -0400
From: Rich Felker <dalias@...c.org>
To: musl@...ts.openwall.com
Subject: Re: Dynamic linker changes

On Sun, Apr 05, 2015 at 06:30:31PM -0400, Rich Felker wrote:
> As part of the dynamic linker overhaul project for ssp-enabled
> libc.so, I'd like to make some somewhat unrelated changes to the
> dynamic linker. Some aspects of these are just general improvements,
> but most of them eliminate implementation snags I'm forseeing in the
> early-relocation code. Anyway, here they are:
> 
> 
> Revisiting how we find load base address:
> [...]
> Revisiting how ld.so skips argv entries:
> [...]
> Stripping down entry point asm further:
> [...]

Here's the draft code for what runs before libc.so/ldso itself is
relocated:

void *__dlstart_c(uintptr_t sp, uintptr_t dynamic)
{
	size_t i, aux[AUX_CNT] = {0}, dyn[DYN_CNT] = {0};
	struct dso *self = {0};

	int argc = *(size_t *)sp;
	char **argv = (void *)(sp + sizeof(size_t));

	for (i=argc+1; argv[i]; i++);
	size_t *auxv = (void *)(argv+i+1);

	decode_vec(auxv, aux, AUX_CNT);

	if (!aux[AT_BASE]) {
		size_t phnum = aux[AT_PHNUM];
		size_t phentsize = aux[AT_PHENT];
		Phdr *ph = (void *)aux[AT_PHDR];
		for (i=phnum; i--; ph = (void *)((char *)ph + phentsize)) {
			if (ph->p_type == PT_DYNAMIC) {
				aux[AT_BASE] = dynamic - ph->p_vaddr;
				break;
			}
		}
	}

	self.dynv = (void *)dynamic;
	self.base = (void *)aux[AT_BASE];
	decode_dyn(&self);
	reloc_dso(&self, &self);

	dynlink = (void (*)())find_sym(&self, "__dynlink", 1).sym;
	return dynlink(argc, argv, auxv);
}

I'm hand-waving at some additional changes that need to be made:
reloc_dso is like the current reloc_all but it takes an additional
argument for the root dso to search for symbols (rather than using a
global var) and it doesn't call mprotect for relro (two reasons -- 1,
that would preclude patching up libc's PLT relocs later, and 2,
mprotect can't be called yet since it's external and we're not
assuming external calls can be made without relocating GOT/PLT).
Anyway this requires some changes several levels of function calls
down to get rid of global data, but that's a big cleanup win anyway.

Also, the core symbol lookup code is calling strcmp, which is
external. That needs to be replaced with a call to a static function,
which is no problem. Right now the real strcmp isn't even optimized.
If we eventually do want to optimize it though, this may introduce
some additional complexity in the dynamic linker to use the simple C
strcmp at early load time and switch to an optimized one later. Of
course just leaving the call to strcmp won't break with the current
assumption of -Bsymbolic-functions, but I'd like to eliminate that
assumption and treat it as an optimization rather than a semantic
necessity.

Rich

Powered by blists - more mailing lists

Confused about mailing lists and their use? Read about mailing lists on Wikipedia and check out these guidelines on proper formatting of your messages.