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