[PATCH v3] dlfcn: Add dlinfo request type RTLD_DI_ORIGIN_PATH (bug #24298)
Arjun Shankar
arjun@redhat.com
Fri Jan 16 20:18:42 GMT 2026
The existing dlinfo request type RTLD_DI_ORIGIN used for querying the
value of the '$ORIGIN' dynamic string token is prone to buffer
overflows.
This commit adds a new request type named RTLD_DI_ORIGIN_PATH that
returns a pointer to the dynamic string token (i.e. the 'l_origin' field
in the link map) instead. The dlinfo manual is updated with the new
request type, and the description of RTLD_DI_ORIGIN is updated to
recommend RTLD_DI_ORIGIN_PATH instead.
A test for the new request type is also added to tst-dlinfo.
---
v2: https://inbox.sourceware.org/libc-alpha/20260116150921.3841139-1-arjun@redhat.com/
Changes in v3: Address Carlos' review comments on the manual change:
* Specify the lifetime of the result's validity
---
dlfcn/dlfcn.h | 7 ++++++-
dlfcn/dlinfo.c | 7 +++++++
dlfcn/tst-dlinfo.c | 8 ++++++++
manual/dynlink.texi | 12 +++++++++++-
4 files changed, 32 insertions(+), 2 deletions(-)
diff --git a/dlfcn/dlfcn.h b/dlfcn/dlfcn.h
index a1ee0765bd..a73303a17e 100644
--- a/dlfcn/dlfcn.h
+++ b/dlfcn/dlfcn.h
@@ -167,7 +167,12 @@ enum
the number of program headers in the array. */
RTLD_DI_PHDR = 11,
- RTLD_DI_MAX = 11
+ /* Treat ARG as `const char **' and at that location, store the address
+ of the directory name used to expand $ORIGIN in this shared object's
+ dependency file names. */
+ RTLD_DI_ORIGIN_PATH = 12,
+
+ RTLD_DI_MAX = 12
};
diff --git a/dlfcn/dlinfo.c b/dlfcn/dlinfo.c
index 6a1a7345b5..a4c6ffb5b8 100644
--- a/dlfcn/dlinfo.c
+++ b/dlfcn/dlinfo.c
@@ -67,6 +67,13 @@ dlinfo_doit (void *argsblock)
strcpy (args->arg, l->l_origin);
break;
+ case RTLD_DI_ORIGIN_PATH:
+ if (l->l_origin != (char *) -1)
+ *(const char **) args->arg = l->l_origin;
+ else
+ *(const char **) args->arg = NULL;
+ break;
+
case RTLD_DI_TLS_MODID:
*(size_t *) args->arg = 0;
*(size_t *) args->arg = l->l_tls_modid;
diff --git a/dlfcn/tst-dlinfo.c b/dlfcn/tst-dlinfo.c
index 014cb1b6ff..d0c8d8fb6d 100644
--- a/dlfcn/tst-dlinfo.c
+++ b/dlfcn/tst-dlinfo.c
@@ -20,6 +20,7 @@
#include <stdio.h>
#include <stdlib.h>
#include <error.h>
+#include <support/check.h>
#define TEST_FUNCTION do_test ()
@@ -56,6 +57,13 @@ do_test (void)
printf ("origin: %s\n", origin);
}
+ const char *origin_path;
+ TRY (RTLD_DI_ORIGIN_PATH, &origin_path)
+ {
+ TEST_COMPARE_STRING (origin, origin_path);
+ printf ("origin_path: %s\n", origin_path);
+ }
+
Dl_serinfo counts;
TRY (RTLD_DI_SERINFOSIZE, &counts)
{
diff --git a/manual/dynlink.texi b/manual/dynlink.texi
index a388d7eeeb..477370b81a 100644
--- a/manual/dynlink.texi
+++ b/manual/dynlink.texi
@@ -554,13 +554,23 @@ The namespace identifier of @var{handle} is written to
@code{*@var{arg}}. The @var{arg} argument must be the address of an
object of type @code{Lmid_t}.
+@item RTLD_DI_ORIGIN_PATH
+The @code{$ORIGIN} dynamic string token pointer for @var{handle} is written
+to @code{*@var{arg}}. The @var{arg} argument must be the address of a
+@code{const char *}. If the @code{$ORIGIN} could not be determined, the
+function still returns 0 but writes a null pointer to @code{*@var{arg}}.
+The returned string is only valid as long as the corresponding handle is
+valid. Accessing it after @code{dlclose} has been called for the
+corresponding object is not safe.
+
@item RTLD_DI_ORIGIN
The value of the @code{$ORIGIN} dynamic string token for @var{handle} is
written to the character array starting at @var{arg} as a
null-terminated string.
This request type should not be used because it is prone to buffer
-overflows.
+overflows. Instead, @code{RTLD_DI_ORIGIN_PATH} described above should be
+used.
@item RTLD_DI_SERINFO
@itemx RTLD_DI_SERINFOSIZE
--
2.52.0
More information about the Libc-alpha
mailing list