about summary refs log tree commit diff
path: root/src/ldso
diff options
context:
space:
mode:
authorRich Felker <dalias@aerifal.cx>2014-01-21 00:36:35 -0500
committerRich Felker <dalias@aerifal.cx>2014-01-21 00:36:35 -0500
commit69003e0590e1fc50391a639b285200403a58ad01 (patch)
tree92fa6e746fc8b15182293cc4e121100b80ef8d74 /src/ldso
parent1569f396bb76e9d54f6c4492ed6778e37b87bc70 (diff)
downloadmusl-69003e0590e1fc50391a639b285200403a58ad01.tar.gz
musl-69003e0590e1fc50391a639b285200403a58ad01.tar.xz
musl-69003e0590e1fc50391a639b285200403a58ad01.zip
fix crash in dynamic linker when certain copy relocations are unsatisfied
STB_WEAK is only a weak reference for undefined symbols (those with a
section of SHN_UNDEF). otherwise, it's a weak definition. normally
this distinction would not matter, since a relocation referencing a
symbol that also provides a definition (not SHN_UNDEF) will always
succeed in finding the referenced symbol itself. however, in the case
of copy relocations, the referenced symbol itself is ignored in order
to search for another symbol to copy from, and thus it's possible that
no definition is found. in this case, if the symbol being resolved
happened to be a weak definition, it was misinterpreted as a weak
reference, suppressing the error path and causing a crash when the
copy relocation was performed with a null source pointer passed to
memcpy.

there are almost certainly still situations in which invalid
combinations of symbol and relocation types can cause the dynamic
linker to crash (this is pretty much inevitable), but the intent is
that crashes not be possible for symbol/relocation tables produced by
a valid linker.
Diffstat (limited to 'src/ldso')
-rw-r--r--src/ldso/dynlink.c3
1 files changed, 2 insertions, 1 deletions
diff --git a/src/ldso/dynlink.c b/src/ldso/dynlink.c
index 89e1260b..a1bdf0fb 100644
--- a/src/ldso/dynlink.c
+++ b/src/ldso/dynlink.c
@@ -253,7 +253,8 @@ static void do_relocs(struct dso *dso, size_t *rel, size_t rel_size, size_t stri
 			name = strings + sym->st_name;
 			ctx = IS_COPY(type) ? head->next : head;
 			def = find_sym(ctx, name, IS_PLT(type));
-			if (!def.sym && sym->st_info>>4 != STB_WEAK) {
+			if (!def.sym && (sym->st_shndx != SHN_UNDEF
+			    || sym->st_info>>4 != STB_WEAK)) {
 				snprintf(errbuf, sizeof errbuf,
 					"Error relocating %s: %s: symbol not found",
 					dso->name, name);