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