diff options
Diffstat (limited to 'elf/dl-load.c')
-rw-r--r-- | elf/dl-load.c | 152 |
1 files changed, 137 insertions, 15 deletions
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. */ |