17c478bd9Sstevel@tonic-gate /* 27c478bd9Sstevel@tonic-gate * CDDL HEADER START 37c478bd9Sstevel@tonic-gate * 47c478bd9Sstevel@tonic-gate * The contents of this file are subject to the terms of the 55aefb655Srie * Common Development and Distribution License (the "License"). 65aefb655Srie * You may not use this file except in compliance with the License. 77c478bd9Sstevel@tonic-gate * 87c478bd9Sstevel@tonic-gate * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE 97c478bd9Sstevel@tonic-gate * or http://www.opensolaris.org/os/licensing. 107c478bd9Sstevel@tonic-gate * See the License for the specific language governing permissions 117c478bd9Sstevel@tonic-gate * and limitations under the License. 127c478bd9Sstevel@tonic-gate * 137c478bd9Sstevel@tonic-gate * When distributing Covered Code, include this CDDL HEADER in each 147c478bd9Sstevel@tonic-gate * file and include the License file at usr/src/OPENSOLARIS.LICENSE. 157c478bd9Sstevel@tonic-gate * If applicable, add the following below this CDDL HEADER, with the 167c478bd9Sstevel@tonic-gate * fields enclosed by brackets "[]" replaced with your own identifying 177c478bd9Sstevel@tonic-gate * information: Portions Copyright [yyyy] [name of copyright owner] 187c478bd9Sstevel@tonic-gate * 197c478bd9Sstevel@tonic-gate * CDDL HEADER END 207c478bd9Sstevel@tonic-gate */ 215aefb655Srie 227c478bd9Sstevel@tonic-gate /* 23f441771bSRod Evans * Copyright (c) 1996, 2010, Oracle and/or its affiliates. All rights reserved. 24*38f4bdddSBryan Cantrill * Copyright (c) 2012, Joyent, Inc. All rights reserved. 257c478bd9Sstevel@tonic-gate * 267c478bd9Sstevel@tonic-gate * Audit interfaces. Auditing can be enabled in two ways: 277c478bd9Sstevel@tonic-gate * 282020b2b6SRod Evans * - Using the LD_AUDIT environment variable 297c478bd9Sstevel@tonic-gate * 302020b2b6SRod Evans * - From individual objects containing a DT_DEPAUDIT entry 317c478bd9Sstevel@tonic-gate * (see ld(1) -P/-p options). 327c478bd9Sstevel@tonic-gate * 337c478bd9Sstevel@tonic-gate * The former establishes a global set of audit libraries which can inspect all 347c478bd9Sstevel@tonic-gate * objects from a given process. The latter establishes a local set of audit 357c478bd9Sstevel@tonic-gate * libraries which can inspect the immediate dependencies of the caller. 367c478bd9Sstevel@tonic-gate * 377c478bd9Sstevel@tonic-gate * Audit library capabilities are indicated by flags within the link-map list 387c478bd9Sstevel@tonic-gate * header (for global auditing), see LML_TFLG_AUD_* flags, or by the same flags 397c478bd9Sstevel@tonic-gate * within the individual link-map (for local auditing). Although both sets of 407c478bd9Sstevel@tonic-gate * flags can occur in different data items they are defined as one to simplify 417c478bd9Sstevel@tonic-gate * audit interface requirements. The basic test for all audit interfaces is: 427c478bd9Sstevel@tonic-gate * 432020b2b6SRod Evans * if ((lml->lm_tflags | AFLAGS(lmp)) & LML_TFLG_AUD_MASK) 442020b2b6SRod Evans * 452020b2b6SRod Evans * Note. Auditors themselves are identified with the LML_TFLG_NOAUDIT link-map 462020b2b6SRod Evans * list flag, and no LML_TFLG_AUD_MASK flags. These flags get propagated from 472020b2b6SRod Evans * a callers link-map list to any new link-map lists created. Thus, standard 482020b2b6SRod Evans * link-maps lists have the LML_TFLG_AUD_MASK flags propagated, and should a 492020b2b6SRod Evans * new link-map list be created by an auditor, that list gets tagged as 502020b2b6SRod Evans * LML_TFLG_NOAUDIT. 517c478bd9Sstevel@tonic-gate * 527c478bd9Sstevel@tonic-gate * The latter link-map list equivalence test insures that auditors themselves 537c478bd9Sstevel@tonic-gate * (invoked through DT_DEPAUDIT) are not audited. 542020b2b6SRod Evans * 552020b2b6SRod Evans * The history of version changes: 562020b2b6SRod Evans * 572020b2b6SRod Evans * LAV_VERSION1 (Solaris 2.6) 582020b2b6SRod Evans * Auditing implementation added. 592020b2b6SRod Evans * 602020b2b6SRod Evans * LAV_VERSION2 (Solaris 2.6) 612020b2b6SRod Evans * LA_SYMB_ALTVALUE support added. 622020b2b6SRod Evans * 632020b2b6SRod Evans * LAV_VERSION3 (Solaris 9 update 7) 642020b2b6SRod Evans * ld_objfilter() added. 652020b2b6SRod Evans * 662020b2b6SRod Evans * LAV_VERSION4 (Solaris 10 update 5) 672020b2b6SRod Evans * Correction of activity calls for local auditors, and introduction of 682020b2b6SRod Evans * -z globalaudit concept. 692020b2b6SRod Evans * 702020b2b6SRod Evans * LAV_VERSION5 (Solaris 11) 712020b2b6SRod Evans * Under this version, preinit and activity events are enabled from local 722020b2b6SRod Evans * auditors. The la_preinit and la_activity interfaces require a cookie 732020b2b6SRod Evans * that represents the head of the link-map list being audited. If a 742020b2b6SRod Evans * local preinit or activity interface is detected, the local auditors 752020b2b6SRod Evans * la_objopen() routine is called with a cookie that represents the object 762020b2b6SRod Evans * that heads the link-map list of the object being audited. 772020b2b6SRod Evans * 782020b2b6SRod Evans * A local auditor is loaded through adding a new dependency that requests 792020b2b6SRod Evans * auditing, and therefore an la_activity(ADD) event is already in effect. 802020b2b6SRod Evans * Regardless, the local auditors la_activity() routine is called with the 812020b2b6SRod Evans * cookie that represents the object that heads the link-map list of the 822020b2b6SRod Evans * object being audited. 832020b2b6SRod Evans * 842020b2b6SRod Evans * A local auditor can be loaded prior to the preinit event. In this case, 852020b2b6SRod Evans * the local auditors la_preinit() routine is called with the cookie that 862020b2b6SRod Evans * represents the object that heads the link-map list of the object being 872020b2b6SRod Evans * audited. After the preinit event, any la_preinit() routine within a 882020b2b6SRod Evans * local auditor will not be called. 892020b2b6SRod Evans * 902020b2b6SRod Evans * These events are intended to follow the expected sequence of events 912020b2b6SRod Evans * received by global auditors, ie: 922020b2b6SRod Evans * 932020b2b6SRod Evans * - la_objopen(main) 942020b2b6SRod Evans * - la_activity(ADD) 952020b2b6SRod Evans * - la_objopen(dependency) 962020b2b6SRod Evans * - la_activity(CONSISTENT) 972020b2b6SRod Evans * - la_preinit(main) 987c478bd9Sstevel@tonic-gate */ 997c478bd9Sstevel@tonic-gate 1007c478bd9Sstevel@tonic-gate #include <stdio.h> 1017c478bd9Sstevel@tonic-gate #include <sys/types.h> 1027c478bd9Sstevel@tonic-gate #include <sys/lwp.h> 1037c478bd9Sstevel@tonic-gate #include <stdio.h> 1047c478bd9Sstevel@tonic-gate #include <stdarg.h> 1057c478bd9Sstevel@tonic-gate #include <dlfcn.h> 1067c478bd9Sstevel@tonic-gate #include <string.h> 1075aefb655Srie #include <debug.h> 1087c478bd9Sstevel@tonic-gate #include "_rtld.h" 1097c478bd9Sstevel@tonic-gate #include "_audit.h" 1107c478bd9Sstevel@tonic-gate #include "_elf.h" 1117c478bd9Sstevel@tonic-gate #include "msg.h" 1127c478bd9Sstevel@tonic-gate 1137c478bd9Sstevel@tonic-gate uint_t audit_flags = 0; /* Copy of specific audit flags to */ 1147c478bd9Sstevel@tonic-gate /* simplify boot_elf.s access. */ 1157c478bd9Sstevel@tonic-gate 1162020b2b6SRod Evans /* 1172020b2b6SRod Evans * Obtain a head link-map cookie. Local auditors can provide la_preinit() and 1182020b2b6SRod Evans * la_activity() routines, and these routines require a cookie that represents 1192020b2b6SRod Evans * the object that heads the link-map of the object being audited. A list of 1202020b2b6SRod Evans * these cookies is maintained on the link-map list. This list allows multiple 1212020b2b6SRod Evans * local objects to specify the same auditor, and to obtain the same cookie 1222020b2b6SRod Evans * for the link-map that heads the link-map list. 1232020b2b6SRod Evans * 1242020b2b6SRod Evans * The initial cookie is created by _audit_create_head_client() which is called 1252020b2b6SRod Evans * from _audit_add_head(). This cookies address is then passed to the local 1262020b2b6SRod Evans * auditors ld_objopen() and la_activity() routines. Subsequent preinit and 1272020b2b6SRod Evans * activity events use _audit_get_head_client() to dynamically retrieve the 1282020b2b6SRod Evans * cookies address. 1292020b2b6SRod Evans */ 1302020b2b6SRod Evans static Audit_client * 1312020b2b6SRod Evans _audit_get_head_client(Rt_map *hlmp, Rt_map *almp) 1322020b2b6SRod Evans { 1332020b2b6SRod Evans Audit_client *acp; 1342020b2b6SRod Evans Aliste idx; 1352020b2b6SRod Evans Lm_list *hlml = LIST(hlmp); 1362020b2b6SRod Evans 1372020b2b6SRod Evans for (ALIST_TRAVERSE(hlml->lm_aud_cookies, idx, acp)) { 1382020b2b6SRod Evans if (acp->ac_lmp == almp) 1392020b2b6SRod Evans return (acp); 1402020b2b6SRod Evans } 1412020b2b6SRod Evans return (NULL); 1422020b2b6SRod Evans } 1432020b2b6SRod Evans 1442020b2b6SRod Evans static Audit_client * 1452020b2b6SRod Evans _audit_create_head_client(Rt_map *hlmp, Rt_map *almp) 1462020b2b6SRod Evans { 1472020b2b6SRod Evans Audit_client ac, *acp; 1482020b2b6SRod Evans Lm_list *hlml = LIST(hlmp); 1492020b2b6SRod Evans 1502020b2b6SRod Evans ac.ac_lmp = almp; 1512020b2b6SRod Evans ac.ac_cookie = (uintptr_t)hlmp; 1522020b2b6SRod Evans ac.ac_flags = 0; 1532020b2b6SRod Evans 1542020b2b6SRod Evans if ((acp = alist_append(&(hlml->lm_aud_cookies), &ac, 1552020b2b6SRod Evans sizeof (Audit_client), AL_CNT_COOKIES)) == NULL) 1562020b2b6SRod Evans return (NULL); 1572020b2b6SRod Evans 1582020b2b6SRod Evans return (acp); 1592020b2b6SRod Evans } 1602020b2b6SRod Evans 1612020b2b6SRod Evans /* 1622020b2b6SRod Evans * Determine the appropriate client. Each client structure identifies the 1632020b2b6SRod Evans * link-map of the auditor it is associated with. From the client structure, 1642020b2b6SRod Evans * the address of the associated cookie, that represents the object being 1652020b2b6SRod Evans * audited, is retrieved so that the address can be passed to any audit call. 1662020b2b6SRod Evans * 1672020b2b6SRod Evans * Note, objects that are being locally audited, can provide la_preinit() and 1682020b2b6SRod Evans * la_activity() routines. These routines must be passed cookies that represent 1692020b2b6SRod Evans * the object that heads the link-map list of the object being audited. These 1702020b2b6SRod Evans * cookies are not maintained on this objects Audit_client structure, but are 1712020b2b6SRod Evans * obtained from the associated link-map lists lm_cookies alist. 1722020b2b6SRod Evans */ 1737c478bd9Sstevel@tonic-gate static Audit_client * 1747c478bd9Sstevel@tonic-gate _audit_client(Audit_info *aip, Rt_map *almp) 1757c478bd9Sstevel@tonic-gate { 1767c478bd9Sstevel@tonic-gate int ndx; 1777c478bd9Sstevel@tonic-gate 17857ef7aa9SRod Evans if (aip == NULL) 17957ef7aa9SRod Evans return (NULL); 1807c478bd9Sstevel@tonic-gate 1817c478bd9Sstevel@tonic-gate for (ndx = 0; ndx < aip->ai_cnt; ndx++) { 1827c478bd9Sstevel@tonic-gate if (aip->ai_clients[ndx].ac_lmp == almp) 1837c478bd9Sstevel@tonic-gate return (&(aip->ai_clients[ndx])); 1847c478bd9Sstevel@tonic-gate } 18557ef7aa9SRod Evans return (NULL); 1867c478bd9Sstevel@tonic-gate } 1877c478bd9Sstevel@tonic-gate 1887c478bd9Sstevel@tonic-gate /* 1897247f888Srie * la_filter() caller. Traverse through all audit libraries and call any 1907c478bd9Sstevel@tonic-gate * la_filter() entry points found. A zero return from an auditor indicates 1917c478bd9Sstevel@tonic-gate * that the filtee should be ignored. 1927c478bd9Sstevel@tonic-gate */ 1937c478bd9Sstevel@tonic-gate static int 19457ef7aa9SRod Evans _audit_objfilter(APlist *list, Rt_map *frlmp, const char *ref, Rt_map *felmp, 1957c478bd9Sstevel@tonic-gate uint_t flags) 1967c478bd9Sstevel@tonic-gate { 1977c478bd9Sstevel@tonic-gate Audit_list *alp; 19857ef7aa9SRod Evans Aliste idx; 1992020b2b6SRod Evans Lm_list *frlml = LIST(frlmp); 2007c478bd9Sstevel@tonic-gate 20157ef7aa9SRod Evans for (APLIST_TRAVERSE(list, idx, alp)) { 2027c478bd9Sstevel@tonic-gate Audit_client *fracp, *feacp; 2032020b2b6SRod Evans Rt_map *almp = alp->al_lmp; 2042020b2b6SRod Evans Lm_list *alml = LIST(almp); 205f441771bSRod Evans int ret; 2067c478bd9Sstevel@tonic-gate 20757ef7aa9SRod Evans if (alp->al_objfilter == NULL) 2087c478bd9Sstevel@tonic-gate continue; 2092020b2b6SRod Evans if ((fracp = _audit_client(AUDINFO(frlmp), almp)) == NULL) 2107c478bd9Sstevel@tonic-gate continue; 2112020b2b6SRod Evans if ((feacp = _audit_client(AUDINFO(felmp), almp)) == NULL) 2127c478bd9Sstevel@tonic-gate continue; 2137c478bd9Sstevel@tonic-gate 2142020b2b6SRod Evans DBG_CALL(Dbg_audit_objfilter(frlml, DBG_AUD_CALL, 2152020b2b6SRod Evans alp->al_libname, NAME(frlmp), NAME(felmp), ref)); 2162020b2b6SRod Evans 2172020b2b6SRod Evans leave(alml, thr_flg_reenter); 218f441771bSRod Evans ret = (*alp->al_objfilter)(&(fracp->ac_cookie), ref, 219f441771bSRod Evans &(feacp->ac_cookie), flags); 2208cd45542Sraf (void) enter(thr_flg_reenter); 2212020b2b6SRod Evans 2222020b2b6SRod Evans if (ret == 0) { 2232020b2b6SRod Evans DBG_CALL(Dbg_audit_objfilter(frlml, DBG_AUD_RET, 2242020b2b6SRod Evans alp->al_libname, NAME(frlmp), NULL, NULL)); 225f441771bSRod Evans return (0); 2267c478bd9Sstevel@tonic-gate } 2272020b2b6SRod Evans } 2287c478bd9Sstevel@tonic-gate return (1); 2297c478bd9Sstevel@tonic-gate } 2307c478bd9Sstevel@tonic-gate 2317c478bd9Sstevel@tonic-gate int 2327c478bd9Sstevel@tonic-gate audit_objfilter(Rt_map *frlmp, const char *ref, Rt_map *felmp, uint_t flags) 2337c478bd9Sstevel@tonic-gate { 2342020b2b6SRod Evans uint_t rtldflags; 2352020b2b6SRod Evans int respond = 1; 2367c478bd9Sstevel@tonic-gate 2372a8d6ebaSRod Evans if (rt_critical()) 2382a8d6ebaSRod Evans return (respond); 2392a8d6ebaSRod Evans 2402020b2b6SRod Evans APPLICATION_ENTER(rtldflags); 2417c478bd9Sstevel@tonic-gate 2427c478bd9Sstevel@tonic-gate if (auditors && (auditors->ad_flags & LML_TFLG_AUD_OBJFILTER)) 24357ef7aa9SRod Evans respond = _audit_objfilter(auditors->ad_list, frlmp, 2447c478bd9Sstevel@tonic-gate ref, felmp, flags); 2457c478bd9Sstevel@tonic-gate if (respond && AUDITORS(frlmp) && 2467c478bd9Sstevel@tonic-gate (AUDITORS(frlmp)->ad_flags & LML_TFLG_AUD_OBJFILTER)) 24757ef7aa9SRod Evans respond = _audit_objfilter(AUDITORS(frlmp)->ad_list, frlmp, 2487c478bd9Sstevel@tonic-gate ref, felmp, flags); 2497c478bd9Sstevel@tonic-gate 2502020b2b6SRod Evans APPLICATION_RETURN(rtldflags); 2517c478bd9Sstevel@tonic-gate 2527c478bd9Sstevel@tonic-gate return (respond); 2537c478bd9Sstevel@tonic-gate } 2547c478bd9Sstevel@tonic-gate 2557c478bd9Sstevel@tonic-gate /* 2567247f888Srie * la_objsearch() caller. Traverse through all audit libraries and call any 2577c478bd9Sstevel@tonic-gate * la_objsearch() entry points found. 2587c478bd9Sstevel@tonic-gate * 2597c478bd9Sstevel@tonic-gate * Effectively any audit library can change the name we're working with, so we 2607c478bd9Sstevel@tonic-gate * continue to propagate the new name to each audit library. Any 0 return 2617c478bd9Sstevel@tonic-gate * terminates the search. 2627c478bd9Sstevel@tonic-gate */ 2637c478bd9Sstevel@tonic-gate static char * 2642020b2b6SRod Evans _audit_objsearch(APlist *list, char *oname, Rt_map *clmp, uint_t flags) 2657c478bd9Sstevel@tonic-gate { 2667c478bd9Sstevel@tonic-gate Audit_list *alp; 26757ef7aa9SRod Evans Aliste idx; 2682020b2b6SRod Evans Lm_list *clml = LIST(clmp); 2697c478bd9Sstevel@tonic-gate 27057ef7aa9SRod Evans for (APLIST_TRAVERSE(list, idx, alp)) { 2717c478bd9Sstevel@tonic-gate Audit_client *acp; 2722020b2b6SRod Evans Rt_map *almp = alp->al_lmp; 2732020b2b6SRod Evans Lm_list *alml = LIST(almp); 2742020b2b6SRod Evans char *nname = oname; 2757c478bd9Sstevel@tonic-gate 27657ef7aa9SRod Evans if (alp->al_objsearch == NULL) 2777c478bd9Sstevel@tonic-gate continue; 2782020b2b6SRod Evans if ((acp = _audit_client(AUDINFO(clmp), almp)) == NULL) 2797c478bd9Sstevel@tonic-gate continue; 2807c478bd9Sstevel@tonic-gate 2812020b2b6SRod Evans DBG_CALL(Dbg_audit_objsearch(clml, DBG_AUD_CALL, 2822020b2b6SRod Evans alp->al_libname, nname, flags, NULL)); 2832020b2b6SRod Evans 2842020b2b6SRod Evans leave(alml, thr_flg_reenter); 2857c478bd9Sstevel@tonic-gate nname = (*alp->al_objsearch)(nname, &(acp->ac_cookie), flags); 2868cd45542Sraf (void) enter(thr_flg_reenter); 2872020b2b6SRod Evans 2882020b2b6SRod Evans /* 2892020b2b6SRod Evans * Diagnose any return name that differs from the original name 2902020b2b6SRod Evans * passed to the auditor. 2912020b2b6SRod Evans */ 2922020b2b6SRod Evans if (nname && (nname[0] == '\0')) 2932020b2b6SRod Evans nname = NULL; 2942020b2b6SRod Evans if ((nname != oname) || strcmp(nname, oname)) 2952020b2b6SRod Evans DBG_CALL(Dbg_audit_objsearch(clml, DBG_AUD_RET, 2962020b2b6SRod Evans alp->al_libname, oname, flags, nname)); 2972020b2b6SRod Evans 2982020b2b6SRod Evans if ((oname = nname) == NULL) 2997c478bd9Sstevel@tonic-gate break; 3002020b2b6SRod Evans 3017c478bd9Sstevel@tonic-gate } 3022020b2b6SRod Evans return (oname); 3037c478bd9Sstevel@tonic-gate } 3047c478bd9Sstevel@tonic-gate 3057c478bd9Sstevel@tonic-gate char * 3067c478bd9Sstevel@tonic-gate audit_objsearch(Rt_map *clmp, const char *name, uint_t flags) 3077c478bd9Sstevel@tonic-gate { 3087c478bd9Sstevel@tonic-gate char *nname = (char *)name; 3092020b2b6SRod Evans uint_t rtldflags; 3107c478bd9Sstevel@tonic-gate 3112a8d6ebaSRod Evans if (rt_critical()) 3122a8d6ebaSRod Evans return (nname); 3132a8d6ebaSRod Evans 3142020b2b6SRod Evans APPLICATION_ENTER(rtldflags); 3157c478bd9Sstevel@tonic-gate 3167c478bd9Sstevel@tonic-gate if (auditors && (auditors->ad_flags & LML_TFLG_AUD_OBJSEARCH)) 31757ef7aa9SRod Evans nname = _audit_objsearch(auditors->ad_list, nname, 3187c478bd9Sstevel@tonic-gate clmp, flags); 3197c478bd9Sstevel@tonic-gate if (nname && AUDITORS(clmp) && 3207c478bd9Sstevel@tonic-gate (AUDITORS(clmp)->ad_flags & LML_TFLG_AUD_OBJSEARCH)) 32157ef7aa9SRod Evans nname = _audit_objsearch(AUDITORS(clmp)->ad_list, nname, 3227c478bd9Sstevel@tonic-gate clmp, flags); 3237c478bd9Sstevel@tonic-gate 3242020b2b6SRod Evans APPLICATION_RETURN(rtldflags); 3257c478bd9Sstevel@tonic-gate 3265aefb655Srie DBG_CALL(Dbg_libs_audit(LIST(clmp), name, nname)); 3277c478bd9Sstevel@tonic-gate return (nname); 3287c478bd9Sstevel@tonic-gate } 3297c478bd9Sstevel@tonic-gate 3307c478bd9Sstevel@tonic-gate /* 3317247f888Srie * la_activity() caller. Traverse through all audit libraries and call any 3327c478bd9Sstevel@tonic-gate * la_activity() entry points found. 3337c478bd9Sstevel@tonic-gate */ 3347c478bd9Sstevel@tonic-gate static void 3352020b2b6SRod Evans _audit_activity(APlist *list, Rt_map *clmp, uint_t flags, Boolean client) 3367c478bd9Sstevel@tonic-gate { 3377c478bd9Sstevel@tonic-gate Audit_list *alp; 33857ef7aa9SRod Evans Aliste idx; 3397247f888Srie Lm_list *clml = LIST(clmp); 3407c478bd9Sstevel@tonic-gate 34157ef7aa9SRod Evans for (APLIST_TRAVERSE(list, idx, alp)) { 3427c478bd9Sstevel@tonic-gate Audit_client *acp; 3437247f888Srie Rt_map *almp = alp->al_lmp; 3447247f888Srie Lm_list *alml = LIST(almp); 3452020b2b6SRod Evans uintptr_t *cookie; 3467c478bd9Sstevel@tonic-gate 3477c478bd9Sstevel@tonic-gate if (alp->al_activity == 0) 3487c478bd9Sstevel@tonic-gate continue; 3492020b2b6SRod Evans 3502020b2b6SRod Evans /* 3512020b2b6SRod Evans * Determine what cookie is required. Any auditing that 3522020b2b6SRod Evans * originates from the object that heads the link-map list has 3532020b2b6SRod Evans * its own cookie. Local auditors must obtain the cookie that 3542020b2b6SRod Evans * represents the object that heads the link-map list. 3552020b2b6SRod Evans */ 3562020b2b6SRod Evans if (client) 3572020b2b6SRod Evans acp = _audit_client(AUDINFO(clmp), almp); 3582020b2b6SRod Evans else 3592020b2b6SRod Evans acp = _audit_get_head_client(clml->lm_head, almp); 3602020b2b6SRod Evans 3612020b2b6SRod Evans if (acp == NULL) 3627c478bd9Sstevel@tonic-gate continue; 3632020b2b6SRod Evans cookie = &(acp->ac_cookie); 3647c478bd9Sstevel@tonic-gate 3657247f888Srie /* 3667247f888Srie * Make sure the audit library only sees one addition/deletion 3677247f888Srie * at a time. This ensures the library doesn't see numerous 3687247f888Srie * events from lazy loading a series of libraries. Keep track 3697247f888Srie * of this caller having called an auditor, so that the 3707247f888Srie * appropriate "consistent" event can be supplied on leaving 3717247f888Srie * ld.so.1. 3727247f888Srie */ 3737247f888Srie if ((flags == LA_ACT_ADD) || (flags == LA_ACT_DELETE)) { 3747247f888Srie if (alml->lm_flags & LML_FLG_AUDITNOTIFY) 3757247f888Srie continue; 3767247f888Srie 3777247f888Srie alml->lm_flags |= LML_FLG_AUDITNOTIFY; 3782020b2b6SRod Evans clml->lm_flags |= LML_FLG_ACTAUDIT; 3797247f888Srie } else { 3807247f888Srie if ((alml->lm_flags & LML_FLG_AUDITNOTIFY) == 0) 3817247f888Srie continue; 3827247f888Srie 3837247f888Srie alml->lm_flags &= ~LML_FLG_AUDITNOTIFY; 3847247f888Srie } 3857247f888Srie 3862020b2b6SRod Evans DBG_CALL(Dbg_audit_activity(clml, alp->al_libname, 3872020b2b6SRod Evans NAME(clml->lm_head), flags)); 3882020b2b6SRod Evans 3892020b2b6SRod Evans leave(alml, thr_flg_reenter); 3902020b2b6SRod Evans (*alp->al_activity)(cookie, flags); 3918cd45542Sraf (void) enter(thr_flg_reenter); 3927c478bd9Sstevel@tonic-gate } 3937c478bd9Sstevel@tonic-gate } 3947c478bd9Sstevel@tonic-gate 3957c478bd9Sstevel@tonic-gate void 3967c478bd9Sstevel@tonic-gate audit_activity(Rt_map *clmp, uint_t flags) 3977c478bd9Sstevel@tonic-gate { 3982020b2b6SRod Evans Rt_map *lmp; 3992020b2b6SRod Evans Aliste idx; 4002020b2b6SRod Evans uint_t rtldflags; 4017c478bd9Sstevel@tonic-gate 4022a8d6ebaSRod Evans if (rt_critical()) 4032a8d6ebaSRod Evans return; 4042a8d6ebaSRod Evans 4052020b2b6SRod Evans APPLICATION_ENTER(rtldflags); 4067c478bd9Sstevel@tonic-gate 4077c478bd9Sstevel@tonic-gate if (auditors && (auditors->ad_flags & LML_TFLG_AUD_ACTIVITY)) 4082020b2b6SRod Evans _audit_activity(auditors->ad_list, clmp, flags, TRUE); 4097c478bd9Sstevel@tonic-gate if (AUDITORS(clmp) && 4107c478bd9Sstevel@tonic-gate (AUDITORS(clmp)->ad_flags & LML_TFLG_AUD_ACTIVITY)) 4112020b2b6SRod Evans _audit_activity(AUDITORS(clmp)->ad_list, clmp, flags, TRUE); 4127c478bd9Sstevel@tonic-gate 4132020b2b6SRod Evans for (APLIST_TRAVERSE(aud_activity, idx, lmp)) { 4142020b2b6SRod Evans if ((clmp != lmp) && AUDITORS(lmp) && 4152020b2b6SRod Evans (AUDITORS(lmp)->ad_flags & LML_TFLG_AUD_ACTIVITY)) { 4162020b2b6SRod Evans _audit_activity(AUDITORS(lmp)->ad_list, lmp, flags, 4172020b2b6SRod Evans FALSE); 4182020b2b6SRod Evans } 4192020b2b6SRod Evans } 4202020b2b6SRod Evans 4212020b2b6SRod Evans APPLICATION_RETURN(rtldflags); 4222020b2b6SRod Evans } 4232020b2b6SRod Evans 4242020b2b6SRod Evans /* 4252020b2b6SRod Evans * Determine whether an auditor is in use by the head link-map object. 4262020b2b6SRod Evans */ 4272020b2b6SRod Evans static int 4282020b2b6SRod Evans _audit_used_by_head(Rt_map *hlmp, Rt_map *almp) 4292020b2b6SRod Evans { 4302020b2b6SRod Evans Audit_list *alp; 4312020b2b6SRod Evans Aliste idx; 4322020b2b6SRod Evans 4332020b2b6SRod Evans for (APLIST_TRAVERSE(AUDITORS(hlmp)->ad_list, idx, alp)) { 4342020b2b6SRod Evans if (alp->al_lmp == almp) 4352020b2b6SRod Evans return (1); 4362020b2b6SRod Evans } 4372020b2b6SRod Evans return (0); 4382020b2b6SRod Evans } 4392020b2b6SRod Evans 4402020b2b6SRod Evans /* 4412020b2b6SRod Evans * la_objopen() caller for the head link-map. Global auditors, or an auditor 4422020b2b6SRod Evans * started from the object that heads a link-map list (typically the dynamic 4432020b2b6SRod Evans * executable), are passed to la_objopen(). However, local auditors can 4442020b2b6SRod Evans * provide activity and preinit events, and for these events, a cookie 4452020b2b6SRod Evans * representing the head link-map list object is expected. This routine obtains 4462020b2b6SRod Evans * these cookies from the link-map list lm_cookies element. This element 4472020b2b6SRod Evans * ensures all clients of the same auditor use the same cookie. 4482020b2b6SRod Evans * 4492020b2b6SRod Evans * Although a local auditor will get an la_objopen() call for the object that 4502020b2b6SRod Evans * heads the link-map list of the object being audited, the auditor is not 4512020b2b6SRod Evans * permitted to request binding information for this head object. The head 4522020b2b6SRod Evans * object has already been in existence, and bindings may have been resolved 4532020b2b6SRod Evans * with it. This local auditor is coming into existence too late, and thus we 4542020b2b6SRod Evans * don't allow any bindings to be caught at all. 4552020b2b6SRod Evans */ 4562020b2b6SRod Evans static int 4572020b2b6SRod Evans _audit_add_head(Rt_map *clmp, Rt_map *hlmp, int preinit, int activity) 4582020b2b6SRod Evans { 4592020b2b6SRod Evans Lm_list *clml = LIST(clmp); 4602020b2b6SRod Evans Lmid_t lmid = get_linkmap_id(clml); 4612020b2b6SRod Evans Audit_list *alp; 4622020b2b6SRod Evans Aliste idx; 4632020b2b6SRod Evans int save = 0; 4642020b2b6SRod Evans 4652020b2b6SRod Evans for (APLIST_TRAVERSE(AUDITORS(clmp)->ad_list, idx, alp)) { 4662020b2b6SRod Evans Audit_client *acp; 4672020b2b6SRod Evans Rt_map *almp = alp->al_lmp; 4682020b2b6SRod Evans Lm_list *alml = LIST(almp); 4692020b2b6SRod Evans uintptr_t *cookie; 4702020b2b6SRod Evans uint_t rtldflags; 4712020b2b6SRod Evans 4722020b2b6SRod Evans /* 4732020b2b6SRod Evans * Ensure this local auditor isn't already in existence as an 4742020b2b6SRod Evans * auditor for the head of the link-map list. If it is, then 4752020b2b6SRod Evans * this auditor will have already receive preinit and activity 4762020b2b6SRod Evans * events. 4772020b2b6SRod Evans */ 4782020b2b6SRod Evans if (AUDITORS(hlmp) && _audit_used_by_head(hlmp, almp)) 4792020b2b6SRod Evans continue; 4802020b2b6SRod Evans 4812020b2b6SRod Evans /* 4822020b2b6SRod Evans * Create a cookie that represents the object that heads the 4832020b2b6SRod Evans * link-map list. If the cookie already exists, then this 4842020b2b6SRod Evans * auditor has already been established for another objects 4852020b2b6SRod Evans * local auditing. In this case, do not issue a la_objopen() 4862020b2b6SRod Evans * or la_activity() event, as these will have already occurred. 4872020b2b6SRod Evans */ 4882020b2b6SRod Evans if ((acp = _audit_get_head_client(clml->lm_head, almp)) != NULL) 4892020b2b6SRod Evans continue; 4902020b2b6SRod Evans if ((acp = 4912020b2b6SRod Evans _audit_create_head_client(clml->lm_head, almp)) == NULL) 4922020b2b6SRod Evans return (0); 4932020b2b6SRod Evans 4942020b2b6SRod Evans cookie = &(acp->ac_cookie); 4952020b2b6SRod Evans save++; 4962020b2b6SRod Evans 4972020b2b6SRod Evans /* 4982020b2b6SRod Evans * Call the la_objopen() if available. 4992020b2b6SRod Evans */ 5002020b2b6SRod Evans if (alp->al_objopen) { 5012020b2b6SRod Evans uint_t flags; 5022020b2b6SRod Evans 5032020b2b6SRod Evans DBG_CALL(Dbg_audit_objopen(clml, DBG_AUD_CALL, 5042020b2b6SRod Evans alp->al_libname, NAME(hlmp), 0, FALSE)); 5052020b2b6SRod Evans 5062020b2b6SRod Evans APPLICATION_ENTER(rtldflags); 5072020b2b6SRod Evans leave(alml, thr_flg_reenter); 5082020b2b6SRod Evans flags = (*alp->al_objopen)((Link_map *)hlmp, lmid, 5092020b2b6SRod Evans cookie); 5102020b2b6SRod Evans (void) enter(thr_flg_reenter); 5112020b2b6SRod Evans APPLICATION_RETURN(rtldflags); 5122020b2b6SRod Evans 5132020b2b6SRod Evans if (flags) { 5142020b2b6SRod Evans DBG_CALL(Dbg_audit_objopen(clml, DBG_AUD_RET, 5152020b2b6SRod Evans alp->al_libname, NAME(hlmp), flags, TRUE)); 5162020b2b6SRod Evans } 5172020b2b6SRod Evans } 5182020b2b6SRod Evans 5192020b2b6SRod Evans /* 5202020b2b6SRod Evans * Call the la_activity() if available. 5212020b2b6SRod Evans */ 5222020b2b6SRod Evans if (alp->al_activity) { 5232020b2b6SRod Evans alml->lm_flags |= LML_FLG_AUDITNOTIFY; 5242020b2b6SRod Evans clml->lm_flags |= LML_FLG_ACTAUDIT; 5252020b2b6SRod Evans 5262020b2b6SRod Evans DBG_CALL(Dbg_audit_activity(clml, alp->al_libname, 5272020b2b6SRod Evans NAME(clml->lm_head), LA_ACT_ADD)); 5282020b2b6SRod Evans 5292020b2b6SRod Evans APPLICATION_ENTER(rtldflags); 5302020b2b6SRod Evans leave(alml, thr_flg_reenter); 5312020b2b6SRod Evans (*alp->al_activity)(cookie, LA_ACT_ADD); 5322020b2b6SRod Evans (void) enter(thr_flg_reenter); 5332020b2b6SRod Evans APPLICATION_RETURN(rtldflags); 5342020b2b6SRod Evans } 5352020b2b6SRod Evans } 5362020b2b6SRod Evans 5372020b2b6SRod Evans /* 5382020b2b6SRod Evans * If new head link-map cookies have been generated, then maintain 5392020b2b6SRod Evans * any preinit and/or activity requirements. 5402020b2b6SRod Evans */ 5412020b2b6SRod Evans if (save) { 5422020b2b6SRod Evans if (preinit && (aplist_append(&aud_preinit, clmp, 5432020b2b6SRod Evans AL_CNT_AUDITORS) == NULL)) 5442020b2b6SRod Evans return (0); 5452020b2b6SRod Evans if (activity && (aplist_append(&aud_activity, clmp, 5462020b2b6SRod Evans AL_CNT_AUDITORS) == NULL)) 5472020b2b6SRod Evans return (0); 5482020b2b6SRod Evans } 5492020b2b6SRod Evans return (1); 5507c478bd9Sstevel@tonic-gate } 5517c478bd9Sstevel@tonic-gate 5527c478bd9Sstevel@tonic-gate /* 5537c478bd9Sstevel@tonic-gate * la_objopen() caller. Create an audit information structure for the indicated 5547c478bd9Sstevel@tonic-gate * link-map, regardless of an la_objopen() entry point. This structure is used 5557c478bd9Sstevel@tonic-gate * to supply information to various audit interfaces (see LML_MSK_AUDINFO). 5562020b2b6SRod Evans * Traverse through all audit libraries and call any la_objopen() entry points 5577c478bd9Sstevel@tonic-gate * found. 5587c478bd9Sstevel@tonic-gate */ 5597c478bd9Sstevel@tonic-gate static int 56057ef7aa9SRod Evans _audit_objopen(APlist *list, Rt_map *nlmp, Lmid_t lmid, Audit_info *aip, 5617c478bd9Sstevel@tonic-gate int *ndx) 5627c478bd9Sstevel@tonic-gate { 5632020b2b6SRod Evans Lm_list *nlml = LIST(nlmp); 5647c478bd9Sstevel@tonic-gate Audit_list *alp; 56557ef7aa9SRod Evans Aliste idx; 5667c478bd9Sstevel@tonic-gate 56757ef7aa9SRod Evans for (APLIST_TRAVERSE(list, idx, alp)) { 5687c478bd9Sstevel@tonic-gate uint_t flags; 5697c478bd9Sstevel@tonic-gate Audit_client *acp; 5702020b2b6SRod Evans Rt_map *almp = alp->al_lmp; 5712020b2b6SRod Evans Lm_list *alml = LIST(almp); 5727c478bd9Sstevel@tonic-gate 5737c478bd9Sstevel@tonic-gate /* 5747c478bd9Sstevel@tonic-gate * Associate a cookie with the audit library, and assign the 5757c478bd9Sstevel@tonic-gate * initial cookie as the present link-map. 5767c478bd9Sstevel@tonic-gate */ 5777c478bd9Sstevel@tonic-gate acp = &aip->ai_clients[(*ndx)++]; 5787c478bd9Sstevel@tonic-gate acp->ac_lmp = alp->al_lmp; 5797c478bd9Sstevel@tonic-gate acp->ac_cookie = (uintptr_t)nlmp; 5807c478bd9Sstevel@tonic-gate 58157ef7aa9SRod Evans if (alp->al_objopen == NULL) 5827c478bd9Sstevel@tonic-gate continue; 5837c478bd9Sstevel@tonic-gate 5842020b2b6SRod Evans DBG_CALL(Dbg_audit_objopen(nlml, DBG_AUD_CALL, alp->al_libname, 5852020b2b6SRod Evans NAME(nlmp), 0, FALSE)); 5867c478bd9Sstevel@tonic-gate 5872020b2b6SRod Evans leave(alml, thr_flg_reenter); 5887c478bd9Sstevel@tonic-gate flags = (*alp->al_objopen)((Link_map *)nlmp, lmid, 5897c478bd9Sstevel@tonic-gate &(acp->ac_cookie)); 5908cd45542Sraf (void) enter(thr_flg_reenter); 5917c478bd9Sstevel@tonic-gate 5922020b2b6SRod Evans /* 5932020b2b6SRod Evans * Diagnose any flags returned by the auditor. 5942020b2b6SRod Evans */ 5952020b2b6SRod Evans if (flags) { 5962020b2b6SRod Evans DBG_CALL(Dbg_audit_objopen(nlml, DBG_AUD_RET, 5972020b2b6SRod Evans alp->al_libname, NAME(nlmp), flags, FALSE)); 5982020b2b6SRod Evans } 5992020b2b6SRod Evans 6007c478bd9Sstevel@tonic-gate if (flags & LA_FLG_BINDTO) 6017c478bd9Sstevel@tonic-gate acp->ac_flags |= FLG_AC_BINDTO; 6027c478bd9Sstevel@tonic-gate 6037c478bd9Sstevel@tonic-gate if (flags & LA_FLG_BINDFROM) { 6047c478bd9Sstevel@tonic-gate ulong_t pltcnt; 6057c478bd9Sstevel@tonic-gate 6067c478bd9Sstevel@tonic-gate acp->ac_flags |= FLG_AC_BINDFROM; 60756deab07SRod Evans 6087c478bd9Sstevel@tonic-gate /* 6097c478bd9Sstevel@tonic-gate * We only need dynamic plt's if a pltenter and/or a 6107c478bd9Sstevel@tonic-gate * pltexit() entry point exist in one of our auditing 6117c478bd9Sstevel@tonic-gate * libraries. 6127c478bd9Sstevel@tonic-gate */ 6137c478bd9Sstevel@tonic-gate if (aip->ai_dynplts || (JMPREL(nlmp) == 0) || 6147c478bd9Sstevel@tonic-gate ((audit_flags & (AF_PLTENTER | AF_PLTEXIT)) == 0)) 6157c478bd9Sstevel@tonic-gate continue; 6167c478bd9Sstevel@tonic-gate 6177c478bd9Sstevel@tonic-gate /* 6187c478bd9Sstevel@tonic-gate * Create one dynplt for every 'PLT' that exists in the 6197c478bd9Sstevel@tonic-gate * object. 6207c478bd9Sstevel@tonic-gate */ 6217c478bd9Sstevel@tonic-gate pltcnt = PLTRELSZ(nlmp) / RELENT(nlmp); 6227c478bd9Sstevel@tonic-gate if ((aip->ai_dynplts = calloc(pltcnt, 62356deab07SRod Evans dyn_plt_ent_size)) == NULL) 6247c478bd9Sstevel@tonic-gate return (0); 6257c478bd9Sstevel@tonic-gate } 6267c478bd9Sstevel@tonic-gate } 6277c478bd9Sstevel@tonic-gate return (1); 6287c478bd9Sstevel@tonic-gate } 6297c478bd9Sstevel@tonic-gate 6307c478bd9Sstevel@tonic-gate int 6317c478bd9Sstevel@tonic-gate audit_objopen(Rt_map *clmp, Rt_map *nlmp) 6327c478bd9Sstevel@tonic-gate { 6337c478bd9Sstevel@tonic-gate Lmid_t lmid = get_linkmap_id(LIST(nlmp)); 6342020b2b6SRod Evans int respond = 1, ndx = 0; 6352020b2b6SRod Evans uint_t rtldflags; 6367c478bd9Sstevel@tonic-gate uint_t clients = 0; 6377c478bd9Sstevel@tonic-gate Audit_info *aip; 6387c478bd9Sstevel@tonic-gate 6392a8d6ebaSRod Evans if (rt_critical()) 6402a8d6ebaSRod Evans return (respond); 6412a8d6ebaSRod Evans 6427c478bd9Sstevel@tonic-gate /* 6432020b2b6SRod Evans * Determine the number of auditors that can receive information 6442020b2b6SRod Evans * regarding this object. This provides the number of client 6452020b2b6SRod Evans * structures required for this object. 6467c478bd9Sstevel@tonic-gate */ 6477c478bd9Sstevel@tonic-gate if (auditors) 6487c478bd9Sstevel@tonic-gate clients = auditors->ad_cnt; 6497c478bd9Sstevel@tonic-gate if (AUDITORS(clmp)) 6507c478bd9Sstevel@tonic-gate clients += AUDITORS(clmp)->ad_cnt; 6517c478bd9Sstevel@tonic-gate if ((nlmp != clmp) && AUDITORS(nlmp)) 6527c478bd9Sstevel@tonic-gate clients += AUDITORS(nlmp)->ad_cnt; 6537c478bd9Sstevel@tonic-gate 6547c478bd9Sstevel@tonic-gate /* 6552020b2b6SRod Evans * Allocate an audit information structure. Each audited object 6562020b2b6SRod Evans * maintains a AUDINFO() structure. As this structure can only be 6572020b2b6SRod Evans * created once all auditors are loaded, a client count can now be 6582020b2b6SRod Evans * computed. 6592020b2b6SRod Evans * 6602020b2b6SRod Evans * The allocation of the audit information structure includes an array 6612020b2b6SRod Evans * of audit clients, 1 per audit library that has been loaded. 6627c478bd9Sstevel@tonic-gate * 6637c478bd9Sstevel@tonic-gate * --------------- 6647c478bd9Sstevel@tonic-gate * | ai_cnt | 6657c478bd9Sstevel@tonic-gate * Audit_info | ai_clients |------- 6667c478bd9Sstevel@tonic-gate * | ai_dynplts | | 6677c478bd9Sstevel@tonic-gate * |---------------| | 6687c478bd9Sstevel@tonic-gate * Audit_client | 1 |<------ 6697c478bd9Sstevel@tonic-gate * |---------------| 6707c478bd9Sstevel@tonic-gate * | 2 | 6717c478bd9Sstevel@tonic-gate * ......... 6727c478bd9Sstevel@tonic-gate */ 6737c478bd9Sstevel@tonic-gate if ((AUDINFO(nlmp) = aip = calloc(1, sizeof (Audit_info) + 67456deab07SRod Evans (sizeof (Audit_client) * clients))) == NULL) 6757c478bd9Sstevel@tonic-gate return (0); 6767c478bd9Sstevel@tonic-gate 6777c478bd9Sstevel@tonic-gate aip->ai_cnt = clients; 6787c478bd9Sstevel@tonic-gate aip->ai_clients = (Audit_client *)((uintptr_t)aip + 6797c478bd9Sstevel@tonic-gate sizeof (Audit_info)); 6807c478bd9Sstevel@tonic-gate 6812020b2b6SRod Evans APPLICATION_ENTER(rtldflags); 6827c478bd9Sstevel@tonic-gate 6837c478bd9Sstevel@tonic-gate if (auditors) 68457ef7aa9SRod Evans respond = _audit_objopen(auditors->ad_list, nlmp, 6857c478bd9Sstevel@tonic-gate lmid, aip, &ndx); 6867c478bd9Sstevel@tonic-gate if (respond && AUDITORS(clmp)) 68757ef7aa9SRod Evans respond = _audit_objopen(AUDITORS(clmp)->ad_list, nlmp, 6887c478bd9Sstevel@tonic-gate lmid, aip, &ndx); 6897c478bd9Sstevel@tonic-gate if (respond && (nlmp != clmp) && AUDITORS(nlmp)) 69057ef7aa9SRod Evans respond = _audit_objopen(AUDITORS(nlmp)->ad_list, nlmp, 6917c478bd9Sstevel@tonic-gate lmid, aip, &ndx); 6927c478bd9Sstevel@tonic-gate 6932020b2b6SRod Evans APPLICATION_RETURN(rtldflags); 6947c478bd9Sstevel@tonic-gate 6957c478bd9Sstevel@tonic-gate return (respond); 6967c478bd9Sstevel@tonic-gate } 6977c478bd9Sstevel@tonic-gate 6987c478bd9Sstevel@tonic-gate /* 6992020b2b6SRod Evans * la_objclose() caller. Traverse through all audit libraries and call any 7007c478bd9Sstevel@tonic-gate * la_objclose() entry points found. 7017c478bd9Sstevel@tonic-gate */ 7027c478bd9Sstevel@tonic-gate void 70357ef7aa9SRod Evans _audit_objclose(APlist *list, Rt_map *lmp) 7047c478bd9Sstevel@tonic-gate { 7057c478bd9Sstevel@tonic-gate Audit_list *alp; 70657ef7aa9SRod Evans Aliste idx; 7072020b2b6SRod Evans Lm_list *lml = LIST(lmp); 7087c478bd9Sstevel@tonic-gate 70957ef7aa9SRod Evans for (APLIST_TRAVERSE(list, idx, alp)) { 7107c478bd9Sstevel@tonic-gate Audit_client *acp; 7112020b2b6SRod Evans Rt_map *almp = alp->al_lmp; 7122020b2b6SRod Evans Lm_list *alml = LIST(almp); 7137c478bd9Sstevel@tonic-gate 71457ef7aa9SRod Evans if (alp->al_objclose == NULL) 7157c478bd9Sstevel@tonic-gate continue; 7162020b2b6SRod Evans if ((acp = _audit_client(AUDINFO(lmp), almp)) == NULL) 7177c478bd9Sstevel@tonic-gate continue; 7187c478bd9Sstevel@tonic-gate 7192020b2b6SRod Evans DBG_CALL(Dbg_audit_objclose(lml, alp->al_libname, NAME(lmp))); 7202020b2b6SRod Evans 7212020b2b6SRod Evans leave(alml, thr_flg_reenter); 7227c478bd9Sstevel@tonic-gate (*alp->al_objclose)(&(acp->ac_cookie)); 7238cd45542Sraf (void) enter(thr_flg_reenter); 7247c478bd9Sstevel@tonic-gate } 7257c478bd9Sstevel@tonic-gate } 7267c478bd9Sstevel@tonic-gate 7272020b2b6SRod Evans /* 7282020b2b6SRod Evans * Determine any la_objclose() requirements. An object that is about to be 7292020b2b6SRod Evans * deleted needs to trigger an la_objclose() event to any associated auditors. 7302020b2b6SRod Evans * In the case of local auditing, a deleted object may have a number of callers, 7312020b2b6SRod Evans * and each of these callers may have their own auditing requirements. To 7322020b2b6SRod Evans * ensure only one la_objclose() event is sent to each auditor, collect the 7332020b2b6SRod Evans * auditors from any callers and make sure there's no duplication. 7342020b2b6SRod Evans */ 7352020b2b6SRod Evans inline static void 7362020b2b6SRod Evans add_objclose_list(Rt_map *lmp, APlist **alpp) 7377c478bd9Sstevel@tonic-gate { 7382020b2b6SRod Evans if (AFLAGS(lmp) & LML_TFLG_AUD_OBJCLOSE) { 7392020b2b6SRod Evans Audit_list *alp; 7402020b2b6SRod Evans Aliste idx; 7412020b2b6SRod Evans 7422020b2b6SRod Evans for (APLIST_TRAVERSE(AUDITORS(lmp)->ad_list, idx, alp)) { 7432020b2b6SRod Evans if (aplist_test(alpp, alp, AL_CNT_AUDITORS) == 0) 7442020b2b6SRod Evans return; 7452020b2b6SRod Evans } 7462020b2b6SRod Evans } 7472020b2b6SRod Evans } 7482020b2b6SRod Evans 7492020b2b6SRod Evans void 7502020b2b6SRod Evans audit_objclose(Rt_map *lmp, Rt_map *clmp) 7512020b2b6SRod Evans { 7522020b2b6SRod Evans APlist *alp = NULL; 7532020b2b6SRod Evans uint_t rtldflags; 7547c478bd9Sstevel@tonic-gate 7552a8d6ebaSRod Evans if (rt_critical()) 7562a8d6ebaSRod Evans return; 7572a8d6ebaSRod Evans 7582020b2b6SRod Evans APPLICATION_ENTER(rtldflags); 7597c478bd9Sstevel@tonic-gate 7607c478bd9Sstevel@tonic-gate if (auditors && (auditors->ad_flags & LML_TFLG_AUD_OBJCLOSE)) 76157ef7aa9SRod Evans _audit_objclose(auditors->ad_list, lmp); 7627c478bd9Sstevel@tonic-gate 7632020b2b6SRod Evans /* 7642020b2b6SRod Evans * If this link-map list contains local auditors, determine if this 7652020b2b6SRod Evans * object, or any of this objects CALLERS have instantiated auditors 7662020b2b6SRod Evans * that need to know of la_objclose() events. 7672020b2b6SRod Evans */ 7682020b2b6SRod Evans if (LIST(lmp)->lm_flags & LML_FLG_LOCAUDIT) { 7692020b2b6SRod Evans Bnd_desc *bdp; 7702020b2b6SRod Evans Aliste idx; 7712020b2b6SRod Evans 7722020b2b6SRod Evans add_objclose_list(lmp, &alp); 7732020b2b6SRod Evans 7742020b2b6SRod Evans for (APLIST_TRAVERSE(CALLERS(lmp), idx, bdp)) 7752020b2b6SRod Evans add_objclose_list(bdp->b_caller, &alp); 7767c478bd9Sstevel@tonic-gate } 7777c478bd9Sstevel@tonic-gate 7787c478bd9Sstevel@tonic-gate /* 7792020b2b6SRod Evans * If this close originated from dlclose(), determine whether the caller 7802020b2b6SRod Evans * requires a la_objclose() event. 7812020b2b6SRod Evans */ 7822020b2b6SRod Evans if (clmp) 7832020b2b6SRod Evans add_objclose_list(clmp, &alp); 7842020b2b6SRod Evans 7852020b2b6SRod Evans if (alp) { 7862020b2b6SRod Evans _audit_objclose(alp, lmp); 7872020b2b6SRod Evans free((void *)alp); 7882020b2b6SRod Evans } 7892020b2b6SRod Evans 7902020b2b6SRod Evans APPLICATION_RETURN(rtldflags); 7912020b2b6SRod Evans } 7922020b2b6SRod Evans 7932020b2b6SRod Evans /* 7942020b2b6SRod Evans * la_pltenter() caller. Traverse through all audit libraries and call any 7957c478bd9Sstevel@tonic-gate * la_pltenter() entry points found. NOTE: this routine is called via the 7967c478bd9Sstevel@tonic-gate * glue code established in elf_plt_trace_write(), the symbol descriptor is 7977c478bd9Sstevel@tonic-gate * created as part of the glue and for 32bit environments the st_name is a 7987c478bd9Sstevel@tonic-gate * pointer to the real symbol name (ie. it's already been adjusted with the 7997c478bd9Sstevel@tonic-gate * objects base offset). For 64bit environments the st_name remains the 8007c478bd9Sstevel@tonic-gate * original symbol offset and in this case it is used to compute the real name 8017c478bd9Sstevel@tonic-gate * pointer and pass as a separate argument to the auditor. 8027c478bd9Sstevel@tonic-gate */ 8037c478bd9Sstevel@tonic-gate static void 80457ef7aa9SRod Evans _audit_pltenter(APlist *list, Rt_map *rlmp, Rt_map *dlmp, Sym *sym, 8057c478bd9Sstevel@tonic-gate uint_t ndx, void *regs, uint_t *flags) 8067c478bd9Sstevel@tonic-gate { 8077c478bd9Sstevel@tonic-gate Audit_list *alp; 80857ef7aa9SRod Evans Aliste idx; 8092020b2b6SRod Evans Lm_list *rlml = LIST(rlmp); 8107c478bd9Sstevel@tonic-gate #if defined(_ELF64) 8117c478bd9Sstevel@tonic-gate const char *name = (const char *)(sym->st_name + STRTAB(dlmp)); 8127c478bd9Sstevel@tonic-gate #else 8137c478bd9Sstevel@tonic-gate const char *name = (const char *)(sym->st_name); 8147c478bd9Sstevel@tonic-gate #endif 8157c478bd9Sstevel@tonic-gate 81657ef7aa9SRod Evans for (APLIST_TRAVERSE(list, idx, alp)) { 8177c478bd9Sstevel@tonic-gate Audit_client *racp, *dacp; 8182020b2b6SRod Evans Rt_map *almp = alp->al_lmp; 8192020b2b6SRod Evans Lm_list *alml = LIST(almp); 8202020b2b6SRod Evans Addr ovalue = sym->st_value; 8217c478bd9Sstevel@tonic-gate 8227c478bd9Sstevel@tonic-gate if (alp->al_pltenter == 0) 8237c478bd9Sstevel@tonic-gate continue; 8242020b2b6SRod Evans if ((racp = _audit_client(AUDINFO(rlmp), almp)) == NULL) 8257c478bd9Sstevel@tonic-gate continue; 8262020b2b6SRod Evans if ((dacp = _audit_client(AUDINFO(dlmp), almp)) == NULL) 8277c478bd9Sstevel@tonic-gate continue; 8287c478bd9Sstevel@tonic-gate if (((racp->ac_flags & FLG_AC_BINDFROM) == 0) || 8297c478bd9Sstevel@tonic-gate ((dacp->ac_flags & FLG_AC_BINDTO) == 0)) 8307c478bd9Sstevel@tonic-gate continue; 8317c478bd9Sstevel@tonic-gate 8322020b2b6SRod Evans DBG_CALL(Dbg_audit_pltenter(rlml, DBG_AUD_CALL, 8332020b2b6SRod Evans alp->al_libname, name, ovalue)); 8342020b2b6SRod Evans 8352020b2b6SRod Evans leave(alml, thr_flg_reenter); 8367c478bd9Sstevel@tonic-gate sym->st_value = (Addr)(*alp->al_pltenter)(sym, ndx, 8377c478bd9Sstevel@tonic-gate &(racp->ac_cookie), &(dacp->ac_cookie), regs, 8387247f888Srie /* BEGIN CSTYLED */ 8397c478bd9Sstevel@tonic-gate #if defined(_ELF64) 8407c478bd9Sstevel@tonic-gate flags, name); 8417c478bd9Sstevel@tonic-gate #else 8427c478bd9Sstevel@tonic-gate flags); 8437c478bd9Sstevel@tonic-gate #endif 8447247f888Srie /* END CSTYLED */ 8458cd45542Sraf (void) enter(thr_flg_reenter); 8467c478bd9Sstevel@tonic-gate 8472020b2b6SRod Evans if (ovalue != sym->st_value) { 8482020b2b6SRod Evans DBG_CALL(Dbg_audit_pltenter(rlml, DBG_AUD_RET, 8492020b2b6SRod Evans alp->al_libname, name, sym->st_value)); 8502020b2b6SRod Evans } 8517c478bd9Sstevel@tonic-gate } 8527c478bd9Sstevel@tonic-gate } 8537c478bd9Sstevel@tonic-gate 8547c478bd9Sstevel@tonic-gate Addr 8557c478bd9Sstevel@tonic-gate audit_pltenter(Rt_map *rlmp, Rt_map *dlmp, Sym *sym, uint_t ndx, 8567c478bd9Sstevel@tonic-gate void *regs, uint_t *flags) 8577c478bd9Sstevel@tonic-gate { 8582020b2b6SRod Evans Sym nsym = *sym; 8592020b2b6SRod Evans uint_t rtldflags; 8607c478bd9Sstevel@tonic-gate 8612a8d6ebaSRod Evans if (rt_critical()) 8622020b2b6SRod Evans return (nsym.st_value); 8632a8d6ebaSRod Evans 8647c478bd9Sstevel@tonic-gate /* 8657c478bd9Sstevel@tonic-gate * We're effectively entering ld.so.1 from user (glue) code. 8667c478bd9Sstevel@tonic-gate */ 8678cd45542Sraf (void) enter(0); 8682020b2b6SRod Evans APPLICATION_ENTER(rtldflags); 8697c478bd9Sstevel@tonic-gate 8707c478bd9Sstevel@tonic-gate if (auditors && (auditors->ad_flags & LML_TFLG_AUD_PLTENTER)) 8712020b2b6SRod Evans _audit_pltenter(auditors->ad_list, rlmp, dlmp, &nsym, 8727c478bd9Sstevel@tonic-gate ndx, regs, flags); 8737c478bd9Sstevel@tonic-gate if (AUDITORS(rlmp) && 8747c478bd9Sstevel@tonic-gate (AUDITORS(rlmp)->ad_flags & LML_TFLG_AUD_PLTENTER)) 8752020b2b6SRod Evans _audit_pltenter(AUDITORS(rlmp)->ad_list, rlmp, dlmp, &nsym, 8767c478bd9Sstevel@tonic-gate ndx, regs, flags); 8777c478bd9Sstevel@tonic-gate 8782020b2b6SRod Evans APPLICATION_RETURN(rtldflags); 8798cd45542Sraf leave(LIST(rlmp), 0); 8807c478bd9Sstevel@tonic-gate 8812020b2b6SRod Evans return (nsym.st_value); 8827c478bd9Sstevel@tonic-gate } 8837c478bd9Sstevel@tonic-gate 8847c478bd9Sstevel@tonic-gate /* 8852020b2b6SRod Evans * la_pltexit() caller. Traverse through all audit libraries and call any 8867c478bd9Sstevel@tonic-gate * la_pltexit() entry points found. See notes above (_audit_pltenter) for 8877c478bd9Sstevel@tonic-gate * discussion on st_name. 8887c478bd9Sstevel@tonic-gate */ 8897c478bd9Sstevel@tonic-gate static Addr 89057ef7aa9SRod Evans _audit_pltexit(APlist *list, uintptr_t retval, Rt_map *rlmp, Rt_map *dlmp, 8917c478bd9Sstevel@tonic-gate Sym *sym, uint_t ndx) 8927c478bd9Sstevel@tonic-gate { 8937c478bd9Sstevel@tonic-gate Audit_list *alp; 89457ef7aa9SRod Evans Aliste idx; 8957c478bd9Sstevel@tonic-gate #if defined(_ELF64) 8967c478bd9Sstevel@tonic-gate const char *name = (const char *)(sym->st_name + STRTAB(dlmp)); 8972020b2b6SRod Evans #else 8982020b2b6SRod Evans const char *name = (const char *)(sym->st_name); 8997c478bd9Sstevel@tonic-gate #endif 9002020b2b6SRod Evans Lm_list *rlml = LIST(rlmp); 9017c478bd9Sstevel@tonic-gate 90257ef7aa9SRod Evans for (APLIST_TRAVERSE(list, idx, alp)) { 9037c478bd9Sstevel@tonic-gate Audit_client *racp, *dacp; 9042020b2b6SRod Evans Rt_map *almp = alp->al_lmp; 9052020b2b6SRod Evans Lm_list *alml = LIST(almp); 9067c478bd9Sstevel@tonic-gate 9077c478bd9Sstevel@tonic-gate if (alp->al_pltexit == 0) 9087c478bd9Sstevel@tonic-gate continue; 9092020b2b6SRod Evans if ((racp = _audit_client(AUDINFO(rlmp), almp)) == NULL) 9107c478bd9Sstevel@tonic-gate continue; 9112020b2b6SRod Evans if ((dacp = _audit_client(AUDINFO(dlmp), almp)) == NULL) 9127c478bd9Sstevel@tonic-gate continue; 9137c478bd9Sstevel@tonic-gate if (((racp->ac_flags & FLG_AC_BINDFROM) == 0) || 9147c478bd9Sstevel@tonic-gate ((dacp->ac_flags & FLG_AC_BINDTO) == 0)) 9157c478bd9Sstevel@tonic-gate continue; 9167c478bd9Sstevel@tonic-gate 9172020b2b6SRod Evans DBG_CALL(Dbg_audit_pltexit(rlml, alp->al_libname, name)); 9182020b2b6SRod Evans 9192020b2b6SRod Evans leave(alml, thr_flg_reenter); 9207c478bd9Sstevel@tonic-gate retval = (*alp->al_pltexit)(sym, ndx, 9217c478bd9Sstevel@tonic-gate &(racp->ac_cookie), &(dacp->ac_cookie), 9227247f888Srie /* BEGIN CSTYLED */ 9237c478bd9Sstevel@tonic-gate #if defined(_ELF64) 9247c478bd9Sstevel@tonic-gate retval, name); 9257c478bd9Sstevel@tonic-gate #else 9267c478bd9Sstevel@tonic-gate retval); 9277c478bd9Sstevel@tonic-gate #endif 9287247f888Srie /* END CSTYLED */ 9298cd45542Sraf (void) enter(thr_flg_reenter); 9307c478bd9Sstevel@tonic-gate } 9317c478bd9Sstevel@tonic-gate return (retval); 9327c478bd9Sstevel@tonic-gate } 9337c478bd9Sstevel@tonic-gate 9347c478bd9Sstevel@tonic-gate Addr 9357c478bd9Sstevel@tonic-gate audit_pltexit(uintptr_t retval, Rt_map *rlmp, Rt_map *dlmp, Sym *sym, 9367c478bd9Sstevel@tonic-gate uint_t ndx) 9377c478bd9Sstevel@tonic-gate { 9387c478bd9Sstevel@tonic-gate uintptr_t _retval = retval; 9392020b2b6SRod Evans uint_t rtldflags; 9407c478bd9Sstevel@tonic-gate 9412a8d6ebaSRod Evans if (rt_critical()) 9422a8d6ebaSRod Evans return (_retval); 9432a8d6ebaSRod Evans 9447c478bd9Sstevel@tonic-gate /* 9457c478bd9Sstevel@tonic-gate * We're effectively entering ld.so.1 from user (glue) code. 9467c478bd9Sstevel@tonic-gate */ 9478cd45542Sraf (void) enter(0); 9482020b2b6SRod Evans APPLICATION_ENTER(rtldflags); 9497c478bd9Sstevel@tonic-gate 9507c478bd9Sstevel@tonic-gate if (auditors && (auditors->ad_flags & LML_TFLG_AUD_PLTEXIT)) 95157ef7aa9SRod Evans _retval = _audit_pltexit(auditors->ad_list, _retval, 9527c478bd9Sstevel@tonic-gate rlmp, dlmp, sym, ndx); 9537c478bd9Sstevel@tonic-gate if (AUDITORS(rlmp) && (AUDITORS(rlmp)->ad_flags & LML_TFLG_AUD_PLTEXIT)) 95457ef7aa9SRod Evans _retval = _audit_pltexit(AUDITORS(rlmp)->ad_list, _retval, 9557c478bd9Sstevel@tonic-gate rlmp, dlmp, sym, ndx); 9567c478bd9Sstevel@tonic-gate 9572020b2b6SRod Evans APPLICATION_RETURN(rtldflags); 9588cd45542Sraf leave(LIST(rlmp), 0); 9597c478bd9Sstevel@tonic-gate 9607c478bd9Sstevel@tonic-gate return (_retval); 9617c478bd9Sstevel@tonic-gate } 9627c478bd9Sstevel@tonic-gate 9637c478bd9Sstevel@tonic-gate 9647c478bd9Sstevel@tonic-gate /* 9652020b2b6SRod Evans * la_symbind() caller. Traverse through all audit libraries and call any 9667c478bd9Sstevel@tonic-gate * la_symbind() entry points found. 9677c478bd9Sstevel@tonic-gate */ 9687c478bd9Sstevel@tonic-gate static Addr 96957ef7aa9SRod Evans _audit_symbind(APlist *list, Rt_map *rlmp, Rt_map *dlmp, Sym *sym, uint_t ndx, 9707c478bd9Sstevel@tonic-gate uint_t *flags, int *called) 9717c478bd9Sstevel@tonic-gate { 9727c478bd9Sstevel@tonic-gate Audit_list *alp; 97357ef7aa9SRod Evans Aliste idx; 9742020b2b6SRod Evans Lm_list *rlml = LIST(rlmp); 9757c478bd9Sstevel@tonic-gate #if defined(_ELF64) 9767c478bd9Sstevel@tonic-gate const char *name = (const char *)(sym->st_name + STRTAB(dlmp)); 9777c478bd9Sstevel@tonic-gate #else 9787c478bd9Sstevel@tonic-gate const char *name = (const char *)(sym->st_name); 9797c478bd9Sstevel@tonic-gate #endif 9807c478bd9Sstevel@tonic-gate 98157ef7aa9SRod Evans for (APLIST_TRAVERSE(list, idx, alp)) { 9827c478bd9Sstevel@tonic-gate Audit_client *racp, *dacp; 9832020b2b6SRod Evans Rt_map *almp = alp->al_lmp; 9842020b2b6SRod Evans Lm_list *alml = LIST(almp); 9852020b2b6SRod Evans Addr ovalue = sym->st_value; 9862020b2b6SRod Evans uint_t lflags, oflags = *flags; 9877c478bd9Sstevel@tonic-gate 9887c478bd9Sstevel@tonic-gate if (alp->al_symbind == 0) 9897c478bd9Sstevel@tonic-gate continue; 990*38f4bdddSBryan Cantrill 991*38f4bdddSBryan Cantrill if ((racp = _audit_client(AUDINFO(rlmp), almp)) != NULL && 992*38f4bdddSBryan Cantrill (racp->ac_flags & FLG_AC_BINDFROM) == 0) 9937c478bd9Sstevel@tonic-gate continue; 994*38f4bdddSBryan Cantrill 9952020b2b6SRod Evans if ((dacp = _audit_client(AUDINFO(dlmp), almp)) == NULL) 9967c478bd9Sstevel@tonic-gate continue; 997*38f4bdddSBryan Cantrill 998*38f4bdddSBryan Cantrill if ((dacp->ac_flags & FLG_AC_BINDTO) == 0) 9997c478bd9Sstevel@tonic-gate continue; 10007c478bd9Sstevel@tonic-gate 10017c478bd9Sstevel@tonic-gate /* 1002*38f4bdddSBryan Cantrill * The la_symbind interface is only called when the destination 1003*38f4bdddSBryan Cantrill * object has been identified as BINDTO and either the 1004*38f4bdddSBryan Cantrill * destination object is being locally audited or the calling 1005*38f4bdddSBryan Cantrill * object has been identified as BINDFROM. Use a local version 1006*38f4bdddSBryan Cantrill * of the flags, so that any user update can be collected. 10077c478bd9Sstevel@tonic-gate */ 10082020b2b6SRod Evans (*called)++; 10092020b2b6SRod Evans lflags = (oflags & ~(LA_SYMB_NOPLTENTER | LA_SYMB_NOPLTEXIT)); 10107c478bd9Sstevel@tonic-gate 10112020b2b6SRod Evans DBG_CALL(Dbg_audit_symbind(rlml, DBG_AUD_CALL, 10122020b2b6SRod Evans alp->al_libname, name, ovalue, oflags)); 10132020b2b6SRod Evans 10142020b2b6SRod Evans leave(alml, thr_flg_reenter); 1015*38f4bdddSBryan Cantrill sym->st_value = (*alp->al_symbind)(sym, ndx, racp == NULL ? 1016*38f4bdddSBryan Cantrill NULL : &(racp->ac_cookie), &(dacp->ac_cookie), 10177247f888Srie /* BEGIN CSTYLED */ 10187c478bd9Sstevel@tonic-gate #if defined(_ELF64) 10197c478bd9Sstevel@tonic-gate &lflags, name); 10207c478bd9Sstevel@tonic-gate #else 10217c478bd9Sstevel@tonic-gate &lflags); 10227c478bd9Sstevel@tonic-gate #endif 10237247f888Srie /* END CSTYLED */ 10248cd45542Sraf (void) enter(thr_flg_reenter); 10257c478bd9Sstevel@tonic-gate 10267c478bd9Sstevel@tonic-gate /* 10277c478bd9Sstevel@tonic-gate * If the auditor indicated that they did not want to process 10287c478bd9Sstevel@tonic-gate * pltenter, or pltexit audits for this symbol, retain this 10297c478bd9Sstevel@tonic-gate * information. Also retain whether an alternative symbol value 10307c478bd9Sstevel@tonic-gate * has been supplied. 10317c478bd9Sstevel@tonic-gate */ 10327c478bd9Sstevel@tonic-gate *flags |= (lflags & (LA_SYMB_NOPLTENTER | LA_SYMB_NOPLTEXIT)); 10332020b2b6SRod Evans if ((ovalue != sym->st_value) && 10342020b2b6SRod Evans (alp->al_vernum >= LAV_VERSION2)) 10357c478bd9Sstevel@tonic-gate *flags |= LA_SYMB_ALTVALUE; 10367c478bd9Sstevel@tonic-gate 10372020b2b6SRod Evans if ((ovalue != sym->st_value) || (oflags != *flags)) { 10382020b2b6SRod Evans DBG_CALL(Dbg_audit_symbind(rlml, DBG_AUD_RET, 10392020b2b6SRod Evans alp->al_libname, name, sym->st_value, *flags)); 10402020b2b6SRod Evans } 10417c478bd9Sstevel@tonic-gate } 10427c478bd9Sstevel@tonic-gate return (sym->st_value); 10437c478bd9Sstevel@tonic-gate } 10447c478bd9Sstevel@tonic-gate 10457c478bd9Sstevel@tonic-gate Addr 10467c478bd9Sstevel@tonic-gate audit_symbind(Rt_map *rlmp, Rt_map *dlmp, Sym *sym, uint_t ndx, Addr value, 10477c478bd9Sstevel@tonic-gate uint_t *flags) 10487c478bd9Sstevel@tonic-gate { 10492020b2b6SRod Evans Sym nsym; 10502020b2b6SRod Evans int called = 0; 10512020b2b6SRod Evans uint_t rtldflags; 10527c478bd9Sstevel@tonic-gate 10537c478bd9Sstevel@tonic-gate /* 10547c478bd9Sstevel@tonic-gate * Construct a new symbol from that supplied but with the real address. 10557c478bd9Sstevel@tonic-gate * In the 64-bit world the st_name field is only 32-bits which isn't 10567c478bd9Sstevel@tonic-gate * big enough to hold a character pointer. We pass this pointer as a 10577c478bd9Sstevel@tonic-gate * separate parameter for 64-bit audit libraries. 10587c478bd9Sstevel@tonic-gate */ 10592020b2b6SRod Evans nsym = *sym; 10602020b2b6SRod Evans nsym.st_value = value; 10617c478bd9Sstevel@tonic-gate 10622a8d6ebaSRod Evans if (rt_critical()) 10632020b2b6SRod Evans return (nsym.st_value); 10642a8d6ebaSRod Evans 10657c478bd9Sstevel@tonic-gate #if !defined(_ELF64) 10662020b2b6SRod Evans nsym.st_name += (Word)STRTAB(dlmp); 10677c478bd9Sstevel@tonic-gate #endif 10682020b2b6SRod Evans APPLICATION_ENTER(rtldflags); 10697c478bd9Sstevel@tonic-gate 10707c478bd9Sstevel@tonic-gate if (auditors && (auditors->ad_flags & LML_TFLG_AUD_SYMBIND)) 10712020b2b6SRod Evans nsym.st_value = _audit_symbind(auditors->ad_list, 10722020b2b6SRod Evans rlmp, dlmp, &nsym, ndx, flags, &called); 1073*38f4bdddSBryan Cantrill 10747c478bd9Sstevel@tonic-gate if (AUDITORS(rlmp) && (AUDITORS(rlmp)->ad_flags & LML_TFLG_AUD_SYMBIND)) 10752020b2b6SRod Evans nsym.st_value = _audit_symbind(AUDITORS(rlmp)->ad_list, 10762020b2b6SRod Evans rlmp, dlmp, &nsym, ndx, flags, &called); 10777c478bd9Sstevel@tonic-gate 1078*38f4bdddSBryan Cantrill if (dlmp != rlmp && AUDITORS(dlmp) && 1079*38f4bdddSBryan Cantrill (AUDITORS(dlmp)->ad_flags & LML_TFLG_AUD_SYMBIND)) { 1080*38f4bdddSBryan Cantrill nsym.st_value = _audit_symbind(AUDITORS(dlmp)->ad_list, 1081*38f4bdddSBryan Cantrill rlmp, dlmp, &nsym, ndx, flags, &called); 1082*38f4bdddSBryan Cantrill } 1083*38f4bdddSBryan Cantrill 10847c478bd9Sstevel@tonic-gate /* 10857c478bd9Sstevel@tonic-gate * If no la_symbind() was called for this interface, fabricate that no 10867c478bd9Sstevel@tonic-gate * la_pltenter, or la_pltexit is required. This helps reduce the glue 10877c478bd9Sstevel@tonic-gate * code created for further auditing. 10887c478bd9Sstevel@tonic-gate */ 10892020b2b6SRod Evans if (called == 0) 10907c478bd9Sstevel@tonic-gate *flags |= (LA_SYMB_NOPLTENTER | LA_SYMB_NOPLTEXIT); 10917c478bd9Sstevel@tonic-gate 10922020b2b6SRod Evans APPLICATION_RETURN(rtldflags); 10937c478bd9Sstevel@tonic-gate 10942020b2b6SRod Evans return (nsym.st_value); 10957c478bd9Sstevel@tonic-gate } 10967c478bd9Sstevel@tonic-gate 10977c478bd9Sstevel@tonic-gate /* 10987247f888Srie * la_preinit() caller. Traverse through all audit libraries and call any 10997c478bd9Sstevel@tonic-gate * la_preinit() entry points found. 11007c478bd9Sstevel@tonic-gate */ 11017c478bd9Sstevel@tonic-gate static void 11022020b2b6SRod Evans _audit_preinit(APlist *list, Rt_map *clmp, Boolean client) 11037c478bd9Sstevel@tonic-gate { 11047c478bd9Sstevel@tonic-gate Audit_list *alp; 110557ef7aa9SRod Evans Aliste idx; 11062020b2b6SRod Evans Lm_list *clml = LIST(clmp); 11077c478bd9Sstevel@tonic-gate 110857ef7aa9SRod Evans for (APLIST_TRAVERSE(list, idx, alp)) { 11097c478bd9Sstevel@tonic-gate Audit_client *acp; 11102020b2b6SRod Evans Rt_map *almp = alp->al_lmp; 11112020b2b6SRod Evans Lm_list *alml = LIST(almp); 11122020b2b6SRod Evans uintptr_t *cookie; 11137c478bd9Sstevel@tonic-gate 11147c478bd9Sstevel@tonic-gate if (alp->al_preinit == 0) 11157c478bd9Sstevel@tonic-gate continue; 11167c478bd9Sstevel@tonic-gate 11172020b2b6SRod Evans /* 11182020b2b6SRod Evans * Determine what cookie is required. Any auditing that 11192020b2b6SRod Evans * originates from the object that heads the link-map list has 11202020b2b6SRod Evans * its own cookie. Local auditors must obtain the cookie that 11212020b2b6SRod Evans * represents the object that heads the link-map list. 11222020b2b6SRod Evans */ 11232020b2b6SRod Evans if (client) 11242020b2b6SRod Evans acp = _audit_client(AUDINFO(clmp), almp); 11252020b2b6SRod Evans else 11262020b2b6SRod Evans acp = _audit_get_head_client(clml->lm_head, almp); 11272020b2b6SRod Evans 11282020b2b6SRod Evans if (acp == NULL) 11292020b2b6SRod Evans continue; 11302020b2b6SRod Evans cookie = &(acp->ac_cookie); 11312020b2b6SRod Evans 11322020b2b6SRod Evans DBG_CALL(Dbg_audit_preinit(clml, alp->al_libname, 11332020b2b6SRod Evans NAME(clml->lm_head))); 11342020b2b6SRod Evans 11352020b2b6SRod Evans leave(alml, thr_flg_reenter); 11362020b2b6SRod Evans (*alp->al_preinit)(cookie); 11378cd45542Sraf (void) enter(thr_flg_reenter); 11387c478bd9Sstevel@tonic-gate } 11397c478bd9Sstevel@tonic-gate } 11407c478bd9Sstevel@tonic-gate 11417c478bd9Sstevel@tonic-gate void 11422020b2b6SRod Evans audit_preinit(Rt_map *mlmp) 11437c478bd9Sstevel@tonic-gate { 11442020b2b6SRod Evans Rt_map *clmp; 11452020b2b6SRod Evans Aliste idx; 11462020b2b6SRod Evans uint_t rtldflags; 11477c478bd9Sstevel@tonic-gate 11482a8d6ebaSRod Evans if (rt_critical()) 11492a8d6ebaSRod Evans return; 11502a8d6ebaSRod Evans 11512020b2b6SRod Evans APPLICATION_ENTER(rtldflags); 11527c478bd9Sstevel@tonic-gate 11537c478bd9Sstevel@tonic-gate if (auditors && (auditors->ad_flags & LML_TFLG_AUD_PREINIT)) 11542020b2b6SRod Evans _audit_preinit(auditors->ad_list, mlmp, TRUE); 11557c478bd9Sstevel@tonic-gate 11562020b2b6SRod Evans if (AUDITORS(mlmp) && (AUDITORS(mlmp)->ad_flags & LML_TFLG_AUD_PREINIT)) 11572020b2b6SRod Evans _audit_preinit(AUDITORS(mlmp)->ad_list, mlmp, TRUE); 11582020b2b6SRod Evans 11592020b2b6SRod Evans for (APLIST_TRAVERSE(aud_preinit, idx, clmp)) { 11602020b2b6SRod Evans if (AUDITORS(clmp) && 11612020b2b6SRod Evans (AUDITORS(clmp)->ad_flags & LML_TFLG_AUD_PREINIT)) 11622020b2b6SRod Evans _audit_preinit(AUDITORS(clmp)->ad_list, clmp, FALSE); 11632020b2b6SRod Evans } 11642020b2b6SRod Evans 11652020b2b6SRod Evans APPLICATION_RETURN(rtldflags); 11667c478bd9Sstevel@tonic-gate } 11677c478bd9Sstevel@tonic-gate 11687c478bd9Sstevel@tonic-gate /* 11697c478bd9Sstevel@tonic-gate * Clean up (free) an audit descriptor. First, gather a list of all handles, 11707c478bd9Sstevel@tonic-gate * and then close each one down. This is done rather than using the handles 11717c478bd9Sstevel@tonic-gate * directly from the auditors, as the audit list can be torn down as a result 11727c478bd9Sstevel@tonic-gate * of the dlclose. In other words, what you're pointing at can be removed 11732020b2b6SRod Evans * while you're still pointing at it. 11747c478bd9Sstevel@tonic-gate */ 11757c478bd9Sstevel@tonic-gate void 11767247f888Srie audit_desc_cleanup(Rt_map *clmp) 11777c478bd9Sstevel@tonic-gate { 11787247f888Srie Audit_desc *adp = AUDITORS(clmp); 11797c478bd9Sstevel@tonic-gate Audit_list *alp; 118057ef7aa9SRod Evans Aliste idx; 1181cce0e03bSab196087 APlist *ghalp = NULL; 11827c478bd9Sstevel@tonic-gate 118357ef7aa9SRod Evans if (adp == NULL) 11847c478bd9Sstevel@tonic-gate return; 11857c478bd9Sstevel@tonic-gate if (adp->ad_name) 11867c478bd9Sstevel@tonic-gate free(adp->ad_name); 11877c478bd9Sstevel@tonic-gate 118857ef7aa9SRod Evans for (APLIST_TRAVERSE(adp->ad_list, idx, alp)) 1189cce0e03bSab196087 (void) aplist_append(&ghalp, alp->al_ghp, AL_CNT_GROUPS); 11907c478bd9Sstevel@tonic-gate 119157ef7aa9SRod Evans free(adp->ad_list); 119257ef7aa9SRod Evans adp->ad_list = NULL; 11937c478bd9Sstevel@tonic-gate 11947247f888Srie free(adp); 11952020b2b6SRod Evans 11962020b2b6SRod Evans /* 11972020b2b6SRod Evans * Indicate that the caller is no longer being audited. 11982020b2b6SRod Evans */ 119957ef7aa9SRod Evans AUDITORS(clmp) = NULL; 12002020b2b6SRod Evans AFLAGS(clmp) &= ~LML_TFLG_AUD_MASK; 12017247f888Srie 12027c478bd9Sstevel@tonic-gate if (ghalp) { 1203cce0e03bSab196087 Grp_hdl *ghp; 1204cce0e03bSab196087 Aliste idx; 12057c478bd9Sstevel@tonic-gate 1206cce0e03bSab196087 for (APLIST_TRAVERSE(ghalp, idx, ghp)) { 1207cce0e03bSab196087 (void) dlclose_intn(ghp, clmp); 12087247f888Srie } 12097c478bd9Sstevel@tonic-gate free(ghalp); 12107c478bd9Sstevel@tonic-gate } 12117c478bd9Sstevel@tonic-gate } 12127c478bd9Sstevel@tonic-gate 12137c478bd9Sstevel@tonic-gate /* 12142020b2b6SRod Evans * Objects that establish local auditors may have been added to preinit or 12152020b2b6SRod Evans * activity lists. Remove the object from this list if it is present. 12162020b2b6SRod Evans */ 12172020b2b6SRod Evans static void 12182020b2b6SRod Evans remove_auditor(APlist *alp, Rt_map *clmp) 12192020b2b6SRod Evans { 12202020b2b6SRod Evans Rt_map *lmp; 12212020b2b6SRod Evans Aliste idx; 12222020b2b6SRod Evans 12232020b2b6SRod Evans for (APLIST_TRAVERSE(alp, idx, lmp)) { 12242020b2b6SRod Evans if (lmp == clmp) { 12252020b2b6SRod Evans aplist_delete(alp, &idx); 12262020b2b6SRod Evans return; 12272020b2b6SRod Evans } 12282020b2b6SRod Evans } 12292020b2b6SRod Evans } 12302020b2b6SRod Evans 12312020b2b6SRod Evans /* 12327c478bd9Sstevel@tonic-gate * Clean up (free) an audit information structure. 12337c478bd9Sstevel@tonic-gate */ 12347c478bd9Sstevel@tonic-gate void 12357247f888Srie audit_info_cleanup(Rt_map *clmp) 12367c478bd9Sstevel@tonic-gate { 12377247f888Srie Audit_info *aip = AUDINFO(clmp); 12387247f888Srie 123957ef7aa9SRod Evans if (aip == NULL) 12407c478bd9Sstevel@tonic-gate return; 12417c478bd9Sstevel@tonic-gate 12427c478bd9Sstevel@tonic-gate if (aip->ai_dynplts) 12437c478bd9Sstevel@tonic-gate free(aip->ai_dynplts); 12442020b2b6SRod Evans 12452020b2b6SRod Evans if (aud_preinit) 12462020b2b6SRod Evans remove_auditor(aud_preinit, clmp); 12472020b2b6SRod Evans if (aud_activity) 12482020b2b6SRod Evans remove_auditor(aud_activity, clmp); 12492020b2b6SRod Evans 12507c478bd9Sstevel@tonic-gate free(aip); 12517c478bd9Sstevel@tonic-gate } 12527c478bd9Sstevel@tonic-gate 12537c478bd9Sstevel@tonic-gate /* 12547c478bd9Sstevel@tonic-gate * Create a data structure of symbol lookup names and associated flags to help 12557c478bd9Sstevel@tonic-gate * simplify audit_symget() use. 12567c478bd9Sstevel@tonic-gate */ 12577c478bd9Sstevel@tonic-gate typedef struct { 12587c478bd9Sstevel@tonic-gate Msg sname; 12597c478bd9Sstevel@tonic-gate uint_t alflag; 12607c478bd9Sstevel@tonic-gate uint_t auflag; 12617c478bd9Sstevel@tonic-gate } Aud_info; 12627c478bd9Sstevel@tonic-gate 12637c478bd9Sstevel@tonic-gate static const Aud_info aud_info[] = { 12642020b2b6SRod Evans { MSG_SYM_LAVERSION, 0, 0 }, /* MSG_ORIG(MSG_SYM_LAVERSION) */ 12657c478bd9Sstevel@tonic-gate { MSG_SYM_LAPREINIT, /* MSG_ORIG(MSG_SYM_LAPREINIT) */ 12667c478bd9Sstevel@tonic-gate LML_TFLG_AUD_PREINIT, 0 }, 12677c478bd9Sstevel@tonic-gate { MSG_SYM_LAOBJSEARCH, /* MSG_ORIG(MSG_SYM_LAOBJSEARCH) */ 12687c478bd9Sstevel@tonic-gate LML_TFLG_AUD_OBJSEARCH, 0 }, 12697c478bd9Sstevel@tonic-gate { MSG_SYM_LAOBJOPEN, /* MSG_ORIG(MSG_SYM_LAOBJOPEN) */ 12707c478bd9Sstevel@tonic-gate LML_TFLG_AUD_OBJOPEN, 0 }, 12717c478bd9Sstevel@tonic-gate { MSG_SYM_LAOBJFILTER, /* MSG_ORIG(MSG_SYM_LAOBJFILTER */ 12727c478bd9Sstevel@tonic-gate LML_TFLG_AUD_OBJFILTER, 0 }, 12737c478bd9Sstevel@tonic-gate { MSG_SYM_LAOBJCLOSE, /* MSG_ORIG(MSG_SYM_LAOBJCLOSE) */ 12747c478bd9Sstevel@tonic-gate LML_TFLG_AUD_OBJCLOSE, 0 }, 12757c478bd9Sstevel@tonic-gate { MSG_SYM_LAACTIVITY, /* MSG_ORIG(MSG_SYM_LAACTIVITY) */ 12767c478bd9Sstevel@tonic-gate LML_TFLG_AUD_ACTIVITY, 0 }, 12777c478bd9Sstevel@tonic-gate 12787c478bd9Sstevel@tonic-gate #if defined(_ELF64) 12797c478bd9Sstevel@tonic-gate { MSG_SYM_LASYMBIND_64, /* MSG_ORIG(MSG_SYM_LASYMBIND_64) */ 12807c478bd9Sstevel@tonic-gate #else 12817c478bd9Sstevel@tonic-gate { MSG_SYM_LASYMBIND, /* MSG_ORIG(MSG_SYM_LASYMBIND) */ 12827c478bd9Sstevel@tonic-gate #endif 12837c478bd9Sstevel@tonic-gate LML_TFLG_AUD_SYMBIND, 0 }, 12847c478bd9Sstevel@tonic-gate 12857c478bd9Sstevel@tonic-gate #if defined(__sparcv9) 12867c478bd9Sstevel@tonic-gate { MSG_SYM_LAV9PLTENTER, /* MSG_ORIG(MSG_SYM_LAV9PLTENTER) */ 12877c478bd9Sstevel@tonic-gate #elif defined(__sparc) 12887c478bd9Sstevel@tonic-gate { MSG_SYM_LAV8PLTENTER, /* MSG_ORIG(MSG_SYM_LAV8PLTENTER) */ 12897c478bd9Sstevel@tonic-gate #elif defined(__amd64) 12907c478bd9Sstevel@tonic-gate { MSG_SYM_LAAMD64PLTENTER, /* MSG_ORIG(MSG_SYM_LAAMD64PLTENTER) */ 129102ca3e02Srie #elif defined(__i386) 12927c478bd9Sstevel@tonic-gate { MSG_SYM_LAX86PLTENTER, /* MSG_ORIG(MSG_SYM_LAX86PLTENTER) */ 12937c478bd9Sstevel@tonic-gate #else 12947c478bd9Sstevel@tonic-gate #error platform not defined! 12957c478bd9Sstevel@tonic-gate #endif 12967c478bd9Sstevel@tonic-gate LML_TFLG_AUD_PLTENTER, AF_PLTENTER }, 12977c478bd9Sstevel@tonic-gate 12987c478bd9Sstevel@tonic-gate #if defined(_ELF64) 12997c478bd9Sstevel@tonic-gate { MSG_SYM_LAPLTEXIT_64, /* MSG_ORIG(MSG_SYM_LAPLTEXIT_64) */ 13007c478bd9Sstevel@tonic-gate #else 13017c478bd9Sstevel@tonic-gate { MSG_SYM_LAPLTEXIT, /* MSG_ORIG(MSG_SYM_LAPLTEXIT) */ 13027c478bd9Sstevel@tonic-gate #endif 13037c478bd9Sstevel@tonic-gate LML_TFLG_AUD_PLTEXIT, AF_PLTEXIT } 13047c478bd9Sstevel@tonic-gate }; 13057c478bd9Sstevel@tonic-gate 13067c478bd9Sstevel@tonic-gate #define AI_LAVERSION 0 13077c478bd9Sstevel@tonic-gate #define AI_LAPREINIT 1 13087c478bd9Sstevel@tonic-gate #define AI_LAOBJSEARCH 2 13097c478bd9Sstevel@tonic-gate #define AI_LAOBJOPEN 3 13107c478bd9Sstevel@tonic-gate #define AI_LAOBJFILTER 4 13117c478bd9Sstevel@tonic-gate #define AI_LAOBJCLOSE 5 13127c478bd9Sstevel@tonic-gate #define AI_LAACTIVITY 6 13137c478bd9Sstevel@tonic-gate #define AI_LASYMBIND 7 13147c478bd9Sstevel@tonic-gate #define AI_LAPLTENTER 8 13157c478bd9Sstevel@tonic-gate #define AI_LAPLTEXIT 9 13167c478bd9Sstevel@tonic-gate 13177c478bd9Sstevel@tonic-gate static Addr 13189aa23310Srie audit_symget(Audit_list *alp, int info, int *in_nfavl) 13197c478bd9Sstevel@tonic-gate { 132008278a5eSRod Evans Rt_map *lmp = alp->al_lmp; 13217c478bd9Sstevel@tonic-gate const char *sname = MSG_ORIG(aud_info[info].sname); 13227c478bd9Sstevel@tonic-gate uint_t alflag = aud_info[info].alflag; 13237c478bd9Sstevel@tonic-gate uint_t auflag = aud_info[info].auflag; 13247c478bd9Sstevel@tonic-gate uint_t binfo; 13257c478bd9Sstevel@tonic-gate Slookup sl; 132608278a5eSRod Evans Sresult sr; 13277c478bd9Sstevel@tonic-gate 132875e7992aSrie /* 132908278a5eSRod Evans * Initialize the symbol lookup, and symbol result, data structures. 133075e7992aSrie */ 133175e7992aSrie SLOOKUP_INIT(sl, sname, lml_rtld.lm_head, lmp, ld_entry_cnt, 133208278a5eSRod Evans 0, 0, 0, 0, (LKUP_FIRST | LKUP_DLSYM)); 133308278a5eSRod Evans SRESULT_INIT(sr, sname); 13347c478bd9Sstevel@tonic-gate 133508278a5eSRod Evans if (LM_LOOKUP_SYM(lmp)(&sl, &sr, &binfo, in_nfavl)) { 133608278a5eSRod Evans Addr addr = sr.sr_sym->st_value; 13377c478bd9Sstevel@tonic-gate 13387c478bd9Sstevel@tonic-gate if (!(FLAGS(lmp) & FLG_RT_FIXED)) 13397c478bd9Sstevel@tonic-gate addr += ADDR(lmp); 13407c478bd9Sstevel@tonic-gate 13417c478bd9Sstevel@tonic-gate if (alflag) 13427c478bd9Sstevel@tonic-gate alp->al_flags |= alflag; 13437c478bd9Sstevel@tonic-gate if (auflag) 13447c478bd9Sstevel@tonic-gate audit_flags |= auflag; 13457c478bd9Sstevel@tonic-gate 13462020b2b6SRod Evans /* 13472020b2b6SRod Evans * Note, unlike most other diagnostics, where we wish to 13482020b2b6SRod Evans * identify the lmid of the caller, here we use the lmid of 13492020b2b6SRod Evans * the auditor itself to show the association of the auditor 13502020b2b6SRod Evans * and the interfaces it provides. 13512020b2b6SRod Evans */ 13525aefb655Srie DBG_CALL(Dbg_audit_interface(LIST(alp->al_lmp), 135308278a5eSRod Evans alp->al_libname, sr.sr_name)); 13547c478bd9Sstevel@tonic-gate return (addr); 135508278a5eSRod Evans } 13567c478bd9Sstevel@tonic-gate return (0); 13577c478bd9Sstevel@tonic-gate } 13587c478bd9Sstevel@tonic-gate 13597c478bd9Sstevel@tonic-gate /* 13607c478bd9Sstevel@tonic-gate * Centralize cleanup routines. 13617c478bd9Sstevel@tonic-gate */ 13627c478bd9Sstevel@tonic-gate static int 13637c478bd9Sstevel@tonic-gate audit_disable(char *name, Rt_map *clmp, Grp_hdl *ghp, Audit_list *alp) 13647c478bd9Sstevel@tonic-gate { 13655aefb655Srie eprintf(LIST(clmp), ERR_FATAL, MSG_INTL(MSG_AUD_DISABLED), name); 13667c478bd9Sstevel@tonic-gate if (ghp) 13677c478bd9Sstevel@tonic-gate (void) dlclose_intn(ghp, clmp); 13687c478bd9Sstevel@tonic-gate if (alp) 13697c478bd9Sstevel@tonic-gate free(alp); 13707c478bd9Sstevel@tonic-gate 13717c478bd9Sstevel@tonic-gate return (0); 13727c478bd9Sstevel@tonic-gate } 13737c478bd9Sstevel@tonic-gate 13747c478bd9Sstevel@tonic-gate /* 13757c478bd9Sstevel@tonic-gate * Given a list of one or more audit libraries, open each one and establish a 13767c478bd9Sstevel@tonic-gate * a descriptor representing the entry points it provides. 13777c478bd9Sstevel@tonic-gate */ 13787c478bd9Sstevel@tonic-gate int 13799aa23310Srie audit_setup(Rt_map *clmp, Audit_desc *adp, uint_t orig, int *in_nfavl) 13807c478bd9Sstevel@tonic-gate { 13817c478bd9Sstevel@tonic-gate char *ptr, *next; 13825aefb655Srie Lm_list *clml = LIST(clmp); 13832020b2b6SRod Evans Rt_map *hlmp; 13842020b2b6SRod Evans int error = 1, activity = 0, preinit = 0; 13852020b2b6SRod Evans uint_t rtldflags; 13867c478bd9Sstevel@tonic-gate 13872020b2b6SRod Evans /* 13882020b2b6SRod Evans * Determine the type of auditing for diagnostics. 13892020b2b6SRod Evans */ 13902020b2b6SRod Evans if (DBG_ENABLED) { 13912020b2b6SRod Evans int type; 13922020b2b6SRod Evans 13932020b2b6SRod Evans if (orig & PD_FLG_EXTLOAD) 13942020b2b6SRod Evans type = DBG_AUD_PRELOAD; 13952020b2b6SRod Evans else if (FLAGS1(clmp) & FL1_RT_GLOBAUD) 13962020b2b6SRod Evans type = DBG_AUD_GLOBAL; 13972020b2b6SRod Evans else 13982020b2b6SRod Evans type = DBG_AUD_LOCAL; 13992020b2b6SRod Evans 14002020b2b6SRod Evans DBG_CALL(Dbg_audit_lib(clmp, adp->ad_name, type)); 14012020b2b6SRod Evans } 14027c478bd9Sstevel@tonic-gate 14037c478bd9Sstevel@tonic-gate /* 14047c478bd9Sstevel@tonic-gate * Mark that we have at least one auditing link map 14057c478bd9Sstevel@tonic-gate */ 14067c478bd9Sstevel@tonic-gate rtld_flags2 |= RT_FL2_HASAUDIT; 14077c478bd9Sstevel@tonic-gate 14087c478bd9Sstevel@tonic-gate /* 14097c478bd9Sstevel@tonic-gate * The audit definitions may be a list (which will already have been 14107c478bd9Sstevel@tonic-gate * dupped) so split it into individual tokens. 14117c478bd9Sstevel@tonic-gate */ 141256d7adc6Srie for (ptr = strtok_r(adp->ad_name, MSG_ORIG(MSG_STR_DELIMIT), &next); 141356d7adc6Srie ptr; ptr = strtok_r(NULL, MSG_ORIG(MSG_STR_DELIMIT), &next)) { 14147c478bd9Sstevel@tonic-gate Grp_hdl *ghp; 14157c478bd9Sstevel@tonic-gate Rt_map *lmp; 14162020b2b6SRod Evans Lm_list *lml; 14177c478bd9Sstevel@tonic-gate Rt_map **tobj; 14187c478bd9Sstevel@tonic-gate Audit_list *alp; 14197c478bd9Sstevel@tonic-gate 14202020b2b6SRod Evans DBG_CALL(Dbg_util_nl(clml, DBG_NL_STD)); 14212020b2b6SRod Evans 14227c478bd9Sstevel@tonic-gate /* 14237c478bd9Sstevel@tonic-gate * Open the audit library on its own link-map. 14247c478bd9Sstevel@tonic-gate */ 14257c478bd9Sstevel@tonic-gate if ((ghp = dlmopen_intn((Lm_list *)LM_ID_NEWLM, ptr, 14267c478bd9Sstevel@tonic-gate (RTLD_FIRST | RTLD_GLOBAL | RTLD_WORLD), clmp, 142757ef7aa9SRod Evans FLG_RT_AUDIT, orig)) == NULL) { 14287c478bd9Sstevel@tonic-gate error = audit_disable(ptr, clmp, 0, 0); 14297c478bd9Sstevel@tonic-gate continue; 14307c478bd9Sstevel@tonic-gate } 14315aefb655Srie lmp = ghp->gh_ownlmp; 14322020b2b6SRod Evans lml = LIST(lmp); 14337c478bd9Sstevel@tonic-gate 14347c478bd9Sstevel@tonic-gate /* 14357c478bd9Sstevel@tonic-gate * If this auditor has already been loaded, reuse it. 14367c478bd9Sstevel@tonic-gate */ 14372020b2b6SRod Evans if ((alp = lml->lm_alp) != NULL) { 143857ef7aa9SRod Evans if (aplist_append(&(adp->ad_list), alp, 143957ef7aa9SRod Evans AL_CNT_AUDITORS) == NULL) 14407c478bd9Sstevel@tonic-gate return (audit_disable(ptr, clmp, ghp, alp)); 14417c478bd9Sstevel@tonic-gate 14427c478bd9Sstevel@tonic-gate adp->ad_cnt++; 14437c478bd9Sstevel@tonic-gate adp->ad_flags |= alp->al_flags; 14442020b2b6SRod Evans 14452020b2b6SRod Evans /* 14462020b2b6SRod Evans * If this existing auditor provides preinit or 14472020b2b6SRod Evans * activity routines, track their existence. The 14482020b2b6SRod Evans * instantiation of a local auditor requires a cookie 14492020b2b6SRod Evans * be created that represents the object that heads 14502020b2b6SRod Evans * the link-map list of the object being audited. 14512020b2b6SRod Evans */ 14522020b2b6SRod Evans if (alp->al_preinit) 14532020b2b6SRod Evans preinit++; 14542020b2b6SRod Evans if (alp->al_activity) 14552020b2b6SRod Evans activity++; 14562020b2b6SRod Evans 14577c478bd9Sstevel@tonic-gate continue; 14587c478bd9Sstevel@tonic-gate } 14597c478bd9Sstevel@tonic-gate 14607c478bd9Sstevel@tonic-gate /* 146143d7826aSRod Evans * Prior to the Unified Process Model (UPM) environment, an 146243d7826aSRod Evans * rtld lock had to be held upon leave(). However, even within 146343d7826aSRod Evans * a UPM environment, an old auditor, that has a lazy dependency 146443d7826aSRod Evans * on libc, is still a possibility. As libc isn't loaded, we 146543d7826aSRod Evans * don't know the process model, and will determine this later. 146643d7826aSRod Evans * Refer to external.c:get_lcinterface(). 14677c478bd9Sstevel@tonic-gate */ 14687c478bd9Sstevel@tonic-gate if ((rtld_flags2 & RT_FL2_UNIFPROC) == 0) 14692020b2b6SRod Evans lml->lm_flags |= LML_FLG_HOLDLOCK; 14707c478bd9Sstevel@tonic-gate 14717c478bd9Sstevel@tonic-gate /* 14727c478bd9Sstevel@tonic-gate * Allocate an audit list descriptor for this object and 14737c478bd9Sstevel@tonic-gate * search for all known entry points. 14747c478bd9Sstevel@tonic-gate */ 147556deab07SRod Evans if ((alp = calloc(1, sizeof (Audit_list))) == NULL) 14767c478bd9Sstevel@tonic-gate return (audit_disable(ptr, clmp, ghp, 0)); 14777c478bd9Sstevel@tonic-gate 14787c478bd9Sstevel@tonic-gate alp->al_libname = NAME(lmp); 14797c478bd9Sstevel@tonic-gate alp->al_lmp = lmp; 14807c478bd9Sstevel@tonic-gate alp->al_ghp = ghp; 14817c478bd9Sstevel@tonic-gate 14827c478bd9Sstevel@tonic-gate /* 14837c478bd9Sstevel@tonic-gate * All audit libraries must handshake through la_version(). 14847c478bd9Sstevel@tonic-gate * Determine that the symbol exists, finish initializing the 14857c478bd9Sstevel@tonic-gate * object, and then call the function. 14867c478bd9Sstevel@tonic-gate */ 14879aa23310Srie if ((alp->al_version = (uint_t(*)())audit_symget(alp, 14889aa23310Srie AI_LAVERSION, in_nfavl)) == 0) { 14892020b2b6SRod Evans eprintf(lml, ERR_FATAL, MSG_INTL(MSG_GEN_NOSYM), 14907c478bd9Sstevel@tonic-gate MSG_ORIG(MSG_SYM_LAVERSION)); 14917c478bd9Sstevel@tonic-gate error = audit_disable(ptr, clmp, ghp, alp); 14927c478bd9Sstevel@tonic-gate continue; 14937c478bd9Sstevel@tonic-gate } 14947c478bd9Sstevel@tonic-gate 14952020b2b6SRod Evans if ((tobj = tsort(lmp, lml->lm_init, RT_SORT_REV)) == 14967c478bd9Sstevel@tonic-gate (Rt_map **)S_ERROR) 14977c478bd9Sstevel@tonic-gate return (audit_disable(ptr, clmp, ghp, alp)); 14987c478bd9Sstevel@tonic-gate 14992020b2b6SRod Evans if (tobj) 15007c478bd9Sstevel@tonic-gate call_init(tobj, DBG_INIT_SORT); 15017c478bd9Sstevel@tonic-gate 15022020b2b6SRod Evans APPLICATION_ENTER(rtldflags); 15032020b2b6SRod Evans leave(lml, thr_flg_reenter); 15042020b2b6SRod Evans alp->al_vernum = (*alp->al_version)(LAV_CURRENT); 15052020b2b6SRod Evans (void) enter(thr_flg_reenter); 15062020b2b6SRod Evans APPLICATION_RETURN(rtldflags); 15072020b2b6SRod Evans 15082020b2b6SRod Evans DBG_CALL(Dbg_audit_version(clml, alp->al_libname, 15092020b2b6SRod Evans LAV_CURRENT, alp->al_vernum)); 15107c478bd9Sstevel@tonic-gate 15117c478bd9Sstevel@tonic-gate if ((alp->al_vernum < LAV_VERSION1) || 15127c478bd9Sstevel@tonic-gate (alp->al_vernum > LAV_CURRENT)) { 15132020b2b6SRod Evans eprintf(lml, ERR_FATAL, MSG_INTL(MSG_AUD_BADVERS), 15147c478bd9Sstevel@tonic-gate LAV_CURRENT, alp->al_vernum); 15157c478bd9Sstevel@tonic-gate error = audit_disable(ptr, clmp, ghp, alp); 15167c478bd9Sstevel@tonic-gate continue; 15177c478bd9Sstevel@tonic-gate } 15187c478bd9Sstevel@tonic-gate 151957ef7aa9SRod Evans if (aplist_append(&(adp->ad_list), alp, 152057ef7aa9SRod Evans AL_CNT_AUDITORS) == NULL) 15217c478bd9Sstevel@tonic-gate return (audit_disable(ptr, clmp, ghp, alp)); 15227c478bd9Sstevel@tonic-gate 15237c478bd9Sstevel@tonic-gate adp->ad_cnt++; 15247c478bd9Sstevel@tonic-gate 15257c478bd9Sstevel@tonic-gate /* 15267c478bd9Sstevel@tonic-gate * Collect any remaining entry points. 15277c478bd9Sstevel@tonic-gate */ 15289aa23310Srie alp->al_objsearch = (char *(*)())audit_symget(alp, 15299aa23310Srie AI_LAOBJSEARCH, in_nfavl); 15309aa23310Srie alp->al_objopen = (uint_t(*)())audit_symget(alp, 15319aa23310Srie AI_LAOBJOPEN, in_nfavl); 15329aa23310Srie alp->al_objfilter = (int(*)())audit_symget(alp, 15339aa23310Srie AI_LAOBJFILTER, in_nfavl); 15349aa23310Srie alp->al_objclose = (uint_t(*)())audit_symget(alp, 15359aa23310Srie AI_LAOBJCLOSE, in_nfavl); 15369aa23310Srie alp->al_symbind = (uintptr_t(*)())audit_symget(alp, 15379aa23310Srie AI_LASYMBIND, in_nfavl); 15389aa23310Srie alp->al_pltenter = (uintptr_t(*)())audit_symget(alp, 15399aa23310Srie AI_LAPLTENTER, in_nfavl); 15409aa23310Srie alp->al_pltexit = (uintptr_t(*)())audit_symget(alp, 15419aa23310Srie AI_LAPLTEXIT, in_nfavl); 15427c478bd9Sstevel@tonic-gate 15432020b2b6SRod Evans if ((alp->al_preinit = (void(*)())audit_symget(alp, 15442020b2b6SRod Evans AI_LAPREINIT, in_nfavl)) != NULL) 15452020b2b6SRod Evans preinit++; 15462020b2b6SRod Evans if ((alp->al_activity = (void(*)())audit_symget(alp, 15472020b2b6SRod Evans AI_LAACTIVITY, in_nfavl)) != NULL) 15482020b2b6SRod Evans activity++; 15492020b2b6SRod Evans 15507c478bd9Sstevel@tonic-gate /* 15517c478bd9Sstevel@tonic-gate * Collect the individual object flags, and assign this audit 15527c478bd9Sstevel@tonic-gate * list descriptor to its associated link-map list. 15537c478bd9Sstevel@tonic-gate */ 15547c478bd9Sstevel@tonic-gate adp->ad_flags |= alp->al_flags; 15552020b2b6SRod Evans lml->lm_alp = alp; 155656d7adc6Srie } 15577c478bd9Sstevel@tonic-gate 15587c478bd9Sstevel@tonic-gate /* 15592020b2b6SRod Evans * If the caller isn't the head of its own link-map list, then any 15602020b2b6SRod Evans * preinit or activity entry points need to be tracked separately. 15612020b2b6SRod Evans * These "events" are not associated with a particular link-map, and 15622020b2b6SRod Evans * thus a traversal of any existing preinit and activity clients is 15632020b2b6SRod Evans * required. 15642020b2b6SRod Evans * 15652020b2b6SRod Evans * If either of these events are required, establish a cookie for the 15662020b2b6SRod Evans * object at the head of the link-map list, and make an initial ADD 15672020b2b6SRod Evans * activity for these local auditors. 15682020b2b6SRod Evans */ 15692020b2b6SRod Evans if ((preinit || activity) && ((hlmp = clml->lm_head) != clmp) && 15702020b2b6SRod Evans (_audit_add_head(clmp, hlmp, preinit, activity) == 0)) 15712020b2b6SRod Evans return (0); 15722020b2b6SRod Evans 15732020b2b6SRod Evans /* 15747c478bd9Sstevel@tonic-gate * Free the original audit string, as this descriptor may be used again 15757c478bd9Sstevel@tonic-gate * to add additional auditing. 15767c478bd9Sstevel@tonic-gate */ 15777c478bd9Sstevel@tonic-gate free(adp->ad_name); 157857ef7aa9SRod Evans adp->ad_name = NULL; 15797c478bd9Sstevel@tonic-gate 15807c478bd9Sstevel@tonic-gate return (error); 15817c478bd9Sstevel@tonic-gate } 1582