diff options
author | des <des@FreeBSD.org> | 2009-09-17 16:16:44 +0000 |
---|---|---|
committer | des <des@FreeBSD.org> | 2009-09-17 16:16:44 +0000 |
commit | 9ed1a4b5ebe734049aa444f14884ed8ad4c23aee (patch) | |
tree | dea5b87c905a5175efdc56037f61b7ecb2031d98 /libexec | |
parent | 5f4ee8bdfb4e4ffae101ac65837e519f1f957e43 (diff) | |
parent | 74dba11aaa299f71f2bf2b583d74575fec440e7b (diff) | |
download | FreeBSD-src-9ed1a4b5ebe734049aa444f14884ed8ad4c23aee.zip FreeBSD-src-9ed1a4b5ebe734049aa444f14884ed8ad4c23aee.tar.gz |
Merge from head
Diffstat (limited to 'libexec')
-rw-r--r-- | libexec/Makefile | 2 | ||||
-rw-r--r-- | libexec/bootpd/rtmsg.c | 2 | ||||
-rw-r--r-- | libexec/ftpd/extern.h | 29 | ||||
-rw-r--r-- | libexec/ftpd/ftpcmd.y | 27 | ||||
-rw-r--r-- | libexec/ftpd/ftpd.c | 3 | ||||
-rw-r--r-- | libexec/makekey/Makefile | 10 | ||||
-rw-r--r-- | libexec/makekey/makekey.8 | 69 | ||||
-rw-r--r-- | libexec/makekey/makekey.c | 84 | ||||
-rw-r--r-- | libexec/rtld-elf/Makefile | 2 | ||||
-rw-r--r-- | libexec/rtld-elf/Symbol.map | 1 | ||||
-rw-r--r-- | libexec/rtld-elf/amd64/rtld_machdep.h | 2 | ||||
-rw-r--r-- | libexec/rtld-elf/arm/rtld_machdep.h | 2 | ||||
-rw-r--r-- | libexec/rtld-elf/i386/rtld_machdep.h | 2 | ||||
-rw-r--r-- | libexec/rtld-elf/ia64/rtld_machdep.h | 2 | ||||
-rw-r--r-- | libexec/rtld-elf/map_object.c | 65 | ||||
-rw-r--r-- | libexec/rtld-elf/mips/rtld_machdep.h | 2 | ||||
-rw-r--r-- | libexec/rtld-elf/powerpc/rtld_machdep.h | 2 | ||||
-rw-r--r-- | libexec/rtld-elf/rtld.1 | 26 | ||||
-rw-r--r-- | libexec/rtld-elf/rtld.c | 307 | ||||
-rw-r--r-- | libexec/rtld-elf/rtld.h | 11 | ||||
-rw-r--r-- | libexec/rtld-elf/rtld_lock.c | 2 | ||||
-rw-r--r-- | libexec/rtld-elf/sparc64/rtld_machdep.h | 2 |
22 files changed, 346 insertions, 308 deletions
diff --git a/libexec/Makefile b/libexec/Makefile index 04fc38b..26a8ff2 100644 --- a/libexec/Makefile +++ b/libexec/Makefile @@ -9,9 +9,7 @@ SUBDIR= ${_atrun} \ fingerd \ ftpd \ getty \ - lukemftpd \ ${_mail.local} \ - makekey \ ${_mknetid} \ ${_pppoed} \ rbootd \ diff --git a/libexec/bootpd/rtmsg.c b/libexec/bootpd/rtmsg.c index 071a7d1..b691edc 100644 --- a/libexec/bootpd/rtmsg.c +++ b/libexec/bootpd/rtmsg.c @@ -208,7 +208,7 @@ static int rtmsg(cmd) rtm->rtm_addrs |= RTA_GATEWAY; rtm->rtm_rmx.rmx_expire = expire_time; rtm->rtm_inits = RTV_EXPIRE; - rtm->rtm_flags |= (RTF_HOST | RTF_STATIC); + rtm->rtm_flags |= (RTF_HOST | RTF_STATIC | RTF_LLDATA); sin_m.sin_other = 0; if (doing_proxy) { if (export_only) diff --git a/libexec/ftpd/extern.h b/libexec/ftpd/extern.h index d869f67..895f8ae 100644 --- a/libexec/ftpd/extern.h +++ b/libexec/ftpd/extern.h @@ -73,6 +73,35 @@ void yyerror(char *); int yyparse(void); int ls_main(int, char **); +extern int assumeutf8; +extern char cbuf[]; +extern union sockunion data_dest; +extern int epsvall; +extern int form; +extern int ftpdebug; +extern int guest; +extern union sockunion his_addr; +extern char *homedir; +extern int hostinfo; +extern char *hostname; +extern int maxtimeout; +extern int logged_in; +extern int logging; +extern int noepsv; +extern int noguestretr; +extern int noretr; +extern int paranoid; +extern struct passwd *pw; +extern int pdata; +extern char proctitle[]; +extern int readonly; +extern off_t restart_point; +extern int timeout; +extern char tmpline[]; +extern int type; +extern char *typenames[]; /* defined in <arpa/ftp.h> included from ftpd.c */ +extern int usedefault; + struct sockaddr_in; struct sockaddr_in6; union sockunion { diff --git a/libexec/ftpd/ftpcmd.y b/libexec/ftpd/ftpcmd.y index fcef73e..07ece34 100644 --- a/libexec/ftpd/ftpcmd.y +++ b/libexec/ftpd/ftpcmd.y @@ -76,31 +76,6 @@ __FBSDID("$FreeBSD$"); #include "extern.h" #include "pathnames.h" -extern union sockunion data_dest, his_addr; -extern int hostinfo; -extern int logged_in; -extern struct passwd *pw; -extern int guest; -extern char *homedir; -extern int paranoid; -extern int logging; -extern int type; -extern int form; -extern int ftpdebug; -extern int timeout; -extern int maxtimeout; -extern int pdata; -extern char *hostname; -extern char proctitle[]; -extern int usedefault; -extern char tmpline[]; -extern int readonly; -extern int assumeutf8; -extern int noepsv; -extern int noretr; -extern int noguestretr; -extern char *typenames[]; /* defined in <arpa/ftp.h> included from ftpd.c */ - off_t restart_point; static int cmd_type; @@ -110,8 +85,6 @@ static int state; char cbuf[512]; char *fromname = NULL; -extern int epsvall; - %} %union { diff --git a/libexec/ftpd/ftpd.c b/libexec/ftpd/ftpd.c index 59dc71c..32c15f8 100644 --- a/libexec/ftpd/ftpd.c +++ b/libexec/ftpd/ftpd.c @@ -105,9 +105,6 @@ __FBSDID("$FreeBSD$"); static char version[] = "Version 6.00LS"; #undef main -extern off_t restart_point; -extern char cbuf[]; - union sockunion ctrl_addr; union sockunion data_source; union sockunion data_dest; diff --git a/libexec/makekey/Makefile b/libexec/makekey/Makefile deleted file mode 100644 index d09f812..0000000 --- a/libexec/makekey/Makefile +++ /dev/null @@ -1,10 +0,0 @@ -# @(#)Makefile 8.1 (Berkeley) 6/4/93 -# $FreeBSD$ - -PROG= makekey -MAN= makekey.8 - -DPADD= ${LIBCRYPT} -LDADD= -lcrypt - -.include <bsd.prog.mk> diff --git a/libexec/makekey/makekey.8 b/libexec/makekey/makekey.8 deleted file mode 100644 index 7f7f054d..0000000 --- a/libexec/makekey/makekey.8 +++ /dev/null @@ -1,69 +0,0 @@ -.\" Copyright (c) 1990, 1991, 1993 -.\" The Regents of the University of California. All rights reserved. -.\" -.\" Redistribution and use in source and binary forms, with or without -.\" modification, are permitted provided that the following conditions -.\" are met: -.\" 1. Redistributions of source code must retain the above copyright -.\" notice, this list of conditions and the following disclaimer. -.\" 2. Redistributions in binary form must reproduce the above copyright -.\" notice, this list of conditions and the following disclaimer in the -.\" documentation and/or other materials provided with the distribution. -.\" 3. All advertising materials mentioning features or use of this software -.\" must display the following acknowledgement: -.\" This product includes software developed by the University of -.\" California, Berkeley and its contributors. -.\" 4. Neither the name of the University nor the names of its contributors -.\" may be used to endorse or promote products derived from this software -.\" without specific prior written permission. -.\" -.\" THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND -.\" ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE -.\" IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE -.\" ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE -.\" FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL -.\" DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS -.\" OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) -.\" HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT -.\" LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY -.\" OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF -.\" SUCH DAMAGE. -.\" -.\" @(#)makekey.8 8.2 (Berkeley) 12/11/93 -.\" $FreeBSD$ -.\" -.Dd October 8, 2003 -.Dt MAKEKEY 8 -.Os -.Sh NAME -.Nm makekey -.Nd make encrypted keys or passwords -.Sh SYNOPSIS -.Nm -.Sh DESCRIPTION -.Bf Em -The -.Nm -utility has been deprecated and will be removed in a future release of -.Fx . -.Ef -.Pp -The -.Nm -utility encrypts a key and salt which it reads from the standard input -and writes the result to the standard output. -The key is expected to be -eight bytes; the salt is expected to be two bytes. -See -.Xr crypt 3 -for more information on what characters the key and salt can contain -and how the encrypted value is calculated. -.Sh SEE ALSO -.Xr login 1 , -.Xr openssl 1 , -.Xr crypt 3 -.Sh HISTORY -A -.Nm -utility appeared in -.At v7 . diff --git a/libexec/makekey/makekey.c b/libexec/makekey/makekey.c deleted file mode 100644 index 2b541bf..0000000 --- a/libexec/makekey/makekey.c +++ /dev/null @@ -1,84 +0,0 @@ -/*- - * Copyright (c) 1990, 1993 - * The Regents of the University of California. All rights reserved. - * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions - * are met: - * 1. Redistributions of source code must retain the above copyright - * notice, this list of conditions and the following disclaimer. - * 2. Redistributions in binary form must reproduce the above copyright - * notice, this list of conditions and the following disclaimer in the - * documentation and/or other materials provided with the distribution. - * 3. All advertising materials mentioning features or use of this software - * must display the following acknowledgement: - * This product includes software developed by the University of - * California, Berkeley and its contributors. - * 4. Neither the name of the University nor the names of its contributors - * may be used to endorse or promote products derived from this software - * without specific prior written permission. - * - * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND - * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE - * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE - * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE - * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL - * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS - * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) - * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT - * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY - * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF - * SUCH DAMAGE. - */ - -#ifndef lint -static const char copyright[] = -"@(#) Copyright (c) 1990, 1993\n\ - The Regents of the University of California. All rights reserved.\n"; -#endif /* not lint */ - -#ifndef lint -#if 0 -static char sccsid[] = "@(#)makekey.c 8.1 (Berkeley) 6/4/93"; -#endif -static const char rcsid[] = - "$FreeBSD$"; -#endif /* not lint */ - -#include <sys/types.h> - -#include <err.h> -#include <errno.h> -#include <stdio.h> -#include <stdlib.h> -#include <string.h> -#include <unistd.h> - -static void get(char *, int); - -int -main(int argc __unused, char *argv[] __unused) -{ - int len; - char *r, key[9], salt[3]; - - get(key, sizeof(key) - 1); - get(salt, sizeof(salt) - 1); - len = strlen(r = crypt(key, salt)); - if (write(STDOUT_FILENO, r, len) != len) - err(1, "stdout"); - exit(0); -} - -static void -get(char *bp, int len) -{ - int nr; - - bp[len] = '\0'; - if ((nr = read(STDIN_FILENO, bp, len)) == len) - return; - if (nr >= 0) - errno = EFTYPE; - err(1, "stdin"); -} diff --git a/libexec/rtld-elf/Makefile b/libexec/rtld-elf/Makefile index 7c20398..5e9729c 100644 --- a/libexec/rtld-elf/Makefile +++ b/libexec/rtld-elf/Makefile @@ -22,7 +22,7 @@ MLINKS= rtld.1 ld-elf.so.1.1 \ CFLAGS+= -fpic -DPIC LDFLAGS+= -shared -Wl,-Bsymbolic DPADD= ${LIBC_PIC} -LDADD= -lc_pic +LDADD= -lc_pic -lssp_nonshared .if ${MACHINE_ARCH} != "ia64" .if ${MK_SYMVER} == "yes" diff --git a/libexec/rtld-elf/Symbol.map b/libexec/rtld-elf/Symbol.map index 20f8d60..ce1e3e5 100644 --- a/libexec/rtld-elf/Symbol.map +++ b/libexec/rtld-elf/Symbol.map @@ -8,6 +8,7 @@ FBSD_1.0 { dlerror; dlopen; dlsym; + dlfunc; dlvsym; dladdr; dllockinit; diff --git a/libexec/rtld-elf/amd64/rtld_machdep.h b/libexec/rtld-elf/amd64/rtld_machdep.h index c688eb1..301eb0c 100644 --- a/libexec/rtld-elf/amd64/rtld_machdep.h +++ b/libexec/rtld-elf/amd64/rtld_machdep.h @@ -32,8 +32,6 @@ #include <sys/types.h> #include <machine/atomic.h> -#define CACHE_LINE_SIZE 64 - struct Struct_Obj_Entry; /* Return the address of the .dynamic section in the dynamic linker. */ diff --git a/libexec/rtld-elf/arm/rtld_machdep.h b/libexec/rtld-elf/arm/rtld_machdep.h index dd046a9..8364afa 100644 --- a/libexec/rtld-elf/arm/rtld_machdep.h +++ b/libexec/rtld-elf/arm/rtld_machdep.h @@ -32,8 +32,6 @@ #include <sys/types.h> #include <machine/atomic.h> -#define CACHE_LINE_SIZE 32 - struct Struct_Obj_Entry; /* Return the address of the .dynamic section in the dynamic linker. */ diff --git a/libexec/rtld-elf/i386/rtld_machdep.h b/libexec/rtld-elf/i386/rtld_machdep.h index cbb13eb..9b3dcdf 100644 --- a/libexec/rtld-elf/i386/rtld_machdep.h +++ b/libexec/rtld-elf/i386/rtld_machdep.h @@ -32,8 +32,6 @@ #include <sys/types.h> #include <machine/atomic.h> -#define CACHE_LINE_SIZE 32 - struct Struct_Obj_Entry; /* Return the address of the .dynamic section in the dynamic linker. */ diff --git a/libexec/rtld-elf/ia64/rtld_machdep.h b/libexec/rtld-elf/ia64/rtld_machdep.h index 5cb8bc2..5af9602 100644 --- a/libexec/rtld-elf/ia64/rtld_machdep.h +++ b/libexec/rtld-elf/ia64/rtld_machdep.h @@ -32,8 +32,6 @@ #include <sys/types.h> #include <machine/atomic.h> -#define CACHE_LINE_SIZE 128 - /* * Macros for cracking ia64 function pointers. */ diff --git a/libexec/rtld-elf/map_object.c b/libexec/rtld-elf/map_object.c index f489edd..6de0c9e 100644 --- a/libexec/rtld-elf/map_object.c +++ b/libexec/rtld-elf/map_object.c @@ -91,8 +91,7 @@ map_object(int fd, const char *path, const struct stat *sb) /* * Scan the program header entries, and save key information. * - * We rely on there being exactly two load segments, text and data, - * in that order. + * We expect that the loadable segments are ordered by load address. */ phdr = (Elf_Phdr *) ((char *)hdr + hdr->e_phoff); phsize = hdr->e_phnum * sizeof (phdr[0]); @@ -153,8 +152,8 @@ map_object(int fd, const char *path, const struct stat *sb) mapsize = base_vlimit - base_vaddr; base_addr = hdr->e_type == ET_EXEC ? (caddr_t) base_vaddr : NULL; - mapbase = mmap(base_addr, mapsize, convert_prot(segs[0]->p_flags), - convert_flags(segs[0]->p_flags), fd, base_offset); + mapbase = mmap(base_addr, mapsize, PROT_NONE, MAP_ANON | MAP_PRIVATE | + MAP_NOCORE, -1, 0); if (mapbase == (caddr_t) -1) { _rtld_error("%s: mmap of entire address space failed: %s", path, strerror(errno)); @@ -167,7 +166,7 @@ map_object(int fd, const char *path, const struct stat *sb) return NULL; } - for (i = 0; i <= nsegs; i++) { + for (i = 0; i <= nsegs; i++) { /* Overlay the segment onto the proper region. */ data_offset = trunc_page(segs[i]->p_offset); data_vaddr = trunc_page(segs[i]->p_vaddr); @@ -175,45 +174,49 @@ map_object(int fd, const char *path, const struct stat *sb) data_addr = mapbase + (data_vaddr - base_vaddr); data_prot = convert_prot(segs[i]->p_flags); data_flags = convert_flags(segs[i]->p_flags) | MAP_FIXED; - /* Do not call mmap on the first segment - this is redundant */ - if (i && mmap(data_addr, data_vlimit - data_vaddr, data_prot, + if (mmap(data_addr, data_vlimit - data_vaddr, data_prot, data_flags, fd, data_offset) == (caddr_t) -1) { _rtld_error("%s: mmap of data failed: %s", path, strerror(errno)); return NULL; } - /* Clear any BSS in the last page of the segment. */ - clear_vaddr = segs[i]->p_vaddr + segs[i]->p_filesz; - clear_addr = mapbase + (clear_vaddr - base_vaddr); - clear_page = mapbase + (trunc_page(clear_vaddr) - base_vaddr); - if ((nclear = data_vlimit - clear_vaddr) > 0) { - /* Make sure the end of the segment is writable */ - if ((data_prot & PROT_WRITE) == 0 && - -1 == mprotect(clear_page, PAGE_SIZE, data_prot|PROT_WRITE)) { + /* Do BSS setup */ + if (segs[i]->p_filesz != segs[i]->p_memsz) { + + /* Clear any BSS in the last page of the segment. */ + clear_vaddr = segs[i]->p_vaddr + segs[i]->p_filesz; + clear_addr = mapbase + (clear_vaddr - base_vaddr); + clear_page = mapbase + (trunc_page(clear_vaddr) - base_vaddr); + + if ((nclear = data_vlimit - clear_vaddr) > 0) { + /* Make sure the end of the segment is writable */ + if ((data_prot & PROT_WRITE) == 0 && -1 == + mprotect(clear_page, PAGE_SIZE, data_prot|PROT_WRITE)) { _rtld_error("%s: mprotect failed: %s", path, strerror(errno)); return NULL; - } + } - memset(clear_addr, 0, nclear); + memset(clear_addr, 0, nclear); - /* Reset the data protection back */ - if ((data_prot & PROT_WRITE) == 0) - mprotect(clear_page, PAGE_SIZE, data_prot); - } + /* Reset the data protection back */ + if ((data_prot & PROT_WRITE) == 0) + mprotect(clear_page, PAGE_SIZE, data_prot); + } - /* Overlay the BSS segment onto the proper region. */ - bss_vaddr = data_vlimit; - bss_vlimit = round_page(segs[i]->p_vaddr + segs[i]->p_memsz); - bss_addr = mapbase + (bss_vaddr - base_vaddr); - if (bss_vlimit > bss_vaddr) { /* There is something to do */ - if (mmap(bss_addr, bss_vlimit - bss_vaddr, data_prot, - MAP_PRIVATE|MAP_FIXED|MAP_ANON, -1, 0) == (caddr_t) -1) { - _rtld_error("%s: mmap of bss failed: %s", path, + /* Overlay the BSS segment onto the proper region. */ + bss_vaddr = data_vlimit; + bss_vlimit = round_page(segs[i]->p_vaddr + segs[i]->p_memsz); + bss_addr = mapbase + (bss_vaddr - base_vaddr); + if (bss_vlimit > bss_vaddr) { /* There is something to do */ + if (mprotect(bss_addr, bss_vlimit - bss_vaddr, data_prot) == -1) { + _rtld_error("%s: mprotect of bss failed: %s", path, strerror(errno)); - return NULL; + return NULL; + } } } + if (phdr_vaddr == 0 && data_offset <= hdr->e_phoff && (data_vlimit - data_vaddr + data_offset) >= (hdr->e_phoff + hdr->e_phnum * sizeof (Elf_Phdr))) { @@ -348,6 +351,8 @@ obj_free(Obj_Entry *obj) free(obj->vertab); if (obj->origin_path) free(obj->origin_path); + if (obj->z_origin) + free(obj->rpath); if (obj->priv) free(obj->priv); if (obj->path) diff --git a/libexec/rtld-elf/mips/rtld_machdep.h b/libexec/rtld-elf/mips/rtld_machdep.h index dd046a9..8364afa 100644 --- a/libexec/rtld-elf/mips/rtld_machdep.h +++ b/libexec/rtld-elf/mips/rtld_machdep.h @@ -32,8 +32,6 @@ #include <sys/types.h> #include <machine/atomic.h> -#define CACHE_LINE_SIZE 32 - struct Struct_Obj_Entry; /* Return the address of the .dynamic section in the dynamic linker. */ diff --git a/libexec/rtld-elf/powerpc/rtld_machdep.h b/libexec/rtld-elf/powerpc/rtld_machdep.h index 38e105d..f5f21a4 100644 --- a/libexec/rtld-elf/powerpc/rtld_machdep.h +++ b/libexec/rtld-elf/powerpc/rtld_machdep.h @@ -32,8 +32,6 @@ #include <sys/types.h> #include <machine/atomic.h> -#define CACHE_LINE_SIZE 32 - struct Struct_Obj_Entry; /* Return the address of the .dynamic section in the dynamic linker. */ diff --git a/libexec/rtld-elf/rtld.1 b/libexec/rtld-elf/rtld.1 index 011a693..839d5f1 100644 --- a/libexec/rtld-elf/rtld.1 +++ b/libexec/rtld-elf/rtld.1 @@ -28,7 +28,7 @@ .\" .\" $FreeBSD$ .\" -.Dd May 15, 2008 +.Dd April 1, 2009 .Dt RTLD 1 .Os .Sh NAME @@ -58,6 +58,25 @@ to be called on a per-object basis, giving a shared object an opportunity to perform any extra set-up before execution of the program proper begins. This is useful for C++ libraries that contain static constructors. .Pp +When resolving dependencies for the loaded objects, +.Nm +may be allowed to translate dynamic token strings in rpath and soname +by setting +.Fl "z origin" +option of the static linker +.Xr ld 1 . +The following strings are recognized now: +.Bl -tag -width ".Pa $PLATFORM" +.It Pa $ORIGIN +Translated to the full path of the loaded object. +.It Pa $OSNAME +Translated to the name of the operating system implementation. +.It Pa $OSREL +Translated to the release level of the operating system. +.It Pa $PLATFORM +Translated to the machine hardware platform. +.El +.Pp The .Nm utility itself is loaded by the kernel together with any dynamically-linked @@ -116,6 +135,11 @@ If set, disables the use of and .Ev LD_LIBMAP . This variable is unset for set-user-ID and set-group-ID programs. +.It Ev LD_ELF_HINTS_PATH +This variable will override the default location of +.Dq hints +file. +This variable is unset for set-user-ID and set-group-ID programs. .It Ev LD_LIBRARY_PATH A colon separated list of directories, overriding the default search path for shared libraries. diff --git a/libexec/rtld-elf/rtld.c b/libexec/rtld-elf/rtld.c index f67093a..721fe89 100644 --- a/libexec/rtld-elf/rtld.c +++ b/libexec/rtld-elf/rtld.c @@ -41,6 +41,7 @@ #include <sys/mman.h> #include <sys/stat.h> #include <sys/uio.h> +#include <sys/utsname.h> #include <sys/ktrace.h> #include <dlfcn.h> @@ -104,20 +105,20 @@ static void linkmap_add(Obj_Entry *); static void linkmap_delete(Obj_Entry *); static int load_needed_objects(Obj_Entry *); static int load_preload_objects(void); -static Obj_Entry *load_object(const char *, const Obj_Entry *); +static Obj_Entry *load_object(const char *, const Obj_Entry *, int); static Obj_Entry *obj_from_addr(const void *); -static void objlist_call_fini(Objlist *, int *lockstate); -static void objlist_call_init(Objlist *, int *lockstate); +static void objlist_call_fini(Objlist *, bool, int *); +static void objlist_call_init(Objlist *, int *); static void objlist_clear(Objlist *); static Objlist_Entry *objlist_find(Objlist *, const Obj_Entry *); static void objlist_init(Objlist *); static void objlist_push_head(Objlist *, Obj_Entry *); static void objlist_push_tail(Objlist *, Obj_Entry *); static void objlist_remove(Objlist *, Obj_Entry *); -static void objlist_remove_unref(Objlist *); static void *path_enumerate(const char *, path_enum_proc, void *); static int relocate_objects(Obj_Entry *, bool, Obj_Entry *); static int rtld_dirname(const char *, char *); +static int rtld_dirname_abs(const char *, char *); static void rtld_exit(void); static char *search_library_path(const char *, const char *); static const void **get_program_var_addr(const char *); @@ -134,6 +135,9 @@ static void unlink_object(Obj_Entry *); static void unload_object(Obj_Entry *); static void unref_dag(Obj_Entry *); static void ref_dag(Obj_Entry *); +static int origin_subst_one(char **, const char *, const char *, + const char *, char *); +static char *origin_subst(const char *, const char *); static int rtld_verify_versions(const Objlist *); static int rtld_verify_object_versions(Obj_Entry *); static void object_add_name(Obj_Entry *, const char *); @@ -157,6 +161,7 @@ static char *ld_debug; /* Environment variable for debugging */ static char *ld_library_path; /* Environment variable for search path */ static char *ld_preload; /* Environment variable for libraries to load first */ +static char *ld_elf_hints_path; /* Environment variable for alternative hints path */ static char *ld_tracing; /* Called from ldd to print libs */ static char *ld_utrace; /* Use utrace() to log events. */ static Obj_Entry *obj_list; /* Head of linked list of shared objects */ @@ -194,6 +199,7 @@ static func_ptr_type exports[] = { (func_ptr_type) &dlerror, (func_ptr_type) &dlopen, (func_ptr_type) &dlsym, + (func_ptr_type) &dlfunc, (func_ptr_type) &dlvsym, (func_ptr_type) &dladdr, (func_ptr_type) &dllockinit, @@ -365,17 +371,23 @@ _rtld(Elf_Addr *sp, func_ptr_type *exit_proc, Obj_Entry **objp) unsetenv(LD_ "LIBRARY_PATH"); unsetenv(LD_ "LIBMAP_DISABLE"); unsetenv(LD_ "DEBUG"); + unsetenv(LD_ "ELF_HINTS_PATH"); } ld_debug = getenv(LD_ "DEBUG"); libmap_disable = getenv(LD_ "LIBMAP_DISABLE") != NULL; libmap_override = getenv(LD_ "LIBMAP"); ld_library_path = getenv(LD_ "LIBRARY_PATH"); ld_preload = getenv(LD_ "PRELOAD"); + ld_elf_hints_path = getenv(LD_ "ELF_HINTS_PATH"); dangerous_ld_env = libmap_disable || (libmap_override != NULL) || - (ld_library_path != NULL) || (ld_preload != NULL); + (ld_library_path != NULL) || (ld_preload != NULL) || + (ld_elf_hints_path != NULL); ld_tracing = getenv(LD_ "TRACE_LOADED_OBJECTS"); ld_utrace = getenv(LD_ "UTRACE"); + if ((ld_elf_hints_path == NULL) || strlen(ld_elf_hints_path) == 0) + ld_elf_hints_path = _PATH_ELF_HINTS; + if (ld_debug != NULL && *ld_debug != '\0') debug = 1; dbg("%s is initialized, base address = %p", __progname, @@ -412,7 +424,25 @@ _rtld(Elf_Addr *sp, func_ptr_type *exit_proc, Obj_Entry **objp) die(); } - obj_main->path = xstrdup(argv0); + if (aux_info[AT_EXECPATH] != 0) { + char *kexecpath; + char buf[MAXPATHLEN]; + + kexecpath = aux_info[AT_EXECPATH]->a_un.a_ptr; + dbg("AT_EXECPATH %p %s", kexecpath, kexecpath); + if (kexecpath[0] == '/') + obj_main->path = kexecpath; + else if (getcwd(buf, sizeof(buf)) == NULL || + strlcat(buf, "/", sizeof(buf)) >= sizeof(buf) || + strlcat(buf, kexecpath, sizeof(buf)) >= sizeof(buf)) + obj_main->path = xstrdup(argv0); + else + obj_main->path = xstrdup(buf); + } else { + dbg("No AT_EXECPATH"); + obj_main->path = xstrdup(argv0); + } + dbg("obj_main path %s", obj_main->path); obj_main->mainprog = true; /* @@ -614,6 +644,83 @@ basename(const char *name) return p != NULL ? p + 1 : name; } +static struct utsname uts; + +static int +origin_subst_one(char **res, const char *real, const char *kw, const char *subst, + char *may_free) +{ + const char *p, *p1; + char *res1; + int subst_len; + int kw_len; + + res1 = *res = NULL; + p = real; + subst_len = kw_len = 0; + for (;;) { + p1 = strstr(p, kw); + if (p1 != NULL) { + if (subst_len == 0) { + subst_len = strlen(subst); + kw_len = strlen(kw); + } + if (*res == NULL) { + *res = xmalloc(PATH_MAX); + res1 = *res; + } + if ((res1 - *res) + subst_len + (p1 - p) >= PATH_MAX) { + _rtld_error("Substitution of %s in %s cannot be performed", + kw, real); + if (may_free != NULL) + free(may_free); + free(res); + return (false); + } + memcpy(res1, p, p1 - p); + res1 += p1 - p; + memcpy(res1, subst, subst_len); + res1 += subst_len; + p = p1 + kw_len; + } else { + if (*res == NULL) { + if (may_free != NULL) + *res = may_free; + else + *res = xstrdup(real); + return (true); + } + *res1 = '\0'; + if (may_free != NULL) + free(may_free); + if (strlcat(res1, p, PATH_MAX - (res1 - *res)) >= PATH_MAX) { + free(res); + return (false); + } + return (true); + } + } +} + +static char * +origin_subst(const char *real, const char *origin_path) +{ + char *res1, *res2, *res3, *res4; + + if (uts.sysname[0] == '\0') { + if (uname(&uts) != 0) { + _rtld_error("utsname failed: %d", errno); + return (NULL); + } + } + if (!origin_subst_one(&res1, real, "$ORIGIN", origin_path, NULL) || + !origin_subst_one(&res2, res1, "$OSNAME", uts.sysname, res1) || + !origin_subst_one(&res3, res2, "$OSREL", uts.release, res2) || + !origin_subst_one(&res4, res3, "$PLATFORM", uts.machine, res3)) + return (NULL); + return (res4); +} + static void die(void) { @@ -790,11 +897,8 @@ digest_dynamic(Obj_Entry *obj, int early) #endif case DT_FLAGS: - if (dynp->d_un.d_val & DF_ORIGIN) { - obj->origin_path = xmalloc(PATH_MAX); - if (rtld_dirname(obj->path, obj->origin_path) == -1) - die(); - } + if ((dynp->d_un.d_val & DF_1_ORIGIN) && trust) + obj->z_origin = true; if (dynp->d_un.d_val & DF_SYMBOLIC) obj->symbolic = true; if (dynp->d_un.d_val & DF_TEXTREL) @@ -826,6 +930,17 @@ digest_dynamic(Obj_Entry *obj, int early) break; #endif + case DT_FLAGS_1: + if ((dynp->d_un.d_val & DF_1_ORIGIN) && trust) + obj->z_origin = true; + if (dynp->d_un.d_val & DF_1_GLOBAL) + /* XXX */; + if (dynp->d_un.d_val & DF_1_BIND_NOW) + obj->bind_now = true; + if (dynp->d_un.d_val & DF_1_NODELETE) + obj->z_nodelete = true; + break; + default: if (!early) { dbg("Ignoring d_tag %ld = %#lx", (long)dynp->d_tag, @@ -844,8 +959,17 @@ digest_dynamic(Obj_Entry *obj, int early) obj->pltrelsize = 0; } - if (dyn_rpath != NULL) - obj->rpath = obj->strtab + dyn_rpath->d_un.d_val; + if (obj->z_origin && obj->origin_path == NULL) { + obj->origin_path = xmalloc(PATH_MAX); + if (rtld_dirname_abs(obj->path, obj->origin_path) == -1) + die(); + } + + if (dyn_rpath != NULL) { + obj->rpath = (char *)obj->strtab + dyn_rpath->d_un.d_val; + if (obj->z_origin) + obj->rpath = origin_subst(obj->rpath, obj->origin_path); + } if (dyn_soname != NULL) object_add_name(obj, obj->strtab + dyn_soname->d_un.d_val); @@ -1003,7 +1127,10 @@ find_library(const char *xname, const Obj_Entry *refobj) xname); return NULL; } - return xstrdup(xname); + if (refobj != NULL && refobj->z_origin) + return origin_subst(xname, refobj->origin_path); + else + return xstrdup(xname); } if (libmap_disable || (refobj == NULL) || @@ -1122,7 +1249,7 @@ gethints(void) /* Keep from trying again in case the hints file is bad. */ hints = ""; - if ((fd = open(_PATH_ELF_HINTS, O_RDONLY)) == -1) + if ((fd = open(ld_elf_hints_path, O_RDONLY)) == -1) return NULL; if (read(fd, &hdr, sizeof hdr) != sizeof hdr || hdr.magic != ELFHINTS_MAGIC || @@ -1181,8 +1308,8 @@ init_rtld(caddr_t mapbase) /* * Conjure up an Obj_Entry structure for the dynamic linker. * - * The "path" member can't be initialized yet because string constatns - * cannot yet be acessed. Below we will set it correctly. + * The "path" member can't be initialized yet because string constants + * cannot yet be accessed. Below we will set it correctly. */ memset(&objtmp, 0, sizeof(objtmp)); objtmp.path = NULL; @@ -1251,9 +1378,9 @@ initlist_add_neededs(Needed_Entry *needed, Objlist *list) static void initlist_add_objects(Obj_Entry *obj, Obj_Entry **tail, Objlist *list) { - if (obj->init_done) + if (obj->init_scanned || obj->init_done) return; - obj->init_done = true; + obj->init_scanned = true; /* Recursively process the successor objects. */ if (&obj->next != tail) @@ -1268,8 +1395,10 @@ initlist_add_objects(Obj_Entry *obj, Obj_Entry **tail, Objlist *list) objlist_push_tail(list, obj); /* Add the object to the global fini list in the reverse order. */ - if (obj->fini != (Elf_Addr)NULL) + if (obj->fini != (Elf_Addr)NULL && !obj->on_fini_list) { objlist_push_head(&list_fini, obj); + obj->on_fini_list = true; + } } #ifndef FPTR_TARGET @@ -1297,15 +1426,22 @@ is_exported(const Elf_Sym *def) static int load_needed_objects(Obj_Entry *first) { - Obj_Entry *obj; + Obj_Entry *obj, *obj1; for (obj = first; obj != NULL; obj = obj->next) { Needed_Entry *needed; for (needed = obj->needed; needed != NULL; needed = needed->next) { - needed->obj = load_object(obj->strtab + needed->name, obj); - if (needed->obj == NULL && !ld_tracing) + obj1 = needed->obj = load_object(obj->strtab + needed->name, obj, + false); + if (obj1 == NULL && !ld_tracing) return -1; + if (obj1 != NULL && obj1->z_nodelete && !obj1->ref_nodel) { + dbg("obj %s nodelete", obj1->path); + init_dag(obj1); + ref_dag(obj1); + obj1->ref_nodel = true; + } } } @@ -1328,7 +1464,7 @@ load_preload_objects(void) savech = p[len]; p[len] = '\0'; - if (load_object(p, NULL) == NULL) + if (load_object(p, NULL, false) == NULL) return -1; /* XXX - cleanup */ p[len] = savech; p += len; @@ -1345,7 +1481,7 @@ load_preload_objects(void) * on failure. */ static Obj_Entry * -load_object(const char *name, const Obj_Entry *refobj) +load_object(const char *name, const Obj_Entry *refobj, int noload) { Obj_Entry *obj; int fd = -1; @@ -1391,6 +1527,8 @@ load_object(const char *name, const Obj_Entry *refobj) close(fd); return obj; } + if (noload) + return (NULL); /* First use of this object, so we must map it in */ obj = do_load_object(fd, name, path, &sb); @@ -1466,9 +1604,9 @@ obj_from_addr(const void *addr) * non-NULL fini functions. */ static void -objlist_call_fini(Objlist *list, int *lockstate) +objlist_call_fini(Objlist *list, bool force, int *lockstate) { - Objlist_Entry *elm; + Objlist_Entry *elm, *elm_tmp; char *saved_msg; /* @@ -1476,17 +1614,22 @@ objlist_call_fini(Objlist *list, int *lockstate) * call into the dynamic linker and overwrite it. */ saved_msg = errmsg_save(); - wlock_release(rtld_bind_lock, *lockstate); - STAILQ_FOREACH(elm, list, link) { - if (elm->obj->refcount == 0) { + STAILQ_FOREACH_SAFE(elm, list, link, elm_tmp) { + if (elm->obj->refcount == 0 || force) { dbg("calling fini function for %s at %p", elm->obj->path, (void *)elm->obj->fini); LD_UTRACE(UTRACE_FINI_CALL, elm->obj, (void *)elm->obj->fini, 0, 0, elm->obj->path); + /* Remove object from fini list to prevent recursive invocation. */ + STAILQ_REMOVE(list, elm, Struct_Objlist_Entry, link); + wlock_release(rtld_bind_lock, *lockstate); call_initfini_pointer(elm->obj, elm->obj->fini); + *lockstate = wlock_acquire(rtld_bind_lock); + /* No need to free anything if process is going down. */ + if (!force) + free(elm); } } - *lockstate = wlock_acquire(rtld_bind_lock); errmsg_restore(saved_msg); } @@ -1499,22 +1642,39 @@ static void objlist_call_init(Objlist *list, int *lockstate) { Objlist_Entry *elm; + Obj_Entry *obj; char *saved_msg; /* + * Clean init_scanned flag so that objects can be rechecked and + * possibly initialized earlier if any of vectors called below + * cause the change by using dlopen. + */ + for (obj = obj_list; obj != NULL; obj = obj->next) + obj->init_scanned = false; + + /* * Preserve the current error message since an init function might * call into the dynamic linker and overwrite it. */ saved_msg = errmsg_save(); - wlock_release(rtld_bind_lock, *lockstate); STAILQ_FOREACH(elm, list, link) { + if (elm->obj->init_done) /* Initialized early. */ + continue; dbg("calling init function for %s at %p", elm->obj->path, (void *)elm->obj->init); LD_UTRACE(UTRACE_INIT_CALL, elm->obj, (void *)elm->obj->init, 0, 0, elm->obj->path); + /* + * Race: other thread might try to use this object before current + * one completes the initilization. Not much can be done here + * without better locking. + */ + elm->obj->init_done = true; + wlock_release(rtld_bind_lock, *lockstate); call_initfini_pointer(elm->obj, elm->obj->init); + *lockstate = wlock_acquire(rtld_bind_lock); } - *lockstate = wlock_acquire(rtld_bind_lock); errmsg_restore(saved_msg); } @@ -1579,27 +1739,6 @@ objlist_remove(Objlist *list, Obj_Entry *obj) } /* - * Remove all of the unreferenced objects from "list". - */ -static void -objlist_remove_unref(Objlist *list) -{ - Objlist newlist; - Objlist_Entry *elm; - - STAILQ_INIT(&newlist); - while (!STAILQ_EMPTY(list)) { - elm = STAILQ_FIRST(list); - STAILQ_REMOVE_HEAD(list, link); - if (elm->obj->refcount == 0) - free(elm); - else - STAILQ_INSERT_TAIL(&newlist, elm, link); - } - *list = newlist; -} - -/* * Relocate newly-loaded shared objects. The argument is a pointer to * the Obj_Entry for the first such object. All objects from the first * to the end of the list of objects are relocated. Returns 0 on success, @@ -1674,15 +1813,11 @@ relocate_objects(Obj_Entry *first, bool bind_now, Obj_Entry *rtldobj) static void rtld_exit(void) { - Obj_Entry *obj; int lockstate; lockstate = wlock_acquire(rtld_bind_lock); dbg("rtld_exit()"); - /* Clear all the reference counts so the fini functions will be called. */ - for (obj = obj_list; obj != NULL; obj = obj->next) - obj->refcount = 0; - objlist_call_fini(&list_fini, &lockstate); + objlist_call_fini(&list_fini, true, &lockstate); /* No need to remove the items from the list, since we are exiting. */ if (!libmap_disable) lm_fini(); @@ -1802,8 +1937,7 @@ dlclose(void *handle) * The object is no longer referenced, so we must unload it. * First, call the fini functions. */ - objlist_call_fini(&list_fini, &lockstate); - objlist_remove_unref(&list_fini); + objlist_call_fini(&list_fini, false, &lockstate); /* Finish cleaning up the newly-unreferenced objects. */ GDB_STATE(RT_DELETE,&root->linkmap); @@ -1851,12 +1985,14 @@ dlopen(const char *name, int mode) Obj_Entry **old_obj_tail; Obj_Entry *obj; Objlist initlist; - int result, lockstate; + int result, lockstate, nodelete, noload; LD_UTRACE(UTRACE_DLOPEN_START, NULL, NULL, 0, mode, name); ld_tracing = (mode & RTLD_TRACE) == 0 ? NULL : "1"; if (ld_tracing != NULL) environ = (char **)*get_program_var_addr("environ"); + nodelete = mode & RTLD_NODELETE; + noload = mode & RTLD_NOLOAD; objlist_init(&initlist); @@ -1869,7 +2005,7 @@ dlopen(const char *name, int mode) obj = obj_main; obj->refcount++; } else { - obj = load_object(name, obj_main); + obj = load_object(name, obj_main, noload); } if (obj) { @@ -1904,6 +2040,11 @@ dlopen(const char *name, int mode) if (ld_tracing) goto trace; } + if (obj != NULL && (nodelete || obj->z_nodelete) && !obj->ref_nodel) { + dbg("obj %s nodelete", obj->path); + ref_dag(obj); + obj->z_nodelete = obj->ref_nodel = true; + } } LD_UTRACE(UTRACE_DLOPEN_STOP, obj, NULL, 0, obj ? obj->dl_refcount : 0, @@ -1990,6 +2131,16 @@ do_dlsym(void *handle, const char *name, void *retaddr, const Ver_Entry *ve, /* Search main program and all libraries loaded by it. */ def = symlook_list(name, hash, &list_main, &defobj, ve, flags, &donelist); + + /* + * We do not distinguish between 'main' object and global scope. + * If symbol is not defined by objects loaded at startup, continue + * search among dynamically loaded objects with RTLD_GLOBAL + * scope. + */ + if (def == NULL) + def = symlook_list(name, hash, &list_global, &defobj, ve, + flags, &donelist); } else { Needed_Entry fake; @@ -2031,6 +2182,19 @@ dlsym(void *handle, const char *name) SYMLOOK_DLSYM); } +dlfunc_t +dlfunc(void *handle, const char *name) +{ + union { + void *d; + dlfunc_t f; + } rv; + + rv.d = do_dlsym(handle, name, __builtin_return_address(0), NULL, + SYMLOOK_DLSYM); + return (rv.f); +} + void * dlvsym(void *handle, const char *name, const char *version) { @@ -2309,6 +2473,23 @@ rtld_dirname(const char *path, char *bname) return (0); } +static int +rtld_dirname_abs(const char *path, char *base) +{ + char base_rel[PATH_MAX]; + + if (rtld_dirname(path, base) == -1) + return (-1); + if (base[0] == '/') + return (0); + if (getcwd(base_rel, sizeof(base_rel)) == NULL || + strlcat(base_rel, "/", sizeof(base_rel)) >= sizeof(base_rel) || + strlcat(base_rel, base, sizeof(base_rel)) >= sizeof(base_rel)) + return (-1); + strcpy(base, base_rel); + return (0); +} + static void linkmap_add(Obj_Entry *obj) { diff --git a/libexec/rtld-elf/rtld.h b/libexec/rtld-elf/rtld.h index c76bc76..06086b4 100644 --- a/libexec/rtld-elf/rtld.h +++ b/libexec/rtld-elf/rtld.h @@ -195,7 +195,7 @@ typedef struct Struct_Obj_Entry { const Elf_Hashelt *chains; /* Hash table chain array */ unsigned long nchains; /* Number of chains */ - const char *rpath; /* Search path specified in object */ + char *rpath; /* Search path specified in object */ Needed_Entry *needed; /* Shared objects needed by this one (%) */ STAILQ_HEAD(, Struct_Name_Entry) names; /* List of names for this object we @@ -216,8 +216,13 @@ typedef struct Struct_Obj_Entry { bool init_done : 1; /* Already have added object to init list */ bool tls_done : 1; /* Already allocated offset for static TLS */ bool phdr_alloc : 1; /* Phdr is allocated and needs to be freed. */ + bool z_origin : 1; /* Process rpath and soname tokens */ + bool z_nodelete : 1; /* Do not unload the object and dependencies */ + bool ref_nodel : 1; /* Refcount increased to prevent dlclose */ + bool init_scanned: 1; /* Object is already on init list. */ + bool on_fini_list: 1; /* Object is already on fini list. */ - struct link_map linkmap; /* for GDB and dlinfo() */ + struct link_map linkmap; /* For GDB and dlinfo() */ Objlist dldags; /* Object belongs to these dlopened DAGs (%) */ Objlist dagmembers; /* DAG has these members (%) */ dev_t dev; /* Object's filesystem's device */ @@ -228,7 +233,7 @@ typedef struct Struct_Obj_Entry { #define RTLD_MAGIC 0xd550b87a #define RTLD_VERSION 1 -#define RTLD_STATIC_TLS_EXTRA 64 +#define RTLD_STATIC_TLS_EXTRA 128 /* Flags to be passed into symlook_ family of functions. */ #define SYMLOOK_IN_PLT 0x01 /* Lookup for PLT symbol */ diff --git a/libexec/rtld-elf/rtld_lock.c b/libexec/rtld-elf/rtld_lock.c index bf4caf7..c5e582e 100644 --- a/libexec/rtld-elf/rtld_lock.c +++ b/libexec/rtld-elf/rtld_lock.c @@ -42,6 +42,8 @@ * using assembly language sequences in "rtld_start.S". */ +#include <sys/param.h> + #include <signal.h> #include <stdlib.h> #include <time.h> diff --git a/libexec/rtld-elf/sparc64/rtld_machdep.h b/libexec/rtld-elf/sparc64/rtld_machdep.h index 1556758..a161071 100644 --- a/libexec/rtld-elf/sparc64/rtld_machdep.h +++ b/libexec/rtld-elf/sparc64/rtld_machdep.h @@ -32,8 +32,6 @@ #include <sys/types.h> #include <machine/atomic.h> -#define CACHE_LINE_SIZE 128 - struct Struct_Obj_Entry; /* Return the address of the .dynamic section in the dynamic linker. */ |