From 296fbf9f7d7448b007144be0153241fcd4aeed44 Mon Sep 17 00:00:00 2001 From: semarie Date: Wed, 2 Jun 2021 07:29:03 +0000 Subject: [PATCH] add RTLD_NODELETE support if RTLD_NODELETE isn't POSIX, it is widely deployed: at least linux, freebsd, dragonfly, netbsd, solaris, illumos, apple, and fuchsia have it. ok kettenis@ on previous version with help from and ok guenther@ diff partially inspired from a diff from brad@ --- include/dlfcn.h | 3 ++- lib/libc/shlib_version | 2 +- libexec/ld.so/dlfcn.c | 9 +++++++-- libexec/ld.so/resolve.c | 16 +++++++++++----- libexec/ld.so/resolve.h | 3 ++- share/man/man3/dlfcn.3 | 12 ++++++++++-- 6 files changed, 33 insertions(+), 12 deletions(-) diff --git a/include/dlfcn.h b/include/dlfcn.h index 431065f3eab..4cee44748ff 100644 --- a/include/dlfcn.h +++ b/include/dlfcn.h @@ -1,4 +1,4 @@ -/* $OpenBSD: dlfcn.h,v 1.14 2017/11/28 17:19:47 kettenis Exp $ */ +/* $OpenBSD: dlfcn.h,v 1.15 2021/06/02 07:29:03 semarie Exp $ */ /* $NetBSD: dlfcn.h,v 1.2 1995/06/05 19:38:00 pk Exp $ */ /* @@ -42,6 +42,7 @@ #define RTLD_GLOBAL 0x100 #define RTLD_LOCAL 0x000 #define RTLD_TRACE 0x200 +#define RTLD_NODELETE 0x400 /* * Special handle arguments for dlsym(). diff --git a/lib/libc/shlib_version b/lib/libc/shlib_version index 06f98b01084..5fb0770494f 100644 --- a/lib/libc/shlib_version +++ b/lib/libc/shlib_version @@ -1,4 +1,4 @@ major=96 -minor=0 +minor=1 # note: If changes were made to include/thread_private.h or if system calls # were added/changed then librthread/shlib_version must also be updated. diff --git a/libexec/ld.so/dlfcn.c b/libexec/ld.so/dlfcn.c index b8d5512e32b..384b5ea97aa 100644 --- a/libexec/ld.so/dlfcn.c +++ b/libexec/ld.so/dlfcn.c @@ -1,4 +1,4 @@ -/* $OpenBSD: dlfcn.c,v 1.106 2019/10/04 17:42:16 guenther Exp $ */ +/* $OpenBSD: dlfcn.c,v 1.107 2021/06/02 07:29:03 semarie Exp $ */ /* * Copyright (c) 1998 Per Fogelstrom, Opsycon AB @@ -54,7 +54,7 @@ dlopen(const char *libname, int flags) int failed = 0; int obj_flags; - if (flags & ~(RTLD_TRACE|RTLD_LAZY|RTLD_NOW|RTLD_GLOBAL)) { + if (flags & ~(RTLD_TRACE|RTLD_LAZY|RTLD_NOW|RTLD_GLOBAL|RTLD_NODELETE)) { _dl_errno = DL_INVALID_MODE; return NULL; } @@ -87,9 +87,14 @@ dlopen(const char *libname, int flags) goto loaded; } + if (flags & RTLD_NODELETE) + object->obj_flags |= DF_1_NODELETE; + _dl_link_dlopen(object); if (OBJECT_REF_CNT(object) > 1) { + _dl_handle_nodelete(object); + /* if opened but grpsym_vec has not been filled in */ if (object->grpsym_vec.len == 0) _dl_cache_grpsym_list_setup(object); diff --git a/libexec/ld.so/resolve.c b/libexec/ld.so/resolve.c index 1d882d2109a..4d0928b4f2e 100644 --- a/libexec/ld.so/resolve.c +++ b/libexec/ld.so/resolve.c @@ -1,4 +1,4 @@ -/* $OpenBSD: resolve.c,v 1.94 2019/10/04 17:42:16 guenther Exp $ */ +/* $OpenBSD: resolve.c,v 1.95 2021/06/02 07:29:03 semarie Exp $ */ /* * Copyright (c) 1998 Per Fogelstrom, Opsycon AB @@ -57,11 +57,8 @@ int object_count; static elf_object_t *_dl_last_object; elf_object_t *_dl_loading_object; -/* - * Add a new dynamic object to the object list. - */ void -_dl_add_object(elf_object_t *object) +_dl_handle_nodelete(elf_object_t *object) { /* * If a .so is marked nodelete, then the entire load group that it's @@ -76,6 +73,15 @@ _dl_add_object(elf_object_t *object) object->load_object->opencount++; object->load_object->status |= STAT_NODELETE; } +} + +/* + * Add a new dynamic object to the object list. + */ +void +_dl_add_object(elf_object_t *object) +{ + _dl_handle_nodelete(object); /* * if this is a new object, prev will be NULL diff --git a/libexec/ld.so/resolve.h b/libexec/ld.so/resolve.h index 6c7380fb9b0..7c14005a658 100644 --- a/libexec/ld.so/resolve.h +++ b/libexec/ld.so/resolve.h @@ -1,4 +1,4 @@ -/* $OpenBSD: resolve.h,v 1.97 2021/03/16 18:03:06 kurt Exp $ */ +/* $OpenBSD: resolve.h,v 1.98 2021/06/02 07:29:03 semarie Exp $ */ /* * Copyright (c) 1998 Per Fogelstrom, Opsycon AB @@ -244,6 +244,7 @@ void _dl_debug_state(void); extern char *__progname; __BEGIN_HIDDEN_DECLS +void _dl_handle_nodelete(elf_object_t *_object); void _dl_add_object(elf_object_t *object); elf_object_t *_dl_finalize_object(const char *objname, Elf_Dyn *dynp, Elf_Phdr *phdrp, int phdrc, const int objtype, const long lbase, diff --git a/share/man/man3/dlfcn.3 b/share/man/man3/dlfcn.3 index afdf60ff428..f613f0d3bab 100644 --- a/share/man/man3/dlfcn.3 +++ b/share/man/man3/dlfcn.3 @@ -1,4 +1,4 @@ -.\" $OpenBSD: dlfcn.3,v 1.30 2020/12/03 22:47:22 jmc Exp $ +.\" $OpenBSD: dlfcn.3,v 1.31 2021/06/02 07:29:03 semarie Exp $ .\" $NetBSD: dlfcn.3,v 1.3 1996/01/09 19:43:34 pk Exp $ .\" .\" Copyright (c) 1995 Paul Kranenburg @@ -29,7 +29,7 @@ .\" (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF .\" THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. .\" -.Dd $Mdocdate: December 3 2020 $ +.Dd $Mdocdate: June 2 2021 $ .Dt DLOPEN 3 .Os .Sh NAME @@ -124,6 +124,14 @@ each of the above values together. If an object was opened with RTLD_LOCAL and later opened with RTLD_GLOBAL, then it is promoted to RTLD_GLOBAL. .Pp +Additionally, the following flag may be ORed into the mode argument: +.Pp +.Bl -tag -width "RTLD_NODELETE" -compact -offset indent +.It Sy RTLD_NODELETE +Prevents unload of the loaded object on +.Fn dlclose . +.El +.Pp The main executable's symbols are normally invisible to .Fn dlopen symbol resolution. -- 2.20.1