Page Menu
Home
FreeBSD
Search
Configure Global Search
Log In
Files
F160958349
D29334.diff
No One
Temporary
Actions
View File
Edit File
Delete File
View Transforms
Subscribe
Mute Notifications
Flag For Later
Award Token
Size
14 KB
Referenced Files
None
Subscribers
None
D29334.diff
View Options
diff --git a/libexec/rtld-elf/rtld.1 b/libexec/rtld-elf/rtld.1
--- a/libexec/rtld-elf/rtld.1
+++ b/libexec/rtld-elf/rtld.1
@@ -28,7 +28,7 @@
.\"
.\" $FreeBSD$
.\"
-.Dd June 1, 2020
+.Dd March 24, 2021
.Dt RTLD 1
.Os
.Sh NAME
@@ -189,6 +189,14 @@
other shared libraries.
If the directory is not specified then
the directories specified by
+.It Ev LD_PRELOAD_PATH_FDS
+A colon separated list of file descriptor numbers for libraries.
+This is intended for preloading libraries in which we already have a file
+descriptor.
+This may optimize the process of loading libraries because we do not have to
+look for them in directories.
+It may also be useful in a capability base system where we do not have access to
+global namespaces such as the filesystem.
.Ev LD_LIBRARY_PATH
will be searched first
followed by the set of built-in standard directories.
diff --git a/libexec/rtld-elf/rtld.c b/libexec/rtld-elf/rtld.c
--- a/libexec/rtld-elf/rtld.c
+++ b/libexec/rtld-elf/rtld.c
@@ -119,7 +119,7 @@
static void load_filtees(Obj_Entry *, int flags, RtldLockState *);
static void unload_filtees(Obj_Entry *, RtldLockState *);
static int load_needed_objects(Obj_Entry *, int);
-static int load_preload_objects(void);
+static int load_preload_objects(char *, bool);
static Obj_Entry *load_object(const char *, int fd, const Obj_Entry *, int);
static void map_stacks_exec(RtldLockState *);
static int obj_disable_relro(Obj_Entry *);
@@ -210,6 +210,8 @@
static char *ld_library_dirs; /* Environment variable for library descriptors */
static char *ld_preload; /* Environment variable for libraries to
load first */
+static char *ld_preload_fds; /* Environment variable for libraries represented by
+ descriptors */
static const char *ld_elf_hints_path; /* Environment variable for alternative hints path */
static const char *ld_tracing; /* Called from ldd to print libs */
static char *ld_utrace; /* Use utrace() to log events. */
@@ -564,7 +566,7 @@
ld_bind_now = getenv(_LD("BIND_NOW"));
- /*
+ /*
* If the process is tainted, then we un-set the dangerous environment
* variables. The process will be marked as tainted until setuid(2)
* is called. If any child process calls setuid(2) we do not want any
@@ -575,7 +577,8 @@
unsetenv(_LD("LIBRARY_PATH")) || unsetenv(_LD("LIBRARY_PATH_FDS")) ||
unsetenv(_LD("LIBMAP_DISABLE")) || unsetenv(_LD("BIND_NOT")) ||
unsetenv(_LD("DEBUG")) || unsetenv(_LD("ELF_HINTS_PATH")) ||
- unsetenv(_LD("LOADFLTR")) || unsetenv(_LD("LIBRARY_PATH_RPATH"))) {
+ unsetenv(_LD("LOADFLTR")) || unsetenv(_LD("LIBRARY_PATH_RPATH")) ||
+ unsetenv(_LD("PRELOAD_FDS"))) {
_rtld_error("environment corrupt; aborting");
rtld_die();
}
@@ -588,6 +591,7 @@
ld_library_path = getenv(_LD("LIBRARY_PATH"));
ld_library_dirs = getenv(_LD("LIBRARY_PATH_FDS"));
ld_preload = getenv(_LD("PRELOAD"));
+ ld_preload_fds = getenv(_LD("PRELOAD_FDS"));
ld_elf_hints_path = getenv(_LD("ELF_HINTS_PATH"));
ld_loadfltr = getenv(_LD("LOADFLTR")) != NULL;
library_path_rpath = getenv(_LD("LIBRARY_PATH_RPATH"));
@@ -702,8 +706,12 @@
if (!libmap_disable)
libmap_disable = (bool)lm_init(libmap_override);
+ dbg("loading LD_PRELOAD_FDS libraries");
+ if (load_preload_objects(ld_preload_fds, true) == -1)
+ rtld_die();
+
dbg("loading LD_PRELOAD libraries");
- if (load_preload_objects() == -1)
+ if (load_preload_objects(ld_preload, false) == -1)
rtld_die();
preload_tail = globallist_curr(TAILQ_LAST(&obj_list, obj_entry_q));
@@ -2468,9 +2476,8 @@
}
static int
-load_preload_objects(void)
+load_preload_objects(char *p, bool isfd)
{
- char *p = ld_preload;
Obj_Entry *obj;
static const char delim[] = " \t:;";
@@ -2479,12 +2486,24 @@
p += strspn(p, delim);
while (*p != '\0') {
+ const char *name;
size_t len = strcspn(p, delim);
char savech;
+ int fd;
savech = p[len];
p[len] = '\0';
- obj = load_object(p, -1, NULL, 0);
+ if (isfd) {
+ name = NULL;
+ fd = parse_integer(p);
+ if (fd == -1)
+ return (-1);
+ } else {
+ name = p;
+ fd = -1;
+ }
+
+ obj = load_object(name, fd, NULL, 0);
if (obj == NULL)
return (-1); /* XXX - cleanup */
obj->z_interpose = true;
diff --git a/libexec/rtld-elf/tests/Makefile b/libexec/rtld-elf/tests/Makefile
--- a/libexec/rtld-elf/tests/Makefile
+++ b/libexec/rtld-elf/tests/Makefile
@@ -3,7 +3,14 @@
SUBDIR+= libpythagoras target
SUBDIR_DEPEND_target= libpythagoras
+
ATF_TESTS_C= ld_library_pathfds
+ATF_TESTS_C+= ld_preload_fds
+
+.for t in ${ATF_TESTS_C}
+SRCS.$t= $t.c common.c
+.endfor
+
WARNS?= 3
.include <bsd.test.mk>
diff --git a/libexec/rtld-elf/tests/common.h b/libexec/rtld-elf/tests/common.h
new file mode 100644
--- /dev/null
+++ b/libexec/rtld-elf/tests/common.h
@@ -0,0 +1,43 @@
+/*-
+ * SPDX-License-Identifier: BSD-2-Clause-FreeBSD
+ * Copyright 2014 Jonathan Anderson.
+ * Copyright 2021 Mariusz Zaborski <oshogbo@vexillium.org>
+ *
+ * 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.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``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 AUTHOR 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.
+ *
+ * $FreeBSD$
+ */
+
+#ifndef _LD_COMMON_H_
+#define _LD_COMMON_H_
+
+#define TARGET_ELF_NAME "target"
+#define TARGET_LIBRARY "libpythagoras.so.0"
+
+void expect_success(int binary, char *senv);
+void expect_missing_library(int binary, char *senv);
+
+void try_to_run(int binary, int expected_exit_status, char * const *env,
+ const char *expected_out, const char *expected_err);
+int opendir(const char *name);
+int opendirat(int parent, const char *name);
+
+#endif /* _LD_COMMON_H_ */
diff --git a/libexec/rtld-elf/tests/common.c b/libexec/rtld-elf/tests/common.c
new file mode 100644
--- /dev/null
+++ b/libexec/rtld-elf/tests/common.c
@@ -0,0 +1,81 @@
+/*-
+ * SPDX-License-Identifier: BSD-2-Clause-FreeBSD
+ * Copyright 2014 Jonathan Anderson.
+ * Copyright 2021 Mariusz Zaborski <oshogbo@FreeBSD.org>
+ *
+ * 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.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``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 AUTHOR 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.
+ *
+ * $FreeBSD$
+ */
+
+#include <atf-c.h>
+#include <fcntl.h>
+#include <stdio.h>
+
+#include "common.h"
+
+void
+expect_success(int binary, char *senv)
+{
+ char * const env[] = { senv, NULL };
+
+ try_to_run(binary, 0, env, "the hypotenuse of 3 and 4 is 5\n", "");
+}
+
+void
+expect_missing_library(int binary, char *senv)
+{
+ char * const env[] = { senv, NULL };
+
+ try_to_run(binary, 1, env, "",
+ "ld-elf.so.1: Shared object \"libpythagoras.so.0\" not found,"
+ " required by \"target\"\n");
+}
+
+void
+try_to_run(int binary, int exit_status, char * const *env,
+ const char *expected_out, const char *expected_err)
+{
+ pid_t child = atf_utils_fork();
+
+ if (child == 0) {
+ char * const args[] = { "target", NULL };
+
+ fexecve(binary, args, env);
+ atf_tc_fail("fexecve() failed");
+ }
+
+ atf_utils_wait(child, exit_status, expected_out, expected_err);
+}
+
+int
+opendir(const char *name)
+{
+
+ return open(name, O_RDONLY | O_DIRECTORY);
+}
+
+int
+opendirat(int parent, const char *name)
+{
+
+ return openat(parent, name, O_RDONLY | O_DIRECTORY);
+}
diff --git a/libexec/rtld-elf/tests/ld_library_pathfds.c b/libexec/rtld-elf/tests/ld_library_pathfds.c
--- a/libexec/rtld-elf/tests/ld_library_pathfds.c
+++ b/libexec/rtld-elf/tests/ld_library_pathfds.c
@@ -29,6 +29,7 @@
#include <fcntl.h>
#include <stdio.h>
+#include "common.h"
struct descriptors {
int binary;
@@ -38,14 +39,8 @@
int usr;
};
-static void setup(struct descriptors *, const atf_tc_t *);
-static void expect_success(int binary, char *pathfds);
-static void expect_missing_library(int binary, char *pathfds);
-static void try_to_run(int binary, int expected_exit_status,
- char * const *env, const char *expected_out, const char *expected_err);
-static int opendir(const char *name);
-static int opendirat(int parent, const char *name);
+static void setup(struct descriptors *, const atf_tc_t *);
ATF_TC_WITHOUT_HEAD(missing_library);
@@ -167,55 +162,10 @@
dp->testdir = opendir(atf_tc_get_config_var(tc, "srcdir"));
ATF_REQUIRE(dp->testdir >= 0);
ATF_REQUIRE(
- (dp->binary = openat(dp->testdir, "target", O_RDONLY)) >= 0);
+ (dp->binary = openat(dp->testdir, TARGET_ELF_NAME, O_RDONLY)) >= 0);
ATF_REQUIRE((dp->root = opendir("/")) >= 0);
ATF_REQUIRE((dp->etc = opendirat(dp->root, "etc")) >= 0);
ATF_REQUIRE((dp->usr = opendirat(dp->root, "usr")) >= 0);
}
-static void
-expect_success(int binary, char *pathfds)
-{
- char * const env[] = { pathfds, NULL };
- try_to_run(binary, 0, env, "the hypotenuse of 3 and 4 is 5\n", "");
-}
-
-static void
-expect_missing_library(int binary, char *pathfds)
-{
- char * const env[] = { pathfds, NULL };
- try_to_run(binary, 1, env, "",
- "ld-elf.so.1: Shared object \"libpythagoras.so.0\" not found,"
- " required by \"target\"\n");
-}
-
-
-static void
-try_to_run(int binary, int exit_status, char * const *env,
- const char *expected_out, const char *expected_err)
-{
- pid_t child = atf_utils_fork();
-
- if (child == 0) {
- char * const args[] = { "target", NULL };
-
- fexecve(binary, args, env);
- atf_tc_fail("fexecve() failed");
- }
-
- atf_utils_wait(child, exit_status, expected_out, expected_err);
-}
-
-
-static int
-opendir(const char *name)
-{
- return open(name, O_RDONLY | O_DIRECTORY);
-}
-
-static int
-opendirat(int parent, const char *name)
-{
- return openat(parent, name, O_RDONLY | O_DIRECTORY);
-}
diff --git a/libexec/rtld-elf/tests/ld_preload_fds.c b/libexec/rtld-elf/tests/ld_preload_fds.c
new file mode 100644
--- /dev/null
+++ b/libexec/rtld-elf/tests/ld_preload_fds.c
@@ -0,0 +1,108 @@
+/*-
+ * SPDX-License-Identifier: BSD-2-Clause-FreeBSD
+ * Copyright 2021 Mariusz Zaborski <oshogbo@FreeBSD.org>
+ *
+ * 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.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``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 AUTHOR 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.
+ *
+ * $FreeBSD$
+ */
+
+#include <atf-c.h>
+#include <fcntl.h>
+#include <stdio.h>
+
+#include "common.h"
+
+int binaryfd;
+int libraryfd;
+
+static void
+setup(const atf_tc_t *tc)
+{
+ int testdir;
+
+ testdir = opendir(atf_tc_get_config_var(tc, "srcdir"));
+ ATF_REQUIRE(testdir >= 0);
+
+ binaryfd = openat(testdir, TARGET_ELF_NAME, O_RDONLY);
+ ATF_REQUIRE(binaryfd >= 0);
+ libraryfd = openat(testdir, TARGET_LIBRARY, O_RDONLY);
+ ATF_REQUIRE(libraryfd >= 0);
+
+ close(testdir);
+}
+
+ATF_TC_WITHOUT_HEAD(missing_library);
+ATF_TC_BODY(missing_library, tc)
+{
+
+ setup(tc);
+ expect_missing_library(binaryfd, NULL);
+}
+
+ATF_TC_WITHOUT_HEAD(bad_librarys);
+ATF_TC_BODY(bad_librarys, tc)
+{
+ char *senv;
+
+ ATF_REQUIRE(asprintf(&senv, "LD_PRELOAD_FDS=::") > 0);
+
+ setup(tc);
+ expect_missing_library(binaryfd, senv);
+}
+
+ATF_TC_WITHOUT_HEAD(single_library);
+ATF_TC_BODY(single_library, tc)
+{
+ char *senv;
+
+ setup(tc);
+
+ ATF_REQUIRE(
+ asprintf(&senv, "LD_PRELOAD_FDS=%d", libraryfd) > 0);
+
+ expect_success(binaryfd, senv);
+}
+
+ATF_TC_WITHOUT_HEAD(two_librarys);
+ATF_TC_BODY(two_librarys, tc)
+{
+ char *senv;
+
+ setup(tc);
+
+ ATF_REQUIRE(
+ asprintf(&senv, "LD_PRELOAD_FDS=%d:%d", libraryfd, libraryfd) > 0);
+
+ expect_success(binaryfd, senv);
+}
+
+/* Register test cases with ATF. */
+ATF_TP_ADD_TCS(tp)
+{
+
+ ATF_TP_ADD_TC(tp, missing_library);
+ ATF_TP_ADD_TC(tp, bad_librarys);
+ ATF_TP_ADD_TC(tp, single_library);
+ ATF_TP_ADD_TC(tp, two_librarys);
+
+ return atf_no_error();
+}
File Metadata
Details
Attached
Mime Type
text/plain
Expires
Tue, Jun 30, 10:23 AM (11 h, 20 m)
Storage Engine
blob
Storage Format
Raw Data
Storage Handle
34496676
Default Alt Text
D29334.diff (14 KB)
Attached To
Mode
D29334: rtld: introduce PRELOAD_FDS
Attached
Detach File
Event Timeline
Log In to Comment