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