git: 9986fd59d855 - stable/13 - rtld: add a test for RTLD_DEEPBIND

From: Kyle Evans <kevans_at_FreeBSD.org>
Date: Fri, 15 Dec 2023 18:57:34 UTC
The branch stable/13 has been updated by kevans:

URL: https://cgit.FreeBSD.org/src/commit/?id=9986fd59d855234cbb999b2a4099ad3cd094aa49

commit 9986fd59d855234cbb999b2a4099ad3cd094aa49
Author:     Kyle Evans <kevans@FreeBSD.org>
AuthorDate: 2023-12-01 01:26:09 +0000
Commit:     Kyle Evans <kevans@FreeBSD.org>
CommitDate: 2023-12-15 16:56:59 +0000

    rtld: add a test for RTLD_DEEPBIND
    
    This tests that with RTLD_DEEPBIND, symbols are looked up in all of the
    object's needed objects before the global object.
    
    ATF_REQUIRE_INTEQ was added after stable/13 branched, so we shim it out
    here.
    
    PR:             275393
    Reviewed by:    kib
    Sponsored by:   NetApp, Inc.
    Sponsored by:   Klara, Inc.
    
    (cherry picked from commit d9c543b6b0cabea6e6679d70b4e701018e7eab80)
---
 etc/mtree/BSD.tests.dist                           |  2 +
 libexec/rtld-elf/tests/Makefile                    |  5 +-
 libexec/rtld-elf/tests/Makefile.inc                |  3 +
 libexec/rtld-elf/tests/libdeep/Makefile            | 15 +++++
 libexec/rtld-elf/tests/libdeep/libdeep.c           | 28 +++++++++
 libexec/rtld-elf/tests/libval/Makefile             | 10 +++
 libexec/rtld-elf/tests/libval/libval.c             | 26 ++++++++
 libexec/rtld-elf/tests/libval2/Makefile            |  8 +++
 libexec/rtld-elf/tests/rtld_deepbind/Makefile      | 10 +++
 .../rtld-elf/tests/rtld_deepbind/rtld_deepbind.c   | 72 ++++++++++++++++++++++
 libexec/rtld-elf/tests/target/Makefile             |  2 +-
 11 files changed, 179 insertions(+), 2 deletions(-)

diff --git a/etc/mtree/BSD.tests.dist b/etc/mtree/BSD.tests.dist
index f9a551bbc39b..5714d873cb3b 100644
--- a/etc/mtree/BSD.tests.dist
+++ b/etc/mtree/BSD.tests.dist
@@ -432,6 +432,8 @@
         rc
         ..
         rtld-elf
+            rtld_deepbind
+            ..
         ..
         tftpd
         ..
diff --git a/libexec/rtld-elf/tests/Makefile b/libexec/rtld-elf/tests/Makefile
index 7eacfb899699..06e143a441a1 100644
--- a/libexec/rtld-elf/tests/Makefile
+++ b/libexec/rtld-elf/tests/Makefile
@@ -1,6 +1,9 @@
 
-SUBDIR+=	libpythagoras target
+SUBDIR+=	libpythagoras libdeep libval libval2 target
+TESTS_SUBDIRS+=	rtld_deepbind
 
+SUBDIR_DEPEND_libdeep=	libval2
+SUBDIR_DEPEND_rtld_deepbind=	libval
 SUBDIR_DEPEND_target=	libpythagoras
 
 ATF_TESTS_C=	ld_library_pathfds
diff --git a/libexec/rtld-elf/tests/Makefile.inc b/libexec/rtld-elf/tests/Makefile.inc
new file mode 100644
index 000000000000..dfba72a51ce7
--- /dev/null
+++ b/libexec/rtld-elf/tests/Makefile.inc
@@ -0,0 +1,3 @@
+
+PACKAGE?=	tests
+TESTSDIR?=	${TESTSBASE}/libexec/rtld-elf
diff --git a/libexec/rtld-elf/tests/libdeep/Makefile b/libexec/rtld-elf/tests/libdeep/Makefile
new file mode 100644
index 000000000000..9324b6f25efe
--- /dev/null
+++ b/libexec/rtld-elf/tests/libdeep/Makefile
@@ -0,0 +1,15 @@
+
+SHLIB?=		deep
+SHLIB_MAJOR=	0
+
+LIBDIR=		${TESTSBASE}/libexec/rtld-elf/rtld_deepbind
+SHLIBDIR=	${TESTSBASE}/libexec/rtld-elf/rtld_deepbind
+
+SRCS=	libdeep.c
+
+LIBVAL2=	${.OBJDIR}/../libval2
+LDFLAGS+=	-L${LIBVAL2} -Wl,-rpath,'$$ORIGIN'
+DPADD+=		-lval2
+LDADD+=		-lval2
+
+.include <bsd.lib.mk>
diff --git a/libexec/rtld-elf/tests/libdeep/libdeep.c b/libexec/rtld-elf/tests/libdeep/libdeep.c
new file mode 100644
index 000000000000..e570769300cf
--- /dev/null
+++ b/libexec/rtld-elf/tests/libdeep/libdeep.c
@@ -0,0 +1,28 @@
+/*-
+ *
+ * Copyright (C) 2023 NetApp, Inc.
+ *
+ * SPDX-License-Identifier: BSD-2-Clause
+ *
+ */
+
+#include <stdio.h>
+
+int get_value(void);
+int proxy_get_value(void);
+void set_value(int);
+void proxy_set_value(int);
+
+int
+proxy_get_value(void)
+{
+
+	return (get_value());
+}
+
+void
+proxy_set_value(int val)
+{
+
+	return (set_value(val));
+}
diff --git a/libexec/rtld-elf/tests/libval/Makefile b/libexec/rtld-elf/tests/libval/Makefile
new file mode 100644
index 000000000000..66728c01dc9b
--- /dev/null
+++ b/libexec/rtld-elf/tests/libval/Makefile
@@ -0,0 +1,10 @@
+
+SHLIB?=		val
+SHLIB_MAJOR=	0
+
+LIBDIR=		${TESTSBASE}/libexec/rtld-elf/rtld_deepbind
+SHLIBDIR=	${TESTSBASE}/libexec/rtld-elf/rtld_deepbind
+
+SRCS=	libval.c
+
+.include <bsd.lib.mk>
diff --git a/libexec/rtld-elf/tests/libval/libval.c b/libexec/rtld-elf/tests/libval/libval.c
new file mode 100644
index 000000000000..97c97a0310a7
--- /dev/null
+++ b/libexec/rtld-elf/tests/libval/libval.c
@@ -0,0 +1,26 @@
+/*-
+ *
+ * Copyright (C) 2023 NetApp, Inc.
+ *
+ * SPDX-License-Identifier: BSD-2-Clause
+ *
+ */
+
+static int val;
+
+int get_value(void);
+void set_value(int);
+
+int
+get_value(void)
+{
+
+	return (val);
+}
+
+void
+set_value(int nval)
+{
+
+	val = nval;
+}
diff --git a/libexec/rtld-elf/tests/libval2/Makefile b/libexec/rtld-elf/tests/libval2/Makefile
new file mode 100644
index 000000000000..2b5cf5342092
--- /dev/null
+++ b/libexec/rtld-elf/tests/libval2/Makefile
@@ -0,0 +1,8 @@
+
+LIBVAL=	${.CURDIR}/../libval
+
+# Just rebuild libval
+.PATH:	${LIBVAL:tA}
+SHLIB?=	val2
+
+.include "${LIBVAL}/Makefile"
diff --git a/libexec/rtld-elf/tests/rtld_deepbind/Makefile b/libexec/rtld-elf/tests/rtld_deepbind/Makefile
new file mode 100644
index 000000000000..bcc55d945c7e
--- /dev/null
+++ b/libexec/rtld-elf/tests/rtld_deepbind/Makefile
@@ -0,0 +1,10 @@
+
+TESTSDIR?=	${TESTSBASE}/libexec/rtld-elf/rtld_deepbind
+ATF_TESTS_C=	rtld_deepbind
+
+LIBVAL=	${.OBJDIR}/../libval
+LDFLAGS.rtld_deepbind+=	-L${LIBVAL} -Wl,-rpath,'$$ORIGIN'
+DPADD+=			-lval
+LDADD+=			-lval
+
+.include <bsd.test.mk>
diff --git a/libexec/rtld-elf/tests/rtld_deepbind/rtld_deepbind.c b/libexec/rtld-elf/tests/rtld_deepbind/rtld_deepbind.c
new file mode 100644
index 000000000000..30f71331bc62
--- /dev/null
+++ b/libexec/rtld-elf/tests/rtld_deepbind/rtld_deepbind.c
@@ -0,0 +1,72 @@
+/*-
+ *
+ * Copyright (C) 2023 NetApp, Inc.
+ *
+ * SPDX-License-Identifier: BSD-2-Clause
+ *
+ */
+
+#include <dlfcn.h>
+
+#include <atf-c.h>
+
+int get_value(void);
+void set_value(int);
+
+#define	APP_VALUE	5
+#define	LIB_VALUE	20
+
+#ifndef ATF_REQUIRE_INTEQ
+/* atf-c/macros.h */
+#define ATF_REQUIRE_INTEQ(expected, actual) \
+    ATF_REQUIRE_MSG((expected) == (actual), "%s != %s (%jd != %jd)", #expected, \
+                  #actual, (intmax_t)(expected), (intmax_t)(actual))
+#endif
+
+ATF_TC_WITHOUT_HEAD(deepbind_simple);
+ATF_TC_BODY(deepbind_simple, tc)
+{
+	void *hdl;
+	void (*proxy_set_value)(int);
+	int (*proxy_get_value)(void);
+	int app_value, lib_value;
+
+	set_value(APP_VALUE);
+
+	/*
+	 * libdeep has a dependency on libval2.so, which is a rebuild of
+	 * libval.so that provides get_value() and set_value() for both us and
+	 * the lib.  The lib's get_value() and set_value() should bind to the
+	 * versions in libval2 instead of libval with RTLD_DEEPBIND.
+	 */
+	hdl = dlopen("$ORIGIN/libdeep.so", RTLD_LAZY | RTLD_DEEPBIND);
+	ATF_REQUIRE(hdl != NULL);
+
+	proxy_set_value = dlsym(hdl, "proxy_set_value");
+	ATF_REQUIRE(proxy_set_value != NULL);
+
+	proxy_get_value = dlsym(hdl, "proxy_get_value");
+	ATF_REQUIRE(proxy_get_value != NULL);
+
+	(*proxy_set_value)(LIB_VALUE);
+
+	lib_value = (*proxy_get_value)();
+	app_value = get_value();
+
+	/*
+	 * In the initial implementation or if libdeep.so is *not* linked
+	 * against its own libval2, then these both return the later set
+	 * LIB_VALUE (20) as they bind to the symbol provided by libval and
+	 * use its .bss val.
+	 */
+	ATF_REQUIRE_INTEQ(lib_value, LIB_VALUE);
+	ATF_REQUIRE_INTEQ(app_value, APP_VALUE);
+}
+
+ATF_TP_ADD_TCS(tp)
+{
+
+	ATF_TP_ADD_TC(tp, deepbind_simple);
+
+	return atf_no_error();
+}
diff --git a/libexec/rtld-elf/tests/target/Makefile b/libexec/rtld-elf/tests/target/Makefile
index f63d8072ae3c..aa4875b6748d 100644
--- a/libexec/rtld-elf/tests/target/Makefile
+++ b/libexec/rtld-elf/tests/target/Makefile
@@ -2,7 +2,7 @@
 .include <bsd.own.mk>
 
 PROG=		target
-BINDIR=		${TESTSBASE}/libexec/rtld-elf
+BINDIR=		${TESTSDIR}
 
 WARNS?=		3
 CFLAGS+=	-I${.CURDIR}/../libpythagoras