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