xref: /titanic_50/usr/src/cmd/sgs/rtld/common/audit.c (revision 711890bc9379ceea66272dc8d4981812224ea86e)
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 2006 Sun Microsystems, Inc.  All rights reserved.
24  * Use is subject to license terms.
25  *
26  * Audit interfaces.  Auditing can be enabled in two ways:
27  *
28  *	o	Using the LD_AUDIT environment variable
29  *
30  *	o	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 | FLAGS1(lmp)) & LML_TFLG_AUD_MASK) &&
44  *	(lml == LIST(lmp)))
45  *
46  * The latter link-map list equivalence test insures that auditors themselves
47  * (invoked through DT_DEPAUDIT) are not audited.
48  */
49 #pragma ident	"%Z%%M%	%I%	%E% SMI"
50 
51 #include	<stdio.h>
52 #include	<sys/types.h>
53 #include	<sys/lwp.h>
54 #include	<stdio.h>
55 #include	<stdarg.h>
56 #include	<dlfcn.h>
57 #include	<string.h>
58 #include	<debug.h>
59 #include	"_rtld.h"
60 #include	"_audit.h"
61 #include	"_elf.h"
62 #include	"msg.h"
63 
64 uint_t	audit_flags = 0;		/* Copy of specific audit flags to */
65 					/* simplify boot_elf.s access. */
66 
67 static Audit_client *
68 _audit_client(Audit_info * aip, Rt_map * almp)
69 {
70 	int	ndx;
71 
72 	if (aip == 0)
73 		return (0);
74 
75 	for (ndx = 0; ndx < aip->ai_cnt; ndx++) {
76 		if (aip->ai_clients[ndx].ac_lmp == almp)
77 			return (&(aip->ai_clients[ndx]));
78 	}
79 	return (0);
80 }
81 
82 /*
83  * la_filter() caller.  Traverses through all audit libraries and call any
84  * la_filter() entry points found.  A zero return from an auditor indicates
85  * that the filtee should be ignored.
86  */
87 static int
88 _audit_objfilter(List *list, Rt_map *frlmp, const char *ref, Rt_map *felmp,
89     uint_t flags)
90 {
91 	Audit_list	*alp;
92 	Listnode	*lnp;
93 
94 	for (LIST_TRAVERSE(list, lnp, alp)) {
95 		Audit_client	*fracp, *feacp;
96 
97 		if (alp->al_objfilter == 0)
98 			continue;
99 		if ((fracp = _audit_client(AUDINFO(frlmp), alp->al_lmp)) == 0)
100 			continue;
101 		if ((feacp = _audit_client(AUDINFO(felmp), alp->al_lmp)) == 0)
102 			continue;
103 
104 		leave(LIST(alp->al_lmp));
105 		if ((*alp->al_objfilter)(&(fracp->ac_cookie), ref,
106 		    &(feacp->ac_cookie), flags) == 0)
107 			return (0);
108 		(void) enter();
109 	}
110 	return (1);
111 }
112 
113 int
114 audit_objfilter(Rt_map *frlmp, const char *ref, Rt_map *felmp, uint_t flags)
115 {
116 	int	appl = 0, respond = 1;
117 
118 	if ((rtld_flags & RT_FL_APPLIC) == 0)
119 		appl = rtld_flags |= RT_FL_APPLIC;
120 
121 	if (auditors && (auditors->ad_flags & LML_TFLG_AUD_OBJFILTER))
122 		respond = _audit_objfilter(&(auditors->ad_list), frlmp,
123 		    ref, felmp, flags);
124 	if (respond && AUDITORS(frlmp) &&
125 	    (AUDITORS(frlmp)->ad_flags & LML_TFLG_AUD_OBJFILTER))
126 		respond = _audit_objfilter(&(AUDITORS(frlmp)->ad_list), frlmp,
127 		    ref, felmp, flags);
128 
129 	if (appl)
130 		rtld_flags &= ~RT_FL_APPLIC;
131 
132 	return (respond);
133 }
134 
135 /*
136  * la_objsearch() caller.  Traverses through all audit libraries and call any
137  * la_objsearch() entry points found.
138  *
139  * Effectively any audit library can change the name we're working with, so we
140  * continue to propagate the new name to each audit library.  Any 0 return
141  * terminates the search.
142  */
143 static char *
144 _audit_objsearch(List *list, char *name, Rt_map *clmp, uint_t flags)
145 {
146 	Audit_list	*alp;
147 	Listnode	*lnp;
148 	char		*nname = (char *)name;
149 
150 	for (LIST_TRAVERSE(list, lnp, alp)) {
151 		Audit_client	*acp;
152 
153 		if (alp->al_objsearch == 0)
154 			continue;
155 		if ((acp = _audit_client(AUDINFO(clmp), alp->al_lmp)) == 0)
156 			continue;
157 
158 		leave(LIST(alp->al_lmp));
159 		nname = (*alp->al_objsearch)(nname, &(acp->ac_cookie), flags);
160 		(void) enter();
161 		if (nname == 0)
162 			break;
163 	}
164 	return (nname);
165 }
166 
167 char *
168 audit_objsearch(Rt_map *clmp, const char *name, uint_t flags)
169 {
170 	char	*nname = (char *)name;
171 	int	appl = 0;
172 
173 	if ((rtld_flags & RT_FL_APPLIC) == 0)
174 		appl = rtld_flags |= RT_FL_APPLIC;
175 
176 	if (auditors && (auditors->ad_flags & LML_TFLG_AUD_OBJSEARCH))
177 		nname = _audit_objsearch(&(auditors->ad_list), nname,
178 			clmp, flags);
179 	if (nname && AUDITORS(clmp) &&
180 	    (AUDITORS(clmp)->ad_flags & LML_TFLG_AUD_OBJSEARCH))
181 		nname = _audit_objsearch(&(AUDITORS(clmp)->ad_list), nname,
182 			clmp, flags);
183 
184 	if (appl)
185 		rtld_flags &= ~RT_FL_APPLIC;
186 
187 	DBG_CALL(Dbg_libs_audit(LIST(clmp), name, nname));
188 	return (nname);
189 }
190 
191 /*
192  * la_activity() caller.  Traverses through all audit library and calls any
193  * la_activity() entry points found.
194  */
195 static void
196 _audit_activity(List * list, Rt_map * clmp, uint_t flags)
197 {
198 	Audit_list *	alp;
199 	Listnode *	lnp;
200 
201 	for (LIST_TRAVERSE(list, lnp, alp)) {
202 		Audit_client *	acp;
203 
204 		if (alp->al_activity == 0)
205 			continue;
206 		if ((acp = _audit_client(AUDINFO(clmp), alp->al_lmp)) == 0)
207 			continue;
208 
209 		leave(LIST(alp->al_lmp));
210 		(*alp->al_activity)(&(acp->ac_cookie), flags);
211 		(void) enter();
212 	}
213 }
214 
215 void
216 audit_activity(Rt_map * clmp, uint_t flags)
217 {
218 	int	appl = 0;
219 
220 	/*
221 	 * We want to trigger the first addition or deletion only.  Ignore any
222 	 * consistent calls unless a previous addition or deletion occurred.
223 	 */
224 	if ((flags == LA_ACT_ADD) || (flags == LA_ACT_DELETE)) {
225 		if (rtld_flags & RT_FL_AUNOTIF)
226 			return;
227 		rtld_flags |= RT_FL_AUNOTIF;
228 	} else {
229 		if ((rtld_flags & RT_FL_AUNOTIF) == 0)
230 			return;
231 		rtld_flags &= ~RT_FL_AUNOTIF;
232 	}
233 
234 	if ((rtld_flags & RT_FL_APPLIC) == 0)
235 		appl = rtld_flags |= RT_FL_APPLIC;
236 
237 	if (auditors && (auditors->ad_flags & LML_TFLG_AUD_ACTIVITY))
238 		_audit_activity(&(auditors->ad_list), clmp, flags);
239 	if (AUDITORS(clmp) &&
240 	    (AUDITORS(clmp)->ad_flags & LML_TFLG_AUD_ACTIVITY))
241 		_audit_activity(&(AUDITORS(clmp)->ad_list), clmp, flags);
242 
243 	if (appl)
244 		rtld_flags &= ~RT_FL_APPLIC;
245 }
246 
247 /*
248  * la_objopen() caller.  Create an audit information structure for the indicated
249  * link-map, regardless of an la_objopen() entry point.  This structure is used
250  * to supply information to various audit interfaces (see LML_MSK_AUDINFO).
251  * Traverses through all audit library and calls any la_objopen() entry points
252  * found.
253  */
254 static int
255 _audit_objopen(List *list, Rt_map *nlmp, Lmid_t lmid, Audit_info *aip,
256     int *ndx)
257 {
258 	Audit_list	*alp;
259 	Listnode	*lnp;
260 
261 	for (LIST_TRAVERSE(list, lnp, alp)) {
262 		uint_t		flags;
263 		Audit_client	*acp;
264 
265 		/*
266 		 * Associate a cookie with the audit library, and assign the
267 		 * initial cookie as the present link-map.
268 		 */
269 		acp = &aip->ai_clients[(*ndx)++];
270 		acp->ac_lmp = alp->al_lmp;
271 		acp->ac_cookie = (uintptr_t)nlmp;
272 
273 		if (alp->al_objopen == 0)
274 			continue;
275 
276 		DBG_CALL(Dbg_audit_object(LIST(alp->al_lmp), alp->al_libname,
277 		    NAME(nlmp)));
278 
279 		leave(LIST(alp->al_lmp));
280 		flags = (*alp->al_objopen)((Link_map *)nlmp, lmid,
281 			&(acp->ac_cookie));
282 		(void) enter();
283 
284 		if (flags & LA_FLG_BINDTO)
285 			acp->ac_flags |= FLG_AC_BINDTO;
286 
287 		if (flags & LA_FLG_BINDFROM) {
288 			ulong_t		pltcnt;
289 
290 			acp->ac_flags |= FLG_AC_BINDFROM;
291 			/*
292 			 * We only need dynamic plt's if a pltenter and/or a
293 			 * pltexit() entry point exist in one of our auditing
294 			 * libraries.
295 			 */
296 			if (aip->ai_dynplts || (JMPREL(nlmp) == 0) ||
297 			    ((audit_flags & (AF_PLTENTER | AF_PLTEXIT)) == 0))
298 				continue;
299 
300 			/*
301 			 * Create one dynplt for every 'PLT' that exists in the
302 			 * object.
303 			 */
304 			pltcnt = PLTRELSZ(nlmp) / RELENT(nlmp);
305 			if ((aip->ai_dynplts = calloc(pltcnt,
306 			    dyn_plt_ent_size)) == 0)
307 				return (0);
308 		}
309 	}
310 	return (1);
311 }
312 
313 int
314 audit_objopen(Rt_map *clmp, Rt_map *nlmp)
315 {
316 	Lmid_t		lmid = get_linkmap_id(LIST(nlmp));
317 	int		appl = 0, respond = 1, ndx = 0;
318 	uint_t		clients = 0;
319 	Audit_info *	aip;
320 
321 	/*
322 	 * Determine the total number of audit libraries in use.  This provides
323 	 * the number of client structures required for this object.
324 	 */
325 	if (auditors)
326 		clients = auditors->ad_cnt;
327 	if (AUDITORS(clmp))
328 		clients += AUDITORS(clmp)->ad_cnt;
329 	if ((nlmp != clmp) && AUDITORS(nlmp))
330 		clients += AUDITORS(nlmp)->ad_cnt;
331 
332 	/*
333 	 * The initial allocation of the audit information structure includes
334 	 * an array of audit clients, 1 per audit library presently available.
335 	 *
336 	 *			 ---------------
337 	 *			| ai_cnt	|
338 	 * 	Audit_info	| ai_clients	|-------
339 	 *			| ai_dynplts	|	|
340 	 *			|---------------|	|
341 	 * 	Audit_client    |	1	|<------
342 	 *			|---------------|
343 	 *			|	2	|
344 	 *			    .........
345 	 */
346 	if ((AUDINFO(nlmp) = aip = calloc(1, sizeof (Audit_info) +
347 	    (sizeof (Audit_client) * clients))) == 0)
348 		return (0);
349 
350 	aip->ai_cnt = clients;
351 	aip->ai_clients = (Audit_client *)((uintptr_t)aip +
352 		sizeof (Audit_info));
353 
354 	if ((rtld_flags & RT_FL_APPLIC) == 0)
355 		appl = rtld_flags |= RT_FL_APPLIC;
356 
357 	if (auditors)
358 		respond = _audit_objopen(&(auditors->ad_list), nlmp,
359 		    lmid, aip, &ndx);
360 	if (respond && AUDITORS(clmp))
361 		respond = _audit_objopen(&(AUDITORS(clmp)->ad_list), nlmp,
362 		    lmid, aip, &ndx);
363 	if (respond && (nlmp != clmp) && AUDITORS(nlmp))
364 		respond = _audit_objopen(&(AUDITORS(nlmp)->ad_list), nlmp,
365 		    lmid, aip, &ndx);
366 
367 	if (appl)
368 		rtld_flags &= ~RT_FL_APPLIC;
369 
370 	return (respond);
371 }
372 
373 /*
374  * la_objclose() caller.  Traverses through all audit library and calls any
375  * la_objclose() entry points found.
376  */
377 void
378 _audit_objclose(List * list, Rt_map * lmp)
379 {
380 	Audit_list *	alp;
381 	Listnode *	lnp;
382 
383 	for (LIST_TRAVERSE(list, lnp, alp)) {
384 		Audit_client *	acp;
385 
386 		if (alp->al_objclose == 0)
387 			continue;
388 		if ((acp = _audit_client(AUDINFO(lmp), alp->al_lmp)) == 0)
389 			continue;
390 
391 		leave(LIST(alp->al_lmp));
392 		(*alp->al_objclose)(&(acp->ac_cookie));
393 		(void) enter();
394 	}
395 }
396 
397 void
398 audit_objclose(Rt_map * clmp, Rt_map * lmp)
399 {
400 	int	appl = 0;
401 
402 	if ((rtld_flags & RT_FL_APPLIC) == 0)
403 		appl = rtld_flags |= RT_FL_APPLIC;
404 
405 	if (auditors && (auditors->ad_flags & LML_TFLG_AUD_OBJCLOSE))
406 		_audit_objclose(&(auditors->ad_list), lmp);
407 	if (AUDITORS(clmp) &&
408 	    (AUDITORS(clmp)->ad_flags & LML_TFLG_AUD_OBJCLOSE))
409 		_audit_objclose(&(AUDITORS(clmp)->ad_list), lmp);
410 
411 	if (appl)
412 		rtld_flags &= ~RT_FL_APPLIC;
413 }
414 
415 /*
416  * la_pltenter() caller.  Traverses through all audit library and calls any
417  * la_pltenter() entry points found.  NOTE: this routine is called via the
418  * glue code established in elf_plt_trace_write(), the symbol descriptor is
419  * created as part of the glue and for 32bit environments the st_name is a
420  * pointer to the real symbol name (ie. it's already been adjusted with the
421  * objects base offset).  For 64bit environments the st_name remains the
422  * original symbol offset and in this case it is used to compute the real name
423  * pointer and pass as a separate argument to the auditor.
424  */
425 static void
426 _audit_pltenter(List *list, Rt_map *rlmp, Rt_map *dlmp, Sym *sym,
427     uint_t ndx, void *regs, uint_t *flags)
428 {
429 	Audit_list	*alp;
430 	Listnode	*lnp;
431 #if	defined(_ELF64)
432 	const char	*name = (const char *)(sym->st_name + STRTAB(dlmp));
433 #else
434 	const char	*name = (const char *)(sym->st_name);
435 #endif
436 
437 	for (LIST_TRAVERSE(list, lnp, alp)) {
438 		Audit_client	*racp, *dacp;
439 		Addr		prev = sym->st_value;
440 
441 		if (alp->al_pltenter == 0)
442 			continue;
443 		if ((racp = _audit_client(AUDINFO(rlmp), alp->al_lmp)) == 0)
444 			continue;
445 		if ((dacp = _audit_client(AUDINFO(dlmp), alp->al_lmp)) == 0)
446 			continue;
447 		if (((racp->ac_flags & FLG_AC_BINDFROM) == 0) ||
448 		    ((dacp->ac_flags & FLG_AC_BINDTO) == 0))
449 			continue;
450 
451 		leave(LIST(alp->al_lmp));
452 		sym->st_value = (Addr)(*alp->al_pltenter)(sym, ndx,
453 		    &(racp->ac_cookie), &(dacp->ac_cookie), regs,
454 #if	defined(_ELF64)
455 		    flags, name);
456 #else
457 		    flags);
458 #endif
459 		(void) enter();
460 
461 		DBG_CALL(Dbg_audit_symval(LIST(alp->al_lmp), alp->al_libname,
462 		    MSG_ORIG(MSG_AUD_PLTENTER), name, prev, sym->st_name));
463 	}
464 }
465 
466 Addr
467 audit_pltenter(Rt_map *rlmp, Rt_map *dlmp, Sym *sym, uint_t ndx,
468     void *regs, uint_t *flags)
469 {
470 	Sym	_sym = *sym;
471 	int	_appl = 0;
472 
473 	/*
474 	 * We're effectively entering ld.so.1 from user (glue) code.
475 	 */
476 	(void) enter();
477 	if ((rtld_flags & RT_FL_APPLIC) == 0)
478 		_appl = rtld_flags |= RT_FL_APPLIC;
479 
480 	if (auditors && (auditors->ad_flags & LML_TFLG_AUD_PLTENTER))
481 		_audit_pltenter(&(auditors->ad_list), rlmp, dlmp, &_sym,
482 		    ndx, regs, flags);
483 	if (AUDITORS(rlmp) &&
484 	    (AUDITORS(rlmp)->ad_flags & LML_TFLG_AUD_PLTENTER))
485 		_audit_pltenter(&(AUDITORS(rlmp)->ad_list), rlmp, dlmp, &_sym,
486 		    ndx, regs, flags);
487 
488 	if (_appl)
489 		rtld_flags &= ~RT_FL_APPLIC;
490 	leave(LIST(rlmp));
491 
492 	return (_sym.st_value);
493 }
494 
495 
496 /*
497  * la_pltexit() caller.  Traverses through all audit library and calls any
498  * la_pltexit() entry points found.  See notes above (_audit_pltenter) for
499  * discussion on st_name.
500  */
501 static Addr
502 _audit_pltexit(List *list, uintptr_t retval, Rt_map *rlmp, Rt_map *dlmp,
503     Sym *sym, uint_t ndx)
504 {
505 	Audit_list	*alp;
506 	Listnode	*lnp;
507 #if	defined(_ELF64)
508 	const char	*name = (const char *)(sym->st_name + STRTAB(dlmp));
509 #endif
510 
511 	for (LIST_TRAVERSE(list, lnp, alp)) {
512 		Audit_client	*racp, *dacp;
513 
514 		if (alp->al_pltexit == 0)
515 			continue;
516 		if ((racp = _audit_client(AUDINFO(rlmp), alp->al_lmp)) == 0)
517 			continue;
518 		if ((dacp = _audit_client(AUDINFO(dlmp), alp->al_lmp)) == 0)
519 			continue;
520 		if (((racp->ac_flags & FLG_AC_BINDFROM) == 0) ||
521 		    ((dacp->ac_flags & FLG_AC_BINDTO) == 0))
522 			continue;
523 
524 		leave(LIST(alp->al_lmp));
525 		retval = (*alp->al_pltexit)(sym, ndx,
526 		    &(racp->ac_cookie), &(dacp->ac_cookie),
527 #if	defined(_ELF64)
528 		    retval, name);
529 #else
530 		    retval);
531 #endif
532 		(void) enter();
533 	}
534 	return (retval);
535 }
536 
537 Addr
538 audit_pltexit(uintptr_t retval, Rt_map *rlmp, Rt_map *dlmp, Sym *sym,
539     uint_t ndx)
540 {
541 	uintptr_t	_retval = retval;
542 	int		_appl = 0;
543 
544 	/*
545 	 * We're effectively entering ld.so.1 from user (glue) code.
546 	 */
547 	(void) enter();
548 	if ((rtld_flags & RT_FL_APPLIC) == 0)
549 		_appl = rtld_flags |= RT_FL_APPLIC;
550 
551 	if (auditors && (auditors->ad_flags & LML_TFLG_AUD_PLTEXIT))
552 		_retval = _audit_pltexit(&(auditors->ad_list), _retval,
553 			rlmp, dlmp, sym, ndx);
554 	if (AUDITORS(rlmp) && (AUDITORS(rlmp)->ad_flags & LML_TFLG_AUD_PLTEXIT))
555 		_retval = _audit_pltexit(&(AUDITORS(rlmp)->ad_list), _retval,
556 			rlmp, dlmp, sym, ndx);
557 
558 	if (_appl)
559 		rtld_flags &= ~RT_FL_APPLIC;
560 	leave(LIST(rlmp));
561 
562 	return (_retval);
563 }
564 
565 
566 /*
567  * la_symbind() caller.  Traverses through all audit library and calls any
568  * la_symbind() entry points found.
569  */
570 static Addr
571 _audit_symbind(List *list, Rt_map *rlmp, Rt_map *dlmp, Sym *sym, uint_t ndx,
572     uint_t *flags, int *called)
573 {
574 	Audit_list	*alp;
575 	Listnode	*lnp;
576 #if	defined(_ELF64)
577 	const char	*name = (const char *)(sym->st_name + STRTAB(dlmp));
578 #else
579 	const char	*name = (const char *)(sym->st_name);
580 #endif
581 
582 	for (LIST_TRAVERSE(list, lnp, alp)) {
583 		Audit_client	*racp, *dacp;
584 		Addr		prev = sym->st_value;
585 		uint_t		lflags;
586 
587 		if (alp->al_symbind == 0)
588 			continue;
589 		if ((racp = _audit_client(AUDINFO(rlmp), alp->al_lmp)) == 0)
590 			continue;
591 		if ((dacp = _audit_client(AUDINFO(dlmp), alp->al_lmp)) == 0)
592 			continue;
593 		if (((racp->ac_flags & FLG_AC_BINDFROM) == 0) ||
594 		    ((dacp->ac_flags & FLG_AC_BINDTO) == 0))
595 			continue;
596 
597 		/*
598 		 * The la_symbind interface is only called when the calling
599 		 * object has been identified as BINDFROM, and the destination
600 		 * object has been identified as BINDTO.  Use a local version of
601 		 * the flags, so that any user update can be collected.
602 		 */
603 		called++;
604 		lflags = (*flags & ~(LA_SYMB_NOPLTENTER | LA_SYMB_NOPLTEXIT));
605 
606 		leave(LIST(alp->al_lmp));
607 		sym->st_value = (*alp->al_symbind)(sym, ndx,
608 		    &(racp->ac_cookie), &(dacp->ac_cookie),
609 #if	defined(_ELF64)
610 		    &lflags, name);
611 #else
612 		    &lflags);
613 #endif
614 		(void) enter();
615 
616 		/*
617 		 * If the auditor indicated that they did not want to process
618 		 * pltenter, or pltexit audits for this symbol, retain this
619 		 * information.  Also retain whether an alternative symbol value
620 		 * has been supplied.
621 		 */
622 		*flags |= (lflags & (LA_SYMB_NOPLTENTER | LA_SYMB_NOPLTEXIT));
623 		if ((prev != sym->st_value) && (alp->al_vernum >= LAV_VERSION2))
624 			*flags |= LA_SYMB_ALTVALUE;
625 
626 		DBG_CALL(Dbg_audit_symval(LIST(alp->al_lmp), alp->al_libname,
627 		    MSG_ORIG(MSG_AUD_SYMBIND), name, prev, sym->st_value));
628 	}
629 	return (sym->st_value);
630 }
631 
632 Addr
633 audit_symbind(Rt_map *rlmp, Rt_map *dlmp, Sym *sym, uint_t ndx, Addr value,
634     uint_t *flags)
635 {
636 	Sym	_sym;
637 	int	_appl = 0, called = 0;
638 
639 	/*
640 	 * Construct a new symbol from that supplied but with the real address.
641 	 * In the 64-bit world the st_name field is only 32-bits which isn't
642 	 * big enough to hold a character pointer. We pass this pointer as a
643 	 * separate parameter for 64-bit audit libraries.
644 	 */
645 	_sym = *sym;
646 	_sym.st_value = value;
647 
648 #if	!defined(_ELF64)
649 	_sym.st_name += (Word)STRTAB(dlmp);
650 #endif
651 	if ((rtld_flags & RT_FL_APPLIC) == 0)
652 		_appl = rtld_flags |= RT_FL_APPLIC;
653 
654 	if (auditors && (auditors->ad_flags & LML_TFLG_AUD_SYMBIND))
655 		_sym.st_value = _audit_symbind(&(auditors->ad_list),
656 		    rlmp, dlmp, &_sym, ndx, flags, &called);
657 	if (AUDITORS(rlmp) && (AUDITORS(rlmp)->ad_flags & LML_TFLG_AUD_SYMBIND))
658 		_sym.st_value = _audit_symbind(&(AUDITORS(rlmp)->ad_list),
659 		    rlmp, dlmp, &_sym, ndx, flags, &called);
660 
661 	/*
662 	 * If no la_symbind() was called for this interface, fabricate that no
663 	 * la_pltenter, or la_pltexit is required.  This helps reduce the glue
664 	 * code created for further auditing.
665 	 */
666 	if (caller == 0)
667 		*flags |= (LA_SYMB_NOPLTENTER | LA_SYMB_NOPLTEXIT);
668 
669 	if (_appl)
670 		rtld_flags &= ~RT_FL_APPLIC;
671 
672 	return (_sym.st_value);
673 }
674 
675 
676 /*
677  * la_preinit() caller.  Traverses through all audit libraries and calls any
678  * la_preinit() entry points found.
679  */
680 static void
681 _audit_preinit(List *list, Rt_map *clmp)
682 {
683 	Audit_list	*alp;
684 	Listnode	*lnp;
685 
686 	for (LIST_TRAVERSE(list, lnp, alp)) {
687 		Audit_client	*acp;
688 
689 		if (alp->al_preinit == 0)
690 			continue;
691 		if ((acp = _audit_client(AUDINFO(clmp), alp->al_lmp)) == 0)
692 			continue;
693 
694 		leave(LIST(alp->al_lmp));
695 		(*alp->al_preinit)(&(acp->ac_cookie));
696 		(void) enter();
697 	}
698 }
699 
700 void
701 audit_preinit(Rt_map *clmp)
702 {
703 	int	appl = 0;
704 
705 	if ((rtld_flags & RT_FL_APPLIC) == 0)
706 		appl = rtld_flags |= RT_FL_APPLIC;
707 
708 	if (auditors && (auditors->ad_flags & LML_TFLG_AUD_PREINIT))
709 		_audit_preinit(&(auditors->ad_list), clmp);
710 	if (AUDITORS(clmp) && (AUDITORS(clmp)->ad_flags & LML_TFLG_AUD_PREINIT))
711 		_audit_preinit(&(AUDITORS(clmp)->ad_list), clmp);
712 
713 	if (appl)
714 		rtld_flags &= ~RT_FL_APPLIC;
715 }
716 
717 
718 /*
719  * Clean up (free) an audit descriptor.  First, gather a list of all handles,
720  * and then close each one down.  This is done rather than using the handles
721  * directly from the auditors, as the audit list can be torn down as a result
722  * of the dlclose.  In other words, what you're pointing at can be removed
723  * while your still pointing at it.
724  */
725 void
726 audit_desc_cleanup(Audit_desc *adp, Rt_map *clmp)
727 {
728 	Audit_list	*alp;
729 	Listnode	*lnp, *olnp;
730 	Alist		*ghalp = 0;
731 
732 	if (adp == 0)
733 		return;
734 	if (adp->ad_name)
735 		free(adp->ad_name);
736 
737 	olnp = 0;
738 	for (LIST_TRAVERSE(&(adp->ad_list), lnp, alp)) {
739 		(void) alist_append(&ghalp, &(alp->al_ghp), sizeof (Grp_hdl *),
740 		    AL_CNT_GROUPS);
741 
742 		if (olnp)
743 			free(olnp);
744 		olnp = lnp;
745 	}
746 	if (olnp)
747 		free(olnp);
748 
749 	if (ghalp) {
750 		Grp_hdl **	ghpp;
751 		Aliste		off;
752 
753 		for (ALIST_TRAVERSE(ghalp, off, ghpp))
754 			(void) dlclose_intn(*ghpp, clmp);
755 		free(ghalp);
756 	}
757 	free(adp);
758 }
759 
760 /*
761  * Clean up (free) an audit information structure.
762  */
763 void
764 audit_info_cleanup(Audit_info *aip)
765 {
766 	if (aip == 0)
767 		return;
768 
769 	if (aip->ai_dynplts)
770 		free(aip->ai_dynplts);
771 	free(aip);
772 }
773 
774 /*
775  * Create a data structure of symbol lookup names and associated flags to help
776  * simplify audit_symget() use.
777  */
778 typedef struct {
779 	Msg	sname;
780 	uint_t	alflag;
781 	uint_t	auflag;
782 } Aud_info;
783 
784 static const Aud_info aud_info[] = {
785 	{ MSG_SYM_LAVERSION,	0 },	/* MSG_ORIG(MSG_SYM_LAVERSION) */
786 	{ MSG_SYM_LAPREINIT,		/* MSG_ORIG(MSG_SYM_LAPREINIT) */
787 	    LML_TFLG_AUD_PREINIT, 0 },
788 	{ MSG_SYM_LAOBJSEARCH,		/* MSG_ORIG(MSG_SYM_LAOBJSEARCH) */
789 	    LML_TFLG_AUD_OBJSEARCH, 0 },
790 	{ MSG_SYM_LAOBJOPEN,		/* MSG_ORIG(MSG_SYM_LAOBJOPEN) */
791 	    LML_TFLG_AUD_OBJOPEN, 0 },
792 	{ MSG_SYM_LAOBJFILTER,		/* MSG_ORIG(MSG_SYM_LAOBJFILTER */
793 	    LML_TFLG_AUD_OBJFILTER, 0 },
794 	{ MSG_SYM_LAOBJCLOSE,		/* MSG_ORIG(MSG_SYM_LAOBJCLOSE) */
795 	    LML_TFLG_AUD_OBJCLOSE, 0 },
796 	{ MSG_SYM_LAACTIVITY,		/* MSG_ORIG(MSG_SYM_LAACTIVITY) */
797 	    LML_TFLG_AUD_ACTIVITY, 0 },
798 
799 #if	defined(_ELF64)
800 	{ MSG_SYM_LASYMBIND_64,		/* MSG_ORIG(MSG_SYM_LASYMBIND_64) */
801 #else
802 	{ MSG_SYM_LASYMBIND,		/* MSG_ORIG(MSG_SYM_LASYMBIND) */
803 #endif
804 	    LML_TFLG_AUD_SYMBIND, 0 },
805 
806 #if	defined(__sparcv9)
807 	{ MSG_SYM_LAV9PLTENTER,		/* MSG_ORIG(MSG_SYM_LAV9PLTENTER) */
808 #elif   defined(__sparc)
809 	{ MSG_SYM_LAV8PLTENTER,		/* MSG_ORIG(MSG_SYM_LAV8PLTENTER) */
810 #elif	defined(__amd64)
811 	{ MSG_SYM_LAAMD64PLTENTER, /* MSG_ORIG(MSG_SYM_LAAMD64PLTENTER) */
812 #elif	defined(i386)
813 	{ MSG_SYM_LAX86PLTENTER,	/* MSG_ORIG(MSG_SYM_LAX86PLTENTER) */
814 #else
815 #error platform not defined!
816 #endif
817 	    LML_TFLG_AUD_PLTENTER, AF_PLTENTER },
818 
819 #if	defined(_ELF64)
820 	{ MSG_SYM_LAPLTEXIT_64,		/* MSG_ORIG(MSG_SYM_LAPLTEXIT_64) */
821 #else
822 	{ MSG_SYM_LAPLTEXIT,		/* MSG_ORIG(MSG_SYM_LAPLTEXIT) */
823 #endif
824 	    LML_TFLG_AUD_PLTEXIT, AF_PLTEXIT }
825 };
826 
827 #define	AI_LAVERSION	0
828 #define	AI_LAPREINIT	1
829 #define	AI_LAOBJSEARCH	2
830 #define	AI_LAOBJOPEN	3
831 #define	AI_LAOBJFILTER	4
832 #define	AI_LAOBJCLOSE	5
833 #define	AI_LAACTIVITY	6
834 #define	AI_LASYMBIND	7
835 #define	AI_LAPLTENTER	8
836 #define	AI_LAPLTEXIT	9
837 
838 static Addr
839 audit_symget(Audit_list * alp, int info)
840 {
841 	Rt_map		*_lmp, *lmp = alp->al_lmp;
842 	const char	*sname = MSG_ORIG(aud_info[info].sname);
843 	uint_t		alflag = aud_info[info].alflag;
844 	uint_t		auflag = aud_info[info].auflag;
845 	uint_t		binfo;
846 	Sym		*sym;
847 	Slookup		sl;
848 
849 	sl.sl_name = sname;
850 	sl.sl_cmap = lml_rtld.lm_head;
851 	sl.sl_imap = lmp;
852 	sl.sl_hash = 0;
853 	sl.sl_rsymndx = 0;
854 	sl.sl_flags = LKUP_FIRST;
855 
856 	if (sym = LM_LOOKUP_SYM(lmp)(&sl, &_lmp, &binfo)) {
857 		Addr	addr = sym->st_value;
858 
859 		if (!(FLAGS(lmp) & FLG_RT_FIXED))
860 			addr += ADDR(lmp);
861 
862 		if (alflag)
863 			alp->al_flags |= alflag;
864 		if (auflag)
865 			audit_flags |= auflag;
866 
867 		DBG_CALL(Dbg_audit_interface(LIST(alp->al_lmp),
868 		    alp->al_libname, sname));
869 		return (addr);
870 	} else
871 		return (0);
872 }
873 
874 /*
875  * Centralize cleanup routines.
876  */
877 static int
878 audit_disable(char *name, Rt_map *clmp, Grp_hdl *ghp, Audit_list *alp)
879 {
880 	eprintf(LIST(clmp), ERR_FATAL, MSG_INTL(MSG_AUD_DISABLED), name);
881 	if (ghp)
882 		(void) dlclose_intn(ghp, clmp);
883 	if (alp)
884 		free(alp);
885 
886 	return (0);
887 }
888 
889 /*
890  * Given a list of one or more audit libraries, open each one and establish a
891  * a descriptor representing the entry points it provides.
892  */
893 int
894 audit_setup(Rt_map *clmp, Audit_desc *adp, uint_t orig)
895 {
896 	char	*ptr, *next;
897 	Lm_list	*clml = LIST(clmp);
898 	int	error = 1;
899 
900 	DBG_CALL(Dbg_audit_lib(clml, adp->ad_name));
901 
902 	/*
903 	 * Mark that we have at least one auditing link map
904 	 */
905 	rtld_flags2 |= RT_FL2_HASAUDIT;
906 
907 	/*
908 	 * The audit definitions may be a list (which will already have been
909 	 * dupped) so split it into individual tokens.
910 	 */
911 	for (ptr = strtok_r(adp->ad_name, MSG_ORIG(MSG_STR_DELIMIT), &next);
912 	    ptr; ptr = strtok_r(NULL,  MSG_ORIG(MSG_STR_DELIMIT), &next)) {
913 		Grp_hdl		*ghp;
914 		Rt_map		*lmp;
915 		Rt_map		**tobj;
916 		Audit_list	*alp;
917 
918 		/*
919 		 * Open the audit library on its own link-map.
920 		 */
921 		if ((ghp = dlmopen_intn((Lm_list *)LM_ID_NEWLM, ptr,
922 		    (RTLD_FIRST | RTLD_GLOBAL | RTLD_WORLD), clmp,
923 		    FLG_RT_AUDIT, orig, 0)) == 0) {
924 			error = audit_disable(ptr, clmp, 0, 0);
925 			continue;
926 		}
927 		lmp = ghp->gh_ownlmp;
928 
929 		/*
930 		 * If this auditor has already been loaded, reuse it.
931 		 */
932 		if ((alp = LIST(lmp)->lm_alp) != 0) {
933 			if (list_append(&(adp->ad_list), alp) == 0)
934 				return (audit_disable(ptr, clmp, ghp, alp));
935 
936 			adp->ad_cnt++;
937 			DBG_CALL(Dbg_audit_version(clml, alp->al_libname,
938 			    alp->al_vernum));
939 			adp->ad_flags |= alp->al_flags;
940 			continue;
941 		}
942 
943 		/*
944 		 * If we are not running in the environment where
945 		 * libc/libthread are merged, we hold on to rtld lock
946 		 * upon leave() function.
947 		 *
948 		 * There is a possibility that libc is not mapped in yet.
949 		 * We may later find out that we will be running in
950 		 * libc/libthread merged enviornment. Refer to:
951 		 *	get_lcinterface() in mutex.c.
952 		 */
953 		if ((rtld_flags2 & RT_FL2_UNIFPROC) == 0)
954 			LIST(lmp)->lm_flags |= LML_FLG_HOLDLOCK;
955 
956 		/*
957 		 * Allocate an audit list descriptor for this object and
958 		 * search for all known entry points.
959 		 */
960 		if ((alp = calloc(1, sizeof (Audit_list))) == 0)
961 			return (audit_disable(ptr, clmp, ghp, 0));
962 
963 		alp->al_libname = NAME(lmp);
964 		alp->al_lmp = lmp;
965 		alp->al_ghp = ghp;
966 
967 		/*
968 		 * All audit libraries must handshake through la_version().
969 		 * Determine that the symbol exists, finish initializing the
970 		 * object, and then call the function.
971 		 */
972 		if ((alp->al_version =
973 		    (uint_t(*)())audit_symget(alp, AI_LAVERSION)) == 0) {
974 			eprintf(LIST(lmp), ERR_FATAL, MSG_INTL(MSG_GEN_NOSYM),
975 			    MSG_ORIG(MSG_SYM_LAVERSION));
976 			error = audit_disable(ptr, clmp, ghp, alp);
977 			continue;
978 		}
979 
980 		if ((tobj = tsort(lmp, LIST(lmp)->lm_init, RT_SORT_REV)) ==
981 		    (Rt_map **)S_ERROR)
982 			return (audit_disable(ptr, clmp, ghp, alp));
983 
984 		rtld_flags |= RT_FL_APPLIC;
985 		if (tobj != (Rt_map **)NULL)
986 			call_init(tobj, DBG_INIT_SORT);
987 
988 		alp->al_vernum = alp->al_version(LAV_CURRENT);
989 		rtld_flags &= ~RT_FL_APPLIC;
990 
991 		if ((alp->al_vernum < LAV_VERSION1) ||
992 		    (alp->al_vernum > LAV_CURRENT)) {
993 			eprintf(LIST(lmp), ERR_FATAL, MSG_INTL(MSG_AUD_BADVERS),
994 			    LAV_CURRENT, alp->al_vernum);
995 			error = audit_disable(ptr, clmp, ghp, alp);
996 			continue;
997 		}
998 
999 		if (list_append(&(adp->ad_list), alp) == 0)
1000 			return (audit_disable(ptr, clmp, ghp, alp));
1001 
1002 		adp->ad_cnt++;
1003 		DBG_CALL(Dbg_audit_version(clml, alp->al_libname,
1004 		    alp->al_vernum));
1005 
1006 		/*
1007 		 * Collect any remaining entry points.
1008 		 */
1009 		alp->al_preinit =
1010 		    (void(*)())audit_symget(alp, AI_LAPREINIT);
1011 		alp->al_objsearch =
1012 		    (char *(*)())audit_symget(alp, AI_LAOBJSEARCH);
1013 		alp->al_objopen =
1014 		    (uint_t(*)())audit_symget(alp, AI_LAOBJOPEN);
1015 		alp->al_objfilter =
1016 		    (int(*)())audit_symget(alp, AI_LAOBJFILTER);
1017 		alp->al_objclose =
1018 		    (uint_t(*)())audit_symget(alp, AI_LAOBJCLOSE);
1019 		alp->al_activity =
1020 		    (void (*)())audit_symget(alp, AI_LAACTIVITY);
1021 		alp->al_symbind =
1022 		    (uintptr_t(*)())audit_symget(alp, AI_LASYMBIND);
1023 		alp->al_pltenter =
1024 		    (uintptr_t(*)())audit_symget(alp, AI_LAPLTENTER);
1025 		alp->al_pltexit =
1026 		    (uintptr_t(*)())audit_symget(alp, AI_LAPLTEXIT);
1027 
1028 		/*
1029 		 * Collect the individual object flags, and assign this audit
1030 		 * list descriptor to its associated link-map list.
1031 		 */
1032 		adp->ad_flags |= alp->al_flags;
1033 		LIST(lmp)->lm_alp = alp;
1034 	}
1035 
1036 	/*
1037 	 * Free the original audit string, as this descriptor may be used again
1038 	 * to add additional auditing.
1039 	 */
1040 	free(adp->ad_name);
1041 	adp->ad_name = 0;
1042 
1043 	return (error);
1044 }
1045