summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--libexec/ld.so/library.c10
-rw-r--r--libexec/ld.so/library_mquery.c12
-rw-r--r--libexec/ld.so/loader.c72
-rw-r--r--libexec/ld.so/resolve.c50
-rw-r--r--libexec/ld.so/resolve.h6
5 files changed, 100 insertions, 50 deletions
diff --git a/libexec/ld.so/library.c b/libexec/ld.so/library.c
index ff80119a6dd..7adf2bc81cf 100644
--- a/libexec/ld.so/library.c
+++ b/libexec/ld.so/library.c
@@ -1,4 +1,4 @@
-/* $OpenBSD: library.c,v 1.77 2016/07/04 21:15:06 guenther Exp $ */
+/* $OpenBSD: library.c,v 1.78 2016/08/08 21:59:20 guenther Exp $ */
/*
* Copyright (c) 2002 Dale Rahn
@@ -98,6 +98,7 @@ _dl_tryload_shlib(const char *libname, int type, int flags)
struct load_list *next_load, *load_list = NULL;
Elf_Addr maxva = 0, minva = ELFDEFNNAME(NO_ADDR);
Elf_Addr libaddr, loff, align = _dl_pagesz - 1;
+ Elf_Addr relro_addr = 0, relro_size = 0;
elf_object_t *object;
char hbuf[4096];
Elf_Dyn *dynp = NULL;
@@ -281,6 +282,11 @@ _dl_tryload_shlib(const char *libname, int type, int flags)
phdp->p_memsz);
break;
+ case PT_GNU_RELRO:
+ relro_addr = phdp->p_vaddr + loff;
+ relro_size = phdp->p_memsz;
+ break;
+
default:
break;
}
@@ -299,6 +305,8 @@ _dl_tryload_shlib(const char *libname, int type, int flags)
object->dev = sb.st_dev;
object->inode = sb.st_ino;
object->obj_flags |= flags;
+ object->relro_addr = relro_addr;
+ object->relro_size = relro_size;
_dl_set_sod(object->load_name, &object->sod);
if (ptls != NULL && ptls->p_memsz)
_dl_set_tls(object, ptls, libaddr, libname);
diff --git a/libexec/ld.so/library_mquery.c b/libexec/ld.so/library_mquery.c
index 7a214da55b5..2192d6f691d 100644
--- a/libexec/ld.so/library_mquery.c
+++ b/libexec/ld.so/library_mquery.c
@@ -1,4 +1,4 @@
-/* $OpenBSD: library_mquery.c,v 1.54 2016/07/04 21:15:06 guenther Exp $ */
+/* $OpenBSD: library_mquery.c,v 1.55 2016/08/08 21:59:20 guenther Exp $ */
/*
* Copyright (c) 2002 Dale Rahn
@@ -108,6 +108,7 @@ _dl_tryload_shlib(const char *libname, int type, int flags)
Elf_Addr load_end = 0;
Elf_Addr align = _dl_pagesz - 1, off, size;
Elf_Phdr *ptls = NULL;
+ Elf_Addr relro_addr = 0, relro_size = 0;
struct stat sb;
char hbuf[4096];
@@ -297,10 +298,15 @@ retry:
}
phdp = (Elf_Phdr *)(hbuf + ehdr->e_phoff);
- for (i = 0; i < ehdr->e_phnum; i++, phdp++)
+ for (i = 0; i < ehdr->e_phnum; i++, phdp++) {
if (phdp->p_type == PT_OPENBSD_RANDOMIZE)
_dl_randombuf((char *)(phdp->p_vaddr + LOFF),
phdp->p_memsz);
+ else if (phdp->p_type == PT_GNU_RELRO) {
+ relro_addr = phdp->p_vaddr + LOFF;
+ relro_size = phdp->p_memsz;
+ }
+ }
_dl_close(libfile);
@@ -315,6 +321,8 @@ retry:
object->dev = sb.st_dev;
object->inode = sb.st_ino;
object->obj_flags |= flags;
+ object->relro_addr = relro_addr;
+ object->relro_size = relro_size;
_dl_set_sod(object->load_name, &object->sod);
if (ptls != NULL && ptls->p_memsz)
_dl_set_tls(object, ptls, (Elf_Addr)lowld->start,
diff --git a/libexec/ld.so/loader.c b/libexec/ld.so/loader.c
index 691bbbf4d77..bd7c82e95ab 100644
--- a/libexec/ld.so/loader.c
+++ b/libexec/ld.so/loader.c
@@ -1,4 +1,4 @@
-/* $OpenBSD: loader.c,v 1.162 2016/07/04 21:15:06 guenther Exp $ */
+/* $OpenBSD: loader.c,v 1.163 2016/08/08 21:59:20 guenther Exp $ */
/*
* Copyright (c) 1998 Per Fogelstrom, Opsycon AB
@@ -478,6 +478,10 @@ _dl_boot(const char **argv, char **envp, const long dyn_loff, long *dl_data)
}
ptls = phdp;
break;
+ case PT_GNU_RELRO:
+ exe_obj->relro_addr = phdp->p_vaddr + exe_loff;
+ exe_obj->relro_size = phdp->p_memsz;
+ break;
}
phdp++;
}
@@ -524,37 +528,9 @@ _dl_boot(const char **argv, char **envp, const long dyn_loff, long *dl_data)
_dl_allocate_tls_offsets();
/*
- * Everything should be in place now for doing the relocation
- * and binding. Call _dl_rtld to do the job. Fingers crossed.
- */
- failed = 0;
- if (_dl_traceld == NULL)
- failed = _dl_rtld(_dl_objects);
-
- if (_dl_debug || _dl_traceld) {
- if (_dl_traceld)
- _dl_pledge("stdio rpath", NULL);
- _dl_show_objects();
- }
-
- DL_DEB(("dynamic loading done, %s.\n",
- (failed == 0) ? "success":"failed"));
-
- if (failed != 0)
- _dl_exit(1);
-
- if (_dl_traceld)
- _dl_exit(0);
-
- _dl_loading_object = NULL;
-
- /* set up the TIB for the initial thread */
- _dl_allocate_first_tib();
-
- _dl_fixup_user_env();
-
- /*
- * Finally make something to help gdb when poking around in the code.
+ * Make something to help gdb when poking around in the code.
+ * Do this poking at the .dynamic section now, before relocation
+ * renders it read-only
*/
map_link = NULL;
#ifdef __mips__
@@ -594,6 +570,38 @@ _dl_boot(const char **argv, char **envp, const long dyn_loff, long *dl_data)
#endif
}
+
+ /*
+ * Everything should be in place now for doing the relocation
+ * and binding. Call _dl_rtld to do the job. Fingers crossed.
+ */
+
+ failed = 0;
+ if (_dl_traceld == NULL)
+ failed = _dl_rtld(_dl_objects);
+
+ if (_dl_debug || _dl_traceld) {
+ if (_dl_traceld)
+ _dl_pledge("stdio rpath", NULL);
+ _dl_show_objects();
+ }
+
+ DL_DEB(("dynamic loading done, %s.\n",
+ (failed == 0) ? "success":"failed"));
+
+ if (failed != 0)
+ _dl_exit(1);
+
+ if (_dl_traceld)
+ _dl_exit(0);
+
+ _dl_loading_object = NULL;
+
+ /* set up the TIB for the initial thread */
+ _dl_allocate_first_tib();
+
+ _dl_fixup_user_env();
+
_dl_debug_state();
/*
diff --git a/libexec/ld.so/resolve.c b/libexec/ld.so/resolve.c
index d6c2e525c6e..dc384c7bed0 100644
--- a/libexec/ld.so/resolve.c
+++ b/libexec/ld.so/resolve.c
@@ -1,4 +1,4 @@
-/* $OpenBSD: resolve.c,v 1.73 2016/07/04 21:15:06 guenther Exp $ */
+/* $OpenBSD: resolve.c,v 1.74 2016/08/08 21:59:20 guenther Exp $ */
/*
* Copyright (c) 1998 Per Fogelstrom, Opsycon AB
@@ -442,31 +442,53 @@ _dl_protect_segment(elf_object_t *object, Elf_Addr addr,
const Elf_Sym *this;
Elf_Addr ooff, start, end;
- if (addr == 0) {
+ if (addr == 0 && start_sym[2] == 'g' &&
+ (addr = object->relro_addr) != 0) {
+ DL_DEB(("protect start RELRO = 0x%lx in %s\n",
+ addr, object->load_name));
+ }
+ else if (addr == 0) {
this = NULL;
ooff = _dl_find_symbol(start_sym, &this,
SYM_SEARCH_OBJ | SYM_NOWARNNOTFOUND | SYM_PLT, NULL,
object, NULL);
/* If not found, nothing to do */
- if (this == NULL)
+ if (this == NULL) {
+ DL_DEB(("protect start \"%s\" not found in %s\n",
+ start_sym, object->load_name));
return (NULL);
+ }
addr = ooff + this->st_value;
+ DL_DEB(("protect start \"%s\" to %x = 0x%lx in %s\n",
+ start_sym, prot, addr, object->load_name));
}
- this = NULL;
- ooff = _dl_find_symbol(end_sym, &this,
- SYM_SEARCH_OBJ | SYM_NOWARNNOTFOUND | SYM_PLT, NULL, object, NULL);
- if (this == NULL)
- addr = 0;
- else {
- end = ooff + this->st_value;
- if (addr < end) {
- start = ELF_TRUNC(addr, _dl_pagesz);
- end = ELF_ROUND(end, _dl_pagesz);
- _dl_mprotect((void *)start, end - start, prot);
+ if (object->relro_addr != 0 && start_sym[2] == 'g') {
+ end = object->relro_addr + object->relro_size;
+ DL_DEB(("protect end RELRO = 0x%lx in %s\n",
+ end, object->load_name));
+ } else {
+ this = NULL;
+ ooff = _dl_find_symbol(end_sym, &this,
+ SYM_SEARCH_OBJ | SYM_NOWARNNOTFOUND | SYM_PLT, NULL,
+ object, NULL);
+ if (this == NULL) {
+ DL_DEB(("protect end \"%s\" not found in %s\n",
+ end_sym, object->load_name));
+ addr = 0;
+ } else {
+ end = ooff + this->st_value;
+ DL_DEB(("protect end \"%s\" = 0x%lx in %s\n",
+ end_sym, end, object->load_name));
}
}
+ if (addr != 0 && addr < end) {
+ start = ELF_TRUNC(addr, _dl_pagesz);
+ end = ELF_ROUND(end, _dl_pagesz);
+ _dl_mprotect((void *)start, end - start, prot);
+ }
+
return ((void *)addr);
}
diff --git a/libexec/ld.so/resolve.h b/libexec/ld.so/resolve.h
index ace0e960b1a..df0469c9fc0 100644
--- a/libexec/ld.so/resolve.h
+++ b/libexec/ld.so/resolve.h
@@ -1,4 +1,4 @@
-/* $OpenBSD: resolve.h,v 1.78 2016/07/04 21:15:06 guenther Exp $ */
+/* $OpenBSD: resolve.h,v 1.79 2016/08/08 21:59:20 guenther Exp $ */
/*
* Copyright (c) 1998 Per Fogelstrom, Opsycon AB
@@ -148,6 +148,10 @@ struct elf_object {
const void *tls_static_data;
int tls_offset;
+ /* relro bits */
+ Elf_Addr relro_addr;
+ Elf_Addr relro_size;
+
/* generation number of last grpsym insert on this object */
unsigned int grpsym_gen;