Seeing your e-mail reminded me that I had asked Philip about adding
support for RTLD_NOLOAD / RTLD_NODELETE last year after seeing instances
of their usage in the tree here and there.


----- Forwarded message from Philip Guenther <[email protected]> -----

Date: Thu, 24 Sep 2020 23:19:27 -0700
From: Philip Guenther <[email protected]>
To: Brad Smith <[email protected]>
Subject: Re: dlopen & RTLD_NOLOAD / RTLD_NODELETE
User-Agent: Alpine 2.21 (BSO 202 2017-01-01)

On Sat, 19 Sep 2020, Brad Smith wrote:
> On 8/31/2020 12:24 AM, Philip Guenther wrote:
> > On Sun, 30 Aug 2020, Brad Smith wrote:
> > > Is there any chance that OpenBSD's dlopen() could have support for
> > > RTLD_NOLOAD / RTLD_NODELETE added? Specifically RTLD_NOLOAD as I've had
> > > a patch in MariaDB for ages to allow building on OpenBSD.
> > Sigh.  The hard part is writing the regress.
> 
> Is that a no?

The noload bits are completely untested.

Index: include/dlfcn.h
===================================================================
RCS file: /data/src/openbsd/src/include/dlfcn.h,v
retrieving revision 1.14
diff -u -p -r1.14 dlfcn.h
--- include/dlfcn.h     28 Nov 2017 17:19:47 -0000      1.14
+++ include/dlfcn.h     31 Aug 2020 00:55:55 -0000
@@ -42,6 +42,8 @@
 #define RTLD_GLOBAL    0x100
 #define RTLD_LOCAL     0x000
 #define RTLD_TRACE     0x200
+#define RTLD_NODELETE  0x400
+#define RTLD_NOLOAD    0x800
 
 /*
  * Special handle arguments for dlsym().
Index: libexec/ld.so/dlfcn.c
===================================================================
RCS file: /data/src/openbsd/src/libexec/ld.so/dlfcn.c,v
retrieving revision 1.106
diff -u -p -r1.106 dlfcn.c
--- libexec/ld.so/dlfcn.c       4 Oct 2019 17:42:16 -0000       1.106
+++ libexec/ld.so/dlfcn.c       1 Sep 2020 05:04:40 -0000
@@ -46,6 +46,15 @@ static int _dl_real_close(void *handle);
 static lock_cb *_dl_thread_fnc = NULL;
 static elf_object_t *obj_from_addr(const void *addr);
 
+#define OK_FLAGS       (0 \
+       | RTLD_TRACE    \
+       | RTLD_LAZY     \
+       | RTLD_NOW      \
+       | RTLD_GLOBAL   \
+       | RTLD_NODELETE \
+       | RTLD_NOLOAD   \
+       )
+
 void *
 dlopen(const char *libname, int flags)
 {
@@ -54,7 +63,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 & ~OK_FLAGS) {
                _dl_errno = DL_INVALID_MODE;
                return NULL;
        }
@@ -79,7 +88,10 @@ dlopen(const char *libname, int flags)
        _dl_loading_object = NULL;
 
        obj_flags = (flags & RTLD_NOW ? DF_1_NOW : 0)
-           | (flags & RTLD_GLOBAL ? DF_1_GLOBAL : 0);
+           | (flags & RTLD_GLOBAL ? DF_1_GLOBAL : 0)
+           | (flags & RTLD_NODELETE ? DF_1_NODELETE : 0)
+           | (flags & RTLD_NOLOAD ? DF_1_NOOPEN : 0)
+           ;
        object = _dl_load_shlib(libname, _dl_objects, OBJTYPE_DLO, obj_flags);
        if (object == 0) {
                DL_DEB(("dlopen: failed to open %s\n", libname));
@@ -93,6 +105,10 @@ dlopen(const char *libname, int flags)
                /* if opened but grpsym_vec has not been filled in */
                if (object->grpsym_vec.len == 0)
                        _dl_cache_grpsym_list_setup(object);
+               if (flags & RTLD_NODELETE) {
+                       object->obj_flags |= DF_1_NODELETE;
+                       _dl_handle_nodelete(object);
+               }
                goto loaded;
        }
 
Index: libexec/ld.so/library.c
===================================================================
RCS file: /data/src/openbsd/src/libexec/ld.so/library.c,v
retrieving revision 1.85
diff -u -p -r1.85 library.c
--- libexec/ld.so/library.c     9 Dec 2019 22:15:15 -0000       1.85
+++ libexec/ld.so/library.c     31 Aug 2020 01:36:06 -0000
@@ -127,17 +127,14 @@ _dl_tryload_shlib(const char *libname, i
        for (object = _dl_objects; object != NULL; object = object->next) {
                if (object->dev == sb.st_dev &&
                    object->inode == sb.st_ino) {
-                       object->obj_flags |= flags & DF_1_GLOBAL;
                        _dl_close(libfile);
-                       if (_dl_loading_object == NULL)
-                               _dl_loading_object = object;
-                       if (object->load_object != _dl_objects &&
-                           object->load_object != _dl_loading_object) {
-                               _dl_link_grpref(object->load_object,
-                                   _dl_loading_object);
-                       }
+                       _dl_handle_already_loaded(object, flags);
                        return(object);
                }
+       }
+       if (flags & DF_1_NOOPEN) {
+               _dl_close(libfile);
+               return NULL;
        }
 
        _dl_read(libfile, hbuf, sizeof(hbuf));
Index: libexec/ld.so/library_mquery.c
===================================================================
RCS file: /data/src/openbsd/src/libexec/ld.so/library_mquery.c,v
retrieving revision 1.64
diff -u -p -r1.64 library_mquery.c
--- libexec/ld.so/library_mquery.c      9 Dec 2019 23:15:03 -0000       1.64
+++ libexec/ld.so/library_mquery.c      31 Aug 2020 01:36:00 -0000
@@ -134,15 +134,13 @@ _dl_tryload_shlib(const char *libname, i
                    object->inode == sb.st_ino) {
                        object->obj_flags |= flags & DF_1_GLOBAL;
                        _dl_close(libfile);
-                       if (_dl_loading_object == NULL)
-                               _dl_loading_object = object;
-                       if (object->load_object != _dl_objects &&
-                           object->load_object != _dl_loading_object) {
-                               _dl_link_grpref(object->load_object,
-                                   _dl_loading_object);
-                       }
+                       _dl_handle_already_loaded(object, flags);
                        return(object);
                }
+       }
+       if (flags & DF_1_NOOPEN) {
+               _dl_close(libfile);
+               return NULL;
        }
 
        _dl_read(libfile, hbuf, sizeof(hbuf));
Index: libexec/ld.so/library_subr.c
===================================================================
RCS file: /data/src/openbsd/src/libexec/ld.so/library_subr.c,v
retrieving revision 1.50
diff -u -p -r1.50 library_subr.c
--- libexec/ld.so/library_subr.c        4 Oct 2019 17:42:16 -0000       1.50
+++ libexec/ld.so/library_subr.c        25 Sep 2020 06:13:30 -0000
@@ -241,6 +241,18 @@ _dl_lookup_object(const char *req_name, 
        return(NULL);
 }
 
+void
+_dl_handle_already_loaded(elf_object_t *object, int flags)
+{
+       object->obj_flags |= flags & DF_1_GLOBAL;
+       if (_dl_loading_object == NULL)
+               _dl_loading_object = object;
+       if (object->load_object != _dl_objects &&
+           object->load_object != _dl_loading_object) {
+               _dl_link_grpref(object->load_object, _dl_loading_object);
+       }
+}
+
 static elf_object_t *
 _dl_find_loaded_shlib(const char *req_name, struct sod req_sod, int flags)
 {
@@ -262,15 +274,8 @@ _dl_find_loaded_shlib(const char *req_na
                            req_sod.sod_minor, orig_minor);
        }
 
-       if (object) {   /* Already loaded */
-               object->obj_flags |= flags & DF_1_GLOBAL;
-               if (_dl_loading_object == NULL)
-                       _dl_loading_object = object;
-               if (object->load_object != _dl_objects &&
-                   object->load_object != _dl_loading_object) {
-                       _dl_link_grpref(object->load_object, 
_dl_loading_object);
-               }
-       }
+       if (object)
+               _dl_handle_already_loaded(object, flags);
 
        return (object);
 }
Index: libexec/ld.so/resolve.c
===================================================================
RCS file: /data/src/openbsd/src/libexec/ld.so/resolve.c,v
retrieving revision 1.94
diff -u -p -r1.94 resolve.c
--- libexec/ld.so/resolve.c     4 Oct 2019 17:42:16 -0000       1.94
+++ libexec/ld.so/resolve.c     25 Sep 2020 06:13:26 -0000
@@ -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
Index: libexec/ld.so/resolve.h
===================================================================
RCS file: /data/src/openbsd/src/libexec/ld.so/resolve.h,v
retrieving revision 1.96
diff -u -p -r1.96 resolve.h
--- libexec/ld.so/resolve.h     4 Oct 2019 17:42:16 -0000       1.96
+++ libexec/ld.so/resolve.h     31 Aug 2020 01:26:30 -0000
@@ -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,
@@ -251,6 +252,7 @@ elf_object_t *_dl_finalize_object(const 
 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);
 

----- End forwarded message -----

Reply via email to