From 9dcafc559763e339d4a79580c333127033e39c11 Mon Sep 17 00:00:00 2001 From: Ulrich Drepper Date: Thu, 6 Jan 2005 22:40:27 +0000 Subject: * csu/elf-init.c (__libc_csu_fini): Don't do anything here. * sysdeps/generic/libc-start.c: Don't register program destructor here. * dlfcn/Makefile: Add rules to build dlfcn.c. (LDFLAGS-dl.so): Removed. * dlfcn/dlclose.c: _dl_close is now in ld.so, use function pointer table. * dlfcn/dlmopen.c: Likewise for _dl_open. * dlfcn/dlopen.c: Likewise. * dlfcn/dlopenold.c: Likewise. * elf/dl-libc.c: Likewise for _dl_open and _dl_close. * elf/Makefile (routines): Remove dl-open and dl-close. (dl-routines): Add dl-open, dl-close, and dl-trampoline. Add rules to build and run tst-audit1. * elf/tst-audit1.c: New file. * elf/tst-auditmod1.c: New file. * elf/Versions [libc]: Remove _dl_open and _dl_close. * elf/dl-close.c: Change for use inside ld.so instead of libc.so. * elf/dl-open.c: Likewise. * elf/dl-debug.c (_dl_debug_initialize): Allow reinitialization, signaled by nonzero parameter. * elf/dl-init.c: Fix use of r_state. * elf/dl-load.c: Likewise. * elf/dl-close.c: Add auditing checkpoints. * elf/dl-open.c: Likewise. * elf/dl-fini.c: Likewise. * elf/dl-load.c: Likewise. * elf/dl-sym.c: Likewise. * sysdeps/generic/libc-start.c: Likewise. * elf/dl-object.c: Allocate memory for auditing information. * elf/dl-reloc.c: Remove RESOLV. We now always need the map. Correctly initialize slotinfo. * elf/dynamic-link.h: Adjust after removal of RESOLV. * sysdeps/hppa/dl-lookupcfg.h: Likewise. * sysdeps/ia64/dl-lookupcfg.h: Likewise. * sysdeps/powerpc/powerpc64/dl-lookupcfg.h: Removed. * elf/dl-runtime.c (_dl_fixup): Little cleanup. (_dl_profile_fixup): New parameters to point to register struct and variable for frame size. Add auditing checkpoints. (_dl_call_pltexit): New function. Don't define trampoline code here. * elf/rtld.c: Recognize LD_AUDIT. Load modules on startup. Remove all the functions from _rtld_global_ro which only _dl_open and _dl_close needed. Add auditing checkpoints. * elf/link.h: Define symbols for auditing interfaces. * include/link.h: Likewise. * include/dlfcn.h: Define __RTLD_AUDIT. Remove prototypes for _dl_open and _dl_close. Adjust access to argc and argv in libdl. * dlfcn/dlfcn.c: New file. * sysdeps/generic/dl-lookupcfg.h: Remove all content now that RESOLVE is gone. * sysdeps/generic/ldsodefs.h: Add definitions for auditing interfaces. * sysdeps/generic/unsecvars.h: Add LD_AUDIT. * sysdeps/i386/dl-machine.h: Remove trampoline code here. Adjust for removal of RESOLVE. * sysdeps/x86_64/dl-machine.h: Likewise. * sysdeps/generic/dl-trampoline.c: New file. * sysdeps/i386/dl-trampoline.c: New file. * sysdeps/x86_64/dl-trampoline.c: New file. * sysdeps/generic/dl-tls.c: Cleanups. Fixup for dtv_t change. Fix updating of DTV. * sysdeps/generic/libc-tls.c: Likewise. * sysdeps/arm/bits/link.h: Renamed to ... * sysdeps/arm/buts/linkmap.h: ...this. * sysdeps/generic/bits/link.h: Renamed to... * sysdeps/generic/bits/linkmap.h: ...this. * sysdeps/hppa/bits/link.h: Renamed to... * sysdeps/hppa/bits/linkmap.h: ...this. * sysdeps/hppa/i386/link.h: Renamed to... * sysdeps/hppa/i386/linkmap.h: ...this. * sysdeps/hppa/ia64/link.h: Renamed to... * sysdeps/hppa/ia64/linkmap.h: ...this. * sysdeps/hppa/s390/link.h: Renamed to... * sysdeps/hppa/s390/linkmap.h: ...this. * sysdeps/hppa/sh/link.h: Renamed to... * sysdeps/hppa/sh/linkmap.h: ...this. * sysdeps/hppa/x86_64/link.h: Renamed to... * sysdeps/hppa/x86_64/linkmap.h: ...this. 2005-01-06 Ulrich Drepper * allocatestack.c (init_one_static_tls): Adjust initialization of DTV entry for static tls deallocation fix. * sysdeps/alpha/tls.h (dtv_t): Change pointer type to be struct which also contains information whether the memory pointed to is static TLS or not. * sysdeps/i386/tls.h: Likewise. * sysdeps/ia64/tls.h: Likewise. * sysdeps/powerpc/tls.h: Likewise. * sysdeps/s390/tls.h: Likewise. * sysdeps/sh/tls.h: Likewise. * sysdeps/sparc/tls.h: Likewise. * sysdeps/x86_64/tls.h: Likewise. --- elf/dl-load.c | 152 ++++++++++++++++++++++++++++++++++++++++++++++++++++------ 1 file changed, 137 insertions(+), 15 deletions(-) (limited to 'elf/dl-load.c') diff --git a/elf/dl-load.c b/elf/dl-load.c index eb1a7919fb..7f11b62bf4 100644 --- a/elf/dl-load.c +++ b/elf/dl-load.c @@ -827,6 +827,8 @@ _dl_map_object_from_fd (const char *name, int fd, struct filebuf *fbp, /* Initialize to keep the compiler happy. */ const char *errstring = NULL; int errval = 0; + struct r_debug *r = _dl_debug_initialize (0); + bool make_consistent = false; /* Get file information. */ if (__builtin_expect (__fxstat64 (_STAT_VER, fd, &st) < 0, 0)) @@ -835,6 +837,12 @@ _dl_map_object_from_fd (const char *name, int fd, struct filebuf *fbp, call_lose_errno: errval = errno; call_lose: + if (make_consistent) + { + r->r_state = RT_CONSISTENT; + _dl_debug_state (); + } + lose (errval, fd, name, realname, l, errstring); } @@ -905,6 +913,39 @@ _dl_map_object_from_fd (const char *name, int fd, struct filebuf *fbp, } #endif + /* Signal that we are going to add new objects. */ + if (r->r_state == RT_CONSISTENT) + { +#ifdef SHARED + /* Auditing checkpoint: we are going to add new objects. */ + if (__builtin_expect (GLRO(dl_naudit) > 0, 0)) + { + struct link_map *head = GL(dl_ns)[nsid]._ns_loaded; + /* Do not call the functions for any auditing object. */ + if (head->l_auditing == 0) + { + struct audit_ifaces *afct = GLRO(dl_audit); + for (unsigned int cnt = 0; cnt < GLRO(dl_naudit); ++cnt) + { + if (afct->activity != NULL) + afct->activity (&head->l_audit[cnt].cookie, LA_ACT_ADD); + + afct = afct->next; + } + } + } +#endif + + /* Notify the debugger we have added some objects. We need to + call _dl_debug_initialize in a static program in case dynamic + linking has not been used before. */ + r->r_state = RT_ADD; + _dl_debug_state (); + make_consistent = true; + } + else + assert (r->r_state == RT_ADD); + /* Enter the new object in the list of loaded objects. */ l = _dl_new_object (realname, name, l_type, loader, mode, nsid); if (__builtin_expect (l == NULL, 0)) @@ -1044,7 +1085,7 @@ _dl_map_object_from_fd (const char *name, int fd, struct filebuf *fbp, } # ifdef SHARED - if (l->l_prev == NULL) + if (l->l_prev == NULL || (mode && __RTLD_AUDIT) != 0) /* We are loading the executable itself when the dynamic linker was executed directly. The setup will happen later. */ break; @@ -1424,6 +1465,26 @@ cannot enable executable stack as shared object requires"); add_name_to_object (l, ((const char *) D_PTR (l, l_info[DT_STRTAB]) + l->l_info[DT_SONAME]->d_un.d_val)); +#ifdef SHARED + /* Auditing checkpoint: we have a new object. */ + if (__builtin_expect (GLRO(dl_naudit) > 0, 0)) + { + struct audit_ifaces *afct = GLRO(dl_audit); + for (unsigned int cnt = 0; cnt < GLRO(dl_naudit); ++cnt) + { + if (afct->objopen != NULL) + { + l->l_audit[cnt].bindflags + = afct->objopen (l, nsid, &l->l_audit[cnt].cookie); + + l->l_audit_any_plt |= l->l_audit[cnt].bindflags != 0; + } + + afct = afct->next; + } + } +#endif + return l; } @@ -1471,7 +1532,8 @@ print_search_path (struct r_search_path_elem **list, this could mean there is something wrong in the installation and the user might want to know about this. */ static int -open_verify (const char *name, struct filebuf *fbp) +open_verify (const char *name, struct filebuf *fbp, struct link_map *loader, + int whatcode) { /* This is the expected ELF header. */ #define ELF32_CLASS ELFCLASS32 @@ -1500,13 +1562,34 @@ open_verify (const char *name, struct filebuf *fbp) ElfW(Word) type; char vendor[4]; } expected_note = { 4, 16, 1, "GNU" }; - int fd; /* Initialize it to make the compiler happy. */ const char *errstring = NULL; int errval = 0; +#ifdef SHARED + /* Give the auditing libraries a chance. */ + if (__builtin_expect (GLRO(dl_naudit) > 0, 0) && whatcode != 0 + && loader->l_auditing == 0) + { + struct audit_ifaces *afct = GLRO(dl_audit); + for (unsigned int cnt = 0; cnt < GLRO(dl_naudit); ++cnt) + { + if (afct->objsearch != NULL) + { + name = afct->objsearch (name, &loader->l_audit[cnt].cookie, + whatcode); + if (name == NULL) + /* Ignore the path. */ + return -1; + } + + afct = afct->next; + } + } +#endif + /* Open the file. We always open files read-only. */ - fd = __open (name, O_RDONLY); + int fd = __open (name, O_RDONLY); if (fd != -1) { ElfW(Ehdr) *ehdr; @@ -1664,7 +1747,7 @@ open_verify (const char *name, struct filebuf *fbp) static int open_path (const char *name, size_t namelen, int preloaded, struct r_search_path_struct *sps, char **realname, - struct filebuf *fbp) + struct filebuf *fbp, struct link_map *loader, int whatcode) { struct r_search_path_elem **dirs = sps->dirs; char *buf; @@ -1708,12 +1791,16 @@ open_path (const char *name, size_t namelen, int preloaded, if (__builtin_expect (GLRO(dl_debug_mask) & DL_DEBUG_LIBS, 0)) _dl_debug_printf (" trying file=%s\n", buf); - fd = open_verify (buf, fbp); + fd = open_verify (buf, fbp, loader, whatcode); if (this_dir->status[cnt] == unknown) { if (fd != -1) this_dir->status[cnt] = existing; - else + /* Do not update the directory information when loading + auditing code. We must try to disturb the program as + little as possible. */ + else if (loader == NULL + || GL(dl_ns)[loader->l_ns]._ns_loaded->l_audit == 0) { /* We failed to open machine dependent library. Let's test whether there is any directory at all. */ @@ -1731,7 +1818,7 @@ open_path (const char *name, size_t namelen, int preloaded, } /* Remember whether we found any existing directory. */ - here_any |= this_dir->status[cnt] == existing; + here_any |= this_dir->status[cnt] != nonexisting; if (fd != -1 && __builtin_expect (preloaded, 0) && INTUSE(__libc_enable_secure)) @@ -1847,6 +1934,32 @@ _dl_map_object (struct link_map *loader, const char *name, int preloaded, loader->l_name[0] ? loader->l_name : rtld_progname, loader->l_ns); +#ifdef SHARED + /* Give the auditing libraries a chance to change the name before we + try anything. */ + if (__builtin_expect (GLRO(dl_naudit) > 0, 0) + && (loader == NULL || loader->l_auditing == 0)) + { + struct audit_ifaces *afct = GLRO(dl_audit); + for (unsigned int cnt = 0; cnt < GLRO(dl_naudit); ++cnt) + { + if (afct->objsearch != NULL) + { + name = afct->objsearch (name, &loader->l_audit[cnt].cookie, + LA_SER_ORIG); + if (name == NULL) + { + /* Do not try anything further. */ + fd = -1; + goto no_file; + } + } + + afct = afct->next; + } + } +#endif + if (strchr (name, '/') == NULL) { /* Search for NAME in several places. */ @@ -1867,7 +1980,7 @@ _dl_map_object (struct link_map *loader, const char *name, int preloaded, for (l = loader; fd == -1 && l; l = l->l_loader) if (cache_rpath (l, &l->l_rpath_dirs, DT_RPATH, "RPATH")) fd = open_path (name, namelen, preloaded, &l->l_rpath_dirs, - &realname, &fb); + &realname, &fb, loader, LA_SER_RUNPATH); /* If dynamically linked, try the DT_RPATH of the executable itself. NB: we do this for lookups in any namespace. */ @@ -1877,21 +1990,24 @@ _dl_map_object (struct link_map *loader, const char *name, int preloaded, if (l && l->l_type != lt_loaded && l != loader && cache_rpath (l, &l->l_rpath_dirs, DT_RPATH, "RPATH")) fd = open_path (name, namelen, preloaded, &l->l_rpath_dirs, - &realname, &fb); + &realname, &fb, loader ?: l, LA_SER_RUNPATH); } } /* Try the LD_LIBRARY_PATH environment variable. */ if (fd == -1 && env_path_list.dirs != (void *) -1) fd = open_path (name, namelen, preloaded, &env_path_list, - &realname, &fb); + &realname, &fb, + loader ?: GL(dl_ns)[LM_ID_BASE]._ns_loaded, + LA_SER_LIBPATH); /* Look at the RUNPATH information for this binary. */ if (fd == -1 && loader != NULL && cache_rpath (loader, &loader->l_runpath_dirs, DT_RUNPATH, "RUNPATH")) fd = open_path (name, namelen, preloaded, - &loader->l_runpath_dirs, &realname, &fb); + &loader->l_runpath_dirs, &realname, &fb, loader, + LA_SER_RUNPATH); if (fd == -1 && (__builtin_expect (! preloaded, 1) @@ -1939,7 +2055,9 @@ _dl_map_object (struct link_map *loader, const char *name, int preloaded, if (cached != NULL) { - fd = open_verify (cached, &fb); + fd = open_verify (cached, + &fb, loader ?: GL(dl_ns)[nsid]._ns_loaded, + LA_SER_CONFIG); if (__builtin_expect (fd != -1, 1)) { realname = local_strdup (cached); @@ -1959,7 +2077,7 @@ _dl_map_object (struct link_map *loader, const char *name, int preloaded, || __builtin_expect (!(l->l_flags_1 & DF_1_NODEFLIB), 1)) && rtld_search_dirs.dirs != (void *) -1) fd = open_path (name, namelen, preloaded, &rtld_search_dirs, - &realname, &fb); + &realname, &fb, l, LA_SER_DEFAULT); /* Add another newline when we are tracing the library loading. */ if (__builtin_expect (GLRO(dl_debug_mask) & DL_DEBUG_LIBS, 0)) @@ -1975,12 +2093,16 @@ _dl_map_object (struct link_map *loader, const char *name, int preloaded, fd = -1; else { - fd = open_verify (realname, &fb); + fd = open_verify (realname, &fb, + loader ?: GL(dl_ns)[nsid]._ns_loaded, 0); if (__builtin_expect (fd, 0) == -1) free (realname); } } +#ifdef SHARED + no_file: +#endif /* In case the LOADER information has only been provided to get to the appropriate RUNPATH/RPATH information we do not need it anymore. */ -- cgit 1.4.1