elf: Fix use-after-free in ldconfig [BZ #26779]
[glibc.git] / dlfcn / dlinfo.c
blobfc63c02681913cb50c1c2794ce74667b67361c07
1 /* dlinfo -- Get information from the dynamic linker.
2 Copyright (C) 2003-2022 Free Software Foundation, Inc.
3 This file is part of the GNU C Library.
5 The GNU C Library is free software; you can redistribute it and/or
6 modify it under the terms of the GNU Lesser General Public
7 License as published by the Free Software Foundation; either
8 version 2.1 of the License, or (at your option) any later version.
10 The GNU C Library is distributed in the hope that it will be useful,
11 but WITHOUT ANY WARRANTY; without even the implied warranty of
12 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
13 Lesser General Public License for more details.
15 You should have received a copy of the GNU Lesser General Public
16 License along with the GNU C Library; if not, see
17 <https://www.gnu.org/licenses/>. */
19 #include <dlfcn.h>
20 #include <link.h>
21 #include <ldsodefs.h>
22 #include <libintl.h>
23 #include <dl-tls.h>
24 #include <shlib-compat.h>
26 struct dlinfo_args
28 void *handle;
29 int request;
30 void *arg;
33 static void
34 dlinfo_doit (void *argsblock)
36 struct dlinfo_args *const args = argsblock;
37 struct link_map *l = args->handle;
39 switch (args->request)
41 case RTLD_DI_CONFIGADDR:
42 default:
43 _dl_signal_error (0, NULL, NULL, N_("unsupported dlinfo request"));
44 break;
46 case RTLD_DI_LMID:
47 *(Lmid_t *) args->arg = l->l_ns;
48 break;
50 case RTLD_DI_LINKMAP:
51 *(struct link_map **) args->arg = l;
52 break;
54 case RTLD_DI_SERINFO:
55 _dl_rtld_di_serinfo (l, args->arg, false);
56 break;
57 case RTLD_DI_SERINFOSIZE:
58 _dl_rtld_di_serinfo (l, args->arg, true);
59 break;
61 case RTLD_DI_ORIGIN:
62 strcpy (args->arg, l->l_origin);
63 break;
65 case RTLD_DI_TLS_MODID:
66 *(size_t *) args->arg = 0;
67 *(size_t *) args->arg = l->l_tls_modid;
68 break;
70 case RTLD_DI_TLS_DATA:
72 void *data = NULL;
73 if (l->l_tls_modid != 0)
74 data = GLRO(dl_tls_get_addr_soft) (l);
75 *(void **) args->arg = data;
76 break;
81 static int
82 dlinfo_implementation (void *handle, int request, void *arg)
84 struct dlinfo_args args = { handle, request, arg };
85 return _dlerror_run (&dlinfo_doit, &args) ? -1 : 0;
88 #ifdef SHARED
89 int
90 ___dlinfo (void *handle, int request, void *arg)
92 if (!rtld_active ())
93 return GLRO (dl_dlfcn_hook)->dlinfo (handle, request, arg);
94 else
95 return dlinfo_implementation (handle, request, arg);
97 versioned_symbol (libc, ___dlinfo, dlinfo, GLIBC_2_34);
99 # if OTHER_SHLIB_COMPAT (libdl, GLIBC_2_3_3, GLIBC_2_34)
100 compat_symbol (libc, ___dlinfo, dlinfo, GLIBC_2_3_3);
101 # endif
102 #else /* !SHARED */
103 /* Also used with _dlfcn_hook. */
105 __dlinfo (void *handle, int request, void *arg)
107 return dlinfo_implementation (handle, request, arg);
109 weak_alias (__dlinfo, dlinfo)
110 #endif