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