xref: /illumos-gate/usr/src/cmd/sgs/rtld/common/audit.c (revision 69a119caa6570c7077699161b7c28b6ee9f8b0f4)
1 /*
2  * CDDL HEADER START
3  *
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.
7  *
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.
12  *
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]
18  *
19  * CDDL HEADER END
20  */
21 
22 /*
23  * Copyright (c) 1996, 2010, Oracle and/or its affiliates. All rights reserved.
24  *
25  * Audit interfaces.  Auditing can be enabled in two ways:
26  *
27  *  -	Using the LD_AUDIT environment variable
28  *
29  *  -	From individual objects containing a DT_DEPAUDIT entry
30  *		(see ld(1) -P/-p options).
31  *
32  * The former establishes a global set of audit libraries which can inspect all
33  * objects from a given process.  The latter establishes a local set of audit
34  * libraries which can inspect the immediate dependencies of the caller.
35  *
36  * Audit library capabilities are indicated by flags within the link-map list
37  * header (for global auditing), see LML_TFLG_AUD_* flags, or by the same flags
38  * within the individual link-map (for local auditing).  Although both sets of
39  * flags can occur in different data items they are defined as one to simplify
40  * audit interface requirements.  The basic test for all audit interfaces is:
41  *
42  *    if ((lml->lm_tflags | AFLAGS(lmp)) & LML_TFLG_AUD_MASK)
43  *
44  * Note.  Auditors themselves are identified with the LML_TFLG_NOAUDIT link-map
45  * list flag, and no LML_TFLG_AUD_MASK flags.  These flags get propagated from
46  * a callers link-map list to any new link-map lists created.  Thus, standard
47  * link-maps lists have the LML_TFLG_AUD_MASK flags propagated, and should a
48  * new link-map list be created by an auditor, that list gets tagged as
49  * LML_TFLG_NOAUDIT.
50  *
51  * The latter link-map list equivalence test insures that auditors themselves
52  * (invoked through DT_DEPAUDIT) are not audited.
53  *
54  * The history of version changes:
55  *
56  * LAV_VERSION1 (Solaris 2.6)
57  *	Auditing implementation added.
58  *
59  * LAV_VERSION2 (Solaris 2.6)
60  *	LA_SYMB_ALTVALUE support added.
61  *
62  * LAV_VERSION3 (Solaris 9 update 7)
63  *	ld_objfilter() added.
64  *
65  * LAV_VERSION4 (Solaris 10 update 5)
66  *	Correction of activity calls for local auditors, and introduction of
67  *	-z globalaudit concept.
68  *
69  * LAV_VERSION5 (Solaris 11)
70  *	Under this version, preinit and activity events are enabled from local
71  *	auditors.  The la_preinit and la_activity interfaces require a cookie
72  *	that represents the head of the link-map list being audited.  If a
73  *	local preinit or activity interface is detected, the local auditors
74  *	la_objopen() routine is called with a cookie that represents the object
75  *	that heads the link-map list of the object being audited.
76  *
77  *	A local auditor is loaded through adding a new dependency that requests
78  *	auditing, and therefore an la_activity(ADD) event is already in effect.
79  *	Regardless, the local auditors la_activity() routine is called with the
80  *	cookie that represents the object that heads the link-map list of the
81  *	object being audited.
82  *
83  *	A local auditor can be loaded prior to the preinit event.  In this case,
84  *	the local auditors la_preinit() routine is called with the cookie that
85  *	represents the object that heads the link-map list of the object being
86  *	audited.  After the preinit event, any la_preinit() routine within a
87  *	local auditor will not be called.
88  *
89  *	These events are intended to follow the expected sequence of events
90  *	received by global auditors, ie:
91  *
92  *	  -	la_objopen(main)
93  *	  -	la_activity(ADD)
94  *	  -	la_objopen(dependency)
95  *	  -	la_activity(CONSISTENT)
96  *	  -	la_preinit(main)
97  */
98 
99 #include	<stdio.h>
100 #include	<sys/types.h>
101 #include	<sys/lwp.h>
102 #include	<stdio.h>
103 #include	<stdarg.h>
104 #include	<dlfcn.h>
105 #include	<string.h>
106 #include	<debug.h>
107 #include	"_rtld.h"
108 #include	"_audit.h"
109 #include	"_elf.h"
110 #include	"msg.h"
111 
112 uint_t	audit_flags = 0;		/* Copy of specific audit flags to */
113 					/* simplify boot_elf.s access. */
114 
115 /*
116  * Obtain a head link-map cookie.  Local auditors can provide la_preinit() and
117  * la_activity() routines, and these routines require a cookie that represents
118  * the object that heads the link-map of the object being audited.  A list of
119  * these cookies is maintained on the link-map list.  This list allows multiple
120  * local objects to specify the same auditor, and to obtain the same cookie
121  * for the link-map that heads the link-map list.
122  *
123  * The initial cookie is created by _audit_create_head_client() which is called
124  * from _audit_add_head().  This cookies address is then passed to the local
125  * auditors ld_objopen() and la_activity() routines.  Subsequent preinit and
126  * activity events use _audit_get_head_client() to dynamically retrieve the
127  * cookies address.
128  */
129 static Audit_client *
130 _audit_get_head_client(Rt_map *hlmp, Rt_map *almp)
131 {
132 	Audit_client	*acp;
133 	Aliste		idx;
134 	Lm_list		*hlml = LIST(hlmp);
135 
136 	for (ALIST_TRAVERSE(hlml->lm_aud_cookies, idx, acp)) {
137 		if (acp->ac_lmp == almp)
138 			return (acp);
139 	}
140 	return (NULL);
141 }
142 
143 static Audit_client *
144 _audit_create_head_client(Rt_map *hlmp, Rt_map *almp)
145 {
146 	Audit_client	ac, *acp;
147 	Lm_list		*hlml = LIST(hlmp);
148 
149 	ac.ac_lmp = almp;
150 	ac.ac_cookie = (uintptr_t)hlmp;
151 	ac.ac_flags = 0;
152 
153 	if ((acp = alist_append(&(hlml->lm_aud_cookies), &ac,
154 	    sizeof (Audit_client), AL_CNT_COOKIES)) == NULL)
155 		return (NULL);
156 
157 	return (acp);
158 }
159 
160 /*
161  * Determine the appropriate client.  Each client structure identifies the
162  * link-map of the auditor it is associated with.  From the client structure,
163  * the address of the associated cookie, that represents the object being
164  * audited, is retrieved so that the address can be passed to any audit call.
165  *
166  * Note, objects that are being locally audited, can provide la_preinit() and
167  * la_activity() routines.  These routines must be passed cookies that represent
168  * the object that heads the link-map list of the object being audited.  These
169  * cookies are not maintained on this objects Audit_client structure, but are
170  * obtained from the associated link-map lists lm_cookies alist.
171  */
172 static Audit_client *
173 _audit_client(Audit_info *aip, Rt_map *almp)
174 {
175 	int	ndx;
176 
177 	if (aip == NULL)
178 		return (NULL);
179 
180 	for (ndx = 0; ndx < aip->ai_cnt; ndx++) {
181 		if (aip->ai_clients[ndx].ac_lmp == almp)
182 			return (&(aip->ai_clients[ndx]));
183 	}
184 	return (NULL);
185 }
186 
187 /*
188  * la_filter() caller.  Traverse through all audit libraries and call any
189  * la_filter() entry points found.  A zero return from an auditor indicates
190  * that the filtee should be ignored.
191  */
192 static int
193 _audit_objfilter(APlist *list, Rt_map *frlmp, const char *ref, Rt_map *felmp,
194     uint_t flags)
195 {
196 	Audit_list	*alp;
197 	Aliste		idx;
198 	Lm_list		*frlml = LIST(frlmp);
199 
200 	for (APLIST_TRAVERSE(list, idx, alp)) {
201 		Audit_client	*fracp, *feacp;
202 		Rt_map		*almp = alp->al_lmp;
203 		Lm_list		*alml = LIST(almp);
204 		int		ret;
205 
206 		if (alp->al_objfilter == NULL)
207 			continue;
208 		if ((fracp = _audit_client(AUDINFO(frlmp), almp)) == NULL)
209 			continue;
210 		if ((feacp = _audit_client(AUDINFO(felmp), almp)) == NULL)
211 			continue;
212 
213 		DBG_CALL(Dbg_audit_objfilter(frlml, DBG_AUD_CALL,
214 		    alp->al_libname, NAME(frlmp), NAME(felmp), ref));
215 
216 		leave(alml, thr_flg_reenter);
217 		ret = (*alp->al_objfilter)(&(fracp->ac_cookie), ref,
218 		    &(feacp->ac_cookie), flags);
219 		(void) enter(thr_flg_reenter);
220 
221 		if (ret == 0) {
222 			DBG_CALL(Dbg_audit_objfilter(frlml, DBG_AUD_RET,
223 			    alp->al_libname, NAME(frlmp), NULL, NULL));
224 			return (0);
225 		}
226 	}
227 	return (1);
228 }
229 
230 int
231 audit_objfilter(Rt_map *frlmp, const char *ref, Rt_map *felmp, uint_t flags)
232 {
233 	uint_t	rtldflags;
234 	int	respond = 1;
235 
236 	if (rt_critical())
237 		return (respond);
238 
239 	APPLICATION_ENTER(rtldflags);
240 
241 	if (auditors && (auditors->ad_flags & LML_TFLG_AUD_OBJFILTER))
242 		respond = _audit_objfilter(auditors->ad_list, frlmp,
243 		    ref, felmp, flags);
244 	if (respond && AUDITORS(frlmp) &&
245 	    (AUDITORS(frlmp)->ad_flags & LML_TFLG_AUD_OBJFILTER))
246 		respond = _audit_objfilter(AUDITORS(frlmp)->ad_list, frlmp,
247 		    ref, felmp, flags);
248 
249 	APPLICATION_RETURN(rtldflags);
250 
251 	return (respond);
252 }
253 
254 /*
255  * la_objsearch() caller.  Traverse through all audit libraries and call any
256  * la_objsearch() entry points found.
257  *
258  * Effectively any audit library can change the name we're working with, so we
259  * continue to propagate the new name to each audit library.  Any 0 return
260  * terminates the search.
261  */
262 static char *
263 _audit_objsearch(APlist *list, char *oname, Rt_map *clmp, uint_t flags)
264 {
265 	Audit_list	*alp;
266 	Aliste		idx;
267 	Lm_list		*clml = LIST(clmp);
268 
269 	for (APLIST_TRAVERSE(list, idx, alp)) {
270 		Audit_client	*acp;
271 		Rt_map		*almp = alp->al_lmp;
272 		Lm_list		*alml = LIST(almp);
273 		char		*nname = oname;
274 
275 		if (alp->al_objsearch == NULL)
276 			continue;
277 		if ((acp = _audit_client(AUDINFO(clmp), almp)) == NULL)
278 			continue;
279 
280 		DBG_CALL(Dbg_audit_objsearch(clml, DBG_AUD_CALL,
281 		    alp->al_libname, nname, flags, NULL));
282 
283 		leave(alml, thr_flg_reenter);
284 		nname = (*alp->al_objsearch)(nname, &(acp->ac_cookie), flags);
285 		(void) enter(thr_flg_reenter);
286 
287 		/*
288 		 * Diagnose any return name that differs from the original name
289 		 * passed to the auditor.
290 		 */
291 		if (nname && (nname[0] == '\0'))
292 			nname = NULL;
293 		if ((nname != oname) || strcmp(nname, oname))
294 			DBG_CALL(Dbg_audit_objsearch(clml, DBG_AUD_RET,
295 			    alp->al_libname, oname, flags, nname));
296 
297 		if ((oname = nname) == NULL)
298 			break;
299 
300 	}
301 	return (oname);
302 }
303 
304 char *
305 audit_objsearch(Rt_map *clmp, const char *name, uint_t flags)
306 {
307 	char	*nname = (char *)name;
308 	uint_t	rtldflags;
309 
310 	if (rt_critical())
311 		return (nname);
312 
313 	APPLICATION_ENTER(rtldflags);
314 
315 	if (auditors && (auditors->ad_flags & LML_TFLG_AUD_OBJSEARCH))
316 		nname = _audit_objsearch(auditors->ad_list, nname,
317 		    clmp, flags);
318 	if (nname && AUDITORS(clmp) &&
319 	    (AUDITORS(clmp)->ad_flags & LML_TFLG_AUD_OBJSEARCH))
320 		nname = _audit_objsearch(AUDITORS(clmp)->ad_list, nname,
321 		    clmp, flags);
322 
323 	APPLICATION_RETURN(rtldflags);
324 
325 	DBG_CALL(Dbg_libs_audit(LIST(clmp), name, nname));
326 	return (nname);
327 }
328 
329 /*
330  * la_activity() caller.  Traverse through all audit libraries and call any
331  * la_activity() entry points found.
332  */
333 static void
334 _audit_activity(APlist *list, Rt_map *clmp, uint_t flags, Boolean client)
335 {
336 	Audit_list	*alp;
337 	Aliste		idx;
338 	Lm_list		*clml = LIST(clmp);
339 
340 	for (APLIST_TRAVERSE(list, idx, alp)) {
341 		Audit_client	*acp;
342 		Rt_map		*almp = alp->al_lmp;
343 		Lm_list		*alml = LIST(almp);
344 		uintptr_t	*cookie;
345 
346 		if (alp->al_activity == 0)
347 			continue;
348 
349 		/*
350 		 * Determine what cookie is required.  Any auditing that
351 		 * originates from the object that heads the link-map list has
352 		 * its own cookie.  Local auditors must obtain the cookie that
353 		 * represents the object that heads the link-map list.
354 		 */
355 		if (client)
356 			acp = _audit_client(AUDINFO(clmp), almp);
357 		else
358 			acp = _audit_get_head_client(clml->lm_head, almp);
359 
360 		if (acp == NULL)
361 			continue;
362 		cookie = &(acp->ac_cookie);
363 
364 		/*
365 		 * Make sure the audit library only sees one addition/deletion
366 		 * at a time.  This ensures the library doesn't see numerous
367 		 * events from lazy loading a series of libraries.  Keep track
368 		 * of this caller having called an auditor, so that the
369 		 * appropriate "consistent" event can be supplied on leaving
370 		 * ld.so.1.
371 		 */
372 		if ((flags == LA_ACT_ADD) || (flags == LA_ACT_DELETE)) {
373 			if (alml->lm_flags & LML_FLG_AUDITNOTIFY)
374 				continue;
375 
376 			alml->lm_flags |= LML_FLG_AUDITNOTIFY;
377 			clml->lm_flags |= LML_FLG_ACTAUDIT;
378 		} else {
379 			if ((alml->lm_flags & LML_FLG_AUDITNOTIFY) == 0)
380 				continue;
381 
382 			alml->lm_flags &= ~LML_FLG_AUDITNOTIFY;
383 		}
384 
385 		DBG_CALL(Dbg_audit_activity(clml, alp->al_libname,
386 		    NAME(clml->lm_head), flags));
387 
388 		leave(alml, thr_flg_reenter);
389 		(*alp->al_activity)(cookie, flags);
390 		(void) enter(thr_flg_reenter);
391 	}
392 }
393 
394 void
395 audit_activity(Rt_map *clmp, uint_t flags)
396 {
397 	Rt_map	*lmp;
398 	Aliste	idx;
399 	uint_t	rtldflags;
400 
401 	if (rt_critical())
402 		return;
403 
404 	APPLICATION_ENTER(rtldflags);
405 
406 	if (auditors && (auditors->ad_flags & LML_TFLG_AUD_ACTIVITY))
407 		_audit_activity(auditors->ad_list, clmp, flags, TRUE);
408 	if (AUDITORS(clmp) &&
409 	    (AUDITORS(clmp)->ad_flags & LML_TFLG_AUD_ACTIVITY))
410 		_audit_activity(AUDITORS(clmp)->ad_list, clmp, flags, TRUE);
411 
412 	for (APLIST_TRAVERSE(aud_activity, idx, lmp)) {
413 		if ((clmp != lmp) && AUDITORS(lmp) &&
414 		    (AUDITORS(lmp)->ad_flags & LML_TFLG_AUD_ACTIVITY)) {
415 			_audit_activity(AUDITORS(lmp)->ad_list, lmp, flags,
416 			    FALSE);
417 		}
418 	}
419 
420 	APPLICATION_RETURN(rtldflags);
421 }
422 
423 /*
424  * Determine whether an auditor is in use by the head link-map object.
425  */
426 static int
427 _audit_used_by_head(Rt_map *hlmp, Rt_map *almp)
428 {
429 	Audit_list	*alp;
430 	Aliste		idx;
431 
432 	for (APLIST_TRAVERSE(AUDITORS(hlmp)->ad_list, idx, alp)) {
433 		if (alp->al_lmp == almp)
434 			return (1);
435 	}
436 	return (0);
437 }
438 
439 /*
440  * la_objopen() caller for the head link-map.  Global auditors, or an auditor
441  * started from the object that heads a link-map list (typically the dynamic
442  * executable), are passed to la_objopen().  However, local auditors can
443  * provide activity and preinit events, and for these events, a cookie
444  * representing the head link-map list object is expected.  This routine obtains
445  * these cookies from the link-map list lm_cookies element.  This element
446  * ensures all clients of the same auditor use the same cookie.
447  *
448  * Although a local auditor will get an la_objopen() call for the object that
449  * heads the link-map list of the object being audited, the auditor is not
450  * permitted to request binding information for this head object.  The head
451  * object has already been in existence, and bindings may have been resolved
452  * with it.  This local auditor is coming into existence too late, and thus we
453  * don't allow any bindings to be caught at all.
454  */
455 static int
456 _audit_add_head(Rt_map *clmp, Rt_map *hlmp, int preinit, int activity)
457 {
458 	Lm_list		*clml = LIST(clmp);
459 	Lmid_t		lmid = get_linkmap_id(clml);
460 	Audit_list	*alp;
461 	Aliste		idx;
462 	int		save = 0;
463 
464 	for (APLIST_TRAVERSE(AUDITORS(clmp)->ad_list, idx, alp)) {
465 		Audit_client	*acp;
466 		Rt_map		*almp = alp->al_lmp;
467 		Lm_list		*alml = LIST(almp);
468 		uintptr_t	*cookie;
469 		uint_t		rtldflags;
470 
471 		/*
472 		 * Ensure this local auditor isn't already in existence as an
473 		 * auditor for the head of the link-map list.  If it is, then
474 		 * this auditor will have already receive preinit and activity
475 		 * events.
476 		 */
477 		if (AUDITORS(hlmp) && _audit_used_by_head(hlmp, almp))
478 			continue;
479 
480 		/*
481 		 * Create a cookie that represents the object that heads the
482 		 * link-map list.  If the cookie already exists, then this
483 		 * auditor has already been established for another objects
484 		 * local auditing.  In this case, do not issue a la_objopen()
485 		 * or la_activity() event, as these will have already occurred.
486 		 */
487 		if ((acp = _audit_get_head_client(clml->lm_head, almp)) != NULL)
488 			continue;
489 		if ((acp =
490 		    _audit_create_head_client(clml->lm_head, almp)) == NULL)
491 			return (0);
492 
493 		cookie = &(acp->ac_cookie);
494 		save++;
495 
496 		/*
497 		 * Call the la_objopen() if available.
498 		 */
499 		if (alp->al_objopen) {
500 			uint_t	flags;
501 
502 			DBG_CALL(Dbg_audit_objopen(clml, DBG_AUD_CALL,
503 			    alp->al_libname, NAME(hlmp), 0, FALSE));
504 
505 			APPLICATION_ENTER(rtldflags);
506 			leave(alml, thr_flg_reenter);
507 			flags = (*alp->al_objopen)((Link_map *)hlmp, lmid,
508 			    cookie);
509 			(void) enter(thr_flg_reenter);
510 			APPLICATION_RETURN(rtldflags);
511 
512 			if (flags) {
513 				DBG_CALL(Dbg_audit_objopen(clml, DBG_AUD_RET,
514 				    alp->al_libname, NAME(hlmp), flags, TRUE));
515 			}
516 		}
517 
518 		/*
519 		 * Call the la_activity() if available.
520 		 */
521 		if (alp->al_activity) {
522 			alml->lm_flags |= LML_FLG_AUDITNOTIFY;
523 			clml->lm_flags |= LML_FLG_ACTAUDIT;
524 
525 			DBG_CALL(Dbg_audit_activity(clml, alp->al_libname,
526 			    NAME(clml->lm_head), LA_ACT_ADD));
527 
528 			APPLICATION_ENTER(rtldflags);
529 			leave(alml, thr_flg_reenter);
530 			(*alp->al_activity)(cookie, LA_ACT_ADD);
531 			(void) enter(thr_flg_reenter);
532 			APPLICATION_RETURN(rtldflags);
533 		}
534 	}
535 
536 	/*
537 	 * If new head link-map cookies have been generated, then maintain
538 	 * any preinit and/or activity requirements.
539 	 */
540 	if (save) {
541 		if (preinit && (aplist_append(&aud_preinit, clmp,
542 		    AL_CNT_AUDITORS) == NULL))
543 			return (0);
544 		if (activity && (aplist_append(&aud_activity, clmp,
545 		    AL_CNT_AUDITORS) == NULL))
546 			return (0);
547 	}
548 	return (1);
549 }
550 
551 /*
552  * la_objopen() caller.  Create an audit information structure for the indicated
553  * link-map, regardless of an la_objopen() entry point.  This structure is used
554  * to supply information to various audit interfaces (see LML_MSK_AUDINFO).
555  * Traverse through all audit libraries and call any la_objopen() entry points
556  * found.
557  */
558 static int
559 _audit_objopen(APlist *list, Rt_map *nlmp, Lmid_t lmid, Audit_info *aip,
560     int *ndx)
561 {
562 	Lm_list		*nlml = LIST(nlmp);
563 	Audit_list	*alp;
564 	Aliste		idx;
565 
566 	for (APLIST_TRAVERSE(list, idx, alp)) {
567 		uint_t		flags;
568 		Audit_client	*acp;
569 		Rt_map		*almp = alp->al_lmp;
570 		Lm_list		*alml = LIST(almp);
571 
572 		/*
573 		 * Associate a cookie with the audit library, and assign the
574 		 * initial cookie as the present link-map.
575 		 */
576 		acp = &aip->ai_clients[(*ndx)++];
577 		acp->ac_lmp = alp->al_lmp;
578 		acp->ac_cookie = (uintptr_t)nlmp;
579 
580 		if (alp->al_objopen == NULL)
581 			continue;
582 
583 		DBG_CALL(Dbg_audit_objopen(nlml, DBG_AUD_CALL, alp->al_libname,
584 		    NAME(nlmp), 0, FALSE));
585 
586 		leave(alml, thr_flg_reenter);
587 		flags = (*alp->al_objopen)((Link_map *)nlmp, lmid,
588 		    &(acp->ac_cookie));
589 		(void) enter(thr_flg_reenter);
590 
591 		/*
592 		 * Diagnose any flags returned by the auditor.
593 		 */
594 		if (flags) {
595 			DBG_CALL(Dbg_audit_objopen(nlml, DBG_AUD_RET,
596 			    alp->al_libname, NAME(nlmp), flags, FALSE));
597 		}
598 
599 		if (flags & LA_FLG_BINDTO)
600 			acp->ac_flags |= FLG_AC_BINDTO;
601 
602 		if (flags & LA_FLG_BINDFROM) {
603 			ulong_t		pltcnt;
604 
605 			acp->ac_flags |= FLG_AC_BINDFROM;
606 
607 			/*
608 			 * We only need dynamic plt's if a pltenter and/or a
609 			 * pltexit() entry point exist in one of our auditing
610 			 * libraries.
611 			 */
612 			if (aip->ai_dynplts || (JMPREL(nlmp) == 0) ||
613 			    ((audit_flags & (AF_PLTENTER | AF_PLTEXIT)) == 0))
614 				continue;
615 
616 			/*
617 			 * Create one dynplt for every 'PLT' that exists in the
618 			 * object.
619 			 */
620 			pltcnt = PLTRELSZ(nlmp) / RELENT(nlmp);
621 			if ((aip->ai_dynplts = calloc(pltcnt,
622 			    dyn_plt_ent_size)) == NULL)
623 				return (0);
624 		}
625 	}
626 	return (1);
627 }
628 
629 int
630 audit_objopen(Rt_map *clmp, Rt_map *nlmp)
631 {
632 	Lmid_t		lmid = get_linkmap_id(LIST(nlmp));
633 	int		respond = 1, ndx = 0;
634 	uint_t		rtldflags;
635 	uint_t		clients = 0;
636 	Audit_info	*aip;
637 
638 	if (rt_critical())
639 		return (respond);
640 
641 	/*
642 	 * Determine the number of auditors that can receive information
643 	 * regarding this object.  This provides the number of client
644 	 * structures required for this object.
645 	 */
646 	if (auditors)
647 		clients = auditors->ad_cnt;
648 	if (AUDITORS(clmp))
649 		clients += AUDITORS(clmp)->ad_cnt;
650 	if ((nlmp != clmp) && AUDITORS(nlmp))
651 		clients += AUDITORS(nlmp)->ad_cnt;
652 
653 	/*
654 	 * Allocate an audit information structure.  Each audited object
655 	 * maintains a AUDINFO() structure.  As this structure can only be
656 	 * created once all auditors are loaded, a client count can now be
657 	 * computed.
658 	 *
659 	 * The allocation of the audit information structure includes an array
660 	 * of audit clients, 1 per audit library that has been loaded.
661 	 *
662 	 *			 ---------------
663 	 *			| ai_cnt	|
664 	 * 	Audit_info	| ai_clients	|-------
665 	 *			| ai_dynplts	|	|
666 	 *			|---------------|	|
667 	 * 	Audit_client    |	1	|<------
668 	 *			|---------------|
669 	 *			|	2	|
670 	 *			    .........
671 	 */
672 	if ((AUDINFO(nlmp) = aip = calloc(1, sizeof (Audit_info) +
673 	    (sizeof (Audit_client) * clients))) == NULL)
674 		return (0);
675 
676 	aip->ai_cnt = clients;
677 	aip->ai_clients = (Audit_client *)((uintptr_t)aip +
678 	    sizeof (Audit_info));
679 
680 	APPLICATION_ENTER(rtldflags);
681 
682 	if (auditors)
683 		respond = _audit_objopen(auditors->ad_list, nlmp,
684 		    lmid, aip, &ndx);
685 	if (respond && AUDITORS(clmp))
686 		respond = _audit_objopen(AUDITORS(clmp)->ad_list, nlmp,
687 		    lmid, aip, &ndx);
688 	if (respond && (nlmp != clmp) && AUDITORS(nlmp))
689 		respond = _audit_objopen(AUDITORS(nlmp)->ad_list, nlmp,
690 		    lmid, aip, &ndx);
691 
692 	APPLICATION_RETURN(rtldflags);
693 
694 	return (respond);
695 }
696 
697 /*
698  * la_objclose() caller.  Traverse through all audit libraries and call any
699  * la_objclose() entry points found.
700  */
701 void
702 _audit_objclose(APlist *list, Rt_map *lmp)
703 {
704 	Audit_list	*alp;
705 	Aliste		idx;
706 	Lm_list		*lml = LIST(lmp);
707 
708 	for (APLIST_TRAVERSE(list, idx, alp)) {
709 		Audit_client	*acp;
710 		Rt_map		*almp = alp->al_lmp;
711 		Lm_list		*alml = LIST(almp);
712 
713 		if (alp->al_objclose == NULL)
714 			continue;
715 		if ((acp = _audit_client(AUDINFO(lmp), almp)) == NULL)
716 			continue;
717 
718 		DBG_CALL(Dbg_audit_objclose(lml, alp->al_libname, NAME(lmp)));
719 
720 		leave(alml, thr_flg_reenter);
721 		(*alp->al_objclose)(&(acp->ac_cookie));
722 		(void) enter(thr_flg_reenter);
723 	}
724 }
725 
726 /*
727  * Determine any la_objclose() requirements.  An object that is about to be
728  * deleted needs to trigger an la_objclose() event to any associated auditors.
729  * In the case of local auditing, a deleted object may have a number of callers,
730  * and each of these callers may have their own auditing requirements.  To
731  * ensure only one la_objclose() event is sent to each auditor, collect the
732  * auditors from any callers and make sure there's no duplication.
733  */
734 inline static void
735 add_objclose_list(Rt_map *lmp, APlist **alpp)
736 {
737 	if (AFLAGS(lmp) & LML_TFLG_AUD_OBJCLOSE) {
738 		Audit_list	*alp;
739 		Aliste		idx;
740 
741 		for (APLIST_TRAVERSE(AUDITORS(lmp)->ad_list, idx, alp)) {
742 			if (aplist_test(alpp, alp, AL_CNT_AUDITORS) == 0)
743 				return;
744 		}
745 	}
746 }
747 
748 void
749 audit_objclose(Rt_map *lmp, Rt_map *clmp)
750 {
751 	APlist		*alp = NULL;
752 	uint_t		rtldflags;
753 
754 	if (rt_critical())
755 		return;
756 
757 	APPLICATION_ENTER(rtldflags);
758 
759 	if (auditors && (auditors->ad_flags & LML_TFLG_AUD_OBJCLOSE))
760 		_audit_objclose(auditors->ad_list, lmp);
761 
762 	/*
763 	 * If this link-map list contains local auditors, determine if this
764 	 * object, or any of this objects CALLERS have instantiated auditors
765 	 * that need to know of la_objclose() events.
766 	 */
767 	if (LIST(lmp)->lm_flags & LML_FLG_LOCAUDIT) {
768 		Bnd_desc	*bdp;
769 		Aliste		idx;
770 
771 		add_objclose_list(lmp, &alp);
772 
773 		for (APLIST_TRAVERSE(CALLERS(lmp), idx, bdp))
774 			add_objclose_list(bdp->b_caller, &alp);
775 	}
776 
777 	/*
778 	 * If this close originated from dlclose(), determine whether the caller
779 	 * requires a la_objclose() event.
780 	 */
781 	if (clmp)
782 		add_objclose_list(clmp, &alp);
783 
784 	if (alp) {
785 		_audit_objclose(alp, lmp);
786 		free((void *)alp);
787 	}
788 
789 	APPLICATION_RETURN(rtldflags);
790 }
791 
792 /*
793  * la_pltenter() caller.  Traverse through all audit libraries and call any
794  * la_pltenter() entry points found.  NOTE: this routine is called via the
795  * glue code established in elf_plt_trace_write(), the symbol descriptor is
796  * created as part of the glue and for 32bit environments the st_name is a
797  * pointer to the real symbol name (ie. it's already been adjusted with the
798  * objects base offset).  For 64bit environments the st_name remains the
799  * original symbol offset and in this case it is used to compute the real name
800  * pointer and pass as a separate argument to the auditor.
801  */
802 static void
803 _audit_pltenter(APlist *list, Rt_map *rlmp, Rt_map *dlmp, Sym *sym,
804     uint_t ndx, void *regs, uint_t *flags)
805 {
806 	Audit_list	*alp;
807 	Aliste		idx;
808 	Lm_list		*rlml = LIST(rlmp);
809 #if	defined(_ELF64)
810 	const char	*name = (const char *)(sym->st_name + STRTAB(dlmp));
811 #else
812 	const char	*name = (const char *)(sym->st_name);
813 #endif
814 
815 	for (APLIST_TRAVERSE(list, idx, alp)) {
816 		Audit_client	*racp, *dacp;
817 		Rt_map		*almp = alp->al_lmp;
818 		Lm_list		*alml = LIST(almp);
819 		Addr		ovalue = sym->st_value;
820 
821 		if (alp->al_pltenter == 0)
822 			continue;
823 		if ((racp = _audit_client(AUDINFO(rlmp), almp)) == NULL)
824 			continue;
825 		if ((dacp = _audit_client(AUDINFO(dlmp), almp)) == NULL)
826 			continue;
827 		if (((racp->ac_flags & FLG_AC_BINDFROM) == 0) ||
828 		    ((dacp->ac_flags & FLG_AC_BINDTO) == 0))
829 			continue;
830 
831 		DBG_CALL(Dbg_audit_pltenter(rlml, DBG_AUD_CALL,
832 		    alp->al_libname, name, ovalue));
833 
834 		leave(alml, thr_flg_reenter);
835 		sym->st_value = (Addr)(*alp->al_pltenter)(sym, ndx,
836 		    &(racp->ac_cookie), &(dacp->ac_cookie), regs,
837 		/* BEGIN CSTYLED */
838 #if	defined(_ELF64)
839 		    flags, name);
840 #else
841 		    flags);
842 #endif
843 		/* END CSTYLED */
844 		(void) enter(thr_flg_reenter);
845 
846 		if (ovalue != sym->st_value) {
847 			DBG_CALL(Dbg_audit_pltenter(rlml, DBG_AUD_RET,
848 			    alp->al_libname, name, sym->st_value));
849 		}
850 	}
851 }
852 
853 Addr
854 audit_pltenter(Rt_map *rlmp, Rt_map *dlmp, Sym *sym, uint_t ndx,
855     void *regs, uint_t *flags)
856 {
857 	Sym	nsym = *sym;
858 	uint_t	rtldflags;
859 
860 	if (rt_critical())
861 		return (nsym.st_value);
862 
863 	/*
864 	 * We're effectively entering ld.so.1 from user (glue) code.
865 	 */
866 	(void) enter(0);
867 	APPLICATION_ENTER(rtldflags);
868 
869 	if (auditors && (auditors->ad_flags & LML_TFLG_AUD_PLTENTER))
870 		_audit_pltenter(auditors->ad_list, rlmp, dlmp, &nsym,
871 		    ndx, regs, flags);
872 	if (AUDITORS(rlmp) &&
873 	    (AUDITORS(rlmp)->ad_flags & LML_TFLG_AUD_PLTENTER))
874 		_audit_pltenter(AUDITORS(rlmp)->ad_list, rlmp, dlmp, &nsym,
875 		    ndx, regs, flags);
876 
877 	APPLICATION_RETURN(rtldflags);
878 	leave(LIST(rlmp), 0);
879 
880 	return (nsym.st_value);
881 }
882 
883 /*
884  * la_pltexit() caller.  Traverse through all audit libraries and call any
885  * la_pltexit() entry points found.  See notes above (_audit_pltenter) for
886  * discussion on st_name.
887  */
888 static Addr
889 _audit_pltexit(APlist *list, uintptr_t retval, Rt_map *rlmp, Rt_map *dlmp,
890     Sym *sym, uint_t ndx)
891 {
892 	Audit_list	*alp;
893 	Aliste		idx;
894 #if	defined(_ELF64)
895 	const char	*name = (const char *)(sym->st_name + STRTAB(dlmp));
896 #else
897 	const char	*name = (const char *)(sym->st_name);
898 #endif
899 	Lm_list		*rlml = LIST(rlmp);
900 
901 	for (APLIST_TRAVERSE(list, idx, alp)) {
902 		Audit_client	*racp, *dacp;
903 		Rt_map		*almp = alp->al_lmp;
904 		Lm_list		*alml = LIST(almp);
905 
906 		if (alp->al_pltexit == 0)
907 			continue;
908 		if ((racp = _audit_client(AUDINFO(rlmp), almp)) == NULL)
909 			continue;
910 		if ((dacp = _audit_client(AUDINFO(dlmp), almp)) == NULL)
911 			continue;
912 		if (((racp->ac_flags & FLG_AC_BINDFROM) == 0) ||
913 		    ((dacp->ac_flags & FLG_AC_BINDTO) == 0))
914 			continue;
915 
916 		DBG_CALL(Dbg_audit_pltexit(rlml, alp->al_libname, name));
917 
918 		leave(alml, thr_flg_reenter);
919 		retval = (*alp->al_pltexit)(sym, ndx,
920 		    &(racp->ac_cookie), &(dacp->ac_cookie),
921 		/* BEGIN CSTYLED */
922 #if	defined(_ELF64)
923 		    retval, name);
924 #else
925 		    retval);
926 #endif
927 		/* END CSTYLED */
928 		(void) enter(thr_flg_reenter);
929 	}
930 	return (retval);
931 }
932 
933 Addr
934 audit_pltexit(uintptr_t retval, Rt_map *rlmp, Rt_map *dlmp, Sym *sym,
935     uint_t ndx)
936 {
937 	uintptr_t	_retval = retval;
938 	uint_t		rtldflags;
939 
940 	if (rt_critical())
941 		return (_retval);
942 
943 	/*
944 	 * We're effectively entering ld.so.1 from user (glue) code.
945 	 */
946 	(void) enter(0);
947 	APPLICATION_ENTER(rtldflags);
948 
949 	if (auditors && (auditors->ad_flags & LML_TFLG_AUD_PLTEXIT))
950 		_retval = _audit_pltexit(auditors->ad_list, _retval,
951 		    rlmp, dlmp, sym, ndx);
952 	if (AUDITORS(rlmp) && (AUDITORS(rlmp)->ad_flags & LML_TFLG_AUD_PLTEXIT))
953 		_retval = _audit_pltexit(AUDITORS(rlmp)->ad_list, _retval,
954 		    rlmp, dlmp, sym, ndx);
955 
956 	APPLICATION_RETURN(rtldflags);
957 	leave(LIST(rlmp), 0);
958 
959 	return (_retval);
960 }
961 
962 
963 /*
964  * la_symbind() caller.  Traverse through all audit libraries and call any
965  * la_symbind() entry points found.
966  */
967 static Addr
968 _audit_symbind(APlist *list, Rt_map *rlmp, Rt_map *dlmp, Sym *sym, uint_t ndx,
969     uint_t *flags, int *called)
970 {
971 	Audit_list	*alp;
972 	Aliste		idx;
973 	Lm_list		*rlml = LIST(rlmp);
974 #if	defined(_ELF64)
975 	const char	*name = (const char *)(sym->st_name + STRTAB(dlmp));
976 #else
977 	const char	*name = (const char *)(sym->st_name);
978 #endif
979 
980 	for (APLIST_TRAVERSE(list, idx, alp)) {
981 		Audit_client	*racp, *dacp;
982 		Rt_map		*almp = alp->al_lmp;
983 		Lm_list		*alml = LIST(almp);
984 		Addr		ovalue = sym->st_value;
985 		uint_t		lflags, oflags = *flags;
986 
987 		if (alp->al_symbind == 0)
988 			continue;
989 		if ((racp = _audit_client(AUDINFO(rlmp), almp)) == NULL)
990 			continue;
991 		if ((dacp = _audit_client(AUDINFO(dlmp), almp)) == NULL)
992 			continue;
993 		if (((racp->ac_flags & FLG_AC_BINDFROM) == 0) ||
994 		    ((dacp->ac_flags & FLG_AC_BINDTO) == 0))
995 			continue;
996 
997 		/*
998 		 * The la_symbind interface is only called when the calling
999 		 * object has been identified as BINDFROM, and the destination
1000 		 * object has been identified as BINDTO.  Use a local version of
1001 		 * the flags, so that any user update can be collected.
1002 		 */
1003 		(*called)++;
1004 		lflags = (oflags & ~(LA_SYMB_NOPLTENTER | LA_SYMB_NOPLTEXIT));
1005 
1006 		DBG_CALL(Dbg_audit_symbind(rlml, DBG_AUD_CALL,
1007 		    alp->al_libname, name, ovalue, oflags));
1008 
1009 		leave(alml, thr_flg_reenter);
1010 		sym->st_value = (*alp->al_symbind)(sym, ndx,
1011 		    &(racp->ac_cookie), &(dacp->ac_cookie),
1012 		/* BEGIN CSTYLED */
1013 #if	defined(_ELF64)
1014 		    &lflags, name);
1015 #else
1016 		    &lflags);
1017 #endif
1018 		/* END CSTYLED */
1019 		(void) enter(thr_flg_reenter);
1020 
1021 		/*
1022 		 * If the auditor indicated that they did not want to process
1023 		 * pltenter, or pltexit audits for this symbol, retain this
1024 		 * information.  Also retain whether an alternative symbol value
1025 		 * has been supplied.
1026 		 */
1027 		*flags |= (lflags & (LA_SYMB_NOPLTENTER | LA_SYMB_NOPLTEXIT));
1028 		if ((ovalue != sym->st_value) &&
1029 		    (alp->al_vernum >= LAV_VERSION2))
1030 			*flags |= LA_SYMB_ALTVALUE;
1031 
1032 		if ((ovalue != sym->st_value) || (oflags != *flags)) {
1033 			DBG_CALL(Dbg_audit_symbind(rlml, DBG_AUD_RET,
1034 			    alp->al_libname, name, sym->st_value, *flags));
1035 		}
1036 	}
1037 	return (sym->st_value);
1038 }
1039 
1040 Addr
1041 audit_symbind(Rt_map *rlmp, Rt_map *dlmp, Sym *sym, uint_t ndx, Addr value,
1042     uint_t *flags)
1043 {
1044 	Sym	nsym;
1045 	int	called = 0;
1046 	uint_t	rtldflags;
1047 
1048 	/*
1049 	 * Construct a new symbol from that supplied but with the real address.
1050 	 * In the 64-bit world the st_name field is only 32-bits which isn't
1051 	 * big enough to hold a character pointer. We pass this pointer as a
1052 	 * separate parameter for 64-bit audit libraries.
1053 	 */
1054 	nsym = *sym;
1055 	nsym.st_value = value;
1056 
1057 	if (rt_critical())
1058 		return (nsym.st_value);
1059 
1060 #if	!defined(_ELF64)
1061 	nsym.st_name += (Word)STRTAB(dlmp);
1062 #endif
1063 	APPLICATION_ENTER(rtldflags);
1064 
1065 	if (auditors && (auditors->ad_flags & LML_TFLG_AUD_SYMBIND))
1066 		nsym.st_value = _audit_symbind(auditors->ad_list,
1067 		    rlmp, dlmp, &nsym, ndx, flags, &called);
1068 	if (AUDITORS(rlmp) && (AUDITORS(rlmp)->ad_flags & LML_TFLG_AUD_SYMBIND))
1069 		nsym.st_value = _audit_symbind(AUDITORS(rlmp)->ad_list,
1070 		    rlmp, dlmp, &nsym, ndx, flags, &called);
1071 
1072 	/*
1073 	 * If no la_symbind() was called for this interface, fabricate that no
1074 	 * la_pltenter, or la_pltexit is required.  This helps reduce the glue
1075 	 * code created for further auditing.
1076 	 */
1077 	if (called == 0)
1078 		*flags |= (LA_SYMB_NOPLTENTER | LA_SYMB_NOPLTEXIT);
1079 
1080 	APPLICATION_RETURN(rtldflags);
1081 
1082 	return (nsym.st_value);
1083 }
1084 
1085 /*
1086  * la_preinit() caller.  Traverse through all audit libraries and call any
1087  * la_preinit() entry points found.
1088  */
1089 static void
1090 _audit_preinit(APlist *list, Rt_map *clmp, Boolean client)
1091 {
1092 	Audit_list	*alp;
1093 	Aliste		idx;
1094 	Lm_list		*clml = LIST(clmp);
1095 
1096 	for (APLIST_TRAVERSE(list, idx, alp)) {
1097 		Audit_client	*acp;
1098 		Rt_map		*almp = alp->al_lmp;
1099 		Lm_list		*alml = LIST(almp);
1100 		uintptr_t	*cookie;
1101 
1102 		if (alp->al_preinit == 0)
1103 			continue;
1104 
1105 		/*
1106 		 * Determine what cookie is required.  Any auditing that
1107 		 * originates from the object that heads the link-map list has
1108 		 * its own cookie.  Local auditors must obtain the cookie that
1109 		 * represents the object that heads the link-map list.
1110 		 */
1111 		if (client)
1112 			acp = _audit_client(AUDINFO(clmp), almp);
1113 		else
1114 			acp = _audit_get_head_client(clml->lm_head, almp);
1115 
1116 		if (acp == NULL)
1117 			continue;
1118 		cookie = &(acp->ac_cookie);
1119 
1120 		DBG_CALL(Dbg_audit_preinit(clml, alp->al_libname,
1121 		    NAME(clml->lm_head)));
1122 
1123 		leave(alml, thr_flg_reenter);
1124 		(*alp->al_preinit)(cookie);
1125 		(void) enter(thr_flg_reenter);
1126 	}
1127 }
1128 
1129 void
1130 audit_preinit(Rt_map *mlmp)
1131 {
1132 	Rt_map	*clmp;
1133 	Aliste	idx;
1134 	uint_t	rtldflags;
1135 
1136 	if (rt_critical())
1137 		return;
1138 
1139 	APPLICATION_ENTER(rtldflags);
1140 
1141 	if (auditors && (auditors->ad_flags & LML_TFLG_AUD_PREINIT))
1142 		_audit_preinit(auditors->ad_list, mlmp, TRUE);
1143 
1144 	if (AUDITORS(mlmp) && (AUDITORS(mlmp)->ad_flags & LML_TFLG_AUD_PREINIT))
1145 		_audit_preinit(AUDITORS(mlmp)->ad_list, mlmp, TRUE);
1146 
1147 	for (APLIST_TRAVERSE(aud_preinit, idx, clmp)) {
1148 		if (AUDITORS(clmp) &&
1149 		    (AUDITORS(clmp)->ad_flags & LML_TFLG_AUD_PREINIT))
1150 			_audit_preinit(AUDITORS(clmp)->ad_list, clmp, FALSE);
1151 	}
1152 
1153 	APPLICATION_RETURN(rtldflags);
1154 }
1155 
1156 /*
1157  * Clean up (free) an audit descriptor.  First, gather a list of all handles,
1158  * and then close each one down.  This is done rather than using the handles
1159  * directly from the auditors, as the audit list can be torn down as a result
1160  * of the dlclose.  In other words, what you're pointing at can be removed
1161  * while you're still pointing at it.
1162  */
1163 void
1164 audit_desc_cleanup(Rt_map *clmp)
1165 {
1166 	Audit_desc	*adp = AUDITORS(clmp);
1167 	Audit_list	*alp;
1168 	Aliste		idx;
1169 	APlist		*ghalp = NULL;
1170 
1171 	if (adp == NULL)
1172 		return;
1173 	if (adp->ad_name)
1174 		free(adp->ad_name);
1175 
1176 	for (APLIST_TRAVERSE(adp->ad_list, idx, alp))
1177 		(void) aplist_append(&ghalp, alp->al_ghp, AL_CNT_GROUPS);
1178 
1179 	free(adp->ad_list);
1180 	adp->ad_list = NULL;
1181 
1182 	free(adp);
1183 
1184 	/*
1185 	 * Indicate that the caller is no longer being audited.
1186 	 */
1187 	AUDITORS(clmp) = NULL;
1188 	AFLAGS(clmp) &= ~LML_TFLG_AUD_MASK;
1189 
1190 	if (ghalp) {
1191 		Grp_hdl		*ghp;
1192 		Aliste		idx;
1193 
1194 		for (APLIST_TRAVERSE(ghalp, idx, ghp)) {
1195 			(void) dlclose_intn(ghp, clmp);
1196 		}
1197 		free(ghalp);
1198 	}
1199 }
1200 
1201 /*
1202  * Objects that establish local auditors may have been added to preinit or
1203  * activity lists.  Remove the object from this list if it is present.
1204  */
1205 static void
1206 remove_auditor(APlist *alp, Rt_map *clmp)
1207 {
1208 	Rt_map	*lmp;
1209 	Aliste	idx;
1210 
1211 	for (APLIST_TRAVERSE(alp, idx, lmp)) {
1212 		if (lmp == clmp) {
1213 			aplist_delete(alp, &idx);
1214 			return;
1215 		}
1216 	}
1217 }
1218 
1219 /*
1220  * Clean up (free) an audit information structure.
1221  */
1222 void
1223 audit_info_cleanup(Rt_map *clmp)
1224 {
1225 	Audit_info	*aip = AUDINFO(clmp);
1226 
1227 	if (aip == NULL)
1228 		return;
1229 
1230 	if (aip->ai_dynplts)
1231 		free(aip->ai_dynplts);
1232 
1233 	if (aud_preinit)
1234 		remove_auditor(aud_preinit, clmp);
1235 	if (aud_activity)
1236 		remove_auditor(aud_activity, clmp);
1237 
1238 	free(aip);
1239 }
1240 
1241 /*
1242  * Create a data structure of symbol lookup names and associated flags to help
1243  * simplify audit_symget() use.
1244  */
1245 typedef struct {
1246 	Msg	sname;
1247 	uint_t	alflag;
1248 	uint_t	auflag;
1249 } Aud_info;
1250 
1251 static const Aud_info aud_info[] = {
1252 	{ MSG_SYM_LAVERSION, 0, 0 },	/* MSG_ORIG(MSG_SYM_LAVERSION) */
1253 	{ MSG_SYM_LAPREINIT,		/* MSG_ORIG(MSG_SYM_LAPREINIT) */
1254 	    LML_TFLG_AUD_PREINIT, 0 },
1255 	{ MSG_SYM_LAOBJSEARCH,		/* MSG_ORIG(MSG_SYM_LAOBJSEARCH) */
1256 	    LML_TFLG_AUD_OBJSEARCH, 0 },
1257 	{ MSG_SYM_LAOBJOPEN,		/* MSG_ORIG(MSG_SYM_LAOBJOPEN) */
1258 	    LML_TFLG_AUD_OBJOPEN, 0 },
1259 	{ MSG_SYM_LAOBJFILTER,		/* MSG_ORIG(MSG_SYM_LAOBJFILTER */
1260 	    LML_TFLG_AUD_OBJFILTER, 0 },
1261 	{ MSG_SYM_LAOBJCLOSE,		/* MSG_ORIG(MSG_SYM_LAOBJCLOSE) */
1262 	    LML_TFLG_AUD_OBJCLOSE, 0 },
1263 	{ MSG_SYM_LAACTIVITY,		/* MSG_ORIG(MSG_SYM_LAACTIVITY) */
1264 	    LML_TFLG_AUD_ACTIVITY, 0 },
1265 
1266 #if	defined(_ELF64)
1267 	{ MSG_SYM_LASYMBIND_64,		/* MSG_ORIG(MSG_SYM_LASYMBIND_64) */
1268 #else
1269 	{ MSG_SYM_LASYMBIND,		/* MSG_ORIG(MSG_SYM_LASYMBIND) */
1270 #endif
1271 	    LML_TFLG_AUD_SYMBIND, 0 },
1272 
1273 #if	defined(__sparcv9)
1274 	{ MSG_SYM_LAV9PLTENTER,		/* MSG_ORIG(MSG_SYM_LAV9PLTENTER) */
1275 #elif   defined(__sparc)
1276 	{ MSG_SYM_LAV8PLTENTER,		/* MSG_ORIG(MSG_SYM_LAV8PLTENTER) */
1277 #elif	defined(__amd64)
1278 	{ MSG_SYM_LAAMD64PLTENTER, /* MSG_ORIG(MSG_SYM_LAAMD64PLTENTER) */
1279 #elif	defined(__i386)
1280 	{ MSG_SYM_LAX86PLTENTER,	/* MSG_ORIG(MSG_SYM_LAX86PLTENTER) */
1281 #else
1282 #error platform not defined!
1283 #endif
1284 	    LML_TFLG_AUD_PLTENTER, AF_PLTENTER },
1285 
1286 #if	defined(_ELF64)
1287 	{ MSG_SYM_LAPLTEXIT_64,		/* MSG_ORIG(MSG_SYM_LAPLTEXIT_64) */
1288 #else
1289 	{ MSG_SYM_LAPLTEXIT,		/* MSG_ORIG(MSG_SYM_LAPLTEXIT) */
1290 #endif
1291 	    LML_TFLG_AUD_PLTEXIT, AF_PLTEXIT }
1292 };
1293 
1294 #define	AI_LAVERSION	0
1295 #define	AI_LAPREINIT	1
1296 #define	AI_LAOBJSEARCH	2
1297 #define	AI_LAOBJOPEN	3
1298 #define	AI_LAOBJFILTER	4
1299 #define	AI_LAOBJCLOSE	5
1300 #define	AI_LAACTIVITY	6
1301 #define	AI_LASYMBIND	7
1302 #define	AI_LAPLTENTER	8
1303 #define	AI_LAPLTEXIT	9
1304 
1305 static Addr
1306 audit_symget(Audit_list *alp, int info, int *in_nfavl)
1307 {
1308 	Rt_map		*lmp = alp->al_lmp;
1309 	const char	*sname = MSG_ORIG(aud_info[info].sname);
1310 	uint_t		alflag = aud_info[info].alflag;
1311 	uint_t		auflag = aud_info[info].auflag;
1312 	uint_t		binfo;
1313 	Slookup		sl;
1314 	Sresult		sr;
1315 
1316 	/*
1317 	 * Initialize the symbol lookup, and symbol result, data structures.
1318 	 */
1319 	SLOOKUP_INIT(sl, sname, lml_rtld.lm_head, lmp, ld_entry_cnt,
1320 	    0, 0, 0, 0, (LKUP_FIRST | LKUP_DLSYM));
1321 	SRESULT_INIT(sr, sname);
1322 
1323 	if (LM_LOOKUP_SYM(lmp)(&sl, &sr, &binfo, in_nfavl)) {
1324 		Addr	addr = sr.sr_sym->st_value;
1325 
1326 		if (!(FLAGS(lmp) & FLG_RT_FIXED))
1327 			addr += ADDR(lmp);
1328 
1329 		if (alflag)
1330 			alp->al_flags |= alflag;
1331 		if (auflag)
1332 			audit_flags |= auflag;
1333 
1334 		/*
1335 		 * Note, unlike most other diagnostics, where we wish to
1336 		 * identify the lmid of the caller, here we use the lmid of
1337 		 * the auditor itself to show the association of the auditor
1338 		 * and the interfaces it provides.
1339 		 */
1340 		DBG_CALL(Dbg_audit_interface(LIST(alp->al_lmp),
1341 		    alp->al_libname, sr.sr_name));
1342 		return (addr);
1343 	}
1344 	return (0);
1345 }
1346 
1347 /*
1348  * Centralize cleanup routines.
1349  */
1350 static int
1351 audit_disable(char *name, Rt_map *clmp, Grp_hdl *ghp, Audit_list *alp)
1352 {
1353 	eprintf(LIST(clmp), ERR_FATAL, MSG_INTL(MSG_AUD_DISABLED), name);
1354 	if (ghp)
1355 		(void) dlclose_intn(ghp, clmp);
1356 	if (alp)
1357 		free(alp);
1358 
1359 	return (0);
1360 }
1361 
1362 /*
1363  * Given a list of one or more audit libraries, open each one and establish a
1364  * a descriptor representing the entry points it provides.
1365  */
1366 int
1367 audit_setup(Rt_map *clmp, Audit_desc *adp, uint_t orig, int *in_nfavl)
1368 {
1369 	char		*ptr, *next;
1370 	Lm_list		*clml = LIST(clmp);
1371 	Rt_map		*hlmp;
1372 	int		error = 1, activity = 0, preinit = 0;
1373 	uint_t		rtldflags;
1374 
1375 	/*
1376 	 * Determine the type of auditing for diagnostics.
1377 	 */
1378 	if (DBG_ENABLED) {
1379 		int	type;
1380 
1381 		if (orig & PD_FLG_EXTLOAD)
1382 			type = DBG_AUD_PRELOAD;
1383 		else if (FLAGS1(clmp) & FL1_RT_GLOBAUD)
1384 			type = DBG_AUD_GLOBAL;
1385 		else
1386 			type = DBG_AUD_LOCAL;
1387 
1388 		DBG_CALL(Dbg_audit_lib(clmp, adp->ad_name, type));
1389 	}
1390 
1391 	/*
1392 	 * Mark that we have at least one auditing link map
1393 	 */
1394 	rtld_flags2 |= RT_FL2_HASAUDIT;
1395 
1396 	/*
1397 	 * The audit definitions may be a list (which will already have been
1398 	 * dupped) so split it into individual tokens.
1399 	 */
1400 	for (ptr = strtok_r(adp->ad_name, MSG_ORIG(MSG_STR_DELIMIT), &next);
1401 	    ptr; ptr = strtok_r(NULL,  MSG_ORIG(MSG_STR_DELIMIT), &next)) {
1402 		Grp_hdl		*ghp;
1403 		Rt_map		*lmp;
1404 		Lm_list		*lml;
1405 		Rt_map		**tobj;
1406 		Audit_list	*alp;
1407 
1408 		DBG_CALL(Dbg_util_nl(clml, DBG_NL_STD));
1409 
1410 		/*
1411 		 * Open the audit library on its own link-map.
1412 		 */
1413 		if ((ghp = dlmopen_intn((Lm_list *)LM_ID_NEWLM, ptr,
1414 		    (RTLD_FIRST | RTLD_GLOBAL | RTLD_WORLD), clmp,
1415 		    FLG_RT_AUDIT, orig)) == NULL) {
1416 			error = audit_disable(ptr, clmp, 0, 0);
1417 			continue;
1418 		}
1419 		lmp = ghp->gh_ownlmp;
1420 		lml = LIST(lmp);
1421 
1422 		/*
1423 		 * If this auditor has already been loaded, reuse it.
1424 		 */
1425 		if ((alp = lml->lm_alp) != NULL) {
1426 			if (aplist_append(&(adp->ad_list), alp,
1427 			    AL_CNT_AUDITORS) == NULL)
1428 				return (audit_disable(ptr, clmp, ghp, alp));
1429 
1430 			adp->ad_cnt++;
1431 			adp->ad_flags |= alp->al_flags;
1432 
1433 			/*
1434 			 * If this existing auditor provides preinit or
1435 			 * activity routines, track their existence.  The
1436 			 * instantiation of a local auditor requires a cookie
1437 			 * be created that represents the object that heads
1438 			 * the link-map list of the object being audited.
1439 			 */
1440 			if (alp->al_preinit)
1441 				preinit++;
1442 			if (alp->al_activity)
1443 				activity++;
1444 
1445 			continue;
1446 		}
1447 
1448 		/*
1449 		 * Prior to the Unified Process Model (UPM) environment, an
1450 		 * rtld lock had to be held upon leave().  However, even within
1451 		 * a UPM environment, an old auditor, that has a lazy dependency
1452 		 * on libc, is still a possibility.  As libc isn't loaded, we
1453 		 * don't know the process model, and will determine this later.
1454 		 * Refer to external.c:get_lcinterface().
1455 		 */
1456 		if ((rtld_flags2 & RT_FL2_UNIFPROC) == 0)
1457 			lml->lm_flags |= LML_FLG_HOLDLOCK;
1458 
1459 		/*
1460 		 * Allocate an audit list descriptor for this object and
1461 		 * search for all known entry points.
1462 		 */
1463 		if ((alp = calloc(1, sizeof (Audit_list))) == NULL)
1464 			return (audit_disable(ptr, clmp, ghp, 0));
1465 
1466 		alp->al_libname = NAME(lmp);
1467 		alp->al_lmp = lmp;
1468 		alp->al_ghp = ghp;
1469 
1470 		/*
1471 		 * All audit libraries must handshake through la_version().
1472 		 * Determine that the symbol exists, finish initializing the
1473 		 * object, and then call the function.
1474 		 */
1475 		if ((alp->al_version = (uint_t(*)())audit_symget(alp,
1476 		    AI_LAVERSION, in_nfavl)) == 0) {
1477 			eprintf(lml, ERR_FATAL, MSG_INTL(MSG_GEN_NOSYM),
1478 			    MSG_ORIG(MSG_SYM_LAVERSION));
1479 			error = audit_disable(ptr, clmp, ghp, alp);
1480 			continue;
1481 		}
1482 
1483 		if ((tobj = tsort(lmp, lml->lm_init, RT_SORT_REV)) ==
1484 		    (Rt_map **)S_ERROR)
1485 			return (audit_disable(ptr, clmp, ghp, alp));
1486 
1487 		if (tobj)
1488 			call_init(tobj, DBG_INIT_SORT);
1489 
1490 		APPLICATION_ENTER(rtldflags);
1491 		leave(lml, thr_flg_reenter);
1492 		alp->al_vernum = (*alp->al_version)(LAV_CURRENT);
1493 		(void) enter(thr_flg_reenter);
1494 		APPLICATION_RETURN(rtldflags);
1495 
1496 		DBG_CALL(Dbg_audit_version(clml, alp->al_libname,
1497 		    LAV_CURRENT, alp->al_vernum));
1498 
1499 		if ((alp->al_vernum < LAV_VERSION1) ||
1500 		    (alp->al_vernum > LAV_CURRENT)) {
1501 			eprintf(lml, ERR_FATAL, MSG_INTL(MSG_AUD_BADVERS),
1502 			    LAV_CURRENT, alp->al_vernum);
1503 			error = audit_disable(ptr, clmp, ghp, alp);
1504 			continue;
1505 		}
1506 
1507 		if (aplist_append(&(adp->ad_list), alp,
1508 		    AL_CNT_AUDITORS) == NULL)
1509 			return (audit_disable(ptr, clmp, ghp, alp));
1510 
1511 		adp->ad_cnt++;
1512 
1513 		/*
1514 		 * Collect any remaining entry points.
1515 		 */
1516 		alp->al_objsearch = (char *(*)())audit_symget(alp,
1517 		    AI_LAOBJSEARCH, in_nfavl);
1518 		alp->al_objopen = (uint_t(*)())audit_symget(alp,
1519 		    AI_LAOBJOPEN, in_nfavl);
1520 		alp->al_objfilter = (int(*)())audit_symget(alp,
1521 		    AI_LAOBJFILTER, in_nfavl);
1522 		alp->al_objclose = (uint_t(*)())audit_symget(alp,
1523 		    AI_LAOBJCLOSE, in_nfavl);
1524 		alp->al_symbind = (uintptr_t(*)())audit_symget(alp,
1525 		    AI_LASYMBIND, in_nfavl);
1526 		alp->al_pltenter = (uintptr_t(*)())audit_symget(alp,
1527 		    AI_LAPLTENTER, in_nfavl);
1528 		alp->al_pltexit = (uintptr_t(*)())audit_symget(alp,
1529 		    AI_LAPLTEXIT, in_nfavl);
1530 
1531 		if ((alp->al_preinit = (void(*)())audit_symget(alp,
1532 		    AI_LAPREINIT, in_nfavl)) != NULL)
1533 			preinit++;
1534 		if ((alp->al_activity = (void(*)())audit_symget(alp,
1535 		    AI_LAACTIVITY, in_nfavl)) != NULL)
1536 			activity++;
1537 
1538 		/*
1539 		 * Collect the individual object flags, and assign this audit
1540 		 * list descriptor to its associated link-map list.
1541 		 */
1542 		adp->ad_flags |= alp->al_flags;
1543 		lml->lm_alp = alp;
1544 	}
1545 
1546 	/*
1547 	 * If the caller isn't the head of its own link-map list, then any
1548 	 * preinit or activity entry points need to be tracked separately.
1549 	 * These "events" are not associated with a particular link-map, and
1550 	 * thus a traversal of any existing preinit and activity clients is
1551 	 * required.
1552 	 *
1553 	 * If either of these events are required, establish a cookie for the
1554 	 * object at the head of the link-map list, and make an initial ADD
1555 	 * activity for these local auditors.
1556 	 */
1557 	if ((preinit || activity) && ((hlmp = clml->lm_head) != clmp) &&
1558 	    (_audit_add_head(clmp, hlmp, preinit, activity) == 0))
1559 		return (0);
1560 
1561 	/*
1562 	 * Free the original audit string, as this descriptor may be used again
1563 	 * to add additional auditing.
1564 	 */
1565 	free(adp->ad_name);
1566 	adp->ad_name = NULL;
1567 
1568 	return (error);
1569 }
1570