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