Source-Changes-HG archive

[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index][Old Index]

[src/trunk]: src Add support for DF_1_BIND_NOW, DF_1_NODELETE and DF_1_NOOPEN...



details:   https://anonhg.NetBSD.org/src/rev/466ddeff3880
branches:  trunk
changeset: 760018:466ddeff3880
user:      skrll <skrll%NetBSD.org@localhost>
date:      Fri Dec 24 12:41:42 2010 +0000

description:
Add support for DF_1_BIND_NOW, DF_1_NODELETE and DF_1_NOOPEN marked
objects, and the RTLD_NODELETE and RTLD_NOLOAD flags to dlopen(3).

Mark libpthread as DF_1_NOOPEN and use it to test the functionality.

Somewhat taken from FreeBSD.

Fixes PR 42029.

OK from christos and joerg.

diffstat:

 distrib/sets/lists/tests/mi              |   7 +++-
 include/dlfcn.h                          |   4 +-
 lib/libpthread/Makefile                  |   4 +-
 libexec/ld.elf_so/headers.c              |  12 ++++-
 libexec/ld.elf_so/load.c                 |  49 +++++++++++++++++++-----
 libexec/ld.elf_so/reloc.c                |   6 +-
 libexec/ld.elf_so/rtld.c                 |  55 +++++++++++++++++++++++----
 libexec/ld.elf_so/rtld.h                 |  24 ++++++++++--
 libexec/ld.elf_so/search.c               |  29 ++++++++++----
 share/man/man3/dlfcn.3                   |  48 +++++++++++++++++------
 sys/sys/exec_elf.h                       |   5 ++-
 tests/libexec/ld.elf_so/Makefile         |  12 ++++++
 tests/libexec/ld.elf_so/h_df_1_noopen.c  |  46 +++++++++++++++++++++++
 tests/libexec/ld.elf_so/t_df_1_noopen.sh |  64 ++++++++++++++++++++++++++++++++
 14 files changed, 310 insertions(+), 55 deletions(-)

diffs (truncated from 822 to 300 lines):

diff -r fbef68fb0d56 -r 466ddeff3880 distrib/sets/lists/tests/mi
--- a/distrib/sets/lists/tests/mi       Fri Dec 24 10:11:39 2010 +0000
+++ b/distrib/sets/lists/tests/mi       Fri Dec 24 12:41:42 2010 +0000
@@ -1,4 +1,4 @@
-# $NetBSD: mi,v 1.187 2010/12/23 15:27:44 pgoyette Exp $
+# $NetBSD: mi,v 1.188 2010/12/24 12:41:42 skrll Exp $
 #
 # Note: don't delete entries from here - mark them as "obsolete" instead.
 #
@@ -387,6 +387,8 @@
 ./usr/libdata/debug/usr/tests/lib/libutil/t_sockaddr_snprintf.debug    tests-lib-debug         debug,atf
 ./usr/libdata/debug/usr/tests/libexec                                  tests-lib-debug
 ./usr/libdata/debug/usr/tests/libexec/ld.elf_so                                tests-libexec-debug
+./usr/libdata/debug/usr/tests/libexec/ld.elf_so/h_df_1_noopen1.debug   tests-libexec-debug     debug,atf
+./usr/libdata/debug/usr/tests/libexec/ld.elf_so/h_df_1_noopen2.debug   tests-libexec-debug     debug,atf
 ./usr/libdata/debug/usr/tests/libexec/ld.elf_so/t_dlerror-cleared.debug        tests-libexec-debug     debug,atf
 ./usr/libdata/debug/usr/tests/libexec/ld.elf_so/t_dlerror-false.debug  tests-libexec-debug     debug,atf
 ./usr/libdata/debug/usr/tests/libexec/ld.elf_so/t_dlinfo.debug         tests-libexec-debug     debug,atf
@@ -1632,6 +1634,9 @@
 ./usr/tests/libexec/Atffile                    tests-lib-tests         atf
 ./usr/tests/libexec/ld.elf_so                  tests-libexec-tests
 ./usr/tests/libexec/ld.elf_so/Atffile          tests-libexec-tests     atf
+./usr/tests/libexec/ld.elf_so/h_df_1_noopen1   tests-libexec-tests     atf
+./usr/tests/libexec/ld.elf_so/h_df_1_noopen2   tests-libexec-tests     atf
+./usr/tests/libexec/ld.elf_so/t_df_1_noopen    tests-libexec-tests     atf
 ./usr/tests/libexec/ld.elf_so/t_dlerror-cleared        tests-libexec-tests     atf
 ./usr/tests/libexec/ld.elf_so/t_dlerror-false  tests-libexec-tests     atf
 ./usr/tests/libexec/ld.elf_so/t_dlinfo         tests-libexec-tests     atf
diff -r fbef68fb0d56 -r 466ddeff3880 include/dlfcn.h
--- a/include/dlfcn.h   Fri Dec 24 10:11:39 2010 +0000
+++ b/include/dlfcn.h   Fri Dec 24 12:41:42 2010 +0000
@@ -1,4 +1,4 @@
-/*     $NetBSD: dlfcn.h,v 1.21 2010/01/07 07:35:35 skrll Exp $ */
+/*     $NetBSD: dlfcn.h,v 1.22 2010/12/24 12:41:42 skrll Exp $ */
 
 /*-
  * Copyright (c) 1998 The NetBSD Foundation, Inc.
@@ -64,6 +64,8 @@
 #define RTLD_NOW       2
 #define RTLD_GLOBAL    0x100           /* Allow global searches in object */
 #define RTLD_LOCAL     0x200
+#define RTLD_NODELETE  0x01000         /* Do not remove members. */
+#define RTLD_NOLOAD    0x02000         /* Do not load if not already loaded. */
 #if defined(_NETBSD_SOURCE)
 #define DL_LAZY                RTLD_LAZY       /* Compat */
 #endif
diff -r fbef68fb0d56 -r 466ddeff3880 lib/libpthread/Makefile
--- a/lib/libpthread/Makefile   Fri Dec 24 10:11:39 2010 +0000
+++ b/lib/libpthread/Makefile   Fri Dec 24 12:41:42 2010 +0000
@@ -1,4 +1,4 @@
-#      $NetBSD: Makefile,v 1.70 2010/08/06 05:35:42 christos Exp $
+#      $NetBSD: Makefile,v 1.71 2010/12/24 12:41:42 skrll Exp $
 #
 
 WARNS= 4
@@ -33,6 +33,8 @@
 
 LIB=   pthread
 
+LDFLAGS+=      -Wl,-znodlopen
+
 #
 # NOTE: When you create a new file for libpthread, make sure that pthread.c
 # gets a reference to a symbol in that file.  Otherwise, Unix's stupid static
diff -r fbef68fb0d56 -r 466ddeff3880 libexec/ld.elf_so/headers.c
--- a/libexec/ld.elf_so/headers.c       Fri Dec 24 10:11:39 2010 +0000
+++ b/libexec/ld.elf_so/headers.c       Fri Dec 24 12:41:42 2010 +0000
@@ -1,4 +1,4 @@
-/*     $NetBSD: headers.c,v 1.37 2010/10/16 17:48:12 skrll Exp $        */
+/*     $NetBSD: headers.c,v 1.38 2010/12/24 12:41:43 skrll Exp $        */
 
 /*
  * Copyright 1996 John D. Polstra.
@@ -40,7 +40,7 @@
 
 #include <sys/cdefs.h>
 #ifndef lint
-__RCSID("$NetBSD: headers.c,v 1.37 2010/10/16 17:48:12 skrll Exp $");
+__RCSID("$NetBSD: headers.c,v 1.38 2010/12/24 12:41:43 skrll Exp $");
 #endif /* not lint */
 
 #include <err.h>
@@ -242,8 +242,14 @@
                        break;
 #endif
                case DT_FLAGS_1:
-                       obj->initfirst =
+                       obj->z_now =
+                           ((dynp->d_un.d_val & DF_1_BIND_NOW) != 0);
+                       obj->z_nodelete =
+                           ((dynp->d_un.d_val & DF_1_NODELETE) != 0);
+                       obj->z_initfirst =
                            ((dynp->d_un.d_val & DF_1_INITFIRST) != 0);
+                       obj->z_noopen =
+                           ((dynp->d_un.d_val & DF_1_NOOPEN) != 0);
                        break;
                }
        }
diff -r fbef68fb0d56 -r 466ddeff3880 libexec/ld.elf_so/load.c
--- a/libexec/ld.elf_so/load.c  Fri Dec 24 10:11:39 2010 +0000
+++ b/libexec/ld.elf_so/load.c  Fri Dec 24 12:41:42 2010 +0000
@@ -1,4 +1,4 @@
-/*     $NetBSD: load.c,v 1.41 2010/12/19 17:26:51 skrll Exp $   */
+/*     $NetBSD: load.c,v 1.42 2010/12/24 12:41:43 skrll Exp $   */
 
 /*
  * Copyright 1996 John D. Polstra.
@@ -40,7 +40,7 @@
 
 #include <sys/cdefs.h>
 #ifndef lint
-__RCSID("$NetBSD: load.c,v 1.41 2010/12/19 17:26:51 skrll Exp $");
+__RCSID("$NetBSD: load.c,v 1.42 2010/12/24 12:41:43 skrll Exp $");
 #endif /* not lint */
 
 #include <err.h>
@@ -109,7 +109,7 @@
  * on failure.
  */
 Obj_Entry *
-_rtld_load_object(const char *filepath, int mode)
+_rtld_load_object(const char *filepath, int flags)
 {
        Obj_Entry *obj;
        int fd = -1;
@@ -153,6 +153,18 @@
                        return NULL;
                _rtld_digest_dynamic(filepath, obj);
 
+               if (flags & _RTLD_DLOPEN) {
+                       if (obj->z_noopen || (flags & _RTLD_NOLOAD)) {
+                               dbg(("refusing to load non-loadable \"%s\"",
+                                   obj->path));
+                               _rtld_error("Cannot dlopen non-loadable %s",
+                                   obj->path);
+                               munmap(obj->mapbase, obj->mapsize);
+                               _rtld_obj_free(obj);
+                               return OBJ_ERR;
+                       }
+               }
+
                *_rtld_objtail = obj;
                _rtld_objtail = &obj->next;
                _rtld_objcount++;
@@ -168,12 +180,12 @@
 
        ++obj->refcount;
 #ifdef RTLD_LOADER
-       if (mode & RTLD_MAIN && !obj->mainref) {
+       if (flags & _RTLD_MAIN && !obj->mainref) {
                obj->mainref = 1;
                dbg(("adding %p (%s) to _rtld_list_main", obj, obj->path));
                _rtld_objlist_push_tail(&_rtld_list_main, obj);
        }
-       if (mode & RTLD_GLOBAL && !obj->globalref) {
+       if (flags & _RTLD_GLOBAL && !obj->globalref) {
                obj->globalref = 1;
                dbg(("adding %p (%s) to _rtld_list_global", obj, obj->path));
                _rtld_objlist_push_tail(&_rtld_list_global, obj);
@@ -183,7 +195,8 @@
 }
 
 static bool
-_rtld_load_by_name(const char *name, Obj_Entry *obj, Needed_Entry **needed, int mode)
+_rtld_load_by_name(const char *name, Obj_Entry *obj, Needed_Entry **needed,
+    int flags)
 {
        Library_Xform *x = _rtld_xforms;
        Obj_Entry *o = NULL;
@@ -240,7 +253,7 @@
                for (j = 0; j < RTLD_MAX_LIBRARY &&
                    x->entry[i].library[j] != NULL; j++) {
                        o = _rtld_load_library(x->entry[i].library[j], obj,
-                           mode);
+                           flags);
                        if (o == NULL) {
                                xwarnx("could not load %s for %s",
                                    x->entry[i].library[j], name);
@@ -266,7 +279,7 @@
        if (got)
                return true;
 
-       return ((*needed)->obj = _rtld_load_library(name, obj, mode)) != NULL;
+       return ((*needed)->obj = _rtld_load_library(name, obj, flags)) != NULL;
 }
 
 
@@ -276,7 +289,7 @@
  * returns -1 on failure.
  */
 int
-_rtld_load_needed_objects(Obj_Entry *first, int mode)
+_rtld_load_needed_objects(Obj_Entry *first, int flags)
 {
        Obj_Entry *obj;
        int status = 0;
@@ -287,11 +300,25 @@
                for (needed = obj->needed; needed != NULL;
                    needed = needed->next) {
                        const char *name = obj->strtab + needed->name;
-                       if (!_rtld_load_by_name(name, obj, &needed, mode))
+#ifdef RTLD_LOADER
+                       Obj_Entry *nobj;
+#endif
+                       if (!_rtld_load_by_name(name, obj, &needed,
+                           flags & ~_RTLD_NOLOAD))
                                status = -1;    /* FIXME - cleanup */
 #ifdef RTLD_LOADER
                        if (status == -1)
                                return status;
+
+                       if (flags & _RTLD_MAIN)
+                               continue;
+
+                       nobj = needed->obj;
+                       if (nobj->z_nodelete && !obj->ref_nodel) {
+                               dbg(("obj %s nodelete", nobj->path));
+                               _rtld_ref_dag(nobj);
+                               nobj->ref_nodel = true;
+                       }
 #endif
                }
        }
@@ -310,7 +337,7 @@
        if (preload_path != NULL && *preload_path != '\0') {
                cp = buf = xstrdup(preload_path);
                while ((path = strsep(&cp, " :")) != NULL && status == 0) {
-                       if (!_rtld_load_object(path, RTLD_MAIN))
+                       if (!_rtld_load_object(path, _RTLD_MAIN))
                                status = -1;
                        else
                                dbg((" preloaded \"%s\"", path));
diff -r fbef68fb0d56 -r 466ddeff3880 libexec/ld.elf_so/reloc.c
--- a/libexec/ld.elf_so/reloc.c Fri Dec 24 10:11:39 2010 +0000
+++ b/libexec/ld.elf_so/reloc.c Fri Dec 24 12:41:42 2010 +0000
@@ -1,4 +1,4 @@
-/*     $NetBSD: reloc.c,v 1.102 2010/04/05 14:01:26 joerg Exp $         */
+/*     $NetBSD: reloc.c,v 1.103 2010/12/24 12:41:43 skrll Exp $         */
 
 /*
  * Copyright 1996 John D. Polstra.
@@ -39,7 +39,7 @@
 
 #include <sys/cdefs.h>
 #ifndef lint
-__RCSID("$NetBSD: reloc.c,v 1.102 2010/04/05 14:01:26 joerg Exp $");
+__RCSID("$NetBSD: reloc.c,v 1.103 2010/12/24 12:41:43 skrll Exp $");
 #endif /* not lint */
 
 #include <err.h>
@@ -195,7 +195,7 @@
 #if defined(__hppa__)
                bind_now = 1;
 #endif
-               if (bind_now) {
+               if (obj->z_now || bind_now) {
                        dbg(("doing immediate PLT binding"));
                        if (_rtld_relocate_plt_objects(obj) < 0)
                                ok = 0;
diff -r fbef68fb0d56 -r 466ddeff3880 libexec/ld.elf_so/rtld.c
--- a/libexec/ld.elf_so/rtld.c  Fri Dec 24 10:11:39 2010 +0000
+++ b/libexec/ld.elf_so/rtld.c  Fri Dec 24 12:41:42 2010 +0000
@@ -1,4 +1,4 @@
-/*     $NetBSD: rtld.c,v 1.136 2010/12/19 17:26:51 skrll Exp $  */
+/*     $NetBSD: rtld.c,v 1.137 2010/12/24 12:41:43 skrll Exp $  */
 
 /*
  * Copyright 1996 John D. Polstra.
@@ -40,7 +40,7 @@
 
 #include <sys/cdefs.h>
 #ifndef lint
-__RCSID("$NetBSD: rtld.c,v 1.136 2010/12/19 17:26:51 skrll Exp $");
+__RCSID("$NetBSD: rtld.c,v 1.137 2010/12/24 12:41:43 skrll Exp $");
 #endif /* not lint */
 
 #include <err.h>
@@ -147,7 +147,7 @@
                if (obj->refcount > 0 && !force) {
                        continue;
                }
-               if (obj->fini == NULL || obj->fini_called || obj->initfirst) {
+               if (obj->fini == NULL || obj->fini_called || obj->z_initfirst) {
                        continue;
                }
                dbg (("calling fini function %s at %p",  obj->path,
@@ -188,7 +188,7 @@
        /* First pass: objects marked with DF_1_INITFIRST. */
        SIMPLEQ_FOREACH(elm, &initlist, link) {
                obj = elm->obj;
-               if (obj->init == NULL || obj->init_called || !obj->initfirst) {
+               if (obj->init == NULL || obj->init_called || !obj->z_initfirst) {
                        continue;
                }
                dbg (("calling init function %s at %p (DF_1_INITFIRST)",
@@ -568,7 +568,7 @@
        }
 
        dbg(("loading needed objects"));
-       if (_rtld_load_needed_objects(_rtld_objmain, RTLD_MAIN) == -1)



Home | Main Index | Thread Index | Old Index