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 2008 Sun Microsystems, Inc. All rights reserved. 24 * Use is subject to license terms. 25 */ 26 27 /* 28 * Remove objects. Objects need removal from a process as part of: 29 * 30 * o a dlclose() request 31 * 32 * o tearing down a dlopen(), lazy-load, or filter hierarchy that failed to 33 * completely load 34 * 35 * Any other failure condition will result in process exit (in which case all 36 * we have to do is execute the fini's - tear down is unnecessary). 37 * 38 * Any removal of objects is therefore associated with a dlopen() handle. There 39 * is a small window between creation of the first dlopen() object and creating 40 * its handle (in which case remove_so() can get rid of the new link-map if 41 * necessary), but other than this all object removal is driven by inspecting 42 * the components of a handle. 43 * 44 * Things to note. The creation of a link-map, and its addition to the link-map 45 * list occurs in {elf|aout}_new_lm(), if this returns success the link-map is 46 * valid and added, otherwise any steps (allocations) in the process of creating 47 * the link-map would have been undone. If a failure occurs between creating 48 * the link-map and adding it to a handle, remove_so() is called to remove the 49 * link-map. If a failures occurs after a handle have been created, 50 * remove_hdl() is called to remove the handle and the link-map. 51 */ 52 53 #include <string.h> 54 #include <stdio.h> 55 #include <unistd.h> 56 #include <dlfcn.h> 57 #include <sys/debug.h> 58 #include <sys/avl.h> 59 #include <libc_int.h> 60 #include <debug.h> 61 #include "_rtld.h" 62 #include "_audit.h" 63 #include "_elf.h" 64 #include "msg.h" 65 66 /* 67 * Atexit callback provided by libc. As part of dlclose() determine the address 68 * ranges of all objects that are to be deleted. Pass this information to 69 * libc's pre-atexit routine. Libc will purge any registered atexit() calls 70 * related to those objects about to be deleted. 71 */ 72 static int 73 purge_exit_handlers(Lm_list *lml, Rt_map **tobj) 74 { 75 uint_t num; 76 Rt_map **_tobj; 77 Lc_addr_range_t *addr, *_addr; 78 int error; 79 int (*fptr)(Lc_addr_range_t *, uint_t); 80 81 /* 82 * Has a callback been established? 83 */ 84 if ((fptr = lml->lm_lcs[CI_ATEXIT].lc_un.lc_func) == NULL) 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), 0); 124 error = (*fptr)(addr, (num - 1)); 125 (void) enter(0); 126 127 /* 128 * If we fail to converse with libc, generate an error message to 129 * satisfy any dlerror() usage. 130 */ 131 if (error) 132 eprintf(lml, ERR_FATAL, MSG_INTL(MSG_ARG_ATEXIT), error); 133 134 free(addr); 135 return (error); 136 } 137 138 /* 139 * Remove any rejection message allocations. 140 */ 141 void 142 remove_rej(Rej_desc *rej) 143 { 144 if (rej && (rej->rej_type)) { 145 if (rej->rej_name) 146 free((void *)rej->rej_name); 147 if (rej->rej_str && (rej->rej_str != MSG_ORIG(MSG_EMG_ENOMEM))) 148 free((void *)rej->rej_str); 149 } 150 } 151 152 /* 153 * Break down a Pnode list. 154 */ 155 void 156 remove_pnode(Pnode *pnp) 157 { 158 Pnode *opnp; 159 160 for (opnp = 0; pnp; opnp = pnp, pnp = pnp->p_next) { 161 if (pnp->p_name) 162 free((void *)pnp->p_name); 163 if (pnp->p_oname) 164 free((void *)pnp->p_oname); 165 if (opnp) 166 free((void *)opnp); 167 } 168 if (opnp) 169 free((void *)opnp); 170 } 171 172 173 /* 174 * Remove a link-map list descriptor. This is called to finalize the removal 175 * of an entire link-map list, after all link-maps have been removed, or none 176 * got added. As load_one() can process a list of potential candidate objects, 177 * the link-map descriptor must be maintained as each object is processed. Only 178 * after all objects have been processed can a failure condition finally tear 179 * down the link-map list descriptor. 180 */ 181 void 182 remove_lml(Lm_list *lml) 183 { 184 if (lml && (lml->lm_head == 0)) { 185 /* 186 * As a whole link-map list is being removed, the debuggers 187 * would have been alerted of this deletion (or an addition 188 * in the case we're here to clean up from a failure). Set 189 * the main link-map list so that a consistent registration 190 * can be signaled to the debuggers when we leave ld.so.1. 191 */ 192 lml_main.lm_flags |= LML_FLG_DBNOTIF; 193 194 if (lml->lm_lmidstr) 195 free(lml->lm_lmidstr); 196 if (lml->lm_alp) 197 free(lml->lm_alp); 198 if (lml->lm_lists) 199 free(lml->lm_lists); 200 if (lml->lm_actaudit) 201 free(lml->lm_actaudit); 202 203 /* 204 * Cleanup any pending RTLDINFO in the case where it was 205 * allocated but not called (see _relocate_lmc()). 206 */ 207 if (lml->lm_rti) 208 free(lml->lm_rti); 209 if (lml->lm_fpavl) { 210 /* 211 * As we are freeing the link-map list, all nodes must 212 * have previously been removed. 213 */ 214 ASSERT(avl_numnodes(lml->lm_fpavl) == 0); 215 free(lml->lm_fpavl); 216 } 217 list_delete(&dynlm_list, lml); 218 free(lml); 219 } 220 } 221 222 /* 223 * Remove a link-map. This removes a link-map from its associated list and 224 * free's up the link-map itself. Note, all components that are freed are local 225 * to the link-map, no inter-link-map lists are operated on as these are all 226 * broken down by dlclose() while all objects are still mapped. 227 * 228 * This routine is called from dlclose() to zap individual link-maps after their 229 * interdependencies (DEPENDS(), CALLER(), handles, etc.) have been removed. 230 * This routine is also called from the bowels of load_one() in the case of a 231 * link-map creation failure. 232 */ 233 void 234 remove_so(Lm_list *lml, Rt_map *lmp) 235 { 236 Dyninfo *dip; 237 238 if (lmp == 0) 239 return; 240 241 /* 242 * Unlink the link map from the link-map list. 243 */ 244 if (lml && lmp) 245 lm_delete(lml, lmp); 246 247 /* 248 * If this object contributed any local external vectors for the current 249 * link-map list, remove the vectors. If this object contributed any 250 * global external vectors we should find some new candidates, or leave 251 * this object lying around. 252 */ 253 if (lml) { 254 int tag; 255 256 for (tag = 0; tag < CI_MAX; tag++) { 257 if (lml->lm_lcs[tag].lc_lmp == lmp) { 258 lml->lm_lcs[tag].lc_lmp = 0; 259 lml->lm_lcs[tag].lc_un.lc_val = 0; 260 } 261 if (glcs[tag].lc_lmp == lmp) { 262 ASSERT(glcs[tag].lc_lmp != 0); 263 glcs[tag].lc_lmp = 0; 264 glcs[tag].lc_un.lc_val = 0; 265 } 266 } 267 } 268 269 DBG_CALL(Dbg_file_delete(lmp)); 270 271 /* 272 * If this is a temporary link-map, put in place to facilitate the 273 * link-edit or a relocatable object, then the link-map contains no 274 * information that needs to be cleaned up. 275 */ 276 if (FLAGS(lmp) & FLG_RT_OBJECT) 277 return; 278 279 /* 280 * Unmap the object. 281 */ 282 LM_UNMAP_SO(lmp)(lmp); 283 284 /* 285 * Remove any FullpathNode AVL names if they still exist. 286 */ 287 if (FPNODE(lmp)) 288 fpavl_remove(lmp); 289 290 /* 291 * Remove any alias names. 292 */ 293 if (ALIAS(lmp)) { 294 Aliste idx; 295 char *cp; 296 297 for (APLIST_TRAVERSE(ALIAS(lmp), idx, cp)) 298 free(cp); 299 free(ALIAS(lmp)); 300 } 301 302 /* 303 * Remove any of this objects filtee infrastructure. The filtees them- 304 * selves have already been removed. 305 */ 306 if (((dip = DYNINFO(lmp)) != 0) && (FLAGS1(lmp) & MSK_RT_FILTER)) { 307 uint_t cnt, max = DYNINFOCNT(lmp); 308 309 for (cnt = 0; cnt < max; cnt++, dip++) { 310 if (dip->di_info && (dip->di_flags & MSK_DI_FILTER)) 311 remove_pnode((Pnode *)dip->di_info); 312 } 313 } 314 if (dip) 315 free(DYNINFO(lmp)); 316 317 /* 318 * Deallocate any remaining cruft and free the link-map. 319 */ 320 if (RLIST(lmp)) 321 remove_pnode(RLIST(lmp)); 322 323 if (REFNAME(lmp)) 324 free(REFNAME(lmp)); 325 if (ELFPRV(lmp)) 326 free(ELFPRV(lmp)); 327 if (AUDITORS(lmp)) 328 audit_desc_cleanup(lmp); 329 if (AUDINFO(lmp)) 330 audit_info_cleanup(lmp); 331 332 if (CONDVAR(lmp)) 333 free(CONDVAR(lmp)); 334 /* 335 * Note that COPY_R() and COPY_S() reference the same memory 336 * location, and that we want to release the memory referenced 337 * without regard to which list it logically belongs to. We can 338 * use either pointer to do this. 339 */ 340 if (COPY_R(lmp)) 341 free(COPY_R(lmp)); 342 if (MMAPS(lmp)) 343 free(MMAPS(lmp)); 344 345 /* 346 * During a dlclose() any groups this object was a part of will have 347 * been torn down. However, we can get here to remove an object that 348 * has failed to load, perhaps because its addition to a handle failed. 349 * Therefore if this object indicates that its part of a group tear 350 * these associations down. 351 */ 352 if (GROUPS(lmp) != NULL) { 353 Aliste idx1; 354 Grp_hdl *ghp; 355 356 for (APLIST_TRAVERSE(GROUPS(lmp), idx1, ghp)) { 357 Grp_desc *gdp; 358 Aliste idx2; 359 360 for (ALIST_TRAVERSE(ghp->gh_depends, idx2, gdp)) { 361 if (gdp->gd_depend != lmp) 362 continue; 363 364 alist_delete(ghp->gh_depends, &idx2); 365 break; 366 } 367 } 368 free(GROUPS(lmp)); 369 } 370 if (HANDLES(lmp)) 371 free(HANDLES(lmp)); 372 373 /* 374 * Clean up reglist if needed 375 */ 376 if (reglist != (Reglist *)0) { 377 Reglist *cur, *prv, *del; 378 379 cur = prv = reglist; 380 while (cur != (Reglist *)0) { 381 if (cur->rl_lmp == lmp) { 382 del = cur; 383 if (cur == reglist) { 384 reglist = cur->rl_next; 385 cur = prv = reglist; 386 } else { 387 prv->rl_next = cur->rl_next; 388 cur = cur->rl_next; 389 } 390 free(del); 391 } else { 392 prv = cur; 393 cur = cur->rl_next; 394 } 395 } 396 } 397 398 /* 399 * Finally, free the various names, as these were duplicated so that 400 * they were available in core files. This is left until last, to aid 401 * debugging previous elements of the removal process. 402 * 403 * The original name is set to the pathname by default (see fullpath()), 404 * but is overridden if the file is an alternative. The pathname is set 405 * to the name by default (see [aout|elf]_new_lm()), but is overridden 406 * if the fullpath/resolve path differs (see fullpath()). The original 407 * name is always duplicated, as it typically exists as a text string 408 * (see DT_NEEDED pointer) or was passed in from user code. 409 */ 410 if (ORIGNAME(lmp) != PATHNAME(lmp)) 411 free(ORIGNAME(lmp)); 412 if (PATHNAME(lmp) != NAME(lmp)) 413 free(PATHNAME(lmp)); 414 free(NAME(lmp)); 415 416 free(lmp); 417 } 418 419 420 /* 421 * Traverse an objects dependency list removing callers and dependencies. 422 * There's a chicken and egg problem with tearing down link-maps. Any 423 * relationship between link-maps is maintained on a DEPENDS list, and an 424 * associated CALLERS list. These lists can't be broken down at the time a 425 * single link-map is removed, as any related link-map may have already been 426 * removed. Thus, lists between link-maps must be broken down before the 427 * individual link-maps themselves. 428 */ 429 void 430 remove_lists(Rt_map *lmp, int lazy) 431 { 432 Aliste idx1; 433 Bnd_desc *bdp; 434 435 /* 436 * First, traverse this objects dependencies. 437 */ 438 for (APLIST_TRAVERSE(DEPENDS(lmp), idx1, bdp)) { 439 Rt_map *dlmp = bdp->b_depend; 440 441 /* 442 * Remove this object from the dependencies callers. 443 */ 444 (void) aplist_delete_value(CALLERS(dlmp), bdp); 445 free(bdp); 446 } 447 if (DEPENDS(lmp)) { 448 free(DEPENDS(lmp)); 449 DEPENDS(lmp) = NULL; 450 } 451 452 /* 453 * Second, traverse this objects callers. 454 */ 455 for (APLIST_TRAVERSE(CALLERS(lmp), idx1, bdp)) { 456 Rt_map *clmp = bdp->b_caller; 457 Dyninfo *dip; 458 459 /* 460 * If we're removing an object that was triggered by a lazyload, 461 * remove the callers DYNINFO() entry and bump the lazy counts. 462 * This reinitialization of the lazy information allows a lazy 463 * object to be reloaded again later. Although we may be 464 * breaking down a group of lazyloaded objects because one has 465 * failed to relocate, it's possible that one or more of the 466 * individual objects can be reloaded without a problem. 467 */ 468 if (lazy && ((dip = DYNINFO(clmp)) != NULL)) { 469 uint_t cnt, max = DYNINFOCNT(clmp); 470 471 for (cnt = 0; cnt < max; cnt++, dip++) { 472 if ((dip->di_flags & FLG_DI_LAZY) == 0) 473 continue; 474 475 if (dip->di_info == (void *)lmp) { 476 dip->di_info = 0; 477 478 if (LAZY(clmp)++ == 0) 479 LIST(clmp)->lm_lazy++; 480 } 481 } 482 } 483 484 (void) aplist_delete_value(DEPENDS(clmp), bdp); 485 free(bdp); 486 } 487 if (CALLERS(lmp)) { 488 free(CALLERS(lmp)); 489 CALLERS(lmp) = NULL; 490 } 491 } 492 493 /* 494 * Delete any temporary link-map control list. 495 */ 496 void 497 remove_cntl(Lm_list *lml, Aliste lmco) 498 { 499 if (lmco && (lmco != ALIST_OFF_DATA)) { 500 Aliste _lmco = lmco; 501 #if DEBUG 502 Lm_cntl *lmc; 503 504 lmc = (Lm_cntl *)alist_item_by_offset(lml->lm_lists, lmco); 505 506 /* 507 * This element should be empty. 508 */ 509 ASSERT(lmc->lc_head == 0); 510 #endif 511 alist_delete_by_offset(lml->lm_lists, &_lmco); 512 } 513 } 514 515 /* 516 * If a lazy loaded object, or filtee fails to load, possibly because it, or 517 * one of its dependencies can't be relocated, then tear down any objects 518 * that are apart of this link-map control list. 519 */ 520 void 521 remove_incomplete(Lm_list *lml, Aliste lmco) 522 { 523 Rt_map *lmp; 524 Lm_cntl *lmc; 525 526 /* LINTED */ 527 lmc = (Lm_cntl *)alist_item_by_offset(lml->lm_lists, lmco); 528 529 /* 530 * First, remove any lists that may point between objects. 531 */ 532 for (lmp = lmc->lc_head; lmp; lmp = NEXT_RT_MAP(lmp)) 533 remove_lists(lmp, 1); 534 535 /* 536 * Finally, remove each object. remove_so() calls lm_delete(), thus 537 * effectively the link-map control head gets updated to point to the 538 * next link-map. 539 */ 540 while ((lmp = lmc->lc_head) != 0) 541 remove_so(lml, lmp); 542 543 lmc->lc_head = lmc->lc_tail = 0; 544 } 545 546 /* 547 * Determine whether an object is deletable. 548 */ 549 static int 550 is_deletable(APlist **lmalp, APlist **ghalp, Rt_map *lmp) 551 { 552 Aliste idx; 553 Bnd_desc *bdp; 554 Grp_hdl *ghp; 555 556 /* 557 * If the object hasn't yet been relocated take this as a sign that 558 * it's loading failed, thus we're here to cleanup. If the object is 559 * relocated it will only be retained if it was marked non-deletable, 560 * and exists on the main link-map control list. 561 */ 562 if ((FLAGS(lmp) & FLG_RT_RELOCED) && 563 (MODE(lmp) & RTLD_NODELETE) && (CNTL(lmp) == ALIST_OFF_DATA)) 564 return (0); 565 566 /* 567 * If this object is the head of a handle that has not been captured as 568 * a candidate for deletion, then this object is in use from a dlopen() 569 * outside of the scope of this dlclose() family. Dlopen'ed objects, 570 * and filtees, have group descriptors for their callers. Typically 571 * this parent will have callers that are not apart of this dlclose() 572 * family, and thus would be caught by the CALLERS test below. However, 573 * if the caller had itself been dlopen'ed, it may not have any explicit 574 * callers registered for itself. Thus, but looking for objects with 575 * handles we can ferret out these outsiders. 576 */ 577 for (APLIST_TRAVERSE(HANDLES(lmp), idx, ghp)) { 578 if (aplist_test(ghalp, ghp, 0) != ALE_EXISTS) 579 return (0); 580 } 581 582 /* 583 * If this object is called by any object outside of the family of 584 * objects selected for deletion, it can't be deleted. 585 */ 586 for (APLIST_TRAVERSE(CALLERS(lmp), idx, bdp)) { 587 if (aplist_test(lmalp, bdp->b_caller, 0) != 588 ALE_EXISTS) 589 return (0); 590 } 591 592 /* 593 * This object is a candidate for deletion. 594 */ 595 return (1); 596 } 597 598 /* 599 * Collect the groups (handles) and associated objects that are candidates for 600 * deletion. The criteria for deleting an object is whether it is only refer- 601 * enced from the objects within the groups that are candidates for deletion. 602 */ 603 static int 604 gdp_collect(APlist **ghalpp, APlist **lmalpp, Grp_hdl *ghp1) 605 { 606 Aliste idx; 607 Grp_desc *gdp; 608 int action; 609 610 /* 611 * Add this group to our group collection. If it isn't added either an 612 * allocation has failed, or it already exists. 613 */ 614 if ((action = aplist_test(ghalpp, ghp1, AL_CNT_GRPCLCT)) != 615 ALE_CREATE) 616 return (action); 617 618 /* 619 * Traverse the dependencies of the group and collect the associated 620 * objects. 621 */ 622 for (ALIST_TRAVERSE(ghp1->gh_depends, idx, gdp)) { 623 Rt_map *lmp = gdp->gd_depend; 624 625 /* 626 * We only want to process dependencies for deletion. Although 627 * we want to purge group descriptors for parents, we don't want 628 * to analyze the parent itself for additional filters or 629 * deletion. 630 */ 631 if ((gdp->gd_flags & GPD_PARENT) || 632 ((gdp->gd_flags & GPD_ADDEPS) == 0)) 633 continue; 634 635 if ((action = aplist_test(lmalpp, lmp, AL_CNT_GRPCLCT)) == 636 ALE_ALLOCFAIL) 637 return (0); 638 if (action == ALE_EXISTS) 639 continue; 640 641 /* 642 * If this object is a candidate for deletion, determine if the 643 * object provides any filtees. If so, the filter groups are 644 * added to the group collection. 645 * 646 * An object is a candidate for deletion if: 647 * 648 * . the object hasn't yet been relocated, in which case 649 * we're here to clean up a failed load, or 650 * . the object doesn't reside on the base link-map control 651 * list, in which case a group of objects, typically 652 * lazily loaded, or filtees, need cleaning up, or 653 * . the object isn't tagged as non-deletable. 654 */ 655 if ((((FLAGS(lmp) & FLG_RT_RELOCED) == 0) || 656 (CNTL(lmp) != ALIST_OFF_DATA) || 657 ((MODE(lmp) & RTLD_NODELETE) == 0)) && 658 (FLAGS1(lmp) & MSK_RT_FILTER)) { 659 Dyninfo *dip = DYNINFO(lmp); 660 uint_t cnt, max = DYNINFOCNT(lmp); 661 662 for (cnt = 0; cnt < max; cnt++, dip++) { 663 Pnode *pnp; 664 665 if ((dip->di_info == 0) || 666 ((dip->di_flags & MSK_DI_FILTER) == 0)) 667 continue; 668 669 for (pnp = (Pnode *)dip->di_info; pnp; 670 pnp = pnp->p_next) { 671 Grp_hdl *ghp2; 672 673 if ((pnp->p_len == 0) || ((ghp2 = 674 (Grp_hdl *)pnp->p_info) == 0)) 675 continue; 676 677 if (gdp_collect(ghalpp, lmalpp, 678 ghp2) == 0) 679 return (0); 680 } 681 } 682 } 683 } 684 return (1); 685 } 686 687 /* 688 * Traverse the list of deletable candidates. If an object can't be deleted 689 * then neither can its dependencies or filtees. Any object that is cleared 690 * from being deleted drops the deletion count, plus, if there are no longer 691 * any deletions pending we can discontinue any further processing. 692 */ 693 static int 694 remove_rescan(APlist *lmalp, APlist *ghalp, int *delcnt) 695 { 696 Aliste idx1; 697 Rt_map *lmp; 698 int rescan = 0; 699 700 for (APLIST_TRAVERSE(lmalp, idx1, lmp)) { 701 Aliste idx2; 702 Bnd_desc *bdp; 703 Dyninfo *dip; 704 uint_t cnt, max; 705 706 if (FLAGS(lmp) & FLG_RT_DELETE) 707 continue; 708 709 /* 710 * As this object can't be deleted, make sure its dependencies 711 * aren't deleted either. 712 */ 713 for (APLIST_TRAVERSE(DEPENDS(lmp), idx2, bdp)) { 714 Rt_map *dlmp = bdp->b_depend; 715 716 if (FLAGS(dlmp) & FLG_RT_DELETE) { 717 FLAGS(dlmp) &= ~FLG_RT_DELETE; 718 if (--(*delcnt) == 0) 719 return (0); 720 rescan = 1; 721 } 722 } 723 724 /* 725 * If this object is a filtee and one of its filters is outside 726 * of this dlclose family, then it can't be deleted either. 727 */ 728 if ((FLAGS1(lmp) & MSK_RT_FILTER) == 0) 729 continue; 730 731 dip = DYNINFO(lmp); 732 max = DYNINFOCNT(lmp); 733 734 for (cnt = 0; cnt < max; cnt++, dip++) { 735 Pnode *pnp; 736 737 if ((dip->di_info == 0) || 738 ((dip->di_flags & MSK_DI_FILTER) == 0)) 739 continue; 740 741 for (pnp = (Pnode *)dip->di_info; pnp; 742 pnp = pnp->p_next) { 743 Grp_hdl *ghp; 744 Grp_desc *gdp; 745 746 if ((pnp->p_len == 0) || 747 ((ghp = (Grp_hdl *)pnp->p_info) == 0)) 748 continue; 749 750 if (aplist_test(&ghalp, ghp, 0) == 751 ALE_EXISTS) 752 continue; 753 754 for (ALIST_TRAVERSE(ghp->gh_depends, idx2, 755 gdp)) { 756 Rt_map *dlmp = gdp->gd_depend; 757 758 if (FLAGS(dlmp) & FLG_RT_DELETE) { 759 FLAGS(dlmp) &= ~FLG_RT_DELETE; 760 if (--(*delcnt) == 0) 761 return (0); 762 rescan = 1; 763 } 764 } 765 766 /* 767 * Remove this group handle from our dynamic 768 * deletion list. 769 */ 770 (void) aplist_delete_value(ghalp, ghp); 771 } 772 } 773 } 774 return (rescan); 775 } 776 777 /* 778 * Cleanup any collection alists we've created. 779 */ 780 static void 781 remove_collect(APlist *ghalp, APlist *lmalp) 782 { 783 if (ghalp) 784 free(ghalp); 785 if (lmalp) 786 free(lmalp); 787 } 788 789 /* 790 * Remove a handle, leaving the associated objects intact. Besides the classic 791 * dlopen() usage, handles are used as a means of associating a group of objects 792 * and promoting modes. Once object promotion is completed, the handle should 793 * be discarded while leaving the associated objects intact. Leaving the handle 794 * would prevent the object from being deleted (as it looks like it's in use 795 * by another user). 796 */ 797 void 798 free_hdl(Grp_hdl *ghp, Rt_map *clmp, uint_t cdflags) 799 { 800 Grp_desc *gdp; 801 Aliste idx; 802 803 if (--(ghp->gh_refcnt) == 0) { 804 uintptr_t ndx; 805 806 for (ALIST_TRAVERSE(ghp->gh_depends, idx, gdp)) { 807 Rt_map *lmp = gdp->gd_depend; 808 809 if (ghp->gh_ownlmp == lmp) 810 (void) aplist_delete_value(HANDLES(lmp), ghp); 811 (void) aplist_delete_value(GROUPS(lmp), ghp); 812 } 813 (void) free(ghp->gh_depends); 814 815 /* LINTED */ 816 ndx = (uintptr_t)ghp % HDLIST_SZ; 817 list_delete(&hdl_list[ndx], ghp); 818 819 (void) free(ghp); 820 821 } else if (clmp) { 822 /* 823 * It's possible that an RTLD_NOW promotion (via GPD_PROMOTE) 824 * has associated a caller with a handle that is already in use. 825 * In this case, find the caller and either remove the caller 826 * from the handle, or if the caller is used for any other 827 * reason, clear the promotion flag. 828 */ 829 for (ALIST_TRAVERSE(ghp->gh_depends, idx, gdp)) { 830 Rt_map *lmp = gdp->gd_depend; 831 832 if (lmp != clmp) 833 continue; 834 835 if (gdp->gd_flags == cdflags) { 836 alist_delete(ghp->gh_depends, &idx); 837 (void) aplist_delete_value(GROUPS(lmp), ghp); 838 } else { 839 gdp->gd_flags &= ~cdflags; 840 } 841 return; 842 } 843 } 844 } 845 846 /* 847 * If a load operation, using a new link-map control list, has failed, then 848 * forcibly remove the failed objects. This failure can occur as a result 849 * of a lazy load, a dlopen(), or a filtee load, once the application is 850 * running. If the link-map control list has not yet started relocation, then 851 * cleanup is simply a process of removing all the objects from the control 852 * list. If relocation has begun, then other loads may have been triggered to 853 * satisfy the relocations, and thus we need to break down the control list 854 * using handles. 855 * 856 * The objects associated with this load must be part of a unique handle. In 857 * the case of a dlopen() or filtee request, a handle will have been created. 858 * For a lazyload request, a handle must be generated so that the remove 859 * process can use the handle. 860 * 861 * During the course of processing these objects, other objects (handles) may 862 * have been loaded to satisfy relocation requirements. After these families 863 * have successfully loaded, they will have been propagated to the same link-map 864 * control list. The failed objects need to be removed from this list, while 865 * any successfully loaded families can be left alone, and propagated to the 866 * previous link-map control list. By associating each load request with a 867 * handle, we can isolate the failed objects while not interfering with any 868 * successfully loaded families. 869 */ 870 void 871 remove_lmc(Lm_list *lml, Rt_map *clmp, Lm_cntl *lmc, Aliste lmco, 872 const char *name) 873 { 874 Grp_hdl *ghp; 875 Grp_desc *gdp; 876 Aliste idx; 877 Rt_map *lmp; 878 879 DBG_CALL(Dbg_file_cleanup(lml, name, lmco)); 880 881 /* 882 * Obtain a handle for the first object on the link-map control list. 883 * If none exists (which would occur from a lazy load request), and 884 * the link-map control list is being relocated, create a handle. 885 */ 886 lmp = lmc->lc_head; 887 if (HANDLES(lmp)) { 888 ghp = (Grp_hdl *)HANDLES(lmp)->apl_data[0]; 889 890 } else if (lmc->lc_flags & LMC_FLG_RELOCATING) { 891 /* 892 * Establish a handle, and should anything fail, fall through 893 * to remove the link-map control list. 894 */ 895 if (((ghp = 896 hdl_create(lml, lmc->lc_head, 0, 0, GPD_ADDEPS, 0)) == 0) || 897 (hdl_initialize(ghp, lmc->lc_head, 0, 0) == 0)) 898 lmc->lc_flags &= ~LMC_FLG_RELOCATING; 899 } else { 900 ghp = 0; 901 } 902 903 /* 904 * If relocation hasn't begun, simply remove all the objects from this 905 * list, and any handle that may have been created. 906 */ 907 if ((lmc->lc_flags & LMC_FLG_RELOCATING) == 0) { 908 remove_incomplete(lml, lmco); 909 910 if (ghp) { 911 ghp->gh_refcnt = 1; 912 free_hdl(ghp, 0, 0); 913 } 914 return; 915 } 916 917 ASSERT(ghp != 0); 918 919 /* 920 * As the objects of this handle are being forcibly removed, first 921 * remove any associations to objects on parent link-map control 922 * lists. This breaks the bond between a caller and a hierarchy of 923 * dependencies represented by the handle, thus the caller doesn't lock 924 * the hierarchy and prevent their deletion from the generic handle 925 * processing or remove_hdl(). 926 * 927 * This scenario can be produced when the relocation of a object 928 * results in vectoring through a filter that is already loaded. The 929 * filtee may be on the link-map list that is presently being processed, 930 * however an association between the filter and filtee would have been 931 * established during filtee processing. It is this association that 932 * must be broken to allow the objects on this link-map list to be 933 * removed. 934 */ 935 for (ALIST_TRAVERSE(ghp->gh_depends, idx, gdp)) { 936 Rt_map *lmp = gdp->gd_depend; 937 938 /* 939 * If this object has not been relocated, break down any 940 * dependency relationships the object might have established. 941 */ 942 if ((FLAGS(lmp) & FLG_RT_RELOCED) == 0) 943 remove_lists(lmp, 1); 944 945 if (CNTL(lmp) == lmco) 946 continue; 947 948 if (gdp->gd_flags & GPD_FILTER) { 949 Dyninfo *dip = DYNINFO(lmp); 950 uint_t cnt, max = DYNINFOCNT(lmp); 951 952 for (cnt = 0; cnt < max; cnt++, dip++) { 953 Pnode *pnp; 954 955 if ((dip->di_info == 0) || 956 ((dip->di_flags & MSK_DI_FILTER) == 0)) 957 continue; 958 959 for (pnp = (Pnode *)dip->di_info; pnp; 960 pnp = pnp->p_next) { 961 if ((Grp_hdl *)pnp->p_info == ghp) { 962 pnp->p_info = 0; 963 break; 964 } 965 } 966 } 967 } 968 (void) aplist_delete_value(GROUPS(lmp), ghp); 969 alist_delete(ghp->gh_depends, &idx); 970 } 971 972 /* 973 * Having removed any callers, set the group handle reference count to 974 * one, and let the generic handle remover delete the associated 975 * objects. 976 */ 977 ghp->gh_refcnt = 1; 978 (void) remove_hdl(ghp, clmp, 0); 979 980 /* 981 * If this link-map control list still contains objects, determine the 982 * previous control list and move the objects. 983 */ 984 if (lmc->lc_head) { 985 Lm_cntl *plmc; 986 Aliste plmco; 987 988 plmco = lmco - lml->lm_lists->al_size; 989 /* LINTED */ 990 plmc = (Lm_cntl *)alist_item_by_offset(lml->lm_lists, plmco); 991 992 lm_move(lml, lmco, plmco, lmc, plmc); 993 } 994 } 995 996 /* 997 * Remove the objects associated with a handle. There are two goals here, to 998 * delete the objects associated with the handle, and to remove the handle 999 * itself. Things get a little more complex if the objects selected for 1000 * deletion are filters, in this case we also need to collect their filtees, 1001 * and process the combined groups as a whole. But, care still must be exer- 1002 * cised to make sure any filtees found aren't being used by filters outside of 1003 * the groups we've collect. The series of events is basically: 1004 * 1005 * o Determine the groups (handles) that might be deletable. 1006 * 1007 * o Determine the objects of these handles that can be deleted. 1008 * 1009 * o Fire the fini's of those objects selected for deletion. 1010 * 1011 * o Remove all inter-dependency linked lists while the objects link-maps 1012 * are still available. 1013 * 1014 * o Remove all deletable objects link-maps and unmap the objects themselves. 1015 * 1016 * o Remove the handle descriptors for each deleted object, and hopefully 1017 * the whole handle. 1018 * 1019 * An handle that can't be deleted is added to an orphans list. This list is 1020 * revisited any time another dlclose() request results in handle descriptors 1021 * being deleted. These deleted descriptors can be sufficient to allow the 1022 * final deletion of the orphaned handles. 1023 */ 1024 int 1025 remove_hdl(Grp_hdl *ghp, Rt_map *clmp, int *removed) 1026 { 1027 Rt_map *lmp; 1028 int rescan = 0; 1029 int delcnt = 0, rmcnt = 0, error = 0, orphans; 1030 APlist *lmalp = NULL, *ghalp = NULL; 1031 Aliste idx1, idx2; 1032 Grp_hdl *ghp2; 1033 Grp_desc *gdp; 1034 Lm_list *lml = NULL; 1035 1036 /* 1037 * Generate the family of groups and objects that are candidates for 1038 * deletion. This consists of the objects that are explicitly defined 1039 * as dependencies of this handle, plus any filtee handles and their 1040 * associated objects. 1041 */ 1042 if (gdp_collect(&ghalp, &lmalp, ghp) == 0) { 1043 remove_collect(ghalp, lmalp); 1044 return (0); 1045 } 1046 1047 DBG_CALL(Dbg_file_hdl_title(DBG_HDL_DELETE)); 1048 1049 /* 1050 * Traverse the groups we've collected to determine if any filtees are 1051 * included. If so, and the filtee handle is in use by a filter outside 1052 * of the family of objects collected for this deletion, it can not be 1053 * removed. 1054 */ 1055 for (APLIST_TRAVERSE(ghalp, idx1, ghp2)) { 1056 Grp_hdl *ghp = ghp2; 1057 1058 DBG_CALL(Dbg_file_hdl_collect(ghp, 0)); 1059 1060 if ((ghp->gh_flags & GPH_FILTEE) == 0) 1061 continue; 1062 1063 /* 1064 * Special case for ld.so.1. There can be multiple instances of 1065 * libdl.so.1 using this handle, so although we want the handles 1066 * reference count to be decremented, we don't want the handle 1067 * removed. 1068 */ 1069 if (ghp->gh_flags & GPH_LDSO) { 1070 DBG_CALL(Dbg_file_hdl_collect(ghp, 1071 NAME(lml_rtld.lm_head))); 1072 aplist_delete(ghalp, &idx1); 1073 continue; 1074 } 1075 1076 for (ALIST_TRAVERSE(ghp->gh_depends, idx2, gdp)) { 1077 Grp_hdl *ghp3; 1078 Aliste idx3; 1079 1080 /* 1081 * Determine whether this dependency is the filtee's 1082 * parent filter, and that it isn't also an explicit 1083 * dependency (in which case it would have added its own 1084 * dependencies to the handle). 1085 */ 1086 if ((gdp->gd_flags & 1087 (GPD_FILTER | GPD_ADDEPS)) != GPD_FILTER) 1088 continue; 1089 1090 if (aplist_test(&lmalp, gdp->gd_depend, 0) == 1091 ALE_EXISTS) 1092 continue; 1093 1094 /* 1095 * Remove this group handle from our dynamic deletion 1096 * list. In addition, recompute the list of objects 1097 * that are candidates for deletion to continue this 1098 * group verification. 1099 */ 1100 DBG_CALL(Dbg_file_hdl_collect(ghp, 1101 NAME(gdp->gd_depend))); 1102 aplist_delete(ghalp, &idx1); 1103 1104 free(lmalp); 1105 lmalp = NULL; 1106 for (APLIST_TRAVERSE(ghalp, idx3, ghp3)) { 1107 Aliste idx4; 1108 Grp_desc *gdp4; 1109 1110 for (ALIST_TRAVERSE(ghp3->gh_depends, 1111 idx4, gdp4)) { 1112 if ((gdp4->gd_flags & GPD_ADDEPS) == 0) 1113 continue; 1114 if (aplist_test(&lmalp, gdp4->gd_depend, 1115 AL_CNT_GRPCLCT) == ALE_ALLOCFAIL) { 1116 remove_collect(ghalp, lmalp); 1117 return (0); 1118 } 1119 } 1120 } 1121 break; 1122 } 1123 } 1124 1125 /* 1126 * Now that we've collected all the handles dependencies, traverse the 1127 * collection determining whether they are a candidate for deletion. 1128 */ 1129 for (APLIST_TRAVERSE(lmalp, idx1, lmp)) { 1130 /* 1131 * Establish which link-map list we're dealing with for later 1132 * .fini processing. 1133 */ 1134 if (lml == 0) 1135 lml = LIST(lmp); 1136 1137 /* 1138 * If an object isn't a candidate for deletion we'll have to 1139 * rescan the handle insuring that this objects dependencies 1140 * aren't deleted either. 1141 */ 1142 if (is_deletable(&lmalp, &ghalp, lmp)) { 1143 FLAGS(lmp) |= FLG_RT_DELETE; 1144 delcnt++; 1145 } else 1146 rescan = 1; 1147 } 1148 1149 /* 1150 * Rescan the handle if any objects where found non-deletable. 1151 */ 1152 while (rescan) 1153 rescan = remove_rescan(lmalp, ghalp, &delcnt); 1154 1155 /* 1156 * Now that we have determined the number of groups that are candidates 1157 * for removal, mark each group descriptor as a candidate for removal 1158 * from the group. 1159 */ 1160 for (APLIST_TRAVERSE(ghalp, idx1, ghp2)) { 1161 for (ALIST_TRAVERSE(ghp2->gh_depends, idx2, gdp)) 1162 gdp->gd_flags |= GPD_REMOVE; 1163 } 1164 1165 /* 1166 * Now that we know which objects on this handle can't be deleted 1167 * determine whether they still need to remain identified as belonging 1168 * to this group to be able to continue binding to one another. 1169 */ 1170 for (APLIST_TRAVERSE(ghalp, idx1, ghp2)) { 1171 Grp_hdl *ghp = ghp2; 1172 1173 for (ALIST_TRAVERSE(ghp->gh_depends, idx2, gdp)) { 1174 Aliste idx3; 1175 Bnd_desc *bdp; 1176 1177 lmp = gdp->gd_depend; 1178 1179 if (FLAGS(lmp) & FLG_RT_DELETE) 1180 continue; 1181 1182 for (APLIST_TRAVERSE(DEPENDS(lmp), idx3, bdp)) { 1183 Aliste idx4; 1184 Grp_desc *gdp4; 1185 Rt_map *dlmp = bdp->b_depend; 1186 1187 /* 1188 * If this dependency (dlmp) can be referenced 1189 * by the caller (clmp) without being part of 1190 * this group (ghp) then belonging to this group 1191 * is no longer necessary. This can occur when 1192 * objects are part of multiple handles, or if a 1193 * previously deleted handle was moved to the 1194 * orphan list and has been reopened. Note, 1195 * first make sure the caller can reference the 1196 * dependency with this group, if it can't we 1197 * must be bound to a filtee, so there's no need 1198 * to remain a part of this group either. 1199 */ 1200 if ((callable(lmp, dlmp, 0, 0) == 0) || 1201 callable(lmp, dlmp, ghp, 0)) 1202 continue; 1203 1204 if (gdp->gd_flags & GPD_REMOVE) 1205 gdp->gd_flags &= ~GPD_REMOVE; 1206 1207 for (ALIST_TRAVERSE(ghp->gh_depends, 1208 idx4, gdp4)) { 1209 if (gdp4->gd_depend != dlmp) 1210 continue; 1211 1212 if (gdp4->gd_flags & GPD_REMOVE) 1213 gdp4->gd_flags &= ~GPD_REMOVE; 1214 } 1215 } 1216 } 1217 } 1218 1219 /* 1220 * If the owner of a handle can't be deleted and it's handle descriptor 1221 * must remain also, don't delete the handle at all. Leave it for 1222 * possible later use. Although it's left intact, it will still be 1223 * moved to the orphans list, as we might be able to revisit it on later 1224 * dlclose() operations and finally remove the underlying objects. Note 1225 * that the handle still remains attached to the owner via the HANDLES 1226 * list, so that it can be re-associated to the owner if a dlopen() 1227 * of this object reoccurs. 1228 */ 1229 for (APLIST_TRAVERSE(ghalp, idx1, ghp2)) { 1230 Grp_hdl *ghp = ghp2; 1231 1232 /* 1233 * If this handle is already an orphan, or if it's owner is 1234 * deletable there's no need to inspect its dependencies. 1235 */ 1236 if ((ghp->gh_ownlmp == 0) || 1237 (FLAGS(ghp->gh_ownlmp) & FLG_RT_DELETE)) 1238 continue; 1239 1240 /* 1241 * Make sure all handle dependencies aren't removed or the 1242 * dependencies themselves aren't deleted. 1243 */ 1244 for (ALIST_TRAVERSE(ghp->gh_depends, idx2, gdp)) { 1245 lmp = gdp->gd_depend; 1246 1247 /* 1248 * The first dependency of a non-orphaned handle is the 1249 * owner. If the handle descriptor for this isn't 1250 * required there's no need to look at any other of the 1251 * handles dependencies. 1252 */ 1253 if ((lmp == ghp->gh_ownlmp) && 1254 (gdp->gd_flags & GPD_REMOVE)) 1255 break; 1256 1257 if (gdp->gd_flags & GPD_REMOVE) 1258 gdp->gd_flags &= ~GPD_REMOVE; 1259 if (FLAGS(lmp) & FLG_RT_DELETE) { 1260 FLAGS(lmp) &= ~FLG_RT_DELETE; 1261 delcnt--; 1262 } 1263 } 1264 } 1265 1266 /* 1267 * Final scan of objects to see if any objects are to to be deleted. 1268 * Also - display diagnostic information on what operations are to be 1269 * performed on the collected handles before firing .fini's (which 1270 * produces additional diagnostics). 1271 */ 1272 for (APLIST_TRAVERSE(ghalp, idx1, ghp2)) { 1273 Grp_hdl *ghp = ghp2; 1274 1275 DBG_CALL(Dbg_file_hdl_title(DBG_HDL_DELETE)); 1276 1277 for (ALIST_TRAVERSE(ghp->gh_depends, idx2, gdp)) { 1278 int flag; 1279 1280 lmp = gdp->gd_depend; 1281 1282 /* 1283 * Note, we must never delete a parent. The parent 1284 * may already be tagged for deletion from a previous 1285 * dlclose(). That dlclose has triggered this dlclose(), 1286 * but the parents deletion is the responsibility of the 1287 * previous dlclose(), not this one. 1288 */ 1289 if ((FLAGS(lmp) & FLG_RT_DELETE) && 1290 ((gdp->gd_flags & GPD_PARENT) == 0)) { 1291 flag = DBG_DEP_DELETE; 1292 1293 /* 1294 * Remove any pathnames from the FullpathNode 1295 * AVL tree. As we're about to fire .fini's, 1296 * it's possible this object will be required 1297 * again, in which case we want to make sure a 1298 * new version of the object gets loaded. 1299 */ 1300 if (FPNODE(lmp)) 1301 fpavl_remove(lmp); 1302 } else if (gdp->gd_flags & GPD_REMOVE) 1303 flag = DBG_DEP_REMOVE; 1304 else 1305 flag = DBG_DEP_REMAIN; 1306 1307 DBG_CALL(Dbg_file_hdl_action(ghp, lmp, flag, 0)); 1308 } 1309 } 1310 1311 /* 1312 * If there are objects to be deleted process their .fini's. 1313 */ 1314 if (delcnt) { 1315 Rt_map **tobj; 1316 1317 /* 1318 * If we're being audited tell the audit library that we're 1319 * about to go deleting dependencies. 1320 */ 1321 if (clmp && ((LIST(clmp)->lm_tflags | FLAGS1(clmp)) & 1322 LML_TFLG_AUD_ACTIVITY)) 1323 audit_activity(clmp, LA_ACT_DELETE); 1324 1325 /* 1326 * Sort and fire all fini's of the objects selected for 1327 * deletion. Note that we have to start our search from the 1328 * link-map head - there's no telling whether this object has 1329 * dependencies on objects that were loaded before it and which 1330 * can now be deleted. If the tsort() fails because of an 1331 * allocation error then that might just be a symptom of why 1332 * we're here in the first place - forgo the fini's but 1333 * continue to try cleaning up. 1334 */ 1335 lml->lm_flags |= LML_FLG_OBJDELETED; 1336 1337 if (((tobj = tsort(lml->lm_head, delcnt, 1338 (RT_SORT_DELETE | RT_SORT_FWD))) != 0) && 1339 (tobj != (Rt_map **)S_ERROR)) { 1340 error = purge_exit_handlers(lml, tobj); 1341 call_fini(lml, tobj); 1342 } 1343 1344 /* 1345 * Audit the closure of the dlopen'ed object to any local 1346 * auditors. Any global auditors would have been caught by 1347 * call_fini(), but as the link-maps CALLERS was removed 1348 * already we do the local auditors explicitly. 1349 */ 1350 for (APLIST_TRAVERSE(ghalp, idx1, ghp2)) { 1351 Grp_hdl *ghp = ghp2; 1352 Rt_map *dlmp = ghp->gh_ownlmp; 1353 1354 if (clmp && dlmp && 1355 ((LIST(dlmp)->lm_flags & LML_FLG_NOAUDIT) == 0) && 1356 (FLAGS1(clmp) & LML_TFLG_AUD_OBJCLOSE)) 1357 _audit_objclose(&(AUDITORS(clmp)->ad_list), 1358 dlmp); 1359 } 1360 } 1361 1362 /* 1363 * Now that .fini processing (which may have involved new bindings) 1364 * is complete, remove all inter-dependency lists from those objects 1365 * selected for deletion. 1366 */ 1367 for (APLIST_TRAVERSE(lmalp, idx1, lmp)) { 1368 Dyninfo *dip; 1369 uint_t cnt, max; 1370 1371 if (FLAGS(lmp) & FLG_RT_DELETE) 1372 remove_lists(lmp, 0); 1373 1374 /* 1375 * Determine whether we're dealing with a filter, and if so 1376 * process any inter-dependencies with its filtee's. 1377 */ 1378 if ((FLAGS1(lmp) & MSK_RT_FILTER) == 0) 1379 continue; 1380 1381 dip = DYNINFO(lmp); 1382 max = DYNINFOCNT(lmp); 1383 1384 for (cnt = 0; cnt < max; cnt++, dip++) { 1385 Pnode *pnp; 1386 1387 if ((dip->di_info == 0) || 1388 ((dip->di_flags & MSK_DI_FILTER) == 0)) 1389 continue; 1390 1391 for (pnp = (Pnode *)dip->di_info; pnp; 1392 pnp = pnp->p_next) { 1393 Grp_hdl *ghp; 1394 1395 if ((pnp->p_len == 0) || 1396 ((ghp = (Grp_hdl *)pnp->p_info) == 0)) 1397 continue; 1398 1399 /* 1400 * Determine whether this filtee's handle is a 1401 * part of the list of handles being deleted. 1402 */ 1403 if (aplist_test(&ghalp, ghp, 0) == ALE_EXISTS) { 1404 /* 1405 * If this handle exists on the deletion 1406 * list, then it has been removed. If 1407 * this filter isn't going to be 1408 * deleted, sever its reference to the 1409 * handle. 1410 */ 1411 pnp->p_info = 0; 1412 } else { 1413 /* 1414 * If this handle isn't on the deletion 1415 * list, then it must still exist. If 1416 * this filter is being deleted, make 1417 * sure the filtees reference count 1418 * gets decremented. 1419 */ 1420 if ((FLAGS(lmp) & FLG_RT_DELETE) && 1421 ((gdp->gd_flags & 1422 GPD_PARENT) == 0)) { 1423 (void) dlclose_core(ghp, 1424 lmp, lml); 1425 } 1426 } 1427 } 1428 } 1429 } 1430 1431 /* 1432 * If called from dlclose(), determine if there are already handles on 1433 * the orphans list that we can reinvestigate. 1434 */ 1435 if ((removed == 0) && hdl_list[HDLIST_ORP].head) 1436 orphans = 1; 1437 else 1438 orphans = 0; 1439 1440 /* 1441 * Finally remove any handle infrastructure and remove any objects 1442 * marked for deletion. 1443 */ 1444 for (APLIST_TRAVERSE(ghalp, idx1, ghp2)) { 1445 Grp_hdl *ghp = ghp2; 1446 1447 /* 1448 * If we're not dealing with orphaned handles remove this handle 1449 * from its present handle list. 1450 */ 1451 if (removed == 0) { 1452 uintptr_t ndx; 1453 1454 /* LINTED */ 1455 ndx = (uintptr_t)ghp % HDLIST_SZ; 1456 list_delete(&hdl_list[ndx], ghp); 1457 } 1458 1459 /* 1460 * Traverse each handle dependency. Retain the dependencies 1461 * flags to insure we don't delete any parents (the flags 1462 * information is deleted as part of the alist removal that 1463 * occurs before we inspect the object for deletion). 1464 */ 1465 for (ALIST_TRAVERSE(ghp->gh_depends, idx2, gdp)) { 1466 uint_t flags = gdp->gd_flags; 1467 1468 if ((flags & GPD_REMOVE) == 0) 1469 continue; 1470 1471 lmp = gdp->gd_depend; 1472 rmcnt++; 1473 1474 /* 1475 * If this object is the owner of the handle break that 1476 * association in case the handle is retained. 1477 */ 1478 if (ghp->gh_ownlmp == lmp) { 1479 (void) aplist_delete_value(HANDLES(lmp), ghp); 1480 ghp->gh_ownlmp = 0; 1481 } 1482 1483 (void) aplist_delete_value(GROUPS(lmp), ghp); 1484 alist_delete(ghp->gh_depends, &idx2); 1485 1486 /* 1487 * Complete the link-map deletion if appropriate. 1488 */ 1489 if ((FLAGS(lmp) & FLG_RT_DELETE) && 1490 ((flags & GPD_PARENT) == 0)) { 1491 tls_modaddrem(lmp, TM_FLG_MODREM); 1492 remove_so(LIST(lmp), lmp); 1493 } 1494 } 1495 1496 /* 1497 * If we've deleted all the dependencies of the handle, finalize 1498 * the cleanup by removing the handle itself. 1499 * 1500 * Otherwise we're left with a handle containing one or more 1501 * objects that can not be deleted (they're in use by other 1502 * handles, non-deletable, etc.), but require to remain a part 1503 * of this group to allow them to continue binding to one 1504 * another. 1505 * 1506 * If the handles reference count is zero, or represents a 1507 * link-map list (dlopen(0)), then move that handle to the 1508 * orphans list. Should another dlclose() operation occur that 1509 * results in the removal of handle descriptors, these orphan 1510 * handles are re-examined to determine if their deletion can 1511 * be completed. 1512 */ 1513 if (ghp->gh_depends->al_nitems == 0) { 1514 free(ghp->gh_depends); 1515 free(ghp); 1516 1517 } else if ((removed == 0) && (ghp->gh_refcnt == 0) && 1518 ((ghp->gh_flags & GPH_ZERO) == 0)) { 1519 /* 1520 * Move this handle to the orphans list. 1521 */ 1522 (void) list_append(&hdl_list[HDLIST_ORP], ghp); 1523 1524 if (DBG_ENABLED) { 1525 DBG_CALL(Dbg_file_hdl_title(DBG_HDL_ORPHAN)); 1526 for (ALIST_TRAVERSE(ghp->gh_depends, idx1, gdp)) 1527 DBG_CALL(Dbg_file_hdl_action(ghp, 1528 gdp->gd_depend, DBG_DEP_ORPHAN, 0)); 1529 } 1530 } 1531 } 1532 1533 /* 1534 * If no handle descriptors got removed there's no point in looking for 1535 * orphans to process. 1536 */ 1537 if (rmcnt == 0) 1538 orphans = 0; 1539 1540 /* 1541 * Cleanup any alists we've created. 1542 */ 1543 remove_collect(ghalp, lmalp); 1544 1545 /* 1546 * If orphan processing isn't required we're done. If our processing 1547 * originated from investigating orphans, return the number of handle 1548 * descriptors removed as an indication whether orphan processing 1549 * should continue. 1550 */ 1551 if (orphans == 0) { 1552 if (removed) 1553 *removed = rmcnt; 1554 return (error); 1555 } 1556 1557 /* 1558 * Traverse the orphans list as many times as necessary until no 1559 * handle removals occur. 1560 */ 1561 do { 1562 List list; 1563 Listnode *lnp; 1564 Grp_hdl *ghp, *oghp = 0; 1565 int title = 0; 1566 1567 /* 1568 * Effectively clean the HDLIST_ORP list. Any object that can't 1569 * be removed will be re-added to the list. 1570 */ 1571 list = hdl_list[HDLIST_ORP]; 1572 hdl_list[HDLIST_ORP].head = hdl_list[HDLIST_ORP].tail = 0; 1573 1574 rescan = 0; 1575 for (LIST_TRAVERSE(&list, lnp, ghp)) { 1576 int _error, _remove; 1577 1578 if (title++ == 0) 1579 DBG_CALL(Dbg_file_del_rescan(ghp->gh_ownlml)); 1580 1581 if (oghp) { 1582 list_delete(&list, oghp); 1583 oghp = 0; 1584 } 1585 1586 if (((_error = remove_hdl(ghp, clmp, &_remove)) != 0) && 1587 (error == 0)) 1588 error = _error; 1589 1590 if (_remove) 1591 rescan++; 1592 1593 oghp = ghp; 1594 } 1595 if (oghp) { 1596 list_delete(&list, oghp); 1597 oghp = 0; 1598 } 1599 1600 } while (rescan && hdl_list[HDLIST_ORP].head); 1601 1602 return (error); 1603 } 1604