summaryrefslogtreecommitdiff
path: root/libexec/ld.so
diff options
context:
space:
mode:
authorMatthew Dempsky <matthew@cvs.openbsd.org>2012-08-20 23:25:08 +0000
committerMatthew Dempsky <matthew@cvs.openbsd.org>2012-08-20 23:25:08 +0000
commite8aa6e1c7aa4074e069f239019ca7c438fbe8fe6 (patch)
tree26a226348a9cd5eb3a30c52e2291b5c5bf316a9e /libexec/ld.so
parent56a2a8770254909ecd8125ccde946f43704bb32a (diff)
Add support for .openbsd.randomdata sections and PT_OPENBSD_RANDOMIZE
segments to the kernel, ld (2.15), and ld.so. Tested on alpha, amd64, i386, macppc, and sparc64 (thanks naddy, mpi, and okan!). Idea discussed for some time; committing now for further testing. ok deraadt
Diffstat (limited to 'libexec/ld.so')
-rw-r--r--libexec/ld.so/SPECS.randomdata48
-rw-r--r--libexec/ld.so/library.c15
-rw-r--r--libexec/ld.so/library_mquery.c8
3 files changed, 68 insertions, 3 deletions
diff --git a/libexec/ld.so/SPECS.randomdata b/libexec/ld.so/SPECS.randomdata
new file mode 100644
index 00000000000..434de2ee3de
--- /dev/null
+++ b/libexec/ld.so/SPECS.randomdata
@@ -0,0 +1,48 @@
+$OpenBSD: SPECS.randomdata,v 1.1 2012/08/20 23:25:07 matthew Exp $
+
+This document describes the OpenBSD operating system supplement for
+adding "random data" sections to the ELF ABI. These sections can be
+useful for holding values like GCC's stack-smashing protector cookies
+and offer additional benefits like ensuring the data is initialized
+before any constructor methods are called and allowing the dynamic
+linker to mark the memory as read-only after initialization.
+
+
+Program Header
+
+OpenBSD defines the following operating system-specific segment type:
+
+ Name Value
+ PT_OPENBSD_RANDOMIZE 0x65a3dbe6
+
+
+ PT_OPENBSD_RANDOMIZE
+
+ The array element specifies the location and size of a random data
+ section. The system will initialize the specified memory range
+ with random data. The memory range must be separately mapped
+ (e.g., by use of a PT_LOAD segment).
+
+
+Special Sections
+
+OpenBSD defines the following operating system-specific special
+sections:
+
+ Name Type Attributes
+ .openbsd.randomdata SHT_PROGBITS SHF_ALLOC
+
+
+ .openbsd.randomdata
+
+ This section holds the random data section.
+
+
+Implementation Notes
+
+On OpenBSD, PT_OPENBSD_RANDOMIZE segments are handled alongside
+PT_LOAD segments: the kernel handles initializing random data segments
+in executables and program interpreters (i.e., ld.so), while ld.so
+handles initializing them in shared libraries. Additionally, the
+kernel limits the total number of PT_OPENBSD_RANDOMIZE segment bytes
+in an executable or interpreter to 1024 bytes.
diff --git a/libexec/ld.so/library.c b/libexec/ld.so/library.c
index 1dd2013e6df..60c69f370c6 100644
--- a/libexec/ld.so/library.c
+++ b/libexec/ld.so/library.c
@@ -1,4 +1,4 @@
-/* $OpenBSD: library.c,v 1.66 2012/06/12 20:32:17 matthew Exp $ */
+/* $OpenBSD: library.c,v 1.67 2012/08/20 23:25:07 matthew Exp $ */
/*
* Copyright (c) 2002 Dale Rahn
@@ -181,7 +181,8 @@ _dl_tryload_shlib(const char *libname, int type, int flags)
phdp = (Elf_Phdr *)(hbuf + ehdr->e_phoff);
for (i = 0; i < ehdr->e_phnum; i++, phdp++) {
- if (phdp->p_type == PT_LOAD) {
+ switch (phdp->p_type) {
+ case PT_LOAD: {
char *start = (char *)(TRUNC_PG(phdp->p_vaddr)) + loff;
Elf_Addr off = (phdp->p_vaddr & align);
Elf_Addr size = off + phdp->p_filesz;
@@ -233,6 +234,16 @@ _dl_tryload_shlib(const char *libname, int type, int flags)
return(0);
}
}
+ break;
+ }
+
+ case PT_OPENBSD_RANDOMIZE:
+ _dl_randombuf((char *)(phdp->p_vaddr + loff),
+ phdp->p_memsz);
+ break;
+
+ default:
+ break;
}
}
diff --git a/libexec/ld.so/library_mquery.c b/libexec/ld.so/library_mquery.c
index aedfd091f8b..abbde2e533d 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.43 2012/07/21 06:46:58 matthew Exp $ */
+/* $OpenBSD: library_mquery.c,v 1.44 2012/08/20 23:25:07 matthew Exp $ */
/*
* Copyright (c) 2002 Dale Rahn
@@ -266,6 +266,12 @@ retry:
load_end = (Elf_Addr)ld->start + ROUND_PG(ld->size);
}
+ phdp = (Elf_Phdr *)(hbuf + ehdr->e_phoff);
+ 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);
+
prebind_data = prebind_load_fd(libfile, libname);
_dl_close(libfile);