1 /* Audit common functions.
2 Copyright (C) 2021-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/>. */
22 #include <dl-machine.h>
23 #include <dl-runtime.h>
24 #include <dl-fixup-attribute.h>
27 _dl_audit_activity_map (struct link_map
*l
, int action
)
29 struct audit_ifaces
*afct
= GLRO(dl_audit
);
30 for (unsigned int cnt
= 0; cnt
< GLRO(dl_naudit
); ++cnt
)
32 if (afct
->activity
!= NULL
)
33 afct
->activity (&link_map_audit_state (l
, cnt
)->cookie
, action
);
39 _dl_audit_activity_nsid (Lmid_t nsid
, int action
)
41 /* If head is NULL, the namespace has become empty, and the audit interface
42 does not give us a way to signal LA_ACT_CONSISTENT for it because the
43 first loaded module is used to identify the namespace. */
44 struct link_map
*head
= GL(dl_ns
)[nsid
]._ns_loaded
;
45 if (__glibc_likely (GLRO(dl_naudit
) == 0)
46 || head
== NULL
|| head
->l_auditing
)
49 _dl_audit_activity_map (head
, action
);
53 _dl_audit_objsearch (const char *name
, struct link_map
*l
, unsigned int code
)
55 if (l
== NULL
|| l
->l_auditing
|| code
== 0)
58 struct audit_ifaces
*afct
= GLRO(dl_audit
);
59 for (unsigned int cnt
= 0; cnt
< GLRO(dl_naudit
); ++cnt
)
61 if (afct
->objsearch
!= NULL
)
63 struct auditstate
*state
= link_map_audit_state (l
, cnt
);
64 name
= afct
->objsearch (name
, &state
->cookie
, code
);
75 _dl_audit_objopen (struct link_map
*l
, Lmid_t nsid
)
77 if (__glibc_likely (GLRO(dl_naudit
) == 0))
80 struct audit_ifaces
*afct
= GLRO(dl_audit
);
81 for (unsigned int cnt
= 0; cnt
< GLRO(dl_naudit
); ++cnt
)
83 if (afct
->objopen
!= NULL
)
85 struct auditstate
*state
= link_map_audit_state (l
, cnt
);
86 state
->bindflags
= afct
->objopen (l
, nsid
, &state
->cookie
);
87 l
->l_audit_any_plt
|= state
->bindflags
!= 0;
95 _dl_audit_objclose (struct link_map
*l
)
97 if (__glibc_likely (GLRO(dl_naudit
) == 0)
98 || GL(dl_ns
)[l
->l_ns
]._ns_loaded
->l_auditing
)
101 struct audit_ifaces
*afct
= GLRO(dl_audit
);
102 for (unsigned int cnt
= 0; cnt
< GLRO(dl_naudit
); ++cnt
)
104 if (afct
->objclose
!= NULL
)
106 struct auditstate
*state
= link_map_audit_state (l
, cnt
);
107 /* Return value is ignored. */
108 afct
->objclose (&state
->cookie
);
116 _dl_audit_preinit (struct link_map
*l
)
118 if (__glibc_likely (GLRO(dl_naudit
) == 0))
121 struct audit_ifaces
*afct
= GLRO(dl_audit
);
122 for (unsigned int cnt
= 0; cnt
< GLRO(dl_naudit
); ++cnt
)
124 if (afct
->preinit
!= NULL
)
125 afct
->preinit (&link_map_audit_state (l
, cnt
)->cookie
);
131 _dl_audit_symbind_alt (struct link_map
*l
, const ElfW(Sym
) *ref
, void **value
,
134 if ((l
->l_audit_any_plt
| result
->l_audit_any_plt
) == 0)
137 const char *strtab
= (const char *) D_PTR (result
, l_info
[DT_STRTAB
]);
138 /* Compute index of the symbol entry in the symbol table of the DSO with
140 unsigned int ndx
= (ref
- (ElfW(Sym
) *) D_PTR (result
, l_info
[DT_SYMTAB
]));
142 unsigned int altvalue
= 0;
143 /* Synthesize a symbol record where the st_value field is the result. */
144 ElfW(Sym
) sym
= *ref
;
145 sym
.st_value
= (ElfW(Addr
)) *value
;
147 struct audit_ifaces
*afct
= GLRO(dl_audit
);
148 for (unsigned int cnt
= 0; cnt
< GLRO(dl_naudit
); ++cnt
)
150 struct auditstate
*match_audit
= link_map_audit_state (l
, cnt
);
151 struct auditstate
*result_audit
= link_map_audit_state (result
, cnt
);
152 if (afct
->symbind
!= NULL
153 && ((match_audit
->bindflags
& LA_FLG_BINDFROM
) != 0
154 || ((result_audit
->bindflags
& LA_FLG_BINDTO
)
157 unsigned int flags
= altvalue
| LA_SYMB_DLSYM
;
158 uintptr_t new_value
= afct
->symbind (&sym
, ndx
,
159 &match_audit
->cookie
,
160 &result_audit
->cookie
,
161 &flags
, strtab
+ ref
->st_name
);
162 if (new_value
!= (uintptr_t) sym
.st_value
)
164 altvalue
= LA_SYMB_ALTVALUE
;
165 sym
.st_value
= new_value
;
171 *value
= (void *) sym
.st_value
;
174 rtld_hidden_def (_dl_audit_symbind_alt
)
177 _dl_audit_symbind (struct link_map
*l
, struct reloc_result
*reloc_result
,
178 const ElfW(Sym
) *defsym
, DL_FIXUP_VALUE_TYPE
*value
,
181 bool for_jmp_slot
= reloc_result
== NULL
;
183 /* Compute index of the symbol entry in the symbol table of the DSO
184 with the definition. */
185 unsigned int boundndx
= defsym
- (ElfW(Sym
) *) D_PTR (result
,
189 reloc_result
->bound
= result
;
190 reloc_result
->boundndx
= boundndx
;
193 if ((l
->l_audit_any_plt
| result
->l_audit_any_plt
) == 0)
195 /* Set all bits since this symbol binding is not interesting. */
197 reloc_result
->enterexit
= (1u << DL_NNS
) - 1;
201 /* Synthesize a symbol record where the st_value field is the result. */
202 ElfW(Sym
) sym
= *defsym
;
203 sym
.st_value
= DL_FIXUP_VALUE_ADDR (*value
);
205 /* Keep track whether there is any interest in tracing the call in the lower
207 assert (DL_NNS
* 2 <= sizeof (reloc_result
->flags
) * 8);
208 assert ((LA_SYMB_NOPLTENTER
| LA_SYMB_NOPLTEXIT
) == 3);
209 uint32_t enterexit
= LA_SYMB_NOPLTENTER
| LA_SYMB_NOPLTEXIT
;
211 const char *strtab2
= (const void *) D_PTR (result
, l_info
[DT_STRTAB
]);
213 unsigned int flags
= 0;
214 struct audit_ifaces
*afct
= GLRO(dl_audit
);
215 uintptr_t new_value
= (uintptr_t) sym
.st_value
;
216 for (unsigned int cnt
= 0; cnt
< GLRO(dl_naudit
); ++cnt
)
218 /* XXX Check whether both DSOs must request action or only one */
219 struct auditstate
*l_state
= link_map_audit_state (l
, cnt
);
220 struct auditstate
*result_state
= link_map_audit_state (result
, cnt
);
221 if ((l_state
->bindflags
& LA_FLG_BINDFROM
) != 0
222 && (result_state
->bindflags
& LA_FLG_BINDTO
) != 0)
224 if (afct
->symbind
!= NULL
)
226 flags
|= for_jmp_slot
? LA_SYMB_NOPLTENTER
| LA_SYMB_NOPLTEXIT
228 new_value
= afct
->symbind (&sym
, boundndx
,
230 &result_state
->cookie
, &flags
,
231 strtab2
+ defsym
->st_name
);
232 if (new_value
!= (uintptr_t) sym
.st_value
)
234 flags
|= LA_SYMB_ALTVALUE
;
235 sym
.st_value
= for_jmp_slot
236 ? DL_FIXUP_BINDNOW_ADDR_VALUE (new_value
) : new_value
;
240 /* Remember the results for every audit library and store a summary
241 in the first two bits. */
242 enterexit
&= flags
& (LA_SYMB_NOPLTENTER
| LA_SYMB_NOPLTEXIT
);
243 enterexit
|= ((flags
& (LA_SYMB_NOPLTENTER
| LA_SYMB_NOPLTEXIT
))
247 /* If the bind flags say this auditor is not interested, set the bits
249 enterexit
|= ((LA_SYMB_NOPLTENTER
| LA_SYMB_NOPLTEXIT
)
256 reloc_result
->enterexit
= enterexit
;
257 reloc_result
->flags
= flags
;
260 if (flags
& LA_SYMB_ALTVALUE
)
261 DL_FIXUP_BINDNOW_RELOC (value
, new_value
, sym
.st_value
);
265 _dl_audit_pltenter (struct link_map
*l
, struct reloc_result
*reloc_result
,
266 DL_FIXUP_VALUE_TYPE
*value
, void *regs
, long int *framesize
)
268 /* Don't do anything if no auditor wants to intercept this call. */
269 if (GLRO(dl_naudit
) == 0
270 || (reloc_result
->enterexit
& LA_SYMB_NOPLTENTER
))
273 /* Sanity check: DL_FIXUP_VALUE_CODE_ADDR (value) should have been
274 initialized earlier in this function or in another thread. */
275 assert (DL_FIXUP_VALUE_CODE_ADDR (*value
) != 0);
276 ElfW(Sym
) *defsym
= ((ElfW(Sym
) *) D_PTR (reloc_result
->bound
,
278 + reloc_result
->boundndx
);
280 /* Set up the sym parameter. */
281 ElfW(Sym
) sym
= *defsym
;
282 sym
.st_value
= DL_FIXUP_VALUE_ADDR (*value
);
284 /* Get the symbol name. */
285 const char *strtab
= (const void *) D_PTR (reloc_result
->bound
,
287 const char *symname
= strtab
+ sym
.st_name
;
289 /* Keep track of overwritten addresses. */
290 unsigned int flags
= reloc_result
->flags
;
292 struct audit_ifaces
*afct
= GLRO(dl_audit
);
293 for (unsigned int cnt
= 0; cnt
< GLRO(dl_naudit
); ++cnt
)
295 if (afct
->ARCH_LA_PLTENTER
!= NULL
296 && (reloc_result
->enterexit
297 & (LA_SYMB_NOPLTENTER
<< (2 * (cnt
+ 1)))) == 0)
299 long int new_framesize
= -1;
300 struct auditstate
*l_state
= link_map_audit_state (l
, cnt
);
301 struct auditstate
*bound_state
302 = link_map_audit_state (reloc_result
->bound
, cnt
);
304 = afct
->ARCH_LA_PLTENTER (&sym
, reloc_result
->boundndx
,
305 &l_state
->cookie
, &bound_state
->cookie
,
306 regs
, &flags
, symname
, &new_framesize
);
307 if (new_value
!= (uintptr_t) sym
.st_value
)
309 flags
|= LA_SYMB_ALTVALUE
;
310 sym
.st_value
= new_value
;
313 /* Remember the results for every audit library and store a summary
314 in the first two bits. */
315 reloc_result
->enterexit
|= ((flags
& (LA_SYMB_NOPLTENTER
316 | LA_SYMB_NOPLTEXIT
))
319 if ((reloc_result
->enterexit
& (LA_SYMB_NOPLTEXIT
321 == 0 && new_framesize
!= -1 && *framesize
!= -2)
323 /* If this is the first call providing information, use it. */
324 if (*framesize
== -1)
325 *framesize
= new_framesize
;
326 /* If two pltenter calls provide conflicting information, use
328 else if (new_framesize
!= *framesize
)
329 *framesize
= MAX (new_framesize
, *framesize
);
336 *value
= DL_FIXUP_ADDR_VALUE (sym
.st_value
);
340 DL_ARCH_FIXUP_ATTRIBUTE
341 _dl_audit_pltexit (struct link_map
*l
, ElfW(Word
) reloc_arg
,
342 const void *inregs
, void *outregs
)
344 const uintptr_t pltgot
= (uintptr_t) D_PTR (l
, l_info
[DT_PLTGOT
]);
346 /* This is the address in the array where we store the result of previous
348 // XXX Maybe the bound information must be stored on the stack since
349 // XXX with bind_not a new value could have been stored in the meantime.
350 struct reloc_result
*reloc_result
=
351 &l
->l_reloc_result
[reloc_index (pltgot
, reloc_arg
, sizeof (PLTREL
))];
352 ElfW(Sym
) *defsym
= ((ElfW(Sym
) *) D_PTR (reloc_result
->bound
,
354 + reloc_result
->boundndx
);
356 /* Set up the sym parameter. */
357 ElfW(Sym
) sym
= *defsym
;
358 sym
.st_value
= DL_FIXUP_VALUE_ADDR (reloc_result
->addr
);
360 /* Get the symbol name. */
361 const char *strtab
= (const void *) D_PTR (reloc_result
->bound
,
363 const char *symname
= strtab
+ sym
.st_name
;
365 struct audit_ifaces
*afct
= GLRO(dl_audit
);
366 for (unsigned int cnt
= 0; cnt
< GLRO(dl_naudit
); ++cnt
)
368 if (afct
->ARCH_LA_PLTEXIT
!= NULL
369 && (reloc_result
->enterexit
370 & (LA_SYMB_NOPLTEXIT
>> (2 * cnt
))) == 0)
372 struct auditstate
*l_state
= link_map_audit_state (l
, cnt
);
373 struct auditstate
*bound_state
374 = link_map_audit_state (reloc_result
->bound
, cnt
);
375 afct
->ARCH_LA_PLTEXIT (&sym
, reloc_result
->boundndx
,
376 &l_state
->cookie
, &bound_state
->cookie
,
377 inregs
, outregs
, symname
);