From e8aa6e1c7aa4074e069f239019ca7c438fbe8fe6 Mon Sep 17 00:00:00 2001 From: Matthew Dempsky Date: Mon, 20 Aug 2012 23:25:08 +0000 Subject: 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 --- libexec/ld.so/SPECS.randomdata | 48 ++++++++++++++++++++++++++++++++++++++++++ libexec/ld.so/library.c | 15 +++++++++++-- libexec/ld.so/library_mquery.c | 8 ++++++- 3 files changed, 68 insertions(+), 3 deletions(-) create mode 100644 libexec/ld.so/SPECS.randomdata (limited to 'libexec/ld.so') 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); -- cgit v1.2.3