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