svn commit: r343093 - in head: include lib/libc/gen libexec/rtld-elf

Dag-Erling Smørgrav des at FreeBSD.org
Wed Jan 16 12:12:41 UTC 2019


Author: des
Date: Wed Jan 16 12:12:40 2019
New Revision: 343093
URL: https://svnweb.freebsd.org/changeset/base/343093

Log:
  Implement dlopenat(3).
  
  MFC after:	3 weeks

Modified:
  head/include/dlfcn.h
  head/lib/libc/gen/dlopen.3
  head/libexec/rtld-elf/rtld.c

Modified: head/include/dlfcn.h
==============================================================================
--- head/include/dlfcn.h	Wed Jan 16 12:11:29 2019	(r343092)
+++ head/include/dlfcn.h	Wed Jan 16 12:12:40 2019	(r343093)
@@ -120,6 +120,7 @@ void	*dlopen(const char *, int);
 void	*dlsym(void * __restrict, const char * __restrict);
 
 #if __BSD_VISIBLE
+void	*dlopenat(int, const char *, int);
 void	*fdlopen(int, int);
 int	 dladdr(const void * __restrict, Dl_info * __restrict);
 dlfunc_t dlfunc(void * __restrict, const char * __restrict);

Modified: head/lib/libc/gen/dlopen.3
==============================================================================
--- head/lib/libc/gen/dlopen.3	Wed Jan 16 12:11:29 2019	(r343092)
+++ head/lib/libc/gen/dlopen.3	Wed Jan 16 12:12:40 2019	(r343093)
@@ -32,11 +32,12 @@
 .\" @(#) dlopen.3 1.6 90/01/31 SMI
 .\" $FreeBSD$
 .\"
-.Dd January 2, 2019
+.Dd January 15, 2019
 .Dt DLOPEN 3
 .Os
 .Sh NAME
 .Nm dlopen ,
+.Nm dlopenat ,
 .Nm fdlopen ,
 .Nm dlsym ,
 .Nm dlvsym ,
@@ -51,6 +52,8 @@
 .Ft void *
 .Fn dlopen "const char *path" "int mode"
 .Ft void *
+.Fn dlopenat "int fd" "const char *path" "int mode"
+.Ft void *
 .Fn fdlopen "int fd" "int mode"
 .Ft void *
 .Fn dlsym "void * restrict handle" "const char * restrict symbol"
@@ -169,6 +172,24 @@ If
 fails, it returns a null pointer, and sets an error condition which may
 be interrogated with
 .Fn dlerror .
+.Pp
+The
+.Fn dlopenat
+function is equivalent to
+.Fn dlopen
+except in the case where the path specifies a relative path.
+In this case the file to be opened is determined relative to the
+directory associated with the file descriptor fd instead of the
+current working directory.
+If
+.Fn dlopenat
+is passed the special value
+.Dv AT_FDCWD
+in the
+.Fa fd
+parameter, the current working directory is used and the behavior is
+identical to a call to
+.Fn dlopen .
 .Pp
 The
 .Fn fdlopen

Modified: head/libexec/rtld-elf/rtld.c
==============================================================================
--- head/libexec/rtld-elf/rtld.c	Wed Jan 16 12:11:29 2019	(r343092)
+++ head/libexec/rtld-elf/rtld.c	Wed Jan 16 12:12:40 2019	(r343093)
@@ -93,8 +93,8 @@ static void digest_dynamic(Obj_Entry *, int);
 static Obj_Entry *digest_phdr(const Elf_Phdr *, int, caddr_t, const char *);
 static Obj_Entry *dlcheck(void *);
 static int dlclose_locked(void *, RtldLockState *);
-static Obj_Entry *dlopen_object(const char *name, int fd, Obj_Entry *refobj,
-    int lo_flags, int mode, RtldLockState *lockstate);
+static Obj_Entry *dlopen_object(int, const char *name, int fd,
+    Obj_Entry *refobj, int lo_flags, int mode, RtldLockState *lockstate);
 static Obj_Entry *do_load_object(int, const char *, char *, struct stat *, int);
 static int do_search_info(const Obj_Entry *obj, int, struct dl_serinfo *);
 static bool donelist_check(DoneList *, const Obj_Entry *);
@@ -118,7 +118,7 @@ static void load_filtees(Obj_Entry *, int flags, RtldL
 static void unload_filtees(Obj_Entry *, RtldLockState *);
 static int load_needed_objects(Obj_Entry *, int);
 static int load_preload_objects(void);
-static Obj_Entry *load_object(const char *, int fd, const Obj_Entry *, int);
+static Obj_Entry *load_object(int, const char *, int, const Obj_Entry *, int);
 static void map_stacks_exec(RtldLockState *);
 static int obj_disable_relro(Obj_Entry *);
 static int obj_enforce_relro(Obj_Entry *);
@@ -147,7 +147,7 @@ static int relocate_objects(Obj_Entry *, bool, Obj_Ent
 static int resolve_object_ifunc(Obj_Entry *, bool, int, RtldLockState *);
 static int rtld_dirname(const char *, char *);
 static int rtld_dirname_abs(const char *, char *);
-static void *rtld_dlopen(const char *name, int fd, int mode);
+static void *rtld_dlopen(int, const char *name, int fd, int mode);
 static void rtld_exit(void);
 static char *search_library_path(const char *, const char *, const char *,
     int *);
@@ -231,6 +231,7 @@ extern Elf_Dyn _DYNAMIC;
 int dlclose(void *) __exported;
 char *dlerror(void) __exported;
 void *dlopen(const char *, int) __exported;
+void *dlopenat(int, const char *, int) __exported;
 void *fdlopen(int, int) __exported;
 void *dlsym(void *, const char *) __exported;
 dlfunc_t dlfunc(void *, const char *) __exported;
@@ -2292,8 +2293,8 @@ load_filtee1(Obj_Entry *obj, Needed_Entry *needed, int
 {
 
     for (; needed != NULL; needed = needed->next) {
-	needed->obj = dlopen_object(obj->strtab + needed->name, -1, obj,
-	  flags, ((ld_loadfltr || obj->z_loadfltr) ? RTLD_NOW : RTLD_LAZY) |
+	needed->obj = dlopen_object(AT_FDCWD, obj->strtab + needed->name, -1,
+	  obj, flags, ((ld_loadfltr || obj->z_loadfltr) ? RTLD_NOW : RTLD_LAZY) |
 	  RTLD_LOCAL, lockstate);
     }
 }
@@ -2316,8 +2317,8 @@ process_needed(Obj_Entry *obj, Needed_Entry *needed, i
     Obj_Entry *obj1;
 
     for (; needed != NULL; needed = needed->next) {
-	obj1 = needed->obj = load_object(obj->strtab + needed->name, -1, obj,
-	  flags & ~RTLD_LO_NOLOAD);
+	obj1 = needed->obj = load_object(AT_FDCWD, obj->strtab + needed->name,
+	-1, obj, flags & ~RTLD_LO_NOLOAD);
 	if (obj1 == NULL && !ld_tracing && (flags & RTLD_LO_FILTEES) == 0)
 	    return (-1);
     }
@@ -2360,7 +2361,7 @@ load_preload_objects(void)
 
 	savech = p[len];
 	p[len] = '\0';
-	obj = load_object(p, -1, NULL, 0);
+	obj = load_object(AT_FDCWD, p, -1, NULL, 0);
 	if (obj == NULL)
 	    return -1;	/* XXX - cleanup */
 	obj->z_interpose = true;
@@ -2389,7 +2390,8 @@ printable_path(const char *path)
  * on failure.
  */
 static Obj_Entry *
-load_object(const char *name, int fd_u, const Obj_Entry *refobj, int flags)
+load_object(int atfd, const char *name, int fd_u, const Obj_Entry *refobj,
+    int flags)
 {
     Obj_Entry *obj;
     int fd;
@@ -2426,7 +2428,7 @@ load_object(const char *name, int fd_u, const Obj_Entr
 	 * To avoid a race, we open the file and use fstat() rather than
 	 * using stat().
 	 */
-	if ((fd = open(path, O_RDONLY | O_CLOEXEC | O_VERIFY)) == -1) {
+	if ((fd = openat(atfd, path, O_RDONLY | O_CLOEXEC | O_VERIFY)) == -1) {
 	    _rtld_error("Cannot open \"%s\"", path);
 	    free(path);
 	    return (NULL);
@@ -3255,21 +3257,28 @@ dllockinit(void *context,
 }
 
 void *
+dlopenat(int fd, const char *name, int mode)
+{
+
+	return (rtld_dlopen(fd, name, -1, mode));
+}
+
+void *
 dlopen(const char *name, int mode)
 {
 
-	return (rtld_dlopen(name, -1, mode));
+	return (rtld_dlopen(AT_FDCWD, name, -1, mode));
 }
 
 void *
 fdlopen(int fd, int mode)
 {
 
-	return (rtld_dlopen(NULL, fd, mode));
+	return (rtld_dlopen(AT_FDCWD, NULL, fd, mode));
 }
 
 static void *
-rtld_dlopen(const char *name, int fd, int mode)
+rtld_dlopen(int atfd, const char *name, int fd, int mode)
 {
     RtldLockState lockstate;
     int lo_flags;
@@ -3291,7 +3300,7 @@ rtld_dlopen(const char *name, int fd, int mode)
     if (ld_tracing != NULL)
 	    lo_flags |= RTLD_LO_TRACE;
 
-    return (dlopen_object(name, fd, obj_main, lo_flags,
+    return (dlopen_object(atfd, name, fd, obj_main, lo_flags,
       mode & (RTLD_MODEMASK | RTLD_GLOBAL), NULL));
 }
 
@@ -3306,8 +3315,8 @@ dlopen_cleanup(Obj_Entry *obj, RtldLockState *lockstat
 }
 
 static Obj_Entry *
-dlopen_object(const char *name, int fd, Obj_Entry *refobj, int lo_flags,
-    int mode, RtldLockState *lockstate)
+dlopen_object(int atfd, const char *name, int fd, Obj_Entry *refobj,
+    int lo_flags, int mode, RtldLockState *lockstate)
 {
     Obj_Entry *old_obj_tail;
     Obj_Entry *obj;
@@ -3329,7 +3338,7 @@ dlopen_object(const char *name, int fd, Obj_Entry *ref
 	obj = obj_main;
 	obj->refcount++;
     } else {
-	obj = load_object(name, fd, refobj, lo_flags);
+	obj = load_object(atfd, name, fd, refobj, lo_flags);
     }
 
     if (obj) {


More information about the svn-src-all mailing list