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, Version 1.0 only 6 * (the "License"). You may not use this file except in compliance 7 * with the License. 8 * 9 * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE 10 * or http://www.opensolaris.org/os/licensing. 11 * See the License for the specific language governing permissions 12 * and limitations under the License. 13 * 14 * When distributing Covered Code, include this CDDL HEADER in each 15 * file and include the License file at usr/src/OPENSOLARIS.LICENSE. 16 * If applicable, add the following below this CDDL HEADER, with the 17 * fields enclosed by brackets "[]" replaced with your own identifying 18 * information: Portions Copyright [yyyy] [name of copyright owner] 19 * 20 * CDDL HEADER END 21 */ 22 /* 23 * Copyright 2005 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(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(alp->al_libname, NAME(nlmp))); 277 278 leave(LIST(alp->al_lmp)); 279 flags = (*alp->al_objopen)((Link_map *)nlmp, lmid, 280 &(acp->ac_cookie)); 281 (void) enter(); 282 283 if (flags & LA_FLG_BINDTO) 284 acp->ac_flags |= FLG_AC_BINDTO; 285 286 if (flags & LA_FLG_BINDFROM) { 287 ulong_t pltcnt; 288 289 acp->ac_flags |= FLG_AC_BINDFROM; 290 /* 291 * We only need dynamic plt's if a pltenter and/or a 292 * pltexit() entry point exist in one of our auditing 293 * libraries. 294 */ 295 if (aip->ai_dynplts || (JMPREL(nlmp) == 0) || 296 ((audit_flags & (AF_PLTENTER | AF_PLTEXIT)) == 0)) 297 continue; 298 299 /* 300 * Create one dynplt for every 'PLT' that exists in the 301 * object. 302 */ 303 pltcnt = PLTRELSZ(nlmp) / RELENT(nlmp); 304 if ((aip->ai_dynplts = calloc(pltcnt, 305 dyn_plt_ent_size)) == 0) 306 return (0); 307 } 308 } 309 return (1); 310 } 311 312 int 313 audit_objopen(Rt_map * clmp, Rt_map * nlmp) 314 { 315 Lmid_t lmid = get_linkmap_id(LIST(nlmp)); 316 int appl = 0, respond = 1, ndx = 0; 317 uint_t clients = 0; 318 Audit_info * aip; 319 320 /* 321 * Determine the total number of audit libraries in use. This provides 322 * the number of client structures required for this object. 323 */ 324 if (auditors) 325 clients = auditors->ad_cnt; 326 if (AUDITORS(clmp)) 327 clients += AUDITORS(clmp)->ad_cnt; 328 if ((nlmp != clmp) && AUDITORS(nlmp)) 329 clients += AUDITORS(nlmp)->ad_cnt; 330 331 /* 332 * The initial allocation of the audit information structure includes 333 * an array of audit clients, 1 per audit library presently available. 334 * 335 * --------------- 336 * | ai_cnt | 337 * Audit_info | ai_clients |------- 338 * | ai_dynplts | | 339 * |---------------| | 340 * Audit_client | 1 |<------ 341 * |---------------| 342 * | 2 | 343 * ......... 344 */ 345 if ((AUDINFO(nlmp) = aip = calloc(1, sizeof (Audit_info) + 346 (sizeof (Audit_client) * clients))) == 0) 347 return (0); 348 349 aip->ai_cnt = clients; 350 aip->ai_clients = (Audit_client *)((uintptr_t)aip + 351 sizeof (Audit_info)); 352 353 if ((rtld_flags & RT_FL_APPLIC) == 0) 354 appl = rtld_flags |= RT_FL_APPLIC; 355 356 if (auditors) 357 respond = _audit_objopen(&(auditors->ad_list), nlmp, 358 lmid, aip, &ndx); 359 if (respond && AUDITORS(clmp)) 360 respond = _audit_objopen(&(AUDITORS(clmp)->ad_list), nlmp, 361 lmid, aip, &ndx); 362 if (respond && (nlmp != clmp) && AUDITORS(nlmp)) 363 respond = _audit_objopen(&(AUDITORS(nlmp)->ad_list), nlmp, 364 lmid, aip, &ndx); 365 366 if (appl) 367 rtld_flags &= ~RT_FL_APPLIC; 368 369 return (respond); 370 } 371 372 /* 373 * la_objclose() caller. Traverses through all audit library and calls any 374 * la_objclose() entry points found. 375 */ 376 void 377 _audit_objclose(List * list, Rt_map * lmp) 378 { 379 Audit_list * alp; 380 Listnode * lnp; 381 382 for (LIST_TRAVERSE(list, lnp, alp)) { 383 Audit_client * acp; 384 385 if (alp->al_objclose == 0) 386 continue; 387 if ((acp = _audit_client(AUDINFO(lmp), alp->al_lmp)) == 0) 388 continue; 389 390 leave(LIST(alp->al_lmp)); 391 (*alp->al_objclose)(&(acp->ac_cookie)); 392 (void) enter(); 393 } 394 } 395 396 void 397 audit_objclose(Rt_map * clmp, Rt_map * lmp) 398 { 399 int appl = 0; 400 401 if ((rtld_flags & RT_FL_APPLIC) == 0) 402 appl = rtld_flags |= RT_FL_APPLIC; 403 404 if (auditors && (auditors->ad_flags & LML_TFLG_AUD_OBJCLOSE)) 405 _audit_objclose(&(auditors->ad_list), lmp); 406 if (AUDITORS(clmp) && 407 (AUDITORS(clmp)->ad_flags & LML_TFLG_AUD_OBJCLOSE)) 408 _audit_objclose(&(AUDITORS(clmp)->ad_list), lmp); 409 410 if (appl) 411 rtld_flags &= ~RT_FL_APPLIC; 412 } 413 414 /* 415 * la_pltenter() caller. Traverses through all audit library and calls any 416 * la_pltenter() entry points found. NOTE: this routine is called via the 417 * glue code established in elf_plt_trace_write(), the symbol descriptor is 418 * created as part of the glue and for 32bit environments the st_name is a 419 * pointer to the real symbol name (ie. it's already been adjusted with the 420 * objects base offset). For 64bit environments the st_name remains the 421 * original symbol offset and in this case it is used to compute the real name 422 * pointer and pass as a separate argument to the auditor. 423 */ 424 static void 425 _audit_pltenter(List *list, Rt_map *rlmp, Rt_map *dlmp, Sym *sym, 426 uint_t ndx, void *regs, uint_t *flags) 427 { 428 Audit_list *alp; 429 Listnode *lnp; 430 #if defined(_ELF64) 431 const char *name = (const char *)(sym->st_name + STRTAB(dlmp)); 432 #else 433 const char *name = (const char *)(sym->st_name); 434 #endif 435 436 for (LIST_TRAVERSE(list, lnp, alp)) { 437 Audit_client *racp, *dacp; 438 Addr prev = sym->st_value; 439 440 if (alp->al_pltenter == 0) 441 continue; 442 if ((racp = _audit_client(AUDINFO(rlmp), alp->al_lmp)) == 0) 443 continue; 444 if ((dacp = _audit_client(AUDINFO(dlmp), alp->al_lmp)) == 0) 445 continue; 446 if (((racp->ac_flags & FLG_AC_BINDFROM) == 0) || 447 ((dacp->ac_flags & FLG_AC_BINDTO) == 0)) 448 continue; 449 450 leave(LIST(alp->al_lmp)); 451 sym->st_value = (Addr)(*alp->al_pltenter)(sym, ndx, 452 &(racp->ac_cookie), &(dacp->ac_cookie), regs, 453 #if defined(_ELF64) 454 flags, name); 455 #else 456 flags); 457 #endif 458 (void) enter(); 459 460 DBG_CALL(Dbg_audit_symval(alp->al_libname, 461 MSG_ORIG(MSG_AUD_PLTENTER), name, prev, sym->st_name)); 462 } 463 } 464 465 Addr 466 audit_pltenter(Rt_map *rlmp, Rt_map *dlmp, Sym *sym, uint_t ndx, 467 void *regs, uint_t *flags) 468 { 469 Sym _sym = *sym; 470 int _appl = 0; 471 472 /* 473 * We're effectively entering ld.so.1 from user (glue) code. 474 */ 475 (void) enter(); 476 if ((rtld_flags & RT_FL_APPLIC) == 0) 477 _appl = rtld_flags |= RT_FL_APPLIC; 478 479 if (auditors && (auditors->ad_flags & LML_TFLG_AUD_PLTENTER)) 480 _audit_pltenter(&(auditors->ad_list), rlmp, dlmp, &_sym, 481 ndx, regs, flags); 482 if (AUDITORS(rlmp) && 483 (AUDITORS(rlmp)->ad_flags & LML_TFLG_AUD_PLTENTER)) 484 _audit_pltenter(&(AUDITORS(rlmp)->ad_list), rlmp, dlmp, &_sym, 485 ndx, regs, flags); 486 487 if (_appl) 488 rtld_flags &= ~RT_FL_APPLIC; 489 leave(LIST(rlmp)); 490 491 return (_sym.st_value); 492 } 493 494 495 /* 496 * la_pltexit() caller. Traverses through all audit library and calls any 497 * la_pltexit() entry points found. See notes above (_audit_pltenter) for 498 * discussion on st_name. 499 */ 500 static Addr 501 _audit_pltexit(List *list, uintptr_t retval, Rt_map *rlmp, Rt_map *dlmp, 502 Sym *sym, uint_t ndx) 503 { 504 Audit_list *alp; 505 Listnode *lnp; 506 #if defined(_ELF64) 507 const char *name = (const char *)(sym->st_name + STRTAB(dlmp)); 508 #endif 509 510 for (LIST_TRAVERSE(list, lnp, alp)) { 511 Audit_client *racp, *dacp; 512 513 if (alp->al_pltexit == 0) 514 continue; 515 if ((racp = _audit_client(AUDINFO(rlmp), alp->al_lmp)) == 0) 516 continue; 517 if ((dacp = _audit_client(AUDINFO(dlmp), alp->al_lmp)) == 0) 518 continue; 519 if (((racp->ac_flags & FLG_AC_BINDFROM) == 0) || 520 ((dacp->ac_flags & FLG_AC_BINDTO) == 0)) 521 continue; 522 523 leave(LIST(alp->al_lmp)); 524 retval = (*alp->al_pltexit)(sym, ndx, 525 &(racp->ac_cookie), &(dacp->ac_cookie), 526 #if defined(_ELF64) 527 retval, name); 528 #else 529 retval); 530 #endif 531 (void) enter(); 532 } 533 return (retval); 534 } 535 536 Addr 537 audit_pltexit(uintptr_t retval, Rt_map *rlmp, Rt_map *dlmp, Sym *sym, 538 uint_t ndx) 539 { 540 uintptr_t _retval = retval; 541 int _appl = 0; 542 543 /* 544 * We're effectively entering ld.so.1 from user (glue) code. 545 */ 546 (void) enter(); 547 if ((rtld_flags & RT_FL_APPLIC) == 0) 548 _appl = rtld_flags |= RT_FL_APPLIC; 549 550 if (auditors && (auditors->ad_flags & LML_TFLG_AUD_PLTEXIT)) 551 _retval = _audit_pltexit(&(auditors->ad_list), _retval, 552 rlmp, dlmp, sym, ndx); 553 if (AUDITORS(rlmp) && (AUDITORS(rlmp)->ad_flags & LML_TFLG_AUD_PLTEXIT)) 554 _retval = _audit_pltexit(&(AUDITORS(rlmp)->ad_list), _retval, 555 rlmp, dlmp, sym, ndx); 556 557 if (_appl) 558 rtld_flags &= ~RT_FL_APPLIC; 559 leave(LIST(rlmp)); 560 561 return (_retval); 562 } 563 564 565 /* 566 * la_symbind() caller. Traverses through all audit library and calls any 567 * la_symbind() entry points found. 568 */ 569 static Addr 570 _audit_symbind(List *list, Rt_map *rlmp, Rt_map *dlmp, Sym *sym, uint_t ndx, 571 uint_t *flags, int *called) 572 { 573 Audit_list *alp; 574 Listnode *lnp; 575 #if defined(_ELF64) 576 const char *name = (const char *)(sym->st_name + STRTAB(dlmp)); 577 #else 578 const char *name = (const char *)(sym->st_name); 579 #endif 580 581 for (LIST_TRAVERSE(list, lnp, alp)) { 582 Audit_client *racp, *dacp; 583 Addr prev = sym->st_value; 584 uint_t lflags; 585 586 if (alp->al_symbind == 0) 587 continue; 588 if ((racp = _audit_client(AUDINFO(rlmp), alp->al_lmp)) == 0) 589 continue; 590 if ((dacp = _audit_client(AUDINFO(dlmp), alp->al_lmp)) == 0) 591 continue; 592 if (((racp->ac_flags & FLG_AC_BINDFROM) == 0) || 593 ((dacp->ac_flags & FLG_AC_BINDTO) == 0)) 594 continue; 595 596 /* 597 * The la_symbind interface is only called when the calling 598 * object has been identified as BINDFROM, and the destination 599 * object has been identified as BINDTO. Use a local version of 600 * the flags, so that any user update can be collected. 601 */ 602 called++; 603 lflags = (*flags & ~(LA_SYMB_NOPLTENTER | LA_SYMB_NOPLTEXIT)); 604 605 leave(LIST(alp->al_lmp)); 606 sym->st_value = (*alp->al_symbind)(sym, ndx, 607 &(racp->ac_cookie), &(dacp->ac_cookie), 608 #if defined(_ELF64) 609 &lflags, name); 610 #else 611 &lflags); 612 #endif 613 (void) enter(); 614 615 /* 616 * If the auditor indicated that they did not want to process 617 * pltenter, or pltexit audits for this symbol, retain this 618 * information. Also retain whether an alternative symbol value 619 * has been supplied. 620 */ 621 *flags |= (lflags & (LA_SYMB_NOPLTENTER | LA_SYMB_NOPLTEXIT)); 622 if ((prev != sym->st_value) && (alp->al_vernum >= LAV_VERSION2)) 623 *flags |= LA_SYMB_ALTVALUE; 624 625 DBG_CALL(Dbg_audit_symval(alp->al_libname, 626 MSG_ORIG(MSG_AUD_SYMBIND), name, prev, sym->st_value)); 627 } 628 return (sym->st_value); 629 } 630 631 Addr 632 audit_symbind(Rt_map *rlmp, Rt_map *dlmp, Sym *sym, uint_t ndx, Addr value, 633 uint_t *flags) 634 { 635 Sym _sym; 636 int _appl = 0, called = 0; 637 638 /* 639 * Construct a new symbol from that supplied but with the real address. 640 * In the 64-bit world the st_name field is only 32-bits which isn't 641 * big enough to hold a character pointer. We pass this pointer as a 642 * separate parameter for 64-bit audit libraries. 643 */ 644 _sym = *sym; 645 _sym.st_value = value; 646 647 #if !defined(_ELF64) 648 _sym.st_name += (Word)STRTAB(dlmp); 649 #endif 650 if ((rtld_flags & RT_FL_APPLIC) == 0) 651 _appl = rtld_flags |= RT_FL_APPLIC; 652 653 if (auditors && (auditors->ad_flags & LML_TFLG_AUD_SYMBIND)) 654 _sym.st_value = _audit_symbind(&(auditors->ad_list), 655 rlmp, dlmp, &_sym, ndx, flags, &called); 656 if (AUDITORS(rlmp) && (AUDITORS(rlmp)->ad_flags & LML_TFLG_AUD_SYMBIND)) 657 _sym.st_value = _audit_symbind(&(AUDITORS(rlmp)->ad_list), 658 rlmp, dlmp, &_sym, ndx, flags, &called); 659 660 /* 661 * If no la_symbind() was called for this interface, fabricate that no 662 * la_pltenter, or la_pltexit is required. This helps reduce the glue 663 * code created for further auditing. 664 */ 665 if (caller == 0) 666 *flags |= (LA_SYMB_NOPLTENTER | LA_SYMB_NOPLTEXIT); 667 668 if (_appl) 669 rtld_flags &= ~RT_FL_APPLIC; 670 671 return (_sym.st_value); 672 } 673 674 675 /* 676 * la_preinit() caller. Traverses through all audit libraries and calls any 677 * la_preinit() entry points found. 678 */ 679 static void 680 _audit_preinit(List *list, Rt_map *clmp) 681 { 682 Audit_list *alp; 683 Listnode *lnp; 684 685 for (LIST_TRAVERSE(list, lnp, alp)) { 686 Audit_client *acp; 687 688 if (alp->al_preinit == 0) 689 continue; 690 if ((acp = _audit_client(AUDINFO(clmp), alp->al_lmp)) == 0) 691 continue; 692 693 leave(LIST(alp->al_lmp)); 694 (*alp->al_preinit)(&(acp->ac_cookie)); 695 (void) enter(); 696 } 697 } 698 699 void 700 audit_preinit(Rt_map *clmp) 701 { 702 int appl = 0; 703 704 if ((rtld_flags & RT_FL_APPLIC) == 0) 705 appl = rtld_flags |= RT_FL_APPLIC; 706 707 if (auditors && (auditors->ad_flags & LML_TFLG_AUD_PREINIT)) 708 _audit_preinit(&(auditors->ad_list), clmp); 709 if (AUDITORS(clmp) && (AUDITORS(clmp)->ad_flags & LML_TFLG_AUD_PREINIT)) 710 _audit_preinit(&(AUDITORS(clmp)->ad_list), clmp); 711 712 if (appl) 713 rtld_flags &= ~RT_FL_APPLIC; 714 } 715 716 717 /* 718 * Clean up (free) an audit descriptor. First, gather a list of all handles, 719 * and then close each one down. This is done rather than using the handles 720 * directly from the auditors, as the audit list can be torn down as a result 721 * of the dlclose. In other words, what you're pointing at can be removed 722 * while your still pointing at it. 723 */ 724 void 725 audit_desc_cleanup(Audit_desc *adp, Rt_map *clmp) 726 { 727 Audit_list *alp; 728 Listnode *lnp, *olnp; 729 Alist *ghalp = 0; 730 731 if (adp == 0) 732 return; 733 if (adp->ad_name) 734 free(adp->ad_name); 735 736 olnp = 0; 737 for (LIST_TRAVERSE(&(adp->ad_list), lnp, alp)) { 738 (void) alist_append(&ghalp, &(alp->al_ghp), sizeof (Grp_hdl *), 739 AL_CNT_GROUPS); 740 741 if (olnp) 742 free(olnp); 743 olnp = lnp; 744 } 745 if (olnp) 746 free(olnp); 747 748 if (ghalp) { 749 Grp_hdl ** ghpp; 750 Aliste off; 751 752 for (ALIST_TRAVERSE(ghalp, off, ghpp)) 753 (void) dlclose_intn(*ghpp, clmp); 754 free(ghalp); 755 } 756 free(adp); 757 } 758 759 /* 760 * Clean up (free) an audit information structure. 761 */ 762 void 763 audit_info_cleanup(Audit_info *aip) 764 { 765 if (aip == 0) 766 return; 767 768 if (aip->ai_dynplts) 769 free(aip->ai_dynplts); 770 free(aip); 771 } 772 773 /* 774 * Create a data structure of symbol lookup names and associated flags to help 775 * simplify audit_symget() use. 776 */ 777 typedef struct { 778 Msg sname; 779 uint_t alflag; 780 uint_t auflag; 781 } Aud_info; 782 783 static const Aud_info aud_info[] = { 784 { MSG_SYM_LAVERSION, 0 }, /* MSG_ORIG(MSG_SYM_LAVERSION) */ 785 { MSG_SYM_LAPREINIT, /* MSG_ORIG(MSG_SYM_LAPREINIT) */ 786 LML_TFLG_AUD_PREINIT, 0 }, 787 { MSG_SYM_LAOBJSEARCH, /* MSG_ORIG(MSG_SYM_LAOBJSEARCH) */ 788 LML_TFLG_AUD_OBJSEARCH, 0 }, 789 { MSG_SYM_LAOBJOPEN, /* MSG_ORIG(MSG_SYM_LAOBJOPEN) */ 790 LML_TFLG_AUD_OBJOPEN, 0 }, 791 { MSG_SYM_LAOBJFILTER, /* MSG_ORIG(MSG_SYM_LAOBJFILTER */ 792 LML_TFLG_AUD_OBJFILTER, 0 }, 793 { MSG_SYM_LAOBJCLOSE, /* MSG_ORIG(MSG_SYM_LAOBJCLOSE) */ 794 LML_TFLG_AUD_OBJCLOSE, 0 }, 795 { MSG_SYM_LAACTIVITY, /* MSG_ORIG(MSG_SYM_LAACTIVITY) */ 796 LML_TFLG_AUD_ACTIVITY, 0 }, 797 798 #if defined(_ELF64) 799 { MSG_SYM_LASYMBIND_64, /* MSG_ORIG(MSG_SYM_LASYMBIND_64) */ 800 #else 801 { MSG_SYM_LASYMBIND, /* MSG_ORIG(MSG_SYM_LASYMBIND) */ 802 #endif 803 LML_TFLG_AUD_SYMBIND, 0 }, 804 805 #if defined(__sparcv9) 806 { MSG_SYM_LAV9PLTENTER, /* MSG_ORIG(MSG_SYM_LAV9PLTENTER) */ 807 #elif defined(__sparc) 808 { MSG_SYM_LAV8PLTENTER, /* MSG_ORIG(MSG_SYM_LAV8PLTENTER) */ 809 #elif defined(__amd64) 810 { MSG_SYM_LAAMD64PLTENTER, /* MSG_ORIG(MSG_SYM_LAAMD64PLTENTER) */ 811 #elif defined(i386) 812 { MSG_SYM_LAX86PLTENTER, /* MSG_ORIG(MSG_SYM_LAX86PLTENTER) */ 813 #else 814 #error platform not defined! 815 #endif 816 LML_TFLG_AUD_PLTENTER, AF_PLTENTER }, 817 818 #if defined(_ELF64) 819 { MSG_SYM_LAPLTEXIT_64, /* MSG_ORIG(MSG_SYM_LAPLTEXIT_64) */ 820 #else 821 { MSG_SYM_LAPLTEXIT, /* MSG_ORIG(MSG_SYM_LAPLTEXIT) */ 822 #endif 823 LML_TFLG_AUD_PLTEXIT, AF_PLTEXIT } 824 }; 825 826 #define AI_LAVERSION 0 827 #define AI_LAPREINIT 1 828 #define AI_LAOBJSEARCH 2 829 #define AI_LAOBJOPEN 3 830 #define AI_LAOBJFILTER 4 831 #define AI_LAOBJCLOSE 5 832 #define AI_LAACTIVITY 6 833 #define AI_LASYMBIND 7 834 #define AI_LAPLTENTER 8 835 #define AI_LAPLTEXIT 9 836 837 static Addr 838 audit_symget(Audit_list * alp, int info) 839 { 840 Rt_map *_lmp, *lmp = alp->al_lmp; 841 const char *sname = MSG_ORIG(aud_info[info].sname); 842 uint_t alflag = aud_info[info].alflag; 843 uint_t auflag = aud_info[info].auflag; 844 uint_t binfo; 845 Sym *sym; 846 Slookup sl; 847 848 sl.sl_name = sname; 849 sl.sl_cmap = lml_rtld.lm_head; 850 sl.sl_imap = lmp; 851 sl.sl_hash = 0; 852 sl.sl_rsymndx = 0; 853 sl.sl_flags = LKUP_FIRST; 854 855 if (sym = LM_LOOKUP_SYM(lmp)(&sl, &_lmp, &binfo)) { 856 Addr addr = sym->st_value; 857 858 if (!(FLAGS(lmp) & FLG_RT_FIXED)) 859 addr += ADDR(lmp); 860 861 if (alflag) 862 alp->al_flags |= alflag; 863 if (auflag) 864 audit_flags |= auflag; 865 866 DBG_CALL(Dbg_audit_interface(alp->al_libname, sname)); 867 return (addr); 868 } else 869 return (0); 870 } 871 872 /* 873 * Centralize cleanup routines. 874 */ 875 static int 876 audit_disable(char *name, Rt_map *clmp, Grp_hdl *ghp, Audit_list *alp) 877 { 878 eprintf(ERR_FATAL, MSG_INTL(MSG_AUD_DISABLED), name); 879 if (ghp) 880 (void) dlclose_intn(ghp, clmp); 881 if (alp) 882 free(alp); 883 884 return (0); 885 } 886 887 /* 888 * Given a list of one or more audit libraries, open each one and establish a 889 * a descriptor representing the entry points it provides. 890 */ 891 int 892 audit_setup(Rt_map *clmp, Audit_desc *adp, uint_t orig) 893 { 894 char *ptr, *next; 895 int error = 1; 896 897 DBG_CALL(Dbg_audit_lib(adp->ad_name)); 898 899 /* 900 * Mark that we have at least one auditing link map 901 */ 902 rtld_flags2 |= RT_FL2_HASAUDIT; 903 904 /* 905 * The audit definitions may be a list (which will already have been 906 * dupped) so split it into individual tokens. 907 */ 908 for (ptr = strtok_r(adp->ad_name, MSG_ORIG(MSG_STR_DELIMIT), &next); 909 ptr; ptr = strtok_r(NULL, MSG_ORIG(MSG_STR_DELIMIT), &next)) { 910 Grp_hdl *ghp; 911 Rt_map *lmp; 912 Rt_map **tobj; 913 Audit_list *alp; 914 915 /* 916 * Open the audit library on its own link-map. 917 */ 918 if ((ghp = dlmopen_intn((Lm_list *)LM_ID_NEWLM, ptr, 919 (RTLD_FIRST | RTLD_GLOBAL | RTLD_WORLD), clmp, 920 FLG_RT_AUDIT, orig, 0)) == 0) { 921 error = audit_disable(ptr, clmp, 0, 0); 922 continue; 923 } 924 lmp = ghp->gh_owner; 925 926 /* 927 * If this auditor has already been loaded, reuse it. 928 */ 929 if ((alp = LIST(lmp)->lm_alp) != 0) { 930 if (list_append(&(adp->ad_list), alp) == 0) 931 return (audit_disable(ptr, clmp, ghp, alp)); 932 933 adp->ad_cnt++; 934 DBG_CALL(Dbg_audit_version(alp->al_libname, 935 alp->al_vernum)); 936 adp->ad_flags |= alp->al_flags; 937 continue; 938 } 939 940 /* 941 * If we are not running in the environment where 942 * libc/libthread are merged, we hold on to rtld lock 943 * upon leave() function. 944 * 945 * There is a possibility that libc is not mapped in yet. 946 * We may later find out that we will be running in 947 * libc/libthread merged enviornment. Refer to: 948 * get_lcinterface() in mutex.c. 949 */ 950 if ((rtld_flags2 & RT_FL2_UNIFPROC) == 0) 951 LIST(lmp)->lm_flags |= LML_FLG_HOLDLOCK; 952 953 /* 954 * Allocate an audit list descriptor for this object and 955 * search for all known entry points. 956 */ 957 if ((alp = calloc(1, sizeof (Audit_list))) == 0) 958 return (audit_disable(ptr, clmp, ghp, 0)); 959 960 alp->al_libname = NAME(lmp); 961 alp->al_lmp = lmp; 962 alp->al_ghp = ghp; 963 964 /* 965 * All audit libraries must handshake through la_version(). 966 * Determine that the symbol exists, finish initializing the 967 * object, and then call the function. 968 */ 969 if ((alp->al_version = 970 (uint_t(*)())audit_symget(alp, AI_LAVERSION)) == 0) { 971 eprintf(ERR_FATAL, MSG_INTL(MSG_GEN_NOSYM), 972 MSG_ORIG(MSG_SYM_LAVERSION)); 973 error = audit_disable(ptr, clmp, ghp, alp); 974 continue; 975 } 976 977 if ((tobj = tsort(lmp, LIST(lmp)->lm_init, RT_SORT_REV)) == 978 (Rt_map **)S_ERROR) 979 return (audit_disable(ptr, clmp, ghp, alp)); 980 981 rtld_flags |= RT_FL_APPLIC; 982 if (tobj != (Rt_map **)NULL) 983 call_init(tobj, DBG_INIT_SORT); 984 985 alp->al_vernum = alp->al_version(LAV_CURRENT); 986 rtld_flags &= ~RT_FL_APPLIC; 987 988 if ((alp->al_vernum < LAV_VERSION1) || 989 (alp->al_vernum > LAV_CURRENT)) { 990 eprintf(ERR_FATAL, MSG_INTL(MSG_AUD_BADVERS), 991 LAV_CURRENT, alp->al_vernum); 992 error = audit_disable(ptr, clmp, ghp, alp); 993 continue; 994 } 995 996 if (list_append(&(adp->ad_list), alp) == 0) 997 return (audit_disable(ptr, clmp, ghp, alp)); 998 999 adp->ad_cnt++; 1000 DBG_CALL(Dbg_audit_version(alp->al_libname, alp->al_vernum)); 1001 1002 /* 1003 * Collect any remaining entry points. 1004 */ 1005 alp->al_preinit = 1006 (void(*)())audit_symget(alp, AI_LAPREINIT); 1007 alp->al_objsearch = 1008 (char *(*)())audit_symget(alp, AI_LAOBJSEARCH); 1009 alp->al_objopen = 1010 (uint_t(*)())audit_symget(alp, AI_LAOBJOPEN); 1011 alp->al_objfilter = 1012 (int(*)())audit_symget(alp, AI_LAOBJFILTER); 1013 alp->al_objclose = 1014 (uint_t(*)())audit_symget(alp, AI_LAOBJCLOSE); 1015 alp->al_activity = 1016 (void (*)())audit_symget(alp, AI_LAACTIVITY); 1017 alp->al_symbind = 1018 (uintptr_t(*)())audit_symget(alp, AI_LASYMBIND); 1019 alp->al_pltenter = 1020 (uintptr_t(*)())audit_symget(alp, AI_LAPLTENTER); 1021 alp->al_pltexit = 1022 (uintptr_t(*)())audit_symget(alp, AI_LAPLTEXIT); 1023 1024 /* 1025 * Collect the individual object flags, and assign this audit 1026 * list descriptor to its associated link-map list. 1027 */ 1028 adp->ad_flags |= alp->al_flags; 1029 LIST(lmp)->lm_alp = alp; 1030 } 1031 1032 /* 1033 * Free the original audit string, as this descriptor may be used again 1034 * to add additional auditing. 1035 */ 1036 free(adp->ad_name); 1037 adp->ad_name = 0; 1038 1039 return (error); 1040 } 1041