]> git.ipfire.org Git - thirdparty/glibc.git/commitdiff
dlfcn: Add dlinfo request type RTLD_DI_ORIGIN_PATH (bug #24298)
authorArjun Shankar <arjun@redhat.com>
Mon, 26 Jan 2026 12:49:37 +0000 (13:49 +0100)
committerArjun Shankar <arjun@redhat.com>
Mon, 26 Jan 2026 12:49:37 +0000 (13:49 +0100)
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.

Reviewed-by: Carlos O'Donell <carlos@redhat.com>
dlfcn/dlfcn.h
dlfcn/dlinfo.c
dlfcn/tst-dlinfo.c
manual/dynlink.texi

index a1ee0765bda3538e282159ca709df2f9e1e4b45f..a73303a17efc267eae44ad75dbddf9ef293147e5 100644 (file)
@@ -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
   };
 
 
index 6a1a7345b5c3881bf9a147e45c80f81dcae6f59a..a4c6ffb5b8113d2828e527d8708ab43eb799151e 100644 (file)
@@ -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;
index 014cb1b6ff94da238bcab0967ab16eda36930eb7..d0c8d8fb6d3a14b9f6be3cdf189b9da817058e45 100644 (file)
@@ -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)
     {
index a388d7eeeb81252e0e2ce2dac71692a897b8725b..1091d25a89644530653d05d5510461e33f951d6e 100644 (file)
@@ -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 @var{handle} is undefined behavior.
+
 @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