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