From 07cf23bbb6790446af427f88b376152f4aaa2921 Mon Sep 17 00:00:00 2001 From: deraadt Date: Mon, 7 Nov 2022 10:35:26 +0000 Subject: [PATCH] dtors were broken by trying to reuse DF_1_NODELETE to hint that this library would never unload, and could be immutable. Pass a seperate flag for our purposes Noticed from regress tests by anton, ok kettenis --- libexec/ld.so/dlfcn.c | 4 ++-- libexec/ld.so/library.c | 5 +++-- libexec/ld.so/library_mquery.c | 5 +++-- libexec/ld.so/library_subr.c | 7 ++++--- libexec/ld.so/loader.c | 12 ++++-------- libexec/ld.so/resolve.h | 15 ++++++++++++--- 6 files changed, 28 insertions(+), 20 deletions(-) diff --git a/libexec/ld.so/dlfcn.c b/libexec/ld.so/dlfcn.c index adde27790a8..0881a10f45b 100644 --- a/libexec/ld.so/dlfcn.c +++ b/libexec/ld.so/dlfcn.c @@ -1,4 +1,4 @@ -/* $OpenBSD: dlfcn.c,v 1.111 2022/08/20 14:11:31 sthen Exp $ */ +/* $OpenBSD: dlfcn.c,v 1.112 2022/11/07 10:35:26 deraadt Exp $ */ /* * Copyright (c) 1998 Per Fogelstrom, Opsycon AB @@ -90,7 +90,7 @@ dlopen(const char *libname, int flags) | (flags & RTLD_GLOBAL ? DF_1_GLOBAL : 0) | (flags & RTLD_NOLOAD ? DF_1_NOOPEN : 0) ; - object = _dl_load_shlib(libname, _dl_objects, OBJTYPE_DLO, obj_flags); + object = _dl_load_shlib(libname, _dl_objects, OBJTYPE_DLO, obj_flags, 0); if (object == 0) { DL_DEB(("dlopen: failed to open %s\n", libname)); failed = 1; diff --git a/libexec/ld.so/library.c b/libexec/ld.so/library.c index f8f6b991477..eb641d99c53 100644 --- a/libexec/ld.so/library.c +++ b/libexec/ld.so/library.c @@ -1,4 +1,4 @@ -/* $OpenBSD: library.c,v 1.87 2022/08/20 14:11:31 sthen Exp $ */ +/* $OpenBSD: library.c,v 1.88 2022/11/07 10:35:26 deraadt Exp $ */ /* * Copyright (c) 2002 Dale Rahn @@ -96,7 +96,7 @@ unload: } elf_object_t * -_dl_tryload_shlib(const char *libname, int type, int flags) +_dl_tryload_shlib(const char *libname, int type, int flags, int nodelete) { int libfile, i; struct load_list *next_load, *load_list = NULL; @@ -315,6 +315,7 @@ _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->nodelete = nodelete; object->relro_addr = relro_addr; object->relro_size = relro_size; _dl_set_sod(object->load_name, &object->sod); diff --git a/libexec/ld.so/library_mquery.c b/libexec/ld.so/library_mquery.c index 29893bdc6b2..6903263b7f9 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.67 2022/08/20 14:11:31 sthen Exp $ */ +/* $OpenBSD: library_mquery.c,v 1.68 2022/11/07 10:35:26 deraadt Exp $ */ /* * Copyright (c) 2002 Dale Rahn @@ -101,7 +101,7 @@ unload: elf_object_t * -_dl_tryload_shlib(const char *libname, int type, int flags) +_dl_tryload_shlib(const char *libname, int type, int flags, int nodelete) { int libfile, i; struct load_list *ld, *lowld = NULL; @@ -322,6 +322,7 @@ retry: object->dev = sb.st_dev; object->inode = sb.st_ino; object->obj_flags |= flags; + object->nodelete = nodelete; object->relro_addr = relro_addr; object->relro_size = relro_size; _dl_set_sod(object->load_name, &object->sod); diff --git a/libexec/ld.so/library_subr.c b/libexec/ld.so/library_subr.c index f8c059ee249..c7826c336fe 100644 --- a/libexec/ld.so/library_subr.c +++ b/libexec/ld.so/library_subr.c @@ -1,4 +1,4 @@ -/* $OpenBSD: library_subr.c,v 1.52 2022/08/20 14:11:31 sthen Exp $ */ +/* $OpenBSD: library_subr.c,v 1.53 2022/11/07 10:35:26 deraadt Exp $ */ /* * Copyright (c) 2002 Dale Rahn @@ -310,7 +310,8 @@ _dl_find_loaded_shlib(const char *req_name, struct sod req_sod, int flags) */ elf_object_t * -_dl_load_shlib(const char *libname, elf_object_t *parent, int type, int flags) +_dl_load_shlib(const char *libname, elf_object_t *parent, int type, int flags, + int nodelete) { int try_any_minor, ignore_hints; struct sod sod, req_sod; @@ -423,7 +424,7 @@ done: "using it anyway\n", sod.sod_name, sod.sod_major, req_sod.sod_minor, sod.sod_minor); - object = _dl_tryload_shlib(hint, type, flags); + object = _dl_tryload_shlib(hint, type, flags, nodelete); } _dl_free((char *)sod.sod_name); return(object); diff --git a/libexec/ld.so/loader.c b/libexec/ld.so/loader.c index 1a34127ab81..c0cf506cbd7 100644 --- a/libexec/ld.so/loader.c +++ b/libexec/ld.so/loader.c @@ -1,4 +1,4 @@ -/* $OpenBSD: loader.c,v 1.200 2022/11/06 12:00:20 deraadt Exp $ */ +/* $OpenBSD: loader.c,v 1.201 2022/11/07 10:35:26 deraadt Exp $ */ /* * Copyright (c) 1998 Per Fogelstrom, Opsycon AB @@ -247,7 +247,7 @@ _dl_dopreload(char *paths) dp = paths; while ((cp = _dl_strsep(&dp, ":")) != NULL) { shlib = _dl_load_shlib(cp, _dl_objects, OBJTYPE_LIB, - _dl_objects->obj_flags); + _dl_objects->obj_flags, 1); if (shlib == NULL) _dl_die("can't preload library '%s'", cp); _dl_add_object(shlib); @@ -326,10 +326,6 @@ _dl_load_dep_libs(elf_object_t *object, int flags, int booting) /* propagate DF_1_NOW to deplibs (can be set by dynamic tags) */ depflags = flags | (dynobj->obj_flags & DF_1_NOW); - /* Startup libraries are never unmapped and can be immutable */ - if (booting) - depflags |= DF_1_NODELETE; - for (dynp = dynobj->load_dyn; dynp->d_tag; dynp++) { if (dynp->d_tag == DT_NEEDED) { libcount++; @@ -379,7 +375,7 @@ _dl_load_dep_libs(elf_object_t *object, int flags, int booting) DL_DEB(("loading: %s required by %s\n", libname, dynobj->load_name)); depobj = _dl_load_shlib(libname, dynobj, - OBJTYPE_LIB, depflags); + OBJTYPE_LIB, depflags, booting); if (depobj == 0) { if (booting) { _dl_die( @@ -811,7 +807,7 @@ _dl_relro(elf_object_t *object) _dl_mprotect((void *)addr, object->relro_size, PROT_READ); /* if library will never be unloaded, RELRO can be immutable */ - if ((object->obj_flags & DF_1_NODELETE)) + if (object->nodelete) _dl_mimmutable((void *)addr, object->relro_size); } } diff --git a/libexec/ld.so/resolve.h b/libexec/ld.so/resolve.h index ede1701326f..941ab891110 100644 --- a/libexec/ld.so/resolve.h +++ b/libexec/ld.so/resolve.h @@ -1,4 +1,4 @@ -/* $OpenBSD: resolve.h,v 1.101 2022/08/20 14:11:31 sthen Exp $ */ +/* $OpenBSD: resolve.h,v 1.102 2022/11/07 10:35:26 deraadt Exp $ */ /* * Copyright (c) 1998 Per Fogelstrom, Opsycon AB @@ -77,6 +77,12 @@ struct object_vector { }; void object_vec_grow(struct object_vector *_vec, int _more); +struct mutate { + vaddr_t start; + vaddr_t end; + int valid; +}; + /* * Structure describing a loaded object. * The head of this struct must be compatible @@ -163,6 +169,7 @@ struct elf_object { #define OBJTYPE_LIB 3 #define OBJTYPE_DLO 4 int obj_flags; /* c.f. DF_1_* */ + int nodelete; /* shared by ELF and GNU hash */ u_int32_t nbuckets; @@ -256,8 +263,10 @@ void _dl_remove_object(elf_object_t *object); void _dl_cleanup_objects(void); void _dl_handle_already_loaded(elf_object_t *_object, int _flags); -elf_object_t *_dl_load_shlib(const char *, elf_object_t *, int, int); -elf_object_t *_dl_tryload_shlib(const char *libname, int type, int flags); +elf_object_t *_dl_load_shlib(const char *, elf_object_t *, + int, int, int nodelete); +elf_object_t *_dl_tryload_shlib(const char *libname, int type, + int flags, int nodelete); int _dl_md_reloc(elf_object_t *object, int rel, int relsz); int _dl_md_reloc_got(elf_object_t *object, int lazy); -- 2.20.1