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