4 * The contents of this file are subject to the terms of the
5 * Common Development and Distribution License (the "License").
6 * You may not use this file except in compliance with the License.
8 * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
9 * or http://www.opensolaris.org/os/licensing.
10 * See the License for the specific language governing permissions
11 * and limitations under the License.
13 * When distributing Covered Code, include this CDDL HEADER in each
14 * file and include the License file at usr/src/OPENSOLARIS.LICENSE.
15 * If applicable, add the following below this CDDL HEADER, with the
16 * fields enclosed by brackets "[]" replaced with your own identifying
17 * information: Portions Copyright [yyyy] [name of copyright owner]
23 * Copyright (c) 1996, 2010, Oracle and/or its affiliates. All rights reserved.
24 * Copyright (c) 2012, Joyent, Inc. All rights reserved.
26 * Audit interfaces. Auditing can be enabled in two ways:
28 * - Using the LD_AUDIT environment variable
30 * - From individual objects containing a DT_DEPAUDIT entry
31 * (see ld(1) -P/-p options).
33 * The former establishes a global set of audit libraries which can inspect all
34 * objects from a given process. The latter establishes a local set of audit
35 * libraries which can inspect the immediate dependencies of the caller.
37 * Audit library capabilities are indicated by flags within the link-map list
38 * header (for global auditing), see LML_TFLG_AUD_* flags, or by the same flags
39 * within the individual link-map (for local auditing). Although both sets of
40 * flags can occur in different data items they are defined as one to simplify
41 * audit interface requirements. The basic test for all audit interfaces is:
43 * if ((lml->lm_tflags | AFLAGS(lmp)) & LML_TFLG_AUD_MASK)
45 * Note. Auditors themselves are identified with the LML_TFLG_NOAUDIT link-map
46 * list flag, and no LML_TFLG_AUD_MASK flags. These flags get propagated from
47 * a callers link-map list to any new link-map lists created. Thus, standard
48 * link-maps lists have the LML_TFLG_AUD_MASK flags propagated, and should a
49 * new link-map list be created by an auditor, that list gets tagged as
52 * The latter link-map list equivalence test insures that auditors themselves
53 * (invoked through DT_DEPAUDIT) are not audited.
55 * The history of version changes:
57 * LAV_VERSION1 (Solaris 2.6)
58 * Auditing implementation added.
60 * LAV_VERSION2 (Solaris 2.6)
61 * LA_SYMB_ALTVALUE support added.
63 * LAV_VERSION3 (Solaris 9 update 7)
64 * ld_objfilter() added.
66 * LAV_VERSION4 (Solaris 10 update 5)
67 * Correction of activity calls for local auditors, and introduction of
68 * -z globalaudit concept.
70 * LAV_VERSION5 (Solaris 11)
71 * Under this version, preinit and activity events are enabled from local
72 * auditors. The la_preinit and la_activity interfaces require a cookie
73 * that represents the head of the link-map list being audited. If a
74 * local preinit or activity interface is detected, the local auditors
75 * la_objopen() routine is called with a cookie that represents the object
76 * that heads the link-map list of the object being audited.
78 * A local auditor is loaded through adding a new dependency that requests
79 * auditing, and therefore an la_activity(ADD) event is already in effect.
80 * Regardless, the local auditors la_activity() routine is called with the
81 * cookie that represents the object that heads the link-map list of the
82 * object being audited.
84 * A local auditor can be loaded prior to the preinit event. In this case,
85 * the local auditors la_preinit() routine is called with the cookie that
86 * represents the object that heads the link-map list of the object being
87 * audited. After the preinit event, any la_preinit() routine within a
88 * local auditor will not be called.
90 * These events are intended to follow the expected sequence of events
91 * received by global auditors, ie:
95 * - la_objopen(dependency)
96 * - la_activity(CONSISTENT)
101 #include <sys/types.h>
113 uint_t audit_flags
= 0; /* Copy of specific audit flags to */
114 /* simplify boot_elf.s access. */
117 * Obtain a head link-map cookie. Local auditors can provide la_preinit() and
118 * la_activity() routines, and these routines require a cookie that represents
119 * the object that heads the link-map of the object being audited. A list of
120 * these cookies is maintained on the link-map list. This list allows multiple
121 * local objects to specify the same auditor, and to obtain the same cookie
122 * for the link-map that heads the link-map list.
124 * The initial cookie is created by _audit_create_head_client() which is called
125 * from _audit_add_head(). This cookies address is then passed to the local
126 * auditors ld_objopen() and la_activity() routines. Subsequent preinit and
127 * activity events use _audit_get_head_client() to dynamically retrieve the
130 static Audit_client
*
131 _audit_get_head_client(Rt_map
*hlmp
, Rt_map
*almp
)
135 Lm_list
*hlml
= LIST(hlmp
);
137 for (ALIST_TRAVERSE(hlml
->lm_aud_cookies
, idx
, acp
)) {
138 if (acp
->ac_lmp
== almp
)
144 static Audit_client
*
145 _audit_create_head_client(Rt_map
*hlmp
, Rt_map
*almp
)
147 Audit_client ac
, *acp
;
148 Lm_list
*hlml
= LIST(hlmp
);
151 ac
.ac_cookie
= (uintptr_t)hlmp
;
154 if ((acp
= alist_append(&(hlml
->lm_aud_cookies
), &ac
,
155 sizeof (Audit_client
), AL_CNT_COOKIES
)) == NULL
)
162 * Determine the appropriate client. Each client structure identifies the
163 * link-map of the auditor it is associated with. From the client structure,
164 * the address of the associated cookie, that represents the object being
165 * audited, is retrieved so that the address can be passed to any audit call.
167 * Note, objects that are being locally audited, can provide la_preinit() and
168 * la_activity() routines. These routines must be passed cookies that represent
169 * the object that heads the link-map list of the object being audited. These
170 * cookies are not maintained on this objects Audit_client structure, but are
171 * obtained from the associated link-map lists lm_cookies alist.
173 static Audit_client
*
174 _audit_client(Audit_info
*aip
, Rt_map
*almp
)
181 for (ndx
= 0; ndx
< aip
->ai_cnt
; ndx
++) {
182 if (aip
->ai_clients
[ndx
].ac_lmp
== almp
)
183 return (&(aip
->ai_clients
[ndx
]));
189 * la_filter() caller. Traverse through all audit libraries and call any
190 * la_filter() entry points found. A zero return from an auditor indicates
191 * that the filtee should be ignored.
194 _audit_objfilter(APlist
*list
, Rt_map
*frlmp
, const char *ref
, Rt_map
*felmp
,
199 Lm_list
*frlml
= LIST(frlmp
);
201 for (APLIST_TRAVERSE(list
, idx
, alp
)) {
202 Audit_client
*fracp
, *feacp
;
203 Rt_map
*almp
= alp
->al_lmp
;
204 Lm_list
*alml
= LIST(almp
);
207 if (alp
->al_objfilter
== NULL
)
209 if ((fracp
= _audit_client(AUDINFO(frlmp
), almp
)) == NULL
)
211 if ((feacp
= _audit_client(AUDINFO(felmp
), almp
)) == NULL
)
214 DBG_CALL(Dbg_audit_objfilter(frlml
, DBG_AUD_CALL
,
215 alp
->al_libname
, NAME(frlmp
), NAME(felmp
), ref
));
217 leave(alml
, thr_flg_reenter
);
218 ret
= (*alp
->al_objfilter
)(&(fracp
->ac_cookie
), ref
,
219 &(feacp
->ac_cookie
), flags
);
220 (void) enter(thr_flg_reenter
);
223 DBG_CALL(Dbg_audit_objfilter(frlml
, DBG_AUD_RET
,
224 alp
->al_libname
, NAME(frlmp
), NULL
, NULL
));
232 audit_objfilter(Rt_map
*frlmp
, const char *ref
, Rt_map
*felmp
, uint_t flags
)
240 APPLICATION_ENTER(rtldflags
);
242 if (auditors
&& (auditors
->ad_flags
& LML_TFLG_AUD_OBJFILTER
))
243 respond
= _audit_objfilter(auditors
->ad_list
, frlmp
,
245 if (respond
&& AUDITORS(frlmp
) &&
246 (AUDITORS(frlmp
)->ad_flags
& LML_TFLG_AUD_OBJFILTER
))
247 respond
= _audit_objfilter(AUDITORS(frlmp
)->ad_list
, frlmp
,
250 APPLICATION_RETURN(rtldflags
);
256 * la_objsearch() caller. Traverse through all audit libraries and call any
257 * la_objsearch() entry points found.
259 * Effectively any audit library can change the name we're working with, so we
260 * continue to propagate the new name to each audit library. Any 0 return
261 * terminates the search.
264 _audit_objsearch(APlist
*list
, char *oname
, Rt_map
*clmp
, uint_t flags
)
268 Lm_list
*clml
= LIST(clmp
);
270 for (APLIST_TRAVERSE(list
, idx
, alp
)) {
272 Rt_map
*almp
= alp
->al_lmp
;
273 Lm_list
*alml
= LIST(almp
);
276 if (alp
->al_objsearch
== NULL
)
278 if ((acp
= _audit_client(AUDINFO(clmp
), almp
)) == NULL
)
281 DBG_CALL(Dbg_audit_objsearch(clml
, DBG_AUD_CALL
,
282 alp
->al_libname
, nname
, flags
, NULL
));
284 leave(alml
, thr_flg_reenter
);
285 nname
= (*alp
->al_objsearch
)(nname
, &(acp
->ac_cookie
), flags
);
286 (void) enter(thr_flg_reenter
);
289 * Diagnose any return name that differs from the original name
290 * passed to the auditor.
292 if (nname
&& (nname
[0] == '\0'))
294 if ((nname
!= oname
) || strcmp(nname
, oname
))
295 DBG_CALL(Dbg_audit_objsearch(clml
, DBG_AUD_RET
,
296 alp
->al_libname
, oname
, flags
, nname
));
298 if ((oname
= nname
) == NULL
)
306 audit_objsearch(Rt_map
*clmp
, const char *name
, uint_t flags
)
308 char *nname
= (char *)name
;
314 APPLICATION_ENTER(rtldflags
);
316 if (auditors
&& (auditors
->ad_flags
& LML_TFLG_AUD_OBJSEARCH
))
317 nname
= _audit_objsearch(auditors
->ad_list
, nname
,
319 if (nname
&& AUDITORS(clmp
) &&
320 (AUDITORS(clmp
)->ad_flags
& LML_TFLG_AUD_OBJSEARCH
))
321 nname
= _audit_objsearch(AUDITORS(clmp
)->ad_list
, nname
,
324 APPLICATION_RETURN(rtldflags
);
326 DBG_CALL(Dbg_libs_audit(LIST(clmp
), name
, nname
));
331 * la_activity() caller. Traverse through all audit libraries and call any
332 * la_activity() entry points found.
335 _audit_activity(APlist
*list
, Rt_map
*clmp
, uint_t flags
, Boolean client
)
339 Lm_list
*clml
= LIST(clmp
);
341 for (APLIST_TRAVERSE(list
, idx
, alp
)) {
343 Rt_map
*almp
= alp
->al_lmp
;
344 Lm_list
*alml
= LIST(almp
);
347 if (alp
->al_activity
== 0)
351 * Determine what cookie is required. Any auditing that
352 * originates from the object that heads the link-map list has
353 * its own cookie. Local auditors must obtain the cookie that
354 * represents the object that heads the link-map list.
357 acp
= _audit_client(AUDINFO(clmp
), almp
);
359 acp
= _audit_get_head_client(clml
->lm_head
, almp
);
363 cookie
= &(acp
->ac_cookie
);
366 * Make sure the audit library only sees one addition/deletion
367 * at a time. This ensures the library doesn't see numerous
368 * events from lazy loading a series of libraries. Keep track
369 * of this caller having called an auditor, so that the
370 * appropriate "consistent" event can be supplied on leaving
373 if ((flags
== LA_ACT_ADD
) || (flags
== LA_ACT_DELETE
)) {
374 if (alml
->lm_flags
& LML_FLG_AUDITNOTIFY
)
377 alml
->lm_flags
|= LML_FLG_AUDITNOTIFY
;
378 clml
->lm_flags
|= LML_FLG_ACTAUDIT
;
380 if ((alml
->lm_flags
& LML_FLG_AUDITNOTIFY
) == 0)
383 alml
->lm_flags
&= ~LML_FLG_AUDITNOTIFY
;
386 DBG_CALL(Dbg_audit_activity(clml
, alp
->al_libname
,
387 NAME(clml
->lm_head
), flags
));
389 leave(alml
, thr_flg_reenter
);
390 (*alp
->al_activity
)(cookie
, flags
);
391 (void) enter(thr_flg_reenter
);
396 audit_activity(Rt_map
*clmp
, uint_t flags
)
405 APPLICATION_ENTER(rtldflags
);
407 if (auditors
&& (auditors
->ad_flags
& LML_TFLG_AUD_ACTIVITY
))
408 _audit_activity(auditors
->ad_list
, clmp
, flags
, TRUE
);
409 if (AUDITORS(clmp
) &&
410 (AUDITORS(clmp
)->ad_flags
& LML_TFLG_AUD_ACTIVITY
))
411 _audit_activity(AUDITORS(clmp
)->ad_list
, clmp
, flags
, TRUE
);
413 for (APLIST_TRAVERSE(aud_activity
, idx
, lmp
)) {
414 if ((clmp
!= lmp
) && AUDITORS(lmp
) &&
415 (AUDITORS(lmp
)->ad_flags
& LML_TFLG_AUD_ACTIVITY
)) {
416 _audit_activity(AUDITORS(lmp
)->ad_list
, lmp
, flags
,
421 APPLICATION_RETURN(rtldflags
);
425 * Determine whether an auditor is in use by the head link-map object.
428 _audit_used_by_head(Rt_map
*hlmp
, Rt_map
*almp
)
433 for (APLIST_TRAVERSE(AUDITORS(hlmp
)->ad_list
, idx
, alp
)) {
434 if (alp
->al_lmp
== almp
)
441 * la_objopen() caller for the head link-map. Global auditors, or an auditor
442 * started from the object that heads a link-map list (typically the dynamic
443 * executable), are passed to la_objopen(). However, local auditors can
444 * provide activity and preinit events, and for these events, a cookie
445 * representing the head link-map list object is expected. This routine obtains
446 * these cookies from the link-map list lm_cookies element. This element
447 * ensures all clients of the same auditor use the same cookie.
449 * Although a local auditor will get an la_objopen() call for the object that
450 * heads the link-map list of the object being audited, the auditor is not
451 * permitted to request binding information for this head object. The head
452 * object has already been in existence, and bindings may have been resolved
453 * with it. This local auditor is coming into existence too late, and thus we
454 * don't allow any bindings to be caught at all.
457 _audit_add_head(Rt_map
*clmp
, Rt_map
*hlmp
, int preinit
, int activity
)
459 Lm_list
*clml
= LIST(clmp
);
460 Lmid_t lmid
= get_linkmap_id(clml
);
465 for (APLIST_TRAVERSE(AUDITORS(clmp
)->ad_list
, idx
, alp
)) {
467 Rt_map
*almp
= alp
->al_lmp
;
468 Lm_list
*alml
= LIST(almp
);
473 * Ensure this local auditor isn't already in existence as an
474 * auditor for the head of the link-map list. If it is, then
475 * this auditor will have already receive preinit and activity
478 if (AUDITORS(hlmp
) && _audit_used_by_head(hlmp
, almp
))
482 * Create a cookie that represents the object that heads the
483 * link-map list. If the cookie already exists, then this
484 * auditor has already been established for another objects
485 * local auditing. In this case, do not issue a la_objopen()
486 * or la_activity() event, as these will have already occurred.
488 if ((acp
= _audit_get_head_client(clml
->lm_head
, almp
)) != NULL
)
491 _audit_create_head_client(clml
->lm_head
, almp
)) == NULL
)
494 cookie
= &(acp
->ac_cookie
);
498 * Call the la_objopen() if available.
500 if (alp
->al_objopen
) {
503 DBG_CALL(Dbg_audit_objopen(clml
, DBG_AUD_CALL
,
504 alp
->al_libname
, NAME(hlmp
), 0, FALSE
));
506 APPLICATION_ENTER(rtldflags
);
507 leave(alml
, thr_flg_reenter
);
508 flags
= (*alp
->al_objopen
)((Link_map
*)hlmp
, lmid
,
510 (void) enter(thr_flg_reenter
);
511 APPLICATION_RETURN(rtldflags
);
514 DBG_CALL(Dbg_audit_objopen(clml
, DBG_AUD_RET
,
515 alp
->al_libname
, NAME(hlmp
), flags
, TRUE
));
520 * Call the la_activity() if available.
522 if (alp
->al_activity
) {
523 alml
->lm_flags
|= LML_FLG_AUDITNOTIFY
;
524 clml
->lm_flags
|= LML_FLG_ACTAUDIT
;
526 DBG_CALL(Dbg_audit_activity(clml
, alp
->al_libname
,
527 NAME(clml
->lm_head
), LA_ACT_ADD
));
529 APPLICATION_ENTER(rtldflags
);
530 leave(alml
, thr_flg_reenter
);
531 (*alp
->al_activity
)(cookie
, LA_ACT_ADD
);
532 (void) enter(thr_flg_reenter
);
533 APPLICATION_RETURN(rtldflags
);
538 * If new head link-map cookies have been generated, then maintain
539 * any preinit and/or activity requirements.
542 if (preinit
&& (aplist_append(&aud_preinit
, clmp
,
543 AL_CNT_AUDITORS
) == NULL
))
545 if (activity
&& (aplist_append(&aud_activity
, clmp
,
546 AL_CNT_AUDITORS
) == NULL
))
553 * la_objopen() caller. Create an audit information structure for the indicated
554 * link-map, regardless of an la_objopen() entry point. This structure is used
555 * to supply information to various audit interfaces (see LML_MSK_AUDINFO).
556 * Traverse through all audit libraries and call any la_objopen() entry points
560 _audit_objopen(APlist
*list
, Rt_map
*nlmp
, Lmid_t lmid
, Audit_info
*aip
,
563 Lm_list
*nlml
= LIST(nlmp
);
567 for (APLIST_TRAVERSE(list
, idx
, alp
)) {
570 Rt_map
*almp
= alp
->al_lmp
;
571 Lm_list
*alml
= LIST(almp
);
574 * Associate a cookie with the audit library, and assign the
575 * initial cookie as the present link-map.
577 acp
= &aip
->ai_clients
[(*ndx
)++];
578 acp
->ac_lmp
= alp
->al_lmp
;
579 acp
->ac_cookie
= (uintptr_t)nlmp
;
581 if (alp
->al_objopen
== NULL
)
584 DBG_CALL(Dbg_audit_objopen(nlml
, DBG_AUD_CALL
, alp
->al_libname
,
585 NAME(nlmp
), 0, FALSE
));
587 leave(alml
, thr_flg_reenter
);
588 flags
= (*alp
->al_objopen
)((Link_map
*)nlmp
, lmid
,
590 (void) enter(thr_flg_reenter
);
593 * Diagnose any flags returned by the auditor.
596 DBG_CALL(Dbg_audit_objopen(nlml
, DBG_AUD_RET
,
597 alp
->al_libname
, NAME(nlmp
), flags
, FALSE
));
600 if (flags
& LA_FLG_BINDTO
)
601 acp
->ac_flags
|= FLG_AC_BINDTO
;
603 if (flags
& LA_FLG_BINDFROM
) {
606 acp
->ac_flags
|= FLG_AC_BINDFROM
;
609 * We only need dynamic plt's if a pltenter and/or a
610 * pltexit() entry point exist in one of our auditing
613 if (aip
->ai_dynplts
|| (JMPREL(nlmp
) == 0) ||
614 ((audit_flags
& (AF_PLTENTER
| AF_PLTEXIT
)) == 0))
618 * Create one dynplt for every 'PLT' that exists in the
621 pltcnt
= PLTRELSZ(nlmp
) / RELENT(nlmp
);
622 if ((aip
->ai_dynplts
= calloc(pltcnt
,
623 dyn_plt_ent_size
)) == NULL
)
631 audit_objopen(Rt_map
*clmp
, Rt_map
*nlmp
)
633 Lmid_t lmid
= get_linkmap_id(LIST(nlmp
));
634 int respond
= 1, ndx
= 0;
643 * Determine the number of auditors that can receive information
644 * regarding this object. This provides the number of client
645 * structures required for this object.
648 clients
= auditors
->ad_cnt
;
650 clients
+= AUDITORS(clmp
)->ad_cnt
;
651 if ((nlmp
!= clmp
) && AUDITORS(nlmp
))
652 clients
+= AUDITORS(nlmp
)->ad_cnt
;
655 * Allocate an audit information structure. Each audited object
656 * maintains a AUDINFO() structure. As this structure can only be
657 * created once all auditors are loaded, a client count can now be
660 * The allocation of the audit information structure includes an array
661 * of audit clients, 1 per audit library that has been loaded.
665 * Audit_info | ai_clients |-------
667 * |---------------| |
668 * Audit_client | 1 |<------
673 if ((AUDINFO(nlmp
) = aip
= calloc(1, sizeof (Audit_info
) +
674 (sizeof (Audit_client
) * clients
))) == NULL
)
677 aip
->ai_cnt
= clients
;
678 aip
->ai_clients
= (Audit_client
*)((uintptr_t)aip
+
679 sizeof (Audit_info
));
681 APPLICATION_ENTER(rtldflags
);
684 respond
= _audit_objopen(auditors
->ad_list
, nlmp
,
686 if (respond
&& AUDITORS(clmp
))
687 respond
= _audit_objopen(AUDITORS(clmp
)->ad_list
, nlmp
,
689 if (respond
&& (nlmp
!= clmp
) && AUDITORS(nlmp
))
690 respond
= _audit_objopen(AUDITORS(nlmp
)->ad_list
, nlmp
,
693 APPLICATION_RETURN(rtldflags
);
699 * la_objclose() caller. Traverse through all audit libraries and call any
700 * la_objclose() entry points found.
703 _audit_objclose(APlist
*list
, Rt_map
*lmp
)
707 Lm_list
*lml
= LIST(lmp
);
709 for (APLIST_TRAVERSE(list
, idx
, alp
)) {
711 Rt_map
*almp
= alp
->al_lmp
;
712 Lm_list
*alml
= LIST(almp
);
714 if (alp
->al_objclose
== NULL
)
716 if ((acp
= _audit_client(AUDINFO(lmp
), almp
)) == NULL
)
719 DBG_CALL(Dbg_audit_objclose(lml
, alp
->al_libname
, NAME(lmp
)));
721 leave(alml
, thr_flg_reenter
);
722 (*alp
->al_objclose
)(&(acp
->ac_cookie
));
723 (void) enter(thr_flg_reenter
);
728 * Determine any la_objclose() requirements. An object that is about to be
729 * deleted needs to trigger an la_objclose() event to any associated auditors.
730 * In the case of local auditing, a deleted object may have a number of callers,
731 * and each of these callers may have their own auditing requirements. To
732 * ensure only one la_objclose() event is sent to each auditor, collect the
733 * auditors from any callers and make sure there's no duplication.
736 add_objclose_list(Rt_map
*lmp
, APlist
**alpp
)
738 if (AFLAGS(lmp
) & LML_TFLG_AUD_OBJCLOSE
) {
742 for (APLIST_TRAVERSE(AUDITORS(lmp
)->ad_list
, idx
, alp
)) {
743 if (aplist_test(alpp
, alp
, AL_CNT_AUDITORS
) == 0)
750 audit_objclose(Rt_map
*lmp
, Rt_map
*clmp
)
758 APPLICATION_ENTER(rtldflags
);
760 if (auditors
&& (auditors
->ad_flags
& LML_TFLG_AUD_OBJCLOSE
))
761 _audit_objclose(auditors
->ad_list
, lmp
);
764 * If this link-map list contains local auditors, determine if this
765 * object, or any of this objects CALLERS have instantiated auditors
766 * that need to know of la_objclose() events.
768 if (LIST(lmp
)->lm_flags
& LML_FLG_LOCAUDIT
) {
772 add_objclose_list(lmp
, &alp
);
774 for (APLIST_TRAVERSE(CALLERS(lmp
), idx
, bdp
))
775 add_objclose_list(bdp
->b_caller
, &alp
);
779 * If this close originated from dlclose(), determine whether the caller
780 * requires a la_objclose() event.
783 add_objclose_list(clmp
, &alp
);
786 _audit_objclose(alp
, lmp
);
790 APPLICATION_RETURN(rtldflags
);
794 * la_pltenter() caller. Traverse through all audit libraries and call any
795 * la_pltenter() entry points found. NOTE: this routine is called via the
796 * glue code established in elf_plt_trace_write(), the symbol descriptor is
797 * created as part of the glue and for 32bit environments the st_name is a
798 * pointer to the real symbol name (ie. it's already been adjusted with the
799 * objects base offset). For 64bit environments the st_name remains the
800 * original symbol offset and in this case it is used to compute the real name
801 * pointer and pass as a separate argument to the auditor.
804 _audit_pltenter(APlist
*list
, Rt_map
*rlmp
, Rt_map
*dlmp
, Sym
*sym
,
805 uint_t ndx
, void *regs
, uint_t
*flags
)
809 Lm_list
*rlml
= LIST(rlmp
);
811 const char *name
= (const char *)(sym
->st_name
+ STRTAB(dlmp
));
813 const char *name
= (const char *)(sym
->st_name
);
816 for (APLIST_TRAVERSE(list
, idx
, alp
)) {
817 Audit_client
*racp
, *dacp
;
818 Rt_map
*almp
= alp
->al_lmp
;
819 Lm_list
*alml
= LIST(almp
);
820 Addr ovalue
= sym
->st_value
;
822 if (alp
->al_pltenter
== 0)
824 if ((racp
= _audit_client(AUDINFO(rlmp
), almp
)) == NULL
)
826 if ((dacp
= _audit_client(AUDINFO(dlmp
), almp
)) == NULL
)
828 if (((racp
->ac_flags
& FLG_AC_BINDFROM
) == 0) ||
829 ((dacp
->ac_flags
& FLG_AC_BINDTO
) == 0))
832 DBG_CALL(Dbg_audit_pltenter(rlml
, DBG_AUD_CALL
,
833 alp
->al_libname
, name
, ovalue
));
835 leave(alml
, thr_flg_reenter
);
836 sym
->st_value
= (Addr
)(*alp
->al_pltenter
)(sym
, ndx
,
837 &(racp
->ac_cookie
), &(dacp
->ac_cookie
), regs
,
845 (void) enter(thr_flg_reenter
);
847 if (ovalue
!= sym
->st_value
) {
848 DBG_CALL(Dbg_audit_pltenter(rlml
, DBG_AUD_RET
,
849 alp
->al_libname
, name
, sym
->st_value
));
855 audit_pltenter(Rt_map
*rlmp
, Rt_map
*dlmp
, Sym
*sym
, uint_t ndx
,
856 void *regs
, uint_t
*flags
)
862 return (nsym
.st_value
);
865 * We're effectively entering ld.so.1 from user (glue) code.
868 APPLICATION_ENTER(rtldflags
);
870 if (auditors
&& (auditors
->ad_flags
& LML_TFLG_AUD_PLTENTER
))
871 _audit_pltenter(auditors
->ad_list
, rlmp
, dlmp
, &nsym
,
873 if (AUDITORS(rlmp
) &&
874 (AUDITORS(rlmp
)->ad_flags
& LML_TFLG_AUD_PLTENTER
))
875 _audit_pltenter(AUDITORS(rlmp
)->ad_list
, rlmp
, dlmp
, &nsym
,
878 APPLICATION_RETURN(rtldflags
);
879 leave(LIST(rlmp
), 0);
881 return (nsym
.st_value
);
885 * la_pltexit() caller. Traverse through all audit libraries and call any
886 * la_pltexit() entry points found. See notes above (_audit_pltenter) for
887 * discussion on st_name.
890 _audit_pltexit(APlist
*list
, uintptr_t retval
, Rt_map
*rlmp
, Rt_map
*dlmp
,
891 Sym
*sym
, uint_t ndx
)
896 const char *name
= (const char *)(sym
->st_name
+ STRTAB(dlmp
));
898 const char *name
= (const char *)(sym
->st_name
);
900 Lm_list
*rlml
= LIST(rlmp
);
902 for (APLIST_TRAVERSE(list
, idx
, alp
)) {
903 Audit_client
*racp
, *dacp
;
904 Rt_map
*almp
= alp
->al_lmp
;
905 Lm_list
*alml
= LIST(almp
);
907 if (alp
->al_pltexit
== 0)
909 if ((racp
= _audit_client(AUDINFO(rlmp
), almp
)) == NULL
)
911 if ((dacp
= _audit_client(AUDINFO(dlmp
), almp
)) == NULL
)
913 if (((racp
->ac_flags
& FLG_AC_BINDFROM
) == 0) ||
914 ((dacp
->ac_flags
& FLG_AC_BINDTO
) == 0))
917 DBG_CALL(Dbg_audit_pltexit(rlml
, alp
->al_libname
, name
));
919 leave(alml
, thr_flg_reenter
);
920 retval
= (*alp
->al_pltexit
)(sym
, ndx
,
921 &(racp
->ac_cookie
), &(dacp
->ac_cookie
),
929 (void) enter(thr_flg_reenter
);
935 audit_pltexit(uintptr_t retval
, Rt_map
*rlmp
, Rt_map
*dlmp
, Sym
*sym
,
938 uintptr_t _retval
= retval
;
945 * We're effectively entering ld.so.1 from user (glue) code.
948 APPLICATION_ENTER(rtldflags
);
950 if (auditors
&& (auditors
->ad_flags
& LML_TFLG_AUD_PLTEXIT
))
951 _retval
= _audit_pltexit(auditors
->ad_list
, _retval
,
952 rlmp
, dlmp
, sym
, ndx
);
953 if (AUDITORS(rlmp
) && (AUDITORS(rlmp
)->ad_flags
& LML_TFLG_AUD_PLTEXIT
))
954 _retval
= _audit_pltexit(AUDITORS(rlmp
)->ad_list
, _retval
,
955 rlmp
, dlmp
, sym
, ndx
);
957 APPLICATION_RETURN(rtldflags
);
958 leave(LIST(rlmp
), 0);
965 * la_symbind() caller. Traverse through all audit libraries and call any
966 * la_symbind() entry points found.
969 _audit_symbind(APlist
*list
, Rt_map
*rlmp
, Rt_map
*dlmp
, Sym
*sym
, uint_t ndx
,
970 uint_t
*flags
, int *called
)
974 Lm_list
*rlml
= LIST(rlmp
);
976 const char *name
= (const char *)(sym
->st_name
+ STRTAB(dlmp
));
978 const char *name
= (const char *)(sym
->st_name
);
981 for (APLIST_TRAVERSE(list
, idx
, alp
)) {
982 Audit_client
*racp
, *dacp
;
983 Rt_map
*almp
= alp
->al_lmp
;
984 Lm_list
*alml
= LIST(almp
);
985 Addr ovalue
= sym
->st_value
;
986 uint_t lflags
, oflags
= *flags
;
988 if (alp
->al_symbind
== 0)
991 if ((racp
= _audit_client(AUDINFO(rlmp
), almp
)) != NULL
&&
992 (racp
->ac_flags
& FLG_AC_BINDFROM
) == 0)
995 if ((dacp
= _audit_client(AUDINFO(dlmp
), almp
)) == NULL
)
998 if ((dacp
->ac_flags
& FLG_AC_BINDTO
) == 0)
1002 * The la_symbind interface is only called when the destination
1003 * object has been identified as BINDTO and either the
1004 * destination object is being locally audited or the calling
1005 * object has been identified as BINDFROM. Use a local version
1006 * of the flags, so that any user update can be collected.
1009 lflags
= (oflags
& ~(LA_SYMB_NOPLTENTER
| LA_SYMB_NOPLTEXIT
));
1011 DBG_CALL(Dbg_audit_symbind(rlml
, DBG_AUD_CALL
,
1012 alp
->al_libname
, name
, ovalue
, oflags
));
1014 leave(alml
, thr_flg_reenter
);
1015 sym
->st_value
= (*alp
->al_symbind
)(sym
, ndx
, racp
== NULL
?
1016 NULL
: &(racp
->ac_cookie
), &(dacp
->ac_cookie
),
1024 (void) enter(thr_flg_reenter
);
1027 * If the auditor indicated that they did not want to process
1028 * pltenter, or pltexit audits for this symbol, retain this
1029 * information. Also retain whether an alternative symbol value
1030 * has been supplied.
1032 *flags
|= (lflags
& (LA_SYMB_NOPLTENTER
| LA_SYMB_NOPLTEXIT
));
1033 if ((ovalue
!= sym
->st_value
) &&
1034 (alp
->al_vernum
>= LAV_VERSION2
))
1035 *flags
|= LA_SYMB_ALTVALUE
;
1037 if ((ovalue
!= sym
->st_value
) || (oflags
!= *flags
)) {
1038 DBG_CALL(Dbg_audit_symbind(rlml
, DBG_AUD_RET
,
1039 alp
->al_libname
, name
, sym
->st_value
, *flags
));
1042 return (sym
->st_value
);
1046 audit_symbind(Rt_map
*rlmp
, Rt_map
*dlmp
, Sym
*sym
, uint_t ndx
, Addr value
,
1054 * Construct a new symbol from that supplied but with the real address.
1055 * In the 64-bit world the st_name field is only 32-bits which isn't
1056 * big enough to hold a character pointer. We pass this pointer as a
1057 * separate parameter for 64-bit audit libraries.
1060 nsym
.st_value
= value
;
1063 return (nsym
.st_value
);
1065 #if !defined(_ELF64)
1066 nsym
.st_name
+= (Word
)STRTAB(dlmp
);
1068 APPLICATION_ENTER(rtldflags
);
1070 if (auditors
&& (auditors
->ad_flags
& LML_TFLG_AUD_SYMBIND
))
1071 nsym
.st_value
= _audit_symbind(auditors
->ad_list
,
1072 rlmp
, dlmp
, &nsym
, ndx
, flags
, &called
);
1074 if (AUDITORS(rlmp
) && (AUDITORS(rlmp
)->ad_flags
& LML_TFLG_AUD_SYMBIND
))
1075 nsym
.st_value
= _audit_symbind(AUDITORS(rlmp
)->ad_list
,
1076 rlmp
, dlmp
, &nsym
, ndx
, flags
, &called
);
1078 if (dlmp
!= rlmp
&& AUDITORS(dlmp
) &&
1079 (AUDITORS(dlmp
)->ad_flags
& LML_TFLG_AUD_SYMBIND
)) {
1080 nsym
.st_value
= _audit_symbind(AUDITORS(dlmp
)->ad_list
,
1081 rlmp
, dlmp
, &nsym
, ndx
, flags
, &called
);
1085 * If no la_symbind() was called for this interface, fabricate that no
1086 * la_pltenter, or la_pltexit is required. This helps reduce the glue
1087 * code created for further auditing.
1090 *flags
|= (LA_SYMB_NOPLTENTER
| LA_SYMB_NOPLTEXIT
);
1092 APPLICATION_RETURN(rtldflags
);
1094 return (nsym
.st_value
);
1098 * la_preinit() caller. Traverse through all audit libraries and call any
1099 * la_preinit() entry points found.
1102 _audit_preinit(APlist
*list
, Rt_map
*clmp
, Boolean client
)
1106 Lm_list
*clml
= LIST(clmp
);
1108 for (APLIST_TRAVERSE(list
, idx
, alp
)) {
1110 Rt_map
*almp
= alp
->al_lmp
;
1111 Lm_list
*alml
= LIST(almp
);
1114 if (alp
->al_preinit
== 0)
1118 * Determine what cookie is required. Any auditing that
1119 * originates from the object that heads the link-map list has
1120 * its own cookie. Local auditors must obtain the cookie that
1121 * represents the object that heads the link-map list.
1124 acp
= _audit_client(AUDINFO(clmp
), almp
);
1126 acp
= _audit_get_head_client(clml
->lm_head
, almp
);
1130 cookie
= &(acp
->ac_cookie
);
1132 DBG_CALL(Dbg_audit_preinit(clml
, alp
->al_libname
,
1133 NAME(clml
->lm_head
)));
1135 leave(alml
, thr_flg_reenter
);
1136 (*alp
->al_preinit
)(cookie
);
1137 (void) enter(thr_flg_reenter
);
1142 audit_preinit(Rt_map
*mlmp
)
1151 APPLICATION_ENTER(rtldflags
);
1153 if (auditors
&& (auditors
->ad_flags
& LML_TFLG_AUD_PREINIT
))
1154 _audit_preinit(auditors
->ad_list
, mlmp
, TRUE
);
1156 if (AUDITORS(mlmp
) && (AUDITORS(mlmp
)->ad_flags
& LML_TFLG_AUD_PREINIT
))
1157 _audit_preinit(AUDITORS(mlmp
)->ad_list
, mlmp
, TRUE
);
1159 for (APLIST_TRAVERSE(aud_preinit
, idx
, clmp
)) {
1160 if (AUDITORS(clmp
) &&
1161 (AUDITORS(clmp
)->ad_flags
& LML_TFLG_AUD_PREINIT
))
1162 _audit_preinit(AUDITORS(clmp
)->ad_list
, clmp
, FALSE
);
1165 APPLICATION_RETURN(rtldflags
);
1169 * Clean up (free) an audit descriptor. First, gather a list of all handles,
1170 * and then close each one down. This is done rather than using the handles
1171 * directly from the auditors, as the audit list can be torn down as a result
1172 * of the dlclose. In other words, what you're pointing at can be removed
1173 * while you're still pointing at it.
1176 audit_desc_cleanup(Rt_map
*clmp
)
1178 Audit_desc
*adp
= AUDITORS(clmp
);
1181 APlist
*ghalp
= NULL
;
1188 for (APLIST_TRAVERSE(adp
->ad_list
, idx
, alp
))
1189 (void) aplist_append(&ghalp
, alp
->al_ghp
, AL_CNT_GROUPS
);
1192 adp
->ad_list
= NULL
;
1197 * Indicate that the caller is no longer being audited.
1199 AUDITORS(clmp
) = NULL
;
1200 AFLAGS(clmp
) &= ~LML_TFLG_AUD_MASK
;
1206 for (APLIST_TRAVERSE(ghalp
, idx
, ghp
)) {
1207 (void) dlclose_intn(ghp
, clmp
);
1214 * Objects that establish local auditors may have been added to preinit or
1215 * activity lists. Remove the object from this list if it is present.
1218 remove_auditor(APlist
*alp
, Rt_map
*clmp
)
1223 for (APLIST_TRAVERSE(alp
, idx
, lmp
)) {
1225 aplist_delete(alp
, &idx
);
1232 * Clean up (free) an audit information structure.
1235 audit_info_cleanup(Rt_map
*clmp
)
1237 Audit_info
*aip
= AUDINFO(clmp
);
1242 free(aip
->ai_dynplts
);
1245 remove_auditor(aud_preinit
, clmp
);
1247 remove_auditor(aud_activity
, clmp
);
1253 * Create a data structure of symbol lookup names and associated flags to help
1254 * simplify audit_symget() use.
1262 static const Aud_info aud_info
[] = {
1263 { MSG_SYM_LAVERSION
, 0, 0 }, /* MSG_ORIG(MSG_SYM_LAVERSION) */
1264 { MSG_SYM_LAPREINIT
, /* MSG_ORIG(MSG_SYM_LAPREINIT) */
1265 LML_TFLG_AUD_PREINIT
, 0 },
1266 { MSG_SYM_LAOBJSEARCH
, /* MSG_ORIG(MSG_SYM_LAOBJSEARCH) */
1267 LML_TFLG_AUD_OBJSEARCH
, 0 },
1268 { MSG_SYM_LAOBJOPEN
, /* MSG_ORIG(MSG_SYM_LAOBJOPEN) */
1269 LML_TFLG_AUD_OBJOPEN
, 0 },
1270 { MSG_SYM_LAOBJFILTER
, /* MSG_ORIG(MSG_SYM_LAOBJFILTER */
1271 LML_TFLG_AUD_OBJFILTER
, 0 },
1272 { MSG_SYM_LAOBJCLOSE
, /* MSG_ORIG(MSG_SYM_LAOBJCLOSE) */
1273 LML_TFLG_AUD_OBJCLOSE
, 0 },
1274 { MSG_SYM_LAACTIVITY
, /* MSG_ORIG(MSG_SYM_LAACTIVITY) */
1275 LML_TFLG_AUD_ACTIVITY
, 0 },
1278 { MSG_SYM_LASYMBIND_64
, /* MSG_ORIG(MSG_SYM_LASYMBIND_64) */
1280 { MSG_SYM_LASYMBIND
, /* MSG_ORIG(MSG_SYM_LASYMBIND) */
1282 LML_TFLG_AUD_SYMBIND
, 0 },
1284 #if defined(__sparcv9)
1285 { MSG_SYM_LAV9PLTENTER
, /* MSG_ORIG(MSG_SYM_LAV9PLTENTER) */
1286 #elif defined(__sparc)
1287 { MSG_SYM_LAV8PLTENTER
, /* MSG_ORIG(MSG_SYM_LAV8PLTENTER) */
1288 #elif defined(__amd64)
1289 { MSG_SYM_LAAMD64PLTENTER
, /* MSG_ORIG(MSG_SYM_LAAMD64PLTENTER) */
1290 #elif defined(__i386)
1291 { MSG_SYM_LAX86PLTENTER
, /* MSG_ORIG(MSG_SYM_LAX86PLTENTER) */
1293 #error platform not defined!
1295 LML_TFLG_AUD_PLTENTER
, AF_PLTENTER
},
1298 { MSG_SYM_LAPLTEXIT_64
, /* MSG_ORIG(MSG_SYM_LAPLTEXIT_64) */
1300 { MSG_SYM_LAPLTEXIT
, /* MSG_ORIG(MSG_SYM_LAPLTEXIT) */
1302 LML_TFLG_AUD_PLTEXIT
, AF_PLTEXIT
}
1305 #define AI_LAVERSION 0
1306 #define AI_LAPREINIT 1
1307 #define AI_LAOBJSEARCH 2
1308 #define AI_LAOBJOPEN 3
1309 #define AI_LAOBJFILTER 4
1310 #define AI_LAOBJCLOSE 5
1311 #define AI_LAACTIVITY 6
1312 #define AI_LASYMBIND 7
1313 #define AI_LAPLTENTER 8
1314 #define AI_LAPLTEXIT 9
1317 audit_symget(Audit_list
*alp
, int info
, int *in_nfavl
)
1319 Rt_map
*lmp
= alp
->al_lmp
;
1320 const char *sname
= MSG_ORIG(aud_info
[info
].sname
);
1321 uint_t alflag
= aud_info
[info
].alflag
;
1322 uint_t auflag
= aud_info
[info
].auflag
;
1328 * Initialize the symbol lookup, and symbol result, data structures.
1330 SLOOKUP_INIT(sl
, sname
, lml_rtld
.lm_head
, lmp
, ld_entry_cnt
,
1331 0, 0, 0, 0, (LKUP_FIRST
| LKUP_DLSYM
));
1332 SRESULT_INIT(sr
, sname
);
1334 if (LM_LOOKUP_SYM(lmp
)(&sl
, &sr
, &binfo
, in_nfavl
)) {
1335 Addr addr
= sr
.sr_sym
->st_value
;
1337 if (!(FLAGS(lmp
) & FLG_RT_FIXED
))
1341 alp
->al_flags
|= alflag
;
1343 audit_flags
|= auflag
;
1346 * Note, unlike most other diagnostics, where we wish to
1347 * identify the lmid of the caller, here we use the lmid of
1348 * the auditor itself to show the association of the auditor
1349 * and the interfaces it provides.
1351 DBG_CALL(Dbg_audit_interface(LIST(alp
->al_lmp
),
1352 alp
->al_libname
, sr
.sr_name
));
1359 * Centralize cleanup routines.
1362 audit_disable(char *name
, Rt_map
*clmp
, Grp_hdl
*ghp
, Audit_list
*alp
)
1364 eprintf(LIST(clmp
), ERR_FATAL
, MSG_INTL(MSG_AUD_DISABLED
), name
);
1366 (void) dlclose_intn(ghp
, clmp
);
1373 * Given a list of one or more audit libraries, open each one and establish a
1374 * a descriptor representing the entry points it provides.
1377 audit_setup(Rt_map
*clmp
, Audit_desc
*adp
, uint_t orig
, int *in_nfavl
)
1380 Lm_list
*clml
= LIST(clmp
);
1382 int error
= 1, activity
= 0, preinit
= 0;
1386 * Determine the type of auditing for diagnostics.
1391 if (orig
& PD_FLG_EXTLOAD
)
1392 type
= DBG_AUD_PRELOAD
;
1393 else if (FLAGS1(clmp
) & FL1_RT_GLOBAUD
)
1394 type
= DBG_AUD_GLOBAL
;
1396 type
= DBG_AUD_LOCAL
;
1398 DBG_CALL(Dbg_audit_lib(clmp
, adp
->ad_name
, type
));
1402 * Mark that we have at least one auditing link map
1404 rtld_flags2
|= RT_FL2_HASAUDIT
;
1407 * The audit definitions may be a list (which will already have been
1408 * dupped) so split it into individual tokens.
1410 for (ptr
= strtok_r(adp
->ad_name
, MSG_ORIG(MSG_STR_DELIMIT
), &next
);
1411 ptr
; ptr
= strtok_r(NULL
, MSG_ORIG(MSG_STR_DELIMIT
), &next
)) {
1418 DBG_CALL(Dbg_util_nl(clml
, DBG_NL_STD
));
1421 * Open the audit library on its own link-map.
1423 if ((ghp
= dlmopen_intn((Lm_list
*)LM_ID_NEWLM
, ptr
,
1424 (RTLD_FIRST
| RTLD_GLOBAL
| RTLD_WORLD
), clmp
,
1425 FLG_RT_AUDIT
, orig
)) == NULL
) {
1426 error
= audit_disable(ptr
, clmp
, 0, 0);
1429 lmp
= ghp
->gh_ownlmp
;
1433 * If this auditor has already been loaded, reuse it.
1435 if ((alp
= lml
->lm_alp
) != NULL
) {
1436 if (aplist_append(&(adp
->ad_list
), alp
,
1437 AL_CNT_AUDITORS
) == NULL
)
1438 return (audit_disable(ptr
, clmp
, ghp
, alp
));
1441 adp
->ad_flags
|= alp
->al_flags
;
1444 * If this existing auditor provides preinit or
1445 * activity routines, track their existence. The
1446 * instantiation of a local auditor requires a cookie
1447 * be created that represents the object that heads
1448 * the link-map list of the object being audited.
1450 if (alp
->al_preinit
)
1452 if (alp
->al_activity
)
1459 * Prior to the Unified Process Model (UPM) environment, an
1460 * rtld lock had to be held upon leave(). However, even within
1461 * a UPM environment, an old auditor, that has a lazy dependency
1462 * on libc, is still a possibility. As libc isn't loaded, we
1463 * don't know the process model, and will determine this later.
1464 * Refer to external.c:get_lcinterface().
1466 if ((rtld_flags2
& RT_FL2_UNIFPROC
) == 0)
1467 lml
->lm_flags
|= LML_FLG_HOLDLOCK
;
1470 * Allocate an audit list descriptor for this object and
1471 * search for all known entry points.
1473 if ((alp
= calloc(1, sizeof (Audit_list
))) == NULL
)
1474 return (audit_disable(ptr
, clmp
, ghp
, 0));
1476 alp
->al_libname
= NAME(lmp
);
1481 * All audit libraries must handshake through la_version().
1482 * Determine that the symbol exists, finish initializing the
1483 * object, and then call the function.
1485 if ((alp
->al_version
= (uint_t(*)())audit_symget(alp
,
1486 AI_LAVERSION
, in_nfavl
)) == 0) {
1487 eprintf(lml
, ERR_FATAL
, MSG_INTL(MSG_GEN_NOSYM
),
1488 MSG_ORIG(MSG_SYM_LAVERSION
));
1489 error
= audit_disable(ptr
, clmp
, ghp
, alp
);
1493 if ((tobj
= tsort(lmp
, lml
->lm_init
, RT_SORT_REV
)) ==
1495 return (audit_disable(ptr
, clmp
, ghp
, alp
));
1498 call_init(tobj
, DBG_INIT_SORT
);
1500 APPLICATION_ENTER(rtldflags
);
1501 leave(lml
, thr_flg_reenter
);
1502 alp
->al_vernum
= (*alp
->al_version
)(LAV_CURRENT
);
1503 (void) enter(thr_flg_reenter
);
1504 APPLICATION_RETURN(rtldflags
);
1506 DBG_CALL(Dbg_audit_version(clml
, alp
->al_libname
,
1507 LAV_CURRENT
, alp
->al_vernum
));
1509 if ((alp
->al_vernum
< LAV_VERSION1
) ||
1510 (alp
->al_vernum
> LAV_CURRENT
)) {
1511 eprintf(lml
, ERR_FATAL
, MSG_INTL(MSG_AUD_BADVERS
),
1512 LAV_CURRENT
, alp
->al_vernum
);
1513 error
= audit_disable(ptr
, clmp
, ghp
, alp
);
1517 if (aplist_append(&(adp
->ad_list
), alp
,
1518 AL_CNT_AUDITORS
) == NULL
)
1519 return (audit_disable(ptr
, clmp
, ghp
, alp
));
1524 * Collect any remaining entry points.
1526 alp
->al_objsearch
= (char *(*)())audit_symget(alp
,
1527 AI_LAOBJSEARCH
, in_nfavl
);
1528 alp
->al_objopen
= (uint_t(*)())audit_symget(alp
,
1529 AI_LAOBJOPEN
, in_nfavl
);
1530 alp
->al_objfilter
= (int(*)())audit_symget(alp
,
1531 AI_LAOBJFILTER
, in_nfavl
);
1532 alp
->al_objclose
= (uint_t(*)())audit_symget(alp
,
1533 AI_LAOBJCLOSE
, in_nfavl
);
1534 alp
->al_symbind
= (uintptr_t(*)())audit_symget(alp
,
1535 AI_LASYMBIND
, in_nfavl
);
1536 alp
->al_pltenter
= (uintptr_t(*)())audit_symget(alp
,
1537 AI_LAPLTENTER
, in_nfavl
);
1538 alp
->al_pltexit
= (uintptr_t(*)())audit_symget(alp
,
1539 AI_LAPLTEXIT
, in_nfavl
);
1541 if ((alp
->al_preinit
= (void(*)())audit_symget(alp
,
1542 AI_LAPREINIT
, in_nfavl
)) != NULL
)
1544 if ((alp
->al_activity
= (void(*)())audit_symget(alp
,
1545 AI_LAACTIVITY
, in_nfavl
)) != NULL
)
1549 * Collect the individual object flags, and assign this audit
1550 * list descriptor to its associated link-map list.
1552 adp
->ad_flags
|= alp
->al_flags
;
1557 * If the caller isn't the head of its own link-map list, then any
1558 * preinit or activity entry points need to be tracked separately.
1559 * These "events" are not associated with a particular link-map, and
1560 * thus a traversal of any existing preinit and activity clients is
1563 * If either of these events are required, establish a cookie for the
1564 * object at the head of the link-map list, and make an initial ADD
1565 * activity for these local auditors.
1567 if ((preinit
|| activity
) && ((hlmp
= clml
->lm_head
) != clmp
) &&
1568 (_audit_add_head(clmp
, hlmp
, preinit
, activity
) == 0))
1572 * Free the original audit string, as this descriptor may be used again
1573 * to add additional auditing.
1576 adp
->ad_name
= NULL
;