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