1 /* 2 * CDDL HEADER START 3 * 4 * The contents of this file are subject to the terms of the 5 * Common Development and Distribution License, Version 1.0 only 6 * (the "License"). You may not use this file except in compliance 7 * with the License. 8 * 9 * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE 10 * or http://www.opensolaris.org/os/licensing. 11 * See the License for the specific language governing permissions 12 * and limitations under the License. 13 * 14 * When distributing Covered Code, include this CDDL HEADER in each 15 * file and include the License file at usr/src/OPENSOLARIS.LICENSE. 16 * If applicable, add the following below this CDDL HEADER, with the 17 * fields enclosed by brackets "[]" replaced with your own identifying 18 * information: Portions Copyright [yyyy] [name of copyright owner] 19 * 20 * CDDL HEADER END 21 */ 22 /* 23 * Copyright 2005 Sun Microsystems, Inc. All rights reserved. 24 * Use is subject to license terms. 25 * 26 * Remove objects. Objects need removal from a process as part of: 27 * 28 * o a dlclose() request 29 * 30 * o tearing down a dlopen(), lazy-load, or filter hierarchy that failed to 31 * completely load 32 * 33 * Any other failure condition will result in process exit (in which case all 34 * we have to do is execute the fini's - tear down is unnecessary). 35 * 36 * Any removal of objects is therefore associated with a dlopen() handle. There 37 * is a small window between creation of the first dlopen() object and creating 38 * its handle (in which case remove_so() can get rid of the new link-map if 39 * necessary), but other than this all object removal is driven by inspecting 40 * the components of a handle. 41 * 42 * Things to note. The creation of a link-map, and its addition to the link-map 43 * list occurs in {elf|aout}_new_lm(), if this returns success the link-map is 44 * valid and added, otherwise any steps (allocations) in the process of creating 45 * the link-map would have been undone. If a failure occurs between creating 46 * the link-map and adding it to a handle, remove_so() is called to remove the 47 * link-map. If a failures occurs after a handle have been created, 48 * remove_hdl() is called to remove the handle and the link-map. 49 */ 50 #pragma ident "%Z%%M% %I% %E% SMI" 51 52 #include "_synonyms.h" 53 54 #include <string.h> 55 #include <stdio.h> 56 #include <unistd.h> 57 #include <dlfcn.h> 58 #include <sys/debug.h> 59 #include <sys/avl.h> 60 #include "libc_int.h" 61 #include "_rtld.h" 62 #include "_audit.h" 63 #include "_elf.h" 64 #include "debug.h" 65 #include "msg.h" 66 67 /* 68 * Atexit callback provided by libc. As part of dlclose() determine the address 69 * ranges of all objects that are to be deleted. Pass this information to 70 * libc's pre-atexit routine. Libc will purge any registered atexit() calls 71 * related to those objects about to be deleted. 72 */ 73 static int 74 purge_exit_handlers(Lm_list *lml, Rt_map **tobj) 75 { 76 uint_t num; 77 Rt_map **_tobj; 78 Lc_addr_range_t *addr, *_addr; 79 int error; 80 81 /* 82 * Has a callback been established? 83 */ 84 if (lml->lm_peh == 0) 85 return (0); 86 87 /* 88 * Determine the total number of mapped segments that will be unloaded. 89 */ 90 for (num = 0, _tobj = tobj; *_tobj != NULL; _tobj++) { 91 Rt_map * lmp = *_tobj; 92 93 num += MMAPCNT(lmp); 94 } 95 96 /* 97 * Account for a null entry at the end of the address range array. 98 */ 99 if (num++ == 0) 100 return (0); 101 102 /* 103 * Allocate an array for the address range. 104 */ 105 if ((addr = malloc(num * sizeof (Lc_addr_range_t))) == 0) 106 return (1); 107 108 /* 109 * Fill the address range with each loadable segments size and address. 110 */ 111 for (_tobj = tobj, _addr = addr; *_tobj != NULL; _tobj++) { 112 Rt_map *lmp = *_tobj; 113 Mmap *mmaps; 114 115 for (mmaps = MMAPS(lmp); mmaps->m_vaddr; mmaps++) { 116 _addr->lb = (void *)mmaps->m_vaddr; 117 _addr->ub = (void *)(mmaps->m_vaddr + mmaps->m_msize); 118 _addr++; 119 } 120 } 121 _addr->lb = _addr->ub = 0; 122 123 leave(LIST(*tobj)); 124 125 error = (* lml->lm_peh)(addr, (num - 1)); 126 127 (void) enter(); 128 129 /* 130 * If we fail to converse with libc, generate an error message to 131 * satisfy any dlerror() usage. 132 */ 133 if (error) 134 eprintf(ERR_FATAL, MSG_INTL(MSG_ARG_ATEXIT), error); 135 136 free(addr); 137 return (error); 138 } 139 140 /* 141 * Remove any rejection message allocations. 142 */ 143 void 144 remove_rej(Rej_desc * rej) 145 { 146 if (rej && (rej->rej_type)) { 147 if (rej->rej_name) 148 free((void *)rej->rej_name); 149 if (rej->rej_str && (rej->rej_str != MSG_ORIG(MSG_EMG_ENOMEM))) 150 free((void *)rej->rej_str); 151 } 152 } 153 154 /* 155 * Break down a Pnode list. 156 */ 157 void 158 remove_pnode(Pnode * pnp) 159 { 160 Pnode * opnp; 161 162 for (opnp = 0; pnp; opnp = pnp, pnp = pnp->p_next) { 163 if (pnp->p_name) 164 free((void *)pnp->p_name); 165 if (pnp->p_oname) 166 free((void *)pnp->p_oname); 167 if (opnp) 168 free((void *)opnp); 169 } 170 if (opnp) 171 free((void *)opnp); 172 } 173 174 175 /* 176 * Remove a link-map list descriptor. This is called to finalize the removal 177 * of an entire link-map list, after all link-maps have been removed, or none 178 * got added. As load_one() can process a list of potential candidates objects, 179 * the link-map descriptor must be maintained as each object is processed. Only 180 * after all objects have been processed can a failure condition finally tear 181 * down the link-map list descriptor. 182 */ 183 void 184 remove_lml(Lm_list *lml) 185 { 186 if (lml && (lml->lm_head == 0)) { 187 if (lml->lm_alp) 188 free(lml->lm_alp); 189 if (lml->lm_lists) 190 free(lml->lm_lists); 191 192 /* 193 * Cleanup rtldinfo in the case where it was allocated but 194 * not called (see _relocate_so()). 195 */ 196 if (lml->lm_rtldinfo) 197 free(lml->lm_rtldinfo); 198 if (lml->lm_fpavl) { 199 /* 200 * As we are freeing the link-map list, all nodes must 201 * have previously been removed. 202 */ 203 ASSERT(avl_numnodes(lml->lm_fpavl) == 0); 204 free(lml->lm_fpavl); 205 } 206 list_delete(&dynlm_list, lml); 207 free(lml); 208 } 209 } 210 211 /* 212 * Remove a link-map. This removes a link-map from its associated list and 213 * free's up the link-map itself. Note, all components that are freed are local 214 * to the link-map, no inter-link-map lists are operated on as these are all 215 * broken down by dlclose() while all objects are still mapped. 216 * 217 * This routine is called from dlclose() to zap individual link-maps after their 218 * interdependencies (DEPENDS(), CALLER(), handles, etc.) have been removed. 219 * This routine is also called from the bowels of load_one() in the case of a 220 * link-map creation failure. 221 */ 222 void 223 remove_so(Lm_list *lml, Rt_map *lmp) 224 { 225 Dyninfo *dip; 226 227 if (lmp == 0) 228 return; 229 230 /* 231 * Unlink the link map from the link-map list. 232 */ 233 if (lml && lmp) 234 lm_delete(lml, lmp); 235 236 /* 237 * If this object contributed the preexec_exit_handler() routine for 238 * the current link-map list, mark the list as no-longer containing a 239 * preexec_exit_handler() routine. 240 */ 241 if (lml && (lml->lm_peh_lmp == lmp)) { 242 lml->lm_peh = 0; 243 lml->lm_peh_lmp = 0; 244 } 245 246 DBG_CALL(Dbg_file_delete(NAME(lmp))); 247 248 /* 249 * Unmap the object. 250 */ 251 LM_UNMAP_SO(lmp)(lmp); 252 253 /* 254 * Remove any FullpathNode AVL names if they still exist. 255 */ 256 if (FPNODE(lmp)) 257 fpavl_remove(lmp); 258 259 /* 260 * Remove any alias names. 261 */ 262 if (ALIAS(lmp)) { 263 Aliste off; 264 char ** cpp; 265 266 for (ALIST_TRAVERSE(ALIAS(lmp), off, cpp)) 267 free(*cpp); 268 free(ALIAS(lmp)); 269 } 270 271 /* 272 * Free the various names, as these were duplicated so that they were 273 * available in core files. 274 * The original name is set to the pathname by default (see fullpath()), 275 * but is overridden if the file is an alternative. The pathname is set 276 * to the name by default (see [aout|elf]_new_lm()), but is overridden 277 * if the fullpath/resolve path differs (see fullpath()). The original 278 * name is always duplicated, as it typically exists as a text string 279 * (see DT_NEEDED pointer) or was passed in from user code. 280 */ 281 if (ORIGNAME(lmp) != PATHNAME(lmp)) 282 free(ORIGNAME(lmp)); 283 if (PATHNAME(lmp) != NAME(lmp)) 284 free(PATHNAME(lmp)); 285 free(NAME(lmp)); 286 287 /* 288 * Remove any of this objects filtee infrastructure. The filtees them- 289 * selves have already been removed. 290 */ 291 if (((dip = DYNINFO(lmp)) != 0) && (FLAGS1(lmp) & MSK_RT_FILTER)) { 292 uint_t cnt, max = DYNINFOCNT(lmp); 293 294 for (cnt = 0; cnt < max; cnt++, dip++) { 295 if (dip->di_info && (dip->di_flags & MSK_DI_FILTER)) 296 remove_pnode((Pnode *)dip->di_info); 297 } 298 } 299 if (dip) 300 free(DYNINFO(lmp)); 301 302 /* 303 * Deallocate any remaining cruft and free the link-map. 304 */ 305 if (RLIST(lmp)) 306 remove_pnode(RLIST(lmp)); 307 308 if (REFNAME(lmp)) 309 free(REFNAME(lmp)); 310 if (ELFPRV(lmp)) 311 free(ELFPRV(lmp)); 312 if (AUDITORS(lmp)) 313 audit_desc_cleanup(AUDITORS(lmp), lmp); 314 if (AUDINFO(lmp)) 315 audit_info_cleanup(AUDINFO(lmp)); 316 317 if (CONDVAR(lmp)) 318 free(CONDVAR(lmp)); 319 if (COPY(lmp)) 320 free(COPY(lmp)); 321 if (MMAPS(lmp)) 322 free(MMAPS(lmp)); 323 324 /* 325 * During a dlclose() any groups this object was a part of will have 326 * been torn down. However, we can get here to remove an object that 327 * has failed to load, perhaps because its addition to a handle failed. 328 * Therefore if this object indicates that its part of a group tear 329 * these associations down. 330 */ 331 if (GROUPS(lmp)) { 332 Aliste off1; 333 Grp_hdl ** ghpp; 334 335 for (ALIST_TRAVERSE(GROUPS(lmp), off1, ghpp)) { 336 Grp_hdl * ghp = *ghpp; 337 Grp_desc * gdp; 338 Aliste off2; 339 340 for (ALIST_TRAVERSE(ghp->gh_depends, off2, gdp)) { 341 if (gdp->gd_depend != lmp) 342 continue; 343 344 (void) alist_delete(ghp->gh_depends, 0, &off2); 345 break; 346 } 347 } 348 free(GROUPS(lmp)); 349 } 350 if (HANDLES(lmp)) 351 free(HANDLES(lmp)); 352 353 /* 354 * Clean up reglist if needed 355 */ 356 if (reglist != (Reglist *)0) { 357 Reglist * cur, * prv, * del; 358 359 cur = prv = reglist; 360 while (cur != (Reglist *)0) { 361 if (cur->rl_lmp == lmp) { 362 del = cur; 363 if (cur == reglist) { 364 reglist = cur->rl_next; 365 cur = prv = reglist; 366 } else { 367 prv->rl_next = cur->rl_next; 368 cur = cur->rl_next; 369 } 370 free(del); 371 } else { 372 prv = cur; 373 cur = cur->rl_next; 374 } 375 } 376 } 377 378 free(lmp); 379 } 380 381 382 /* 383 * Traverse an objects dependency list removing callers and dependencies. 384 * There's a chicken and egg problem with tearing down link-maps. Any 385 * relationship between link-maps is maintained on a DEPENDS, and associated 386 * CALLERS list. These lists can't be broken down at the time a single link- 387 * map is removed as any related link-map may have already been removed. Thus, 388 * lists between link-maps must be broken down before the individual link-maps 389 * themselves. 390 */ 391 void 392 remove_lists(Rt_map * lmp, int lazy) 393 { 394 Aliste off1; 395 Bnd_desc ** bdpp; 396 397 /* 398 * First, traverse this objects dependencies. 399 */ 400 for (ALIST_TRAVERSE(DEPENDS(lmp), off1, bdpp)) { 401 Bnd_desc * bdp = *bdpp; 402 Rt_map * dlmp = bdp->b_depend; 403 404 /* 405 * Remove this object from the dependencies callers. 406 */ 407 (void) alist_delete(CALLERS(dlmp), &bdp, 0); 408 free(bdp); 409 } 410 if (DEPENDS(lmp)) { 411 free(DEPENDS(lmp)); 412 DEPENDS(lmp) = 0; 413 } 414 415 /* 416 * Second, traverse this objects callers. 417 */ 418 for (ALIST_TRAVERSE(CALLERS(lmp), off1, bdpp)) { 419 Bnd_desc * bdp = *bdpp; 420 Rt_map * clmp = bdp->b_caller; 421 422 /* 423 * If we're removing an object that was triggered by a lazyload, 424 * remove the callers DYNINFO() entry and bump the lazy counts. 425 * This reinitialization of the lazy information allows a lazy 426 * object to be reloaded again later. Although we may be 427 * breaking down a group of lazyloaded objects because one has 428 * failed to relocate, it's possible that one or more of the 429 * individual objects can be reloaded without a problem. 430 */ 431 if (lazy) { 432 Dyninfo * dip; 433 434 if ((dip = DYNINFO(clmp)) != 0) { 435 uint_t cnt, max = DYNINFOCNT(clmp); 436 437 for (cnt = 0; cnt < max; cnt++, dip++) { 438 if ((dip->di_flags & 439 FLG_DI_NEEDED) == 0) 440 continue; 441 442 if (dip->di_info == (void *)lmp) { 443 dip->di_info = 0; 444 445 if (LAZY(clmp)++ == 0) 446 LIST(clmp)->lm_lazy++; 447 } 448 } 449 } 450 } 451 452 (void) alist_delete(DEPENDS(clmp), &bdp, 0); 453 free(bdp); 454 } 455 if (CALLERS(lmp)) { 456 free(CALLERS(lmp)); 457 CALLERS(lmp) = 0; 458 } 459 } 460 461 /* 462 * Delete any temporary link-map control list. 463 */ 464 void 465 remove_cntl(Lm_list *lml, Aliste lmco) 466 { 467 if (lmco && (lmco != ALO_DATA)) { 468 Aliste _lmco = lmco; 469 #if DEBUG 470 Lm_cntl *lmc = (Lm_cntl *)((char *)lml->lm_lists + lmco); 471 472 /* 473 * This element should be empty. 474 */ 475 ASSERT(lmc->lc_head == 0); 476 #endif 477 (void) alist_delete(lml->lm_lists, 0, &_lmco); 478 } 479 } 480 481 /* 482 * If a lazy loaded object, or filtee fails to load, possibly because it, or 483 * one of its dependencies can't be relocated, then tear down any objects 484 * that are apart of this link-map control list. 485 */ 486 void 487 remove_incomplete(Lm_list *lml, Aliste lmco) 488 { 489 Rt_map *lmp; 490 Lm_cntl *lmc; 491 492 /* LINTED */ 493 lmc = (Lm_cntl *)((char *)lml->lm_lists + lmco); 494 495 /* 496 * First, remove any lists that may point between objects. 497 */ 498 for (lmp = lmc->lc_head; lmp; lmp = (Rt_map *)NEXT(lmp)) 499 remove_lists(lmp, 1); 500 501 /* 502 * Finally, remove each object. remove_so() calls lm_delete(), thus 503 * effectively the link-map control head gets updated to point to the 504 * next link-map. 505 */ 506 while ((lmp = lmc->lc_head) != 0) 507 remove_so(lml, lmp); 508 509 lmc->lc_head = lmc->lc_tail = 0; 510 } 511 512 /* 513 * Determine whether an object is deletable. 514 */ 515 int 516 is_deletable(Alist ** lmalp, Alist ** ghalp, Rt_map * lmp) 517 { 518 Aliste off; 519 Bnd_desc ** bdpp; 520 Grp_hdl ** ghpp; 521 522 /* 523 * If the object hasn't yet been relocated take this as a sign that 524 * it's loading failed, thus we're here to cleanup. If the object is 525 * relocated it will only be retained if it was marked non-deletable, 526 * and exists on the main link-map control list. 527 */ 528 if ((FLAGS(lmp) & FLG_RT_RELOCED) && 529 (MODE(lmp) & RTLD_NODELETE) && (CNTL(lmp) == ALO_DATA)) 530 return (0); 531 532 /* 533 * If this object is the head of a handle that has not been captured as 534 * a candidate for deletion, then this object is in use from a dlopen() 535 * outside of the scope of this dlclose() family. Dlopen'ed objects, 536 * and filtees, have group descriptors for their callers. Typically 537 * this parent will have callers that are not apart of this dlclose() 538 * family, and thus would be caught by the CALLERS test below. However, 539 * if the caller had itself been dlopen'ed, it may not have any explicit 540 * callers registered for itself. Thus, but looking for objects with 541 * handles we can ferret out these outsiders. 542 */ 543 for (ALIST_TRAVERSE(HANDLES(lmp), off, ghpp)) { 544 if (alist_test(ghalp, *ghpp, 545 sizeof (Grp_hdl *), 0) != ALE_EXISTS) 546 return (0); 547 } 548 549 /* 550 * If this object is called by any object outside of the family of 551 * objects selected for deletion, it can't be deleted. 552 */ 553 for (ALIST_TRAVERSE(CALLERS(lmp), off, bdpp)) { 554 if (alist_test(lmalp, (*bdpp)->b_caller, 555 sizeof (Rt_map *), 0) != ALE_EXISTS) 556 return (0); 557 } 558 559 /* 560 * This object is a candidate for deletion. 561 */ 562 return (1); 563 } 564 565 /* 566 * Collect the groups (handles) and associated objects that are candidates for 567 * deletion. The criteria for deleting an object is whether it is only refer- 568 * enced from the objects within the groups that are candidates for deletion. 569 */ 570 static int 571 gdp_collect(Alist ** ghalpp, Alist ** lmalpp, Grp_hdl * ghp1) 572 { 573 Aliste off; 574 Grp_desc * gdp; 575 int action; 576 577 /* 578 * Add this group to our group collection. If it isn't added either an 579 * allocation has failed, or it already exists. 580 */ 581 if ((action = alist_test(ghalpp, ghp1, sizeof (Grp_hdl *), 582 AL_CNT_GRPCLCT)) != ALE_CREATE) 583 return (action); 584 585 /* 586 * Traverse the dependencies of the group and collect the associated 587 * objects. 588 */ 589 for (ALIST_TRAVERSE(ghp1->gh_depends, off, gdp)) { 590 Rt_map * lmp = gdp->gd_depend; 591 592 /* 593 * We only want to process dependencies for deletion. Although 594 * we want to purge group descriptors for parents, we don't want 595 * to analyze the parent itself for additional filters or 596 * deletion. 597 */ 598 if ((gdp->gd_flags & GPD_ADDEPS) == 0) 599 continue; 600 601 if ((action = alist_test(lmalpp, lmp, sizeof (Rt_map *), 602 AL_CNT_GRPCLCT)) == 0) 603 return (0); 604 if (action == ALE_EXISTS) 605 continue; 606 607 /* 608 * If this object hasn't yet been relocated take this as a sign 609 * that it's loading failed, thus we're here to cleanup. Or, 610 * if this object isn't obviously non-deletable, determine 611 * whether it provides any filtees. Add these groups to the 612 * group collection. 613 */ 614 if ((((FLAGS(lmp) & FLG_RT_RELOCED) == 0) || 615 ((MODE(lmp) & RTLD_NODELETE) == 0)) && 616 (FLAGS1(lmp) & MSK_RT_FILTER)) { 617 Dyninfo * dip = DYNINFO(lmp); 618 uint_t cnt, max = DYNINFOCNT(lmp); 619 620 for (cnt = 0; cnt < max; cnt++, dip++) { 621 Pnode * pnp; 622 623 if ((dip->di_info == 0) || 624 ((dip->di_flags & MSK_DI_FILTER) == 0)) 625 continue; 626 627 for (pnp = (Pnode *)dip->di_info; pnp; 628 pnp = pnp->p_next) { 629 Grp_hdl * ghp2; 630 631 if ((pnp->p_len == 0) || ((ghp2 = 632 (Grp_hdl *)pnp->p_info) == 0)) 633 continue; 634 635 if (gdp_collect(ghalpp, lmalpp, 636 ghp2) == 0) 637 return (0); 638 } 639 } 640 } 641 } 642 return (1); 643 } 644 645 /* 646 * Traverse the list of deletable candidates. If an object can't be deleted 647 * then neither can its dependencies or filtees. Any object that is cleared 648 * from being deleted drops the deletion count, plus, if there are no longer 649 * any deletions pending we can discontinue any further processing. 650 */ 651 static int 652 remove_rescan(Alist * lmalp, Alist * ghalp, int *delcnt) 653 { 654 Aliste off1; 655 Rt_map ** lmpp; 656 int rescan = 0; 657 658 for (ALIST_TRAVERSE(lmalp, off1, lmpp)) { 659 Aliste off2; 660 Bnd_desc ** bdpp; 661 Rt_map * lmp = *lmpp; 662 Dyninfo * dip; 663 uint_t cnt, max; 664 665 if (FLAGS(lmp) & FLG_RT_DELETE) 666 continue; 667 668 /* 669 * As this object can't be deleted, make sure its dependencies 670 * aren't deleted either. 671 */ 672 for (ALIST_TRAVERSE(DEPENDS(lmp), off2, bdpp)) { 673 Rt_map * dlmp = (*bdpp)->b_depend; 674 675 if (FLAGS(dlmp) & FLG_RT_DELETE) { 676 FLAGS(dlmp) &= ~FLG_RT_DELETE; 677 if (--(*delcnt) == 0) 678 return (0); 679 rescan = 1; 680 } 681 } 682 683 /* 684 * If this object is a filtee and one of its filters is outside 685 * of this dlclose family, then it can't be deleted either. 686 */ 687 if ((FLAGS1(lmp) & MSK_RT_FILTER) == 0) 688 continue; 689 690 dip = DYNINFO(lmp); 691 max = DYNINFOCNT(lmp); 692 693 for (cnt = 0; cnt < max; cnt++, dip++) { 694 Pnode * pnp; 695 696 if ((dip->di_info == 0) || 697 ((dip->di_flags & MSK_DI_FILTER) == 0)) 698 continue; 699 700 for (pnp = (Pnode *)dip->di_info; pnp; 701 pnp = pnp->p_next) { 702 Grp_hdl * ghp; 703 Grp_desc * gdp; 704 705 if ((pnp->p_len == 0) || 706 ((ghp = (Grp_hdl *)pnp->p_info) == 0)) 707 continue; 708 709 if (alist_test(&ghalp, ghp, 710 sizeof (Grp_hdl *), 0) == ALE_EXISTS) 711 continue; 712 713 for (ALIST_TRAVERSE(ghp->gh_depends, off2, 714 gdp)) { 715 Rt_map * dlmp = gdp->gd_depend; 716 717 if (FLAGS(dlmp) & FLG_RT_DELETE) { 718 FLAGS(dlmp) &= ~FLG_RT_DELETE; 719 if (--(*delcnt) == 0) 720 return (0); 721 rescan = 1; 722 } 723 } 724 725 /* 726 * Remove this group handle from our dynamic 727 * deletion list. 728 */ 729 (void) alist_delete(ghalp, &ghp, 0); 730 } 731 } 732 } 733 return (rescan); 734 } 735 736 /* 737 * Cleanup any collection alists we've created. 738 */ 739 static void 740 remove_collect(Alist * ghalp, Alist * lmalp) 741 { 742 if (ghalp) 743 free(ghalp); 744 if (lmalp) 745 free(lmalp); 746 } 747 748 /* 749 * Remove a handle, leaving the associated objects intact. Besides the classic 750 * dlopen() usage, handles are used as a means of associating a group of objects 751 * and promoting modes. Once object promotion is completed, the handle should 752 * be discarded while leaving the associated objects intact. Leaving the handle 753 * would prevent the object from being deleted (as it looks like it's in use 754 * by another user). 755 */ 756 void 757 free_hdl(Grp_hdl *ghp) 758 { 759 if (--(ghp->gh_refcnt) == 0) { 760 Grp_desc *gdp; 761 uintptr_t ndx; 762 Aliste off; 763 764 for (ALIST_TRAVERSE(ghp->gh_depends, off, gdp)) { 765 Rt_map *lmp = gdp->gd_depend; 766 767 if (ghp->gh_owner == lmp) 768 (void) alist_delete(HANDLES(lmp), &ghp, 0); 769 (void) alist_delete(GROUPS(lmp), &ghp, 0); 770 } 771 (void) free(ghp->gh_depends); 772 773 /* LINTED */ 774 ndx = (uintptr_t)ghp % HDLIST_SZ; 775 list_delete(&hdl_list[ndx], ghp); 776 777 (void) free(ghp); 778 } 779 } 780 781 /* 782 * Remove a caller from a group handle. This breaks the bond between a caller 783 * and a hierarchy of dependencies represented by a handle, thus the caller 784 * doesn't lock the hierarchy and prevent their deletion should their processing 785 * fail to complete. If the handle count drops to zero, the handle is marked 786 * as sticky to prevent it's removal, or to confuse orphan handle processing. 787 * The caller may establish a binding to this handle again, once the hierarchy 788 * processing has completed, thus retaining the handle saves having to recreate 789 * it over and over again. 790 */ 791 void 792 remove_caller(Grp_hdl *ghp, Rt_map *clmp) 793 { 794 Grp_desc *gdp; 795 Aliste off; 796 797 if (--(ghp->gh_refcnt) == 0) 798 ghp->gh_flags |= GPH_STICKY; 799 800 for (ALIST_TRAVERSE(ghp->gh_depends, off, gdp)) { 801 Rt_map *lmp = gdp->gd_depend; 802 803 if (lmp == clmp) { 804 (void) alist_delete(GROUPS(lmp), &ghp, 0); 805 (void) alist_delete(ghp->gh_depends, 0, &off); 806 break; 807 } 808 } 809 } 810 811 /* 812 * Remove the objects associated with a handle. There are two goals here, to 813 * delete the objects associated with the handle, and to remove the handle 814 * itself. Things get a little more complex if the objects selected for 815 * deletion are filters, in this case we also need to collect their filtees, 816 * and process the combined groups as a whole. But, care still must be exer- 817 * cised to make sure any filtees found aren't being used by filters outside of 818 * the groups we've collect. The series of events is basically: 819 * 820 * o Determine the groups (handles) that might be deletable. 821 * 822 * o Determine the objects of these handles that can be deleted. 823 * 824 * o Fire the fini's of those objects selected for deletion. 825 * 826 * o Remove all inter-dependency linked lists while the objects link-maps 827 * are still available. 828 * 829 * o Remove all deletable objects link-maps and unmap the objects themselves. 830 * 831 * o Remove the handle descriptors for each deleted object, and hopefully 832 * the whole handle. 833 * 834 * An handle that can't be deleted is added to an orphans list. This list is 835 * revisited any time another dlclose() request results in handle descriptors 836 * being deleted. These deleted descriptors can be sufficient to allow the 837 * final deletion of the orphaned handles. 838 */ 839 int 840 remove_hdl(Grp_hdl * ghp, Rt_map * clmp, int *removed) 841 { 842 Rt_map * lmp, ** lmpp; 843 int rescan = 0; 844 int delcnt = 0, rmcnt = 0, error = 0, orphans; 845 Alist * lmalp = 0, * ghalp = 0; 846 Aliste off1, off2; 847 Grp_hdl ** ghpp; 848 Grp_desc * gdp; 849 Lm_list * lml = 0; 850 851 /* 852 * Generate the family of groups and objects that are candidates for 853 * deletion. This consists of the objects that are explicitly defined 854 * as dependencies of this handle, plus any filtee handles and their 855 * associated objects. 856 */ 857 if (gdp_collect(&ghalp, &lmalp, ghp) == 0) { 858 remove_collect(ghalp, lmalp); 859 return (0); 860 } 861 862 DBG_CALL(Dbg_file_hdl_title(DBG_DEP_DELETE)); 863 864 /* 865 * Traverse the groups we've collected to determine if any filtees are 866 * included. If so, and the filtee handle is in use by a filter outside 867 * of the family of objects collected for this deletion, it can not be 868 * removed. 869 */ 870 for (ALIST_TRAVERSE(ghalp, off1, ghpp)) { 871 Grp_hdl * ghp = *ghpp; 872 873 DBG_CALL(Dbg_file_hdl_collect(ghp, 0)); 874 875 if ((ghp->gh_flags & GPH_FILTEE) == 0) 876 continue; 877 878 /* 879 * Special case for ld.so.1. There can be multiple instances of 880 * libdl.so.1 using this handle, so although we want the handles 881 * reference count to be decremented, we don't want the handle 882 * removed. 883 */ 884 if (ghp->gh_flags & GPH_LDSO) { 885 DBG_CALL(Dbg_file_hdl_collect(ghp, 886 NAME(lml_rtld.lm_head))); 887 (void) alist_delete(ghalp, 0, &off1); 888 continue; 889 } 890 891 for (ALIST_TRAVERSE(ghp->gh_depends, off2, gdp)) { 892 Grp_hdl ** ghpp3; 893 Aliste off3; 894 895 /* 896 * Determine whether this dependency is the filtee's 897 * parent filter, and that it isn't also an explicit 898 * dependency (in which case it would have added its own 899 * dependencies to the handle). 900 */ 901 if ((gdp->gd_flags & 902 (GPD_FILTER | GPD_ADDEPS)) != GPD_FILTER) 903 continue; 904 905 if (alist_test(&lmalp, gdp->gd_depend, 906 sizeof (Rt_map *), 0) == ALE_EXISTS) 907 continue; 908 909 /* 910 * Remove this group handle from our dynamic deletion 911 * list. In addition, recompute the list of objects 912 * that are candidates for deletion to continue this 913 * group verification. 914 */ 915 DBG_CALL(Dbg_file_hdl_collect(ghp, 916 NAME(gdp->gd_depend))); 917 (void) alist_delete(ghalp, 0, &off1); 918 919 free(lmalp); 920 lmalp = 0; 921 for (ALIST_TRAVERSE(ghalp, off3, ghpp3)) { 922 Aliste off4; 923 Grp_desc * gdp4; 924 925 for (ALIST_TRAVERSE((*ghpp3)->gh_depends, 926 off4, gdp4)) { 927 if ((gdp4->gd_flags & GPD_ADDEPS) == 0) 928 continue; 929 if (alist_test(&lmalp, gdp4->gd_depend, 930 sizeof (Rt_map *), 931 AL_CNT_GRPCLCT) == 0) { 932 remove_collect(ghalp, lmalp); 933 return (0); 934 } 935 } 936 } 937 break; 938 } 939 } 940 941 /* 942 * Now that we've collected all the handles dependencies, traverse the 943 * collection determining whether they are a candidate for deletion. 944 */ 945 for (ALIST_TRAVERSE(lmalp, off1, lmpp)) { 946 lmp = *lmpp; 947 948 /* 949 * Establish which link-map list we're dealing with for later 950 * .fini processing. 951 */ 952 if (lml == 0) 953 lml = LIST(lmp); 954 955 /* 956 * If an object isn't a candidate for deletion we'll have to 957 * rescan the handle insuring that this objects dependencies 958 * aren't deleted either. 959 */ 960 if (is_deletable(&lmalp, &ghalp, lmp)) { 961 FLAGS(lmp) |= FLG_RT_DELETE; 962 delcnt++; 963 } else 964 rescan = 1; 965 } 966 967 /* 968 * Rescan the handle if any objects where found non-deletable. 969 */ 970 while (rescan) 971 rescan = remove_rescan(lmalp, ghalp, &delcnt); 972 973 /* 974 * Now that we have determined the number of groups that are candidates 975 * for removal, mark each group descriptor as a candidate for removal 976 * from the group. 977 */ 978 for (ALIST_TRAVERSE(ghalp, off1, ghpp)) { 979 for (ALIST_TRAVERSE((*ghpp)->gh_depends, off2, gdp)) 980 gdp->gd_flags |= GPD_REMOVE; 981 } 982 983 /* 984 * Now that we know which objects on this handle can't be deleted 985 * determine whether they still need to remain identified as belonging 986 * to this group to be able to continue binding to one another. 987 */ 988 for (ALIST_TRAVERSE(ghalp, off1, ghpp)) { 989 Grp_hdl * ghp = *ghpp; 990 991 for (ALIST_TRAVERSE(ghp->gh_depends, off2, gdp)) { 992 Aliste off3; 993 Bnd_desc ** bdpp; 994 995 lmp = gdp->gd_depend; 996 997 if (FLAGS(lmp) & FLG_RT_DELETE) 998 continue; 999 1000 for (ALIST_TRAVERSE(DEPENDS(lmp), off3, bdpp)) { 1001 Aliste off4; 1002 Grp_desc * gdp4; 1003 Rt_map * dlmp = (*bdpp)->b_depend; 1004 1005 /* 1006 * If this dependency (dlmp) can be referenced 1007 * by the caller (clmp) without being part of 1008 * this group (ghp) then belonging to this group 1009 * is no longer necessary. This can occur when 1010 * objects are part of multiple handles, or if a 1011 * previously deleted handle was moved to the 1012 * orphan list and has been reopened. Note, 1013 * first make sure the caller can reference the 1014 * dependency with this group, if it can't we 1015 * must be bound to a filtee, so there's no need 1016 * to remain a part of this group either. 1017 */ 1018 if ((callable(lmp, dlmp, 0) == 0) || 1019 callable(lmp, dlmp, ghp)) 1020 continue; 1021 1022 if (gdp->gd_flags & GPD_REMOVE) 1023 gdp->gd_flags &= ~GPD_REMOVE; 1024 1025 for (ALIST_TRAVERSE(ghp->gh_depends, 1026 off4, gdp4)) { 1027 if (gdp4->gd_depend != dlmp) 1028 continue; 1029 1030 if (gdp4->gd_flags & GPD_REMOVE) 1031 gdp4->gd_flags &= ~GPD_REMOVE; 1032 } 1033 } 1034 } 1035 } 1036 1037 /* 1038 * If the owner of a handle can't be deleted and it's handle descriptor 1039 * must remain also, don't delete the handle at all. Leave it for 1040 * possible later use. Although it's left intact, it will still be 1041 * moved to the orphans list, as we might be able to revisit it on later 1042 * dlclose() operations and finally remove the underlying objects. Note 1043 * that the handle still remains attached to the owner via the HANDLES 1044 * list, so that it can be re-associated to the owner if a dlopen() 1045 * of this object reoccurs. 1046 */ 1047 for (ALIST_TRAVERSE(ghalp, off1, ghpp)) { 1048 Grp_hdl * ghp = *ghpp; 1049 1050 /* 1051 * If this handle is already an orphan, or if it's owner is 1052 * deletable there's no need to inspect its dependencies. 1053 */ 1054 if ((ghp->gh_owner == 0) || 1055 (FLAGS(ghp->gh_owner) & FLG_RT_DELETE)) 1056 continue; 1057 1058 /* 1059 * Make sure all handle dependencies aren't removed or the 1060 * dependencies themselves aren't deleted. 1061 */ 1062 for (ALIST_TRAVERSE(ghp->gh_depends, off2, gdp)) { 1063 lmp = gdp->gd_depend; 1064 1065 /* 1066 * The first dependency of a non-orphaned handle is the 1067 * owner. If the handle descriptor for this isn't 1068 * required there's no need to look at any other of the 1069 * handles dependencies. 1070 */ 1071 if ((lmp == ghp->gh_owner) && 1072 (gdp->gd_flags & GPD_REMOVE)) 1073 break; 1074 1075 if (gdp->gd_flags & GPD_REMOVE) 1076 gdp->gd_flags &= ~GPD_REMOVE; 1077 if (FLAGS(lmp) & FLG_RT_DELETE) { 1078 FLAGS(lmp) &= ~FLG_RT_DELETE; 1079 delcnt--; 1080 } 1081 } 1082 } 1083 1084 /* 1085 * Final scan of objects to see if any objects are to to be deleted. 1086 * Also - display diagnostic information on what operations are to be 1087 * performed on the collected handles before firing .fini's (which 1088 * produces additional diagnostics). 1089 */ 1090 for (ALIST_TRAVERSE(ghalp, off1, ghpp)) { 1091 Grp_hdl * ghp = *ghpp; 1092 1093 DBG_CALL(Dbg_file_hdl_title(DBG_DEP_DELETE)); 1094 1095 for (ALIST_TRAVERSE(ghp->gh_depends, off2, gdp)) { 1096 int flag; 1097 1098 lmp = gdp->gd_depend; 1099 1100 if (FLAGS(lmp) & FLG_RT_DELETE) { 1101 flag = DBG_DEP_DELETE; 1102 /* 1103 * Remove any pathnames from the FullpathNode 1104 * AVL tree. As we're about to fire .fini's, 1105 * it's possible this object will be required 1106 * again, in which case we want to make sure a 1107 * new version of the object gets loaded. 1108 */ 1109 if (FPNODE(lmp)) 1110 fpavl_remove(lmp); 1111 } else if (gdp->gd_flags & GPD_REMOVE) 1112 flag = DBG_DEP_REMOVE; 1113 else 1114 flag = DBG_DEP_REMAIN; 1115 1116 DBG_CALL(Dbg_file_hdl_action(ghp, lmp, flag)); 1117 } 1118 } 1119 1120 /* 1121 * If there are objects to be deleted process their .fini's. 1122 */ 1123 if (delcnt) { 1124 Rt_map ** tobj; 1125 1126 /* 1127 * If we're being audited tell the audit library that we're 1128 * about to go deleting dependencies. 1129 */ 1130 if (clmp && ((LIST(clmp)->lm_tflags | FLAGS1(clmp)) & 1131 LML_TFLG_AUD_ACTIVITY)) 1132 audit_activity(clmp, LA_ACT_DELETE); 1133 1134 /* 1135 * Sort and fire all fini's of the objects selected for 1136 * deletion. Note that we have to start our search from the 1137 * link-map head - there's no telling whether this object has 1138 * dependencies on objects that were loaded before it and which 1139 * can now be deleted. If the tsort() fails because of an 1140 * allocation error then that might just be a symptom of why 1141 * we're here in the first place - forgo the fini's but 1142 * continue to try cleaning up. 1143 */ 1144 if (((tobj = tsort(lml->lm_head, delcnt, 1145 (RT_SORT_DELETE | RT_SORT_FWD))) != 0) && 1146 (tobj != (Rt_map **)S_ERROR)) { 1147 error = purge_exit_handlers(lml, tobj); 1148 call_fini(lml, tobj); 1149 } 1150 1151 /* 1152 * Audit the closure of the dlopen'ed object to any local 1153 * auditors. Any global auditors would have been caught by 1154 * call_fini(), but as the link-maps CALLERS was removed 1155 * already we do the local auditors explicitly. 1156 */ 1157 for (ALIST_TRAVERSE(ghalp, off1, ghpp)) { 1158 Grp_hdl * ghp = *ghpp; 1159 Rt_map * dlmp = ghp->gh_owner; 1160 1161 if (clmp && dlmp && 1162 ((LIST(dlmp)->lm_flags & LML_FLG_NOAUDIT) == 0) && 1163 (FLAGS1(clmp) & LML_TFLG_AUD_OBJCLOSE)) 1164 _audit_objclose(&(AUDITORS(clmp)->ad_list), 1165 dlmp); 1166 } 1167 } 1168 1169 /* 1170 * Now that .fini processing (which may have involved new bindings) 1171 * is complete, remove all inter-dependency lists from those objects 1172 * selected for deletion. 1173 */ 1174 for (ALIST_TRAVERSE(lmalp, off1, lmpp)) { 1175 Dyninfo * dip; 1176 uint_t cnt, max; 1177 1178 lmp = *lmpp; 1179 1180 if (FLAGS(lmp) & FLG_RT_DELETE) 1181 remove_lists(lmp, 0); 1182 1183 /* 1184 * Determine whether we're dealing with a filter, and if so 1185 * process any inter-dependencies with its filtee's. 1186 */ 1187 if ((FLAGS1(lmp) & MSK_RT_FILTER) == 0) 1188 continue; 1189 1190 dip = DYNINFO(lmp); 1191 max = DYNINFOCNT(lmp); 1192 1193 for (cnt = 0; cnt < max; cnt++, dip++) { 1194 Pnode * pnp; 1195 1196 if ((dip->di_info == 0) || 1197 ((dip->di_flags & MSK_DI_FILTER) == 0)) 1198 continue; 1199 1200 for (pnp = (Pnode *)dip->di_info; pnp; 1201 pnp = pnp->p_next) { 1202 Grp_hdl * ghp; 1203 1204 if ((pnp->p_len == 0) || 1205 ((ghp = (Grp_hdl *)pnp->p_info) == 0)) 1206 continue; 1207 1208 /* 1209 * Determine whether this filtee's handle is a 1210 * part of the list of handles being deleted. 1211 */ 1212 if (alist_test(&ghalp, ghp, 1213 sizeof (Grp_hdl *), 0) == ALE_EXISTS) { 1214 /* 1215 * If this handle exists on the deletion 1216 * list, then it has been removed. If 1217 * this filter isn't going to be 1218 * deleted, server its reference to the 1219 * handle. 1220 */ 1221 pnp->p_info = 0; 1222 } else { 1223 /* 1224 * If this handle isn't on the deletion 1225 * list, then it must still exist. If 1226 * this filter is being deleted, make 1227 * sure the filtees reference count 1228 * gets decremented. 1229 */ 1230 if (FLAGS(lmp) & FLG_RT_DELETE) 1231 (void) dlclose_core(ghp, lmp); 1232 } 1233 } 1234 } 1235 } 1236 1237 /* 1238 * If called from dlclose(), determine if there are already handles on 1239 * the orphans list that we can reinvestigate. 1240 */ 1241 if ((removed == 0) && hdl_list[HDLIST_ORP].head) 1242 orphans = 1; 1243 else 1244 orphans = 0; 1245 1246 /* 1247 * Finally remove any handle infrastructure and remove any objects 1248 * marked for deletion. 1249 */ 1250 for (ALIST_TRAVERSE(ghalp, off1, ghpp)) { 1251 Grp_hdl * ghp = *ghpp; 1252 1253 /* 1254 * If we're not dealing with orphaned handles remove this handle 1255 * from its present handle list. 1256 */ 1257 if (removed == 0) { 1258 uintptr_t ndx; 1259 1260 /* LINTED */ 1261 ndx = (uintptr_t)ghp % HDLIST_SZ; 1262 list_delete(&hdl_list[ndx], ghp); 1263 } 1264 1265 /* 1266 * Traverse each handle dependency. 1267 */ 1268 for (ALIST_TRAVERSE(ghp->gh_depends, off2, gdp)) { 1269 if ((gdp->gd_flags & GPD_REMOVE) == 0) 1270 continue; 1271 1272 lmp = gdp->gd_depend; 1273 rmcnt++; 1274 1275 /* 1276 * If this object is the owner of the handle break that 1277 * association in case the handle is retained. 1278 */ 1279 if (ghp->gh_owner == lmp) { 1280 (void) alist_delete(HANDLES(lmp), &ghp, 0); 1281 ghp->gh_owner = 0; 1282 } 1283 1284 (void) alist_delete(GROUPS(lmp), &ghp, 0); 1285 (void) alist_delete(ghp->gh_depends, 0, &off2); 1286 1287 /* 1288 * Complete the link-map deletion if appropriate. 1289 */ 1290 if (FLAGS(lmp) & FLG_RT_DELETE) { 1291 tls_modactivity(lmp, TM_FLG_MODREM); 1292 remove_so(LIST(lmp), lmp); 1293 } 1294 } 1295 1296 /* 1297 * If we've deleted all the dependencies of the handle finalize 1298 * the cleanup by removing the handle itself. 1299 * 1300 * Otherwise we're left with a handle containing one or more 1301 * objects that can not be deleted (they're in use by other 1302 * handles, non-deletable, etc.), but require to remain a part 1303 * of this group to allow them to continue binding to one 1304 * another. Should any other dlclose() operation occur that 1305 * results in the removal of handle descriptors, these orphan 1306 * handles are re-examined to determine if their deletion can be 1307 * completed. 1308 */ 1309 if (ghp->gh_depends->al_data[0] == 0) { 1310 remove_lml(lml); 1311 free(ghp->gh_depends); 1312 free(ghp); 1313 } else if (removed == 0) { 1314 /* 1315 * Move this handle to the orphans list (if it isn't 1316 * already there). 1317 */ 1318 (void) list_append(&hdl_list[HDLIST_ORP], ghp); 1319 1320 if (dbg_mask) { 1321 DBG_CALL(Dbg_file_hdl_title(DBG_DEP_ORPHAN)); 1322 for (ALIST_TRAVERSE(ghp->gh_depends, off1, gdp)) 1323 DBG_CALL(Dbg_file_hdl_action(ghp, 1324 gdp->gd_depend, DBG_DEP_REMAIN)); 1325 } 1326 } 1327 } 1328 1329 /* 1330 * If no handle descriptors got removed there's no point in looking for 1331 * orphans to process. 1332 */ 1333 if (rmcnt == 0) 1334 orphans = 0; 1335 1336 /* 1337 * Cleanup any alists we've created. 1338 */ 1339 remove_collect(ghalp, lmalp); 1340 1341 /* 1342 * If orphan processing isn't required we're done. If our processing 1343 * originated from investigating orphans, return the number of handle 1344 * descriptors removed as an indication whether orphan processing 1345 * should continue. 1346 */ 1347 if (orphans == 0) { 1348 if (removed) 1349 *removed = rmcnt; 1350 return (error); 1351 } 1352 1353 /* 1354 * Traverse the orphans list as many times as necessary until no 1355 * handle removals occur. 1356 */ 1357 do { 1358 List list; 1359 Listnode * lnp; 1360 Grp_hdl * ghp, * oghp = 0; 1361 1362 DBG_CALL(Dbg_file_del_rescan()); 1363 1364 /* 1365 * Effectively clean the HDLIST_ORP list. Any object that can't 1366 * be removed will be re-added to the list. 1367 */ 1368 list = hdl_list[HDLIST_ORP]; 1369 hdl_list[HDLIST_ORP].head = hdl_list[HDLIST_ORP].tail = 0; 1370 1371 rescan = 0; 1372 for (LIST_TRAVERSE(&list, lnp, ghp)) { 1373 int _error, _remove; 1374 1375 if (oghp) { 1376 list_delete(&list, oghp); 1377 oghp = 0; 1378 } 1379 1380 if (((_error = remove_hdl(ghp, clmp, &_remove)) != 0) && 1381 (error == 0)) 1382 error = _error; 1383 1384 if (_remove) 1385 rescan++; 1386 1387 oghp = ghp; 1388 } 1389 if (oghp) { 1390 list_delete(&list, oghp); 1391 oghp = 0; 1392 } 1393 1394 } while (rescan && hdl_list[HDLIST_ORP].head); 1395 1396 return (error); 1397 } 1398