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