summaryrefslogtreecommitdiffstats
path: root/libexec
diff options
context:
space:
mode:
authorderaadt <deraadt@openbsd.org>2019-11-29 06:34:44 +0000
committerderaadt <deraadt@openbsd.org>2019-11-29 06:34:44 +0000
commite50417250fb1d11dd90538c8f1a10723b2e4b3af (patch)
tree18b789ba719e74203d4f59bf332c93e337c4c980 /libexec
parentdrm_sched_entity_flush() doesn't care about specific threads, so just (diff)
downloadwireguard-openbsd-e50417250fb1d11dd90538c8f1a10723b2e4b3af.tar.xz
wireguard-openbsd-e50417250fb1d11dd90538c8f1a10723b2e4b3af.zip
Repurpose the "syscalls must be on a writeable page" mechanism to
enforce a new policy: system calls must be in pre-registered regions. We have discussed more strict checks than this, but none satisfy the cost/benefit based upon our understanding of attack methods, anyways let's see what the next iteration looks like. This is intended to harden (translation: attackers must put extra effort into attacking) against a mixture of W^X failures and JIT bugs which allow syscall misinterpretation, especially in environments with polymorphic-instruction/variable-sized instructions. It fits in a bit with libc/libcrypto/ld.so random relink on boot and no-restart-at-crash behaviour, particularily for remote problems. Less effective once on-host since someone the libraries can be read. For static-executables the kernel registers the main program's PIE-mapped exec section valid, as well as the randomly-placed sigtramp page. For dynamic executables ELF ld.so's exec segment is also labelled valid; ld.so then has enough information to register libc's exec section as valid via call-once msyscall(2) For dynamic binaries, we continue to to permit the main program exec segment because "go" (and potentially a few other applications) have embedded system calls in the main program. Hopefully at least go gets fixed soon. We declare the concept of embedded syscalls a bad idea for numerous reasons, as we notice the ecosystem has many of static-syscall-in-base-binary which are dynamically linked against libraries which in turn use libc, which contains another set of syscall stubs. We've been concerned about adding even one additional syscall entry point... but go's approach tends to double the entry-point attack surface. This was started at a nano-hackathon in Bob Beck's basement 2 weeks ago during a long discussion with mortimer trying to hide from the SSL scream-conversations, and finished in more comfortable circumstances next to a wood-stove at Elk Lakes cabin with UVM scream-conversations. ok guenther kettenis mortimer, lots of feedback from others conversations about go with jsing tb sthen
Diffstat (limited to 'libexec')
-rw-r--r--libexec/ld.so/Makefile4
-rw-r--r--libexec/ld.so/aarch64/syscall.h3
-rw-r--r--libexec/ld.so/alpha/syscall.h3
-rw-r--r--libexec/ld.so/amd64/syscall.h3
-rw-r--r--libexec/ld.so/arm/syscall.h3
-rw-r--r--libexec/ld.so/hppa/syscall.h3
-rw-r--r--libexec/ld.so/i386/syscall.h3
-rw-r--r--libexec/ld.so/library.c19
-rw-r--r--libexec/ld.so/library_mquery.c17
-rw-r--r--libexec/ld.so/m88k/syscall.h3
-rw-r--r--libexec/ld.so/mips64/syscall.h3
-rw-r--r--libexec/ld.so/powerpc/syscall.h3
-rw-r--r--libexec/ld.so/sh/syscall.h3
-rw-r--r--libexec/ld.so/sparc64/syscall.h3
14 files changed, 56 insertions, 17 deletions
diff --git a/libexec/ld.so/Makefile b/libexec/ld.so/Makefile
index 92151b25d88..f9dd281ff66 100644
--- a/libexec/ld.so/Makefile
+++ b/libexec/ld.so/Makefile
@@ -1,4 +1,4 @@
-# $OpenBSD: Makefile,v 1.77 2019/10/20 03:44:49 guenther Exp $
+# $OpenBSD: Makefile,v 1.78 2019/11/29 06:34:44 deraadt Exp $
SUBDIR=ldconfig ldd
MAN= ld.so.1
@@ -28,7 +28,7 @@ SRCS+= dl_uname.c dl_dirname.c strlcat.c strlen.c trace.c
SRCS+= malloc.c reallocarray.c tib.c ffs.c
syscall=__syscall close exit fstat getdents getentropy getthrid issetugid \
- mprotect munmap open pledge read __realpath sendsyslog \
+ mprotect munmap msyscall open pledge read __realpath sendsyslog \
__set_tcb sysctl thrkill utrace write
GEN_PREFIX=\t.file "${@:R}.c"\n\#include "SYS.h"
diff --git a/libexec/ld.so/aarch64/syscall.h b/libexec/ld.so/aarch64/syscall.h
index f45c018475a..b1a3a7b442f 100644
--- a/libexec/ld.so/aarch64/syscall.h
+++ b/libexec/ld.so/aarch64/syscall.h
@@ -1,4 +1,4 @@
-/* $OpenBSD: syscall.h,v 1.7 2019/07/14 03:23:12 guenther Exp $ */
+/* $OpenBSD: syscall.h,v 1.8 2019/11/29 06:34:44 deraadt Exp $ */
/*
* Copyright (c) 1998 Per Fogelstrom, Opsycon AB
@@ -48,6 +48,7 @@ int _dl_getthrid(void);
int _dl_mprotect(const void *, size_t, int);
int _dl_munmap(const void *, size_t);
int _dl_open(const char *, int);
+int _dl_msyscall(void *addr, size_t len);
ssize_t _dl_read(int, const char *, size_t);
int _dl_pledge(const char *, const char **);
long _dl___syscall(quad_t, ...);
diff --git a/libexec/ld.so/alpha/syscall.h b/libexec/ld.so/alpha/syscall.h
index 4adb1a619e3..f8f322c9c11 100644
--- a/libexec/ld.so/alpha/syscall.h
+++ b/libexec/ld.so/alpha/syscall.h
@@ -1,4 +1,4 @@
-/* $OpenBSD: syscall.h,v 1.41 2019/07/14 03:23:12 guenther Exp $ */
+/* $OpenBSD: syscall.h,v 1.42 2019/11/29 06:34:44 deraadt Exp $ */
/*
* Copyright (c) 1998 Per Fogelstrom, Opsycon AB
@@ -48,6 +48,7 @@ int _dl_getthrid(void);
int _dl_mprotect(const void *, size_t, int);
int _dl_munmap(const void *, size_t);
int _dl_open(const char *, int);
+int _dl_msyscall(void *addr, size_t len);
ssize_t _dl_read(int, const char *, size_t);
int _dl_pledge(const char *, const char **);
long _dl___syscall(quad_t, ...);
diff --git a/libexec/ld.so/amd64/syscall.h b/libexec/ld.so/amd64/syscall.h
index 9c5c1b6487e..a680d1bddd9 100644
--- a/libexec/ld.so/amd64/syscall.h
+++ b/libexec/ld.so/amd64/syscall.h
@@ -1,4 +1,4 @@
-/* $OpenBSD: syscall.h,v 1.28 2019/07/14 03:23:12 guenther Exp $ */
+/* $OpenBSD: syscall.h,v 1.29 2019/11/29 06:34:44 deraadt Exp $ */
/*
* Copyright (c) 1998 Per Fogelstrom, Opsycon AB
@@ -48,6 +48,7 @@ int _dl_getthrid(void);
int _dl_mprotect(const void *, size_t, int);
int _dl_munmap(const void *, size_t);
int _dl_open(const char *, int);
+int _dl_msyscall(void *addr, size_t len);
ssize_t _dl_read(int, const char *, size_t);
int _dl_pledge(const char *, const char **);
long _dl___syscall(quad_t, ...);
diff --git a/libexec/ld.so/arm/syscall.h b/libexec/ld.so/arm/syscall.h
index 9c5c1b6487e..a680d1bddd9 100644
--- a/libexec/ld.so/arm/syscall.h
+++ b/libexec/ld.so/arm/syscall.h
@@ -1,4 +1,4 @@
-/* $OpenBSD: syscall.h,v 1.28 2019/07/14 03:23:12 guenther Exp $ */
+/* $OpenBSD: syscall.h,v 1.29 2019/11/29 06:34:44 deraadt Exp $ */
/*
* Copyright (c) 1998 Per Fogelstrom, Opsycon AB
@@ -48,6 +48,7 @@ int _dl_getthrid(void);
int _dl_mprotect(const void *, size_t, int);
int _dl_munmap(const void *, size_t);
int _dl_open(const char *, int);
+int _dl_msyscall(void *addr, size_t len);
ssize_t _dl_read(int, const char *, size_t);
int _dl_pledge(const char *, const char **);
long _dl___syscall(quad_t, ...);
diff --git a/libexec/ld.so/hppa/syscall.h b/libexec/ld.so/hppa/syscall.h
index 9c5c1b6487e..a680d1bddd9 100644
--- a/libexec/ld.so/hppa/syscall.h
+++ b/libexec/ld.so/hppa/syscall.h
@@ -1,4 +1,4 @@
-/* $OpenBSD: syscall.h,v 1.28 2019/07/14 03:23:12 guenther Exp $ */
+/* $OpenBSD: syscall.h,v 1.29 2019/11/29 06:34:44 deraadt Exp $ */
/*
* Copyright (c) 1998 Per Fogelstrom, Opsycon AB
@@ -48,6 +48,7 @@ int _dl_getthrid(void);
int _dl_mprotect(const void *, size_t, int);
int _dl_munmap(const void *, size_t);
int _dl_open(const char *, int);
+int _dl_msyscall(void *addr, size_t len);
ssize_t _dl_read(int, const char *, size_t);
int _dl_pledge(const char *, const char **);
long _dl___syscall(quad_t, ...);
diff --git a/libexec/ld.so/i386/syscall.h b/libexec/ld.so/i386/syscall.h
index d0bc750ae5d..b7f329a184a 100644
--- a/libexec/ld.so/i386/syscall.h
+++ b/libexec/ld.so/i386/syscall.h
@@ -1,4 +1,4 @@
-/* $OpenBSD: syscall.h,v 1.32 2019/07/14 03:23:12 guenther Exp $ */
+/* $OpenBSD: syscall.h,v 1.33 2019/11/29 06:34:44 deraadt Exp $ */
/*
* Copyright (c) 1998 Per Fogelstrom, Opsycon AB
@@ -48,6 +48,7 @@ int _dl_getthrid(void);
int _dl_mprotect(const void *, size_t, int);
int _dl_munmap(const void *, size_t);
int _dl_open(const char *, int);
+int _dl_msyscall(void *addr, size_t len);
ssize_t _dl_read(int, const char *, size_t);
int _dl_pledge(const char *, const char **);
long _dl___syscall(quad_t, ...);
diff --git a/libexec/ld.so/library.c b/libexec/ld.so/library.c
index e9def013abc..204e631b201 100644
--- a/libexec/ld.so/library.c
+++ b/libexec/ld.so/library.c
@@ -1,4 +1,4 @@
-/* $OpenBSD: library.c,v 1.83 2019/10/04 17:42:16 guenther Exp $ */
+/* $OpenBSD: library.c,v 1.84 2019/11/29 06:34:44 deraadt Exp $ */
/*
* Copyright (c) 2002 Dale Rahn
@@ -102,7 +102,8 @@ _dl_tryload_shlib(const char *libname, int type, int flags)
Elf_Addr libaddr, loff, align = _dl_pagesz - 1;
Elf_Addr relro_addr = 0, relro_size = 0;
elf_object_t *object;
- char hbuf[4096];
+ char hbuf[4096], *exec_start = 0;
+ size_t exec_size = 0;
Elf_Dyn *dynp = NULL;
Elf_Ehdr *ehdr;
Elf_Phdr *phdp;
@@ -253,6 +254,11 @@ _dl_tryload_shlib(const char *libname, int type, int flags)
_dl_load_list_free(load_list);
return(0);
}
+ if ((flags & PROT_EXEC) && exec_start == 0) {
+ exec_start = start;
+ exec_size = ROUND_PG(size);
+ }
+
if (phdp->p_flags & PF_W) {
/* Zero out everything past the EOF */
if ((size & align) != 0)
@@ -301,6 +307,8 @@ _dl_tryload_shlib(const char *libname, int type, int flags)
(Elf_Phdr *)((char *)libaddr + ehdr->e_phoff), ehdr->e_phnum,type,
libaddr, loff);
if (object) {
+ char *soname = (char *)object->Dyn.info[DT_SONAME];
+
object->load_size = maxva - minva; /*XXX*/
object->load_list = load_list;
/* set inode, dev from stat info */
@@ -312,6 +320,13 @@ _dl_tryload_shlib(const char *libname, int type, int flags)
_dl_set_sod(object->load_name, &object->sod);
if (ptls != NULL && ptls->p_memsz)
_dl_set_tls(object, ptls, libaddr, libname);
+
+ /* Request permission for system calls in libc.so's text segment */
+ if (soname != NULL &&
+ _dl_strncmp(soname, "libc.so.", 8) == 0) {
+ if (_dl_msyscall(exec_start, exec_size) == -1)
+ _dl_printf("msyscall %lx %lx error\n");
+ }
} else {
_dl_munmap((void *)libaddr, maxva - minva);
_dl_load_list_free(load_list);
diff --git a/libexec/ld.so/library_mquery.c b/libexec/ld.so/library_mquery.c
index 6f061410f51..f7e2baaa747 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.60 2019/10/04 17:42:16 guenther Exp $ */
+/* $OpenBSD: library_mquery.c,v 1.61 2019/11/29 06:34:44 deraadt Exp $ */
/*
* Copyright (c) 2002 Dale Rahn
@@ -112,7 +112,8 @@ _dl_tryload_shlib(const char *libname, int type, int flags)
Elf_Phdr *ptls = NULL;
Elf_Addr relro_addr = 0, relro_size = 0;
struct stat sb;
- char hbuf[4096];
+ char hbuf[4096], *exec_start = 0;
+ size_t exec_size = 0;
#define ROUND_PG(x) (((x) + align) & ~(align))
#define TRUNC_PG(x) ((x) & ~(align))
@@ -288,6 +289,11 @@ retry:
load_end = (Elf_Addr)ld->start + ROUND_PG(ld->size);
}
+ if ((flags & PROT_EXEC) && exec_start == 0) {
+ exec_start = ld->start;
+ exec_size = 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)
@@ -318,6 +324,13 @@ retry:
if (ptls != NULL && ptls->p_memsz)
_dl_set_tls(object, ptls, (Elf_Addr)lowld->start,
libname);
+
+ /* Request permission for system calls in libc.so's text segment */
+ if (soname != NULL &&
+ _dl_strncmp(soname, "libc.so.", 8) == 0) {
+ if (_dl_msyscall(exec_start, exec_size) == -1)
+ _dl_printf("msyscall %lx %lx error\n");
+ }
} else {
_dl_load_list_free(lowld);
}
diff --git a/libexec/ld.so/m88k/syscall.h b/libexec/ld.so/m88k/syscall.h
index ded5f6bc6db..f0b4c20e7e6 100644
--- a/libexec/ld.so/m88k/syscall.h
+++ b/libexec/ld.so/m88k/syscall.h
@@ -1,4 +1,4 @@
-/* $OpenBSD: syscall.h,v 1.24 2019/07/14 03:23:12 guenther Exp $ */
+/* $OpenBSD: syscall.h,v 1.25 2019/11/29 06:34:45 deraadt Exp $ */
/*
* Copyright (c) 1998 Per Fogelstrom, Opsycon AB
@@ -48,6 +48,7 @@ int _dl_getthrid(void);
int _dl_mprotect(const void *, size_t, int);
int _dl_munmap(const void *, size_t);
int _dl_open(const char *, int);
+int _dl_msyscall(void *addr, size_t len);
ssize_t _dl_read(int, const char *, size_t);
int _dl_pledge(const char *, const char **);
long _dl___syscall(quad_t, ...);
diff --git a/libexec/ld.so/mips64/syscall.h b/libexec/ld.so/mips64/syscall.h
index fc8e4c2e9d3..0d2497e6f3d 100644
--- a/libexec/ld.so/mips64/syscall.h
+++ b/libexec/ld.so/mips64/syscall.h
@@ -1,4 +1,4 @@
-/* $OpenBSD: syscall.h,v 1.30 2019/07/14 03:23:12 guenther Exp $ */
+/* $OpenBSD: syscall.h,v 1.31 2019/11/29 06:34:45 deraadt Exp $ */
/*
* Copyright (c) 1998 Per Fogelstrom, Opsycon AB
@@ -48,6 +48,7 @@ int _dl_getthrid(void);
int _dl_mprotect(const void *, size_t, int);
int _dl_munmap(const void *, size_t);
int _dl_open(const char *, int);
+int _dl_msyscall(void *addr, size_t len);
ssize_t _dl_read(int, const char *, size_t);
int _dl_pledge(const char *, const char **);
long _dl___syscall(quad_t, ...);
diff --git a/libexec/ld.so/powerpc/syscall.h b/libexec/ld.so/powerpc/syscall.h
index 3d9a8a2207d..ab8811f0615 100644
--- a/libexec/ld.so/powerpc/syscall.h
+++ b/libexec/ld.so/powerpc/syscall.h
@@ -1,4 +1,4 @@
-/* $OpenBSD: syscall.h,v 1.47 2019/07/14 03:23:12 guenther Exp $ */
+/* $OpenBSD: syscall.h,v 1.48 2019/11/29 06:34:45 deraadt Exp $ */
/*
* Copyright (c) 1998 Per Fogelstrom, Opsycon AB
@@ -48,6 +48,7 @@ int _dl_getthrid(void);
int _dl_mprotect(const void *, size_t, int);
int _dl_munmap(const void *, size_t);
int _dl_open(const char *, int);
+int _dl_msyscall(void *addr, size_t len);
ssize_t _dl_read(int, const char *, size_t);
int _dl_pledge(const char *, const char **);
long _dl___syscall(quad_t, ...);
diff --git a/libexec/ld.so/sh/syscall.h b/libexec/ld.so/sh/syscall.h
index 0f39ad62c6b..dbb8084e6b2 100644
--- a/libexec/ld.so/sh/syscall.h
+++ b/libexec/ld.so/sh/syscall.h
@@ -1,4 +1,4 @@
-/* $OpenBSD: syscall.h,v 1.27 2019/07/14 03:23:12 guenther Exp $ */
+/* $OpenBSD: syscall.h,v 1.28 2019/11/29 06:34:45 deraadt Exp $ */
/*
* Copyright (c) 1998 Per Fogelstrom, Opsycon AB
@@ -48,6 +48,7 @@ int _dl_getthrid(void);
int _dl_mprotect(const void *, size_t, int);
int _dl_munmap(const void *, size_t);
int _dl_open(const char *, int);
+int _dl_msyscall(void *addr, size_t len);
ssize_t _dl_read(int, const char *, size_t);
int _dl_pledge(const char *, const char **);
long _dl___syscall(quad_t, ...);
diff --git a/libexec/ld.so/sparc64/syscall.h b/libexec/ld.so/sparc64/syscall.h
index 656747035d4..f597523e8ae 100644
--- a/libexec/ld.so/sparc64/syscall.h
+++ b/libexec/ld.so/sparc64/syscall.h
@@ -1,4 +1,4 @@
-/* $OpenBSD: syscall.h,v 1.40 2019/07/14 03:23:12 guenther Exp $ */
+/* $OpenBSD: syscall.h,v 1.41 2019/11/29 06:34:45 deraadt Exp $ */
/*
* Copyright (c) 1998 Per Fogelstrom, Opsycon AB
@@ -48,6 +48,7 @@ int _dl_getthrid(void);
int _dl_mprotect(const void *, size_t, int);
int _dl_munmap(const void *, size_t);
int _dl_open(const char *, int);
+int _dl_msyscall(void *addr, size_t len);
ssize_t _dl_read(int, const char *, size_t);
int _dl_pledge(const char *, const char **);
long _dl___syscall(quad_t, ...);