From a4ba1e578abc32528c379f6c94024325cd810809 Mon Sep 17 00:00:00 2001 From: deraadt Date: Sat, 18 Feb 2023 01:22:50 +0000 Subject: [PATCH] Lookup the start,len of the "execve" stub in libc.so, and tell the kernel where it is with pinsyscall(). In non-static binaries, kernel execve(2) will now insist upon being called from that small region. Arriving from a different region smells like ROP methodology, and the process is killed. --- libexec/ld.so/Makefile | 6 +++--- libexec/ld.so/loader.c | 20 ++++++++++++++++++-- libexec/ld.so/syscall.h | 3 ++- 3 files changed, 23 insertions(+), 6 deletions(-) diff --git a/libexec/ld.so/Makefile b/libexec/ld.so/Makefile index 308043209a6..c582139541a 100644 --- a/libexec/ld.so/Makefile +++ b/libexec/ld.so/Makefile @@ -1,4 +1,4 @@ -# $OpenBSD: Makefile,v 1.83 2022/11/05 18:44:09 deraadt Exp $ +# $OpenBSD: Makefile,v 1.84 2023/02/18 01:22:50 deraadt Exp $ SUBDIR=ldconfig ldd MAN= ld.so.1 @@ -28,8 +28,8 @@ SRCS+= dl_uname.c dl_dirname.c strlcat.c strlen.c trace.c SRCS+= malloc.c reallocarray.c tib.c ffs.c syscall=close exit fstat getdents getentropy getthrid issetugid kbind \ - mimmutable mmap mprotect munmap msyscall open pledge read \ - __realpath sendsyslog __set_tcb sysctl thrkill utrace write + mimmutable mmap mprotect munmap msyscall open pledge pinsyscall \ + read __realpath sendsyslog __set_tcb sysctl thrkill utrace write \ .if (${MACHINE_ARCH} == "i386") syscall+=mquery diff --git a/libexec/ld.so/loader.c b/libexec/ld.so/loader.c index 889712b9d8d..1413f4380eb 100644 --- a/libexec/ld.so/loader.c +++ b/libexec/ld.so/loader.c @@ -1,4 +1,4 @@ -/* $OpenBSD: loader.c,v 1.210 2023/01/29 20:30:56 gnezdo Exp $ */ +/* $OpenBSD: loader.c,v 1.211 2023/02/18 01:22:50 deraadt Exp $ */ /* * Copyright (c) 1998 Per Fogelstrom, Opsycon AB @@ -30,6 +30,7 @@ #include #include +#include #include #ifdef __i386__ # include @@ -316,7 +317,7 @@ _dl_setup_env(const char *argv0, char **envp) int _dl_load_dep_libs(elf_object_t *object, int flags, int booting) { - elf_object_t *dynobj; + elf_object_t *dynobj, *obj; Elf_Dyn *dynp; unsigned int loop; int libcount; @@ -410,6 +411,21 @@ _dl_load_dep_libs(elf_object_t *object, int flags, int booting) _dl_cache_grpsym_list_setup(object); + for (obj = _dl_objects; booting && obj != NULL; obj = obj->next) { + char *soname = (char *)obj->Dyn.info[DT_SONAME]; + struct sym_res sr; + + if (soname && _dl_strncmp(soname, "libc.so.", 8)) + continue; + sr = _dl_find_symbol("execve", + SYM_SEARCH_SELF|SYM_PLT|SYM_WARNNOTFOUND, NULL, obj); + if (sr.sym) + _dl_pinsyscall(SYS_execve, + (void *)sr.obj->obj_base + sr.sym->st_value, + sr.sym->st_size); + _dl_memset(&sr, 0, sizeof sr); + break; + } return(0); } diff --git a/libexec/ld.so/syscall.h b/libexec/ld.so/syscall.h index a42f7164d83..6e9394d0717 100644 --- a/libexec/ld.so/syscall.h +++ b/libexec/ld.so/syscall.h @@ -1,4 +1,4 @@ -/* $OpenBSD: syscall.h,v 1.3 2022/11/05 18:44:09 deraadt Exp $ */ +/* $OpenBSD: syscall.h,v 1.4 2023/02/18 01:22:50 deraadt Exp $ */ /* * Copyright (c) 1998 Per Fogelstrom, Opsycon AB @@ -51,6 +51,7 @@ void *_dl_mmap(void *, size_t, int, int, int, off_t); int _dl_mprotect(const void *, size_t, int); void *_dl_mquery(void *, size_t, int, int, int, off_t); int _dl_msyscall(void *addr, size_t len); +int _dl_pinsyscall(int, void *addr, size_t len); int _dl_munmap(const void *, size_t); int _dl_mimmutable(const void *, size_t); int _dl_open(const char *, int); -- 2.20.1