xref: /illumos-gate/usr/src/uts/common/fs/autofs/auto_subr.c (revision 33efde4275d24731ef87927237b0ffb0630b6b2d)
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 (c) 1992, 2010, Oracle and/or its affiliates. All rights reserved.
24  */
25 
26 #include <sys/param.h>
27 #include <sys/kmem.h>
28 #include <sys/errno.h>
29 #include <sys/proc.h>
30 #include <sys/disp.h>
31 #include <sys/vfs.h>
32 #include <sys/vnode.h>
33 #include <sys/pathname.h>
34 #include <sys/cred.h>
35 #include <sys/mount.h>
36 #include <sys/cmn_err.h>
37 #include <sys/debug.h>
38 #include <sys/systm.h>
39 #include <sys/dirent.h>
40 #include <fs/fs_subr.h>
41 #include <sys/fs/autofs.h>
42 #include <sys/callb.h>
43 #include <sys/sysmacros.h>
44 #include <sys/zone.h>
45 #include <sys/door.h>
46 #include <sys/fs/mntdata.h>
47 #include <nfs/mount.h>
48 #include <rpc/clnt.h>
49 #include <rpcsvc/autofs_prot.h>
50 #include <nfs/rnode.h>
51 #include <sys/utsname.h>
52 #include <sys/schedctl.h>
53 
54 /*
55  * Autofs and Zones:
56  *
57  * Zones are delegated the responsibility of managing their own autofs mounts
58  * and maps.  Each zone runs its own copy of automountd, with its own timeouts,
59  * and other logically "global" parameters.  kRPC and virtualization in the
60  * loopback transport (tl) will prevent a zone from communicating with another
61  * zone's automountd.
62  *
63  * Each zone has its own "rootfnnode" and associated tree of auto nodes.
64  *
65  * Each zone also has its own set of "unmounter" kernel threads; these are
66  * created and run within the zone's context (ie, they are created via
67  * zthread_create()).
68  *
69  * Cross-zone mount triggers are disallowed.  There is a check in
70  * auto_trigger_mount() to this effect; EPERM is returned to indicate that the
71  * mount is not owned by the caller.
72  *
73  * autofssys() enables a caller in the global zone to clean up in-kernel (as
74  * well as regular) autofs mounts via the unmount_tree() mechanism.  This is
75  * routinely done when all mounts are removed as part of zone shutdown.
76  */
77 #define	TYPICALMAXPATHLEN	64
78 
79 static kmutex_t autofs_nodeid_lock;
80 
81 /* max number of unmount threads running */
82 static int autofs_unmount_threads = 5;
83 static int autofs_unmount_thread_timer = 120;	/* in seconds */
84 
85 static int auto_perform_link(fnnode_t *, struct linka *, cred_t *);
86 static int auto_perform_actions(fninfo_t *, fnnode_t *,
87     action_list *, cred_t *);
88 static int auto_getmntpnt(vnode_t *, char *, vnode_t **, cred_t *);
89 static int auto_lookup_request(fninfo_t *, char *, struct linka *,
90     bool_t, bool_t *, cred_t *);
91 static int auto_mount_request(fninfo_t *, char *, action_list **, cred_t *,
92     bool_t);
93 
94 /*
95  * Clears the MF_INPROG flag, and wakes up those threads sleeping on
96  * fn_cv_mount if MF_WAITING is set.
97  */
98 void
auto_unblock_others(fnnode_t * fnp,uint_t operation)99 auto_unblock_others(
100 	fnnode_t *fnp,
101 	uint_t operation)		/* either MF_INPROG or MF_LOOKUP */
102 {
103 	ASSERT(operation & (MF_INPROG | MF_LOOKUP));
104 	fnp->fn_flags &= ~operation;
105 	if (fnp->fn_flags & MF_WAITING) {
106 		fnp->fn_flags &= ~MF_WAITING;
107 		cv_broadcast(&fnp->fn_cv_mount);
108 	}
109 }
110 
111 int
auto_wait4mount(fnnode_t * fnp)112 auto_wait4mount(fnnode_t *fnp)
113 {
114 	int error;
115 	k_sigset_t smask;
116 
117 	AUTOFS_DPRINT((4, "auto_wait4mount: fnp=%p\n", (void *)fnp));
118 
119 	mutex_enter(&fnp->fn_lock);
120 	while (fnp->fn_flags & (MF_INPROG | MF_LOOKUP)) {
121 		/*
122 		 * There is a mount or a lookup in progress.
123 		 */
124 		fnp->fn_flags |= MF_WAITING;
125 		sigintr(&smask, 1);
126 		if (!cv_wait_sig(&fnp->fn_cv_mount, &fnp->fn_lock)) {
127 			/*
128 			 * Decided not to wait for operation to
129 			 * finish after all.
130 			 */
131 			sigunintr(&smask);
132 			mutex_exit(&fnp->fn_lock);
133 			return (EINTR);
134 		}
135 		sigunintr(&smask);
136 	}
137 	error = fnp->fn_error;
138 
139 	if (error == EINTR) {
140 		/*
141 		 * The thread doing the mount got interrupted, we need to
142 		 * try again, by returning EAGAIN.
143 		 */
144 		error = EAGAIN;
145 	}
146 	mutex_exit(&fnp->fn_lock);
147 
148 	AUTOFS_DPRINT((5, "auto_wait4mount: fnp=%p error=%d\n", (void *)fnp,
149 	    error));
150 	return (error);
151 }
152 
153 int
auto_lookup_aux(fnnode_t * fnp,char * name,cred_t * cred)154 auto_lookup_aux(fnnode_t *fnp, char *name, cred_t *cred)
155 {
156 	struct fninfo *fnip;
157 	struct linka link;
158 	bool_t mountreq = FALSE;
159 	int error = 0;
160 
161 	fnip = vfstofni(fntovn(fnp)->v_vfsp);
162 	bzero(&link, sizeof (link));
163 	error = auto_lookup_request(fnip, name, &link, TRUE, &mountreq, cred);
164 	if (!error) {
165 		if (link.link != NULL) {
166 			error = ENOENT;
167 			/*
168 			 * This node should be a symlink
169 			 */
170 			if (*link.link != '\0')
171 				error = auto_perform_link(fnp, &link, cred);
172 		} else if (mountreq) {
173 			/*
174 			 * The automount daemon is requesting a mount,
175 			 * implying this entry must be a wildcard match and
176 			 * therefore in need of verification that the entry
177 			 * exists on the server.
178 			 */
179 			mutex_enter(&fnp->fn_lock);
180 			AUTOFS_BLOCK_OTHERS(fnp, MF_INPROG);
181 			fnp->fn_error = 0;
182 
183 			/*
184 			 * Unblock other lookup requests on this node,
185 			 * this is needed to let the lookup generated by
186 			 * the mount call to complete. The caveat is
187 			 * other lookups on this node can also get by,
188 			 * i.e., another lookup on this node that occurs
189 			 * while this lookup is attempting the mount
190 			 * would return a positive result no matter what.
191 			 * Therefore two lookups on the this node could
192 			 * potentially get disparate results.
193 			 */
194 			AUTOFS_UNBLOCK_OTHERS(fnp, MF_LOOKUP);
195 			mutex_exit(&fnp->fn_lock);
196 			/*
197 			 * auto_new_mount_thread fires up a new thread which
198 			 * calls automountd finishing up the work
199 			 */
200 			auto_new_mount_thread(fnp, name, cred);
201 
202 			/*
203 			 * At this point, we are simply another thread
204 			 * waiting for the mount to complete
205 			 */
206 			error = auto_wait4mount(fnp);
207 			if (error == AUTOFS_SHUTDOWN)
208 				error = ENOENT;
209 		}
210 	}
211 
212 	if (link.link)
213 		kmem_free(link.link, strlen(link.link) + 1);
214 	if (link.dir)
215 		kmem_free(link.dir, strlen(link.dir) + 1);
216 	mutex_enter(&fnp->fn_lock);
217 	fnp->fn_error = error;
218 
219 	/*
220 	 * Notify threads waiting for lookup/mount that
221 	 * it's done.
222 	 */
223 	if (mountreq) {
224 		AUTOFS_UNBLOCK_OTHERS(fnp, MF_INPROG);
225 	} else {
226 		AUTOFS_UNBLOCK_OTHERS(fnp, MF_LOOKUP);
227 	}
228 	mutex_exit(&fnp->fn_lock);
229 	return (error);
230 }
231 
232 /*
233  * Starting point for thread to handle mount requests with automountd.
234  * XXX auto_mount_thread() is not suspend-safe within the scope of
235  * the present model defined for cpr to suspend the system. Calls
236  * made by the auto_mount_thread() that have been identified to be unsafe
237  * are (1) RPC client handle setup and client calls to automountd which
238  * can block deep down in the RPC library, (2) kmem_alloc() calls with the
239  * KM_SLEEP flag which can block if memory is low, and (3) VFS_*(), and
240  * lookuppnvp() calls which can result in over the wire calls to servers.
241  * The thread should be completely reevaluated to make it suspend-safe in
242  * case of future updates to the cpr model.
243  */
244 static void
auto_mount_thread(struct autofs_callargs * argsp)245 auto_mount_thread(struct autofs_callargs *argsp)
246 {
247 	struct fninfo 		*fnip;
248 	fnnode_t 		*fnp;
249 	vnode_t 		*vp;
250 	char 			*name;
251 	size_t 			namelen;
252 	cred_t 			*cred;
253 	action_list		*alp = NULL;
254 	int 			error;
255 	callb_cpr_t 		cprinfo;
256 	kmutex_t 		auto_mount_thread_cpr_lock;
257 
258 	mutex_init(&auto_mount_thread_cpr_lock, NULL, MUTEX_DEFAULT, NULL);
259 	CALLB_CPR_INIT(&cprinfo, &auto_mount_thread_cpr_lock,
260 	    callb_generic_cpr, "auto_mount_thread");
261 
262 	fnp = argsp->fnc_fnp;
263 	vp = fntovn(fnp);
264 	fnip = vfstofni(vp->v_vfsp);
265 	name = argsp->fnc_name;
266 	cred = argsp->fnc_cred;
267 	ASSERT(crgetzoneid(argsp->fnc_cred) == fnip->fi_zoneid);
268 
269 	error = auto_mount_request(fnip, name, &alp, cred, TRUE);
270 	if (!error)
271 		error = auto_perform_actions(fnip, fnp, alp, cred);
272 	mutex_enter(&fnp->fn_lock);
273 	fnp->fn_error = error;
274 
275 	/*
276 	 * Notify threads waiting for mount that
277 	 * it's done.
278 	 */
279 	AUTOFS_UNBLOCK_OTHERS(fnp, MF_INPROG);
280 	mutex_exit(&fnp->fn_lock);
281 
282 	VN_RELE(vp);
283 	crfree(argsp->fnc_cred);
284 	namelen = strlen(argsp->fnc_name) + 1;
285 	kmem_free(argsp->fnc_name, namelen);
286 	kmem_free(argsp, sizeof (*argsp));
287 
288 	mutex_enter(&auto_mount_thread_cpr_lock);
289 	CALLB_CPR_EXIT(&cprinfo);
290 	mutex_destroy(&auto_mount_thread_cpr_lock);
291 	zthread_exit();
292 	/* NOTREACHED */
293 }
294 
295 static int autofs_thr_success = 0;
296 
297 /*
298  * Creates new thread which calls auto_mount_thread which does
299  * the bulk of the work calling automountd, via 'auto_perform_actions'.
300  */
301 void
auto_new_mount_thread(fnnode_t * fnp,char * name,cred_t * cred)302 auto_new_mount_thread(fnnode_t *fnp, char *name, cred_t *cred)
303 {
304 	struct autofs_callargs *argsp;
305 
306 	argsp = kmem_alloc(sizeof (*argsp), KM_SLEEP);
307 	VN_HOLD(fntovn(fnp));
308 	argsp->fnc_fnp = fnp;
309 	argsp->fnc_name = kmem_alloc(strlen(name) + 1, KM_SLEEP);
310 	(void) strcpy(argsp->fnc_name, name);
311 	argsp->fnc_origin = curthread;
312 	crhold(cred);
313 	argsp->fnc_cred = cred;
314 
315 	(void) zthread_create(NULL, 0, auto_mount_thread, argsp, 0,
316 	    minclsyspri);
317 	autofs_thr_success++;
318 }
319 
320 #define	DOOR_BUF_ALIGN		(1024*1024)
321 #define	DOOR_BUF_MULTIPLIER	3
322 #define	DOOR_BUF_DEFAULT_SZ	(DOOR_BUF_MULTIPLIER * DOOR_BUF_ALIGN)
323 int	doorbuf_defsz = DOOR_BUF_DEFAULT_SZ;
324 
325 /*ARGSUSED*/
326 int
auto_calldaemon(zoneid_t zoneid,int which,xdrproc_t xarg_func,void * argsp,xdrproc_t xresp_func,void * resp,int reslen,bool_t hard)327 auto_calldaemon(
328 	zoneid_t 		zoneid,
329 	int			which,
330 	xdrproc_t		xarg_func,
331 	void 			*argsp,
332 	xdrproc_t		xresp_func,
333 	void 			*resp,
334 	int			reslen,
335 	bool_t 			hard)	/* retry forever? */
336 {
337 	int			 retry;
338 	int			 error = 0;
339 	k_sigset_t		 smask;
340 	door_arg_t		 door_args;
341 	door_handle_t		 dh;
342 	XDR			 xdrarg;
343 	XDR			 xdrres;
344 	struct autofs_globals 	*fngp = NULL;
345 	void			*orp = NULL;
346 	int			 orl;
347 	int			 rlen = 0;	/* MUST be initialized */
348 	autofs_door_args_t	*xdr_argsp;
349 	int			 xdr_len = 0;
350 	int			 printed_not_running_msg = 0;
351 	klwp_t			*lwp = ttolwp(curthread);
352 
353 	/*
354 	 * We know that the current thread is doing work on
355 	 * behalf of its own zone, so it's ok to use
356 	 * curproc->p_zone.
357 	 */
358 	ASSERT(zoneid == getzoneid());
359 	if (zone_status_get(curproc->p_zone) >= ZONE_IS_SHUTTING_DOWN) {
360 		/*
361 		 * There's no point in trying to talk to
362 		 * automountd.  Plus, zone_shutdown() is
363 		 * waiting for us.
364 		 */
365 		return (ECONNREFUSED);
366 	}
367 
368 	do {
369 		retry = 0;
370 		mutex_enter(&autofs_minor_lock);
371 		fngp = zone_getspecific(autofs_key, curproc->p_zone);
372 		mutex_exit(&autofs_minor_lock);
373 		if (fngp == NULL) {
374 			if (hard) {
375 				AUTOFS_DPRINT((5,
376 				    "auto_calldaemon: "\
377 				    "failed to get door handle\n"));
378 				if (!printed_not_running_msg) {
379 					printed_not_running_msg = 1;
380 					zprintf(zoneid, "automountd not "\
381 					    "running, retrying\n");
382 				}
383 				delay(hz);
384 				retry = 1;
385 			} else {
386 				/*
387 				 * There is no global data so no door.
388 				 * There's no point in attempting to talk
389 				 * to automountd if we can't get the door
390 				 * handle.
391 				 */
392 				return (ECONNREFUSED);
393 			}
394 		}
395 	} while (retry);
396 
397 	if (printed_not_running_msg) {
398 		fngp->fng_printed_not_running_msg = printed_not_running_msg;
399 	}
400 
401 	ASSERT(fngp != NULL);
402 
403 	if (argsp != NULL && (xdr_len = xdr_sizeof(xarg_func, argsp)) == 0)
404 		return (EINVAL);
405 	xdr_argsp = kmem_zalloc(xdr_len + sizeof (*xdr_argsp), KM_SLEEP);
406 	xdr_argsp->xdr_len = xdr_len;
407 	xdr_argsp->cmd = which;
408 
409 	if (argsp) {
410 		xdrmem_create(&xdrarg, (char *)&xdr_argsp->xdr_arg,
411 		    xdr_argsp->xdr_len, XDR_ENCODE);
412 
413 		if (!(*xarg_func)(&xdrarg, argsp)) {
414 			kmem_free(xdr_argsp, xdr_len + sizeof (*xdr_argsp));
415 			return (EINVAL);
416 		}
417 	}
418 
419 	/*
420 	 * We're saving off the original pointer and length due to the
421 	 * possibility that the results buffer returned by the door
422 	 * upcall can be different then what we passed in. This is because
423 	 * the door will allocate new memory if the results buffer passed
424 	 * in isn't large enough to hold what we need to send back.
425 	 * In this case we need to free the memory originally allocated
426 	 * for that buffer.
427 	 */
428 	if (resp)
429 		rlen = xdr_sizeof(xresp_func, resp);
430 	orl = (rlen == 0) ? doorbuf_defsz : MAX(rlen, doorbuf_defsz);
431 	orp = kmem_zalloc(orl, KM_SLEEP);
432 
433 	do {
434 		retry = 0;
435 		mutex_enter(&fngp->fng_autofs_daemon_lock);
436 		dh = fngp->fng_autofs_daemon_dh;
437 		if (dh)
438 			door_ki_hold(dh);
439 		mutex_exit(&fngp->fng_autofs_daemon_lock);
440 
441 		if (dh == NULL) {
442 			if (orp)
443 				kmem_free(orp, orl);
444 			kmem_free(xdr_argsp, xdr_len + sizeof (*xdr_argsp));
445 			return (ENOENT);
446 		}
447 		door_args.data_ptr = (char *)xdr_argsp;
448 		door_args.data_size = sizeof (*xdr_argsp) + xdr_argsp->xdr_len;
449 		door_args.desc_ptr = NULL;
450 		door_args.desc_num = 0;
451 		door_args.rbuf = orp ? (char *)orp : NULL;
452 		door_args.rsize = orl;
453 
454 		sigintr(&smask, 1);
455 		error =
456 		    door_ki_upcall_limited(dh, &door_args, NULL, SIZE_MAX, 0);
457 		sigunintr(&smask);
458 
459 		door_ki_rele(dh);
460 
461 		/*
462 		 * Handle daemon errors
463 		 */
464 		if (!error) {
465 			/*
466 			 * Upcall successful. Let's check for soft errors
467 			 * from the daemon. We only recover from overflow
468 			 * type scenarios. Any other errors, we return to
469 			 * the caller.
470 			 */
471 			autofs_door_res_t *adr =
472 			    (autofs_door_res_t *)door_args.rbuf;
473 
474 			if (door_args.rbuf != NULL) {
475 				int	 nl;
476 
477 				switch (error = adr->res_status) {
478 				case 0:	/* no error; continue */
479 					break;
480 
481 				case EOVERFLOW:
482 					/*
483 					 * orig landing buf not big enough.
484 					 * xdr_len in XDR_BYTES_PER_UNIT
485 					 */
486 					if ((nl = adr->xdr_len) > 0 &&
487 					    (btopr(nl) < freemem/64)) {
488 						if (orp)
489 							kmem_free(orp, orl);
490 						orp = kmem_zalloc(nl, KM_SLEEP);
491 						orl = nl;
492 						retry = 1;
493 						break;
494 					}
495 					/*FALLTHROUGH*/
496 
497 				default:
498 					kmem_free(xdr_argsp,
499 					    xdr_len + sizeof (*xdr_argsp));
500 					if (orp)
501 						kmem_free(orp, orl);
502 					return (error);
503 				}
504 			}
505 			continue;
506 		}
507 
508 		/*
509 		 * no daemon errors; now process door/comm errors (if any)
510 		 */
511 		switch (error) {
512 		case EINTR:
513 			/*
514 			 * interrupts should be handled properly by the
515 			 * door upcall. If the door doesn't handle the
516 			 * interupt completely then we need to bail out.
517 			 */
518 			if (lwp && (ISSIG(curthread,
519 			    JUSTLOOKING) || MUSTRETURN(curproc, curthread))) {
520 				if (ISSIG(curthread, FORREAL) ||
521 				    lwp->lwp_sysabort ||
522 				    MUSTRETURN(curproc, curthread)) {
523 					lwp->lwp_sysabort = 0;
524 					return (EINTR);
525 				}
526 			}
527 			/*
528 			 * We may have gotten EINTR for other reasons
529 			 * like the door being revoked on us. Instead
530 			 * of trying to extract this out of the door
531 			 * handle, sleep and try again, if still
532 			 * revoked we will get EBADF next time
533 			 * through.
534 			 *
535 			 * If we have a pending cancellation and we don't
536 			 * have cancellation disabled, we will get EINTR
537 			 * forever, no matter how many times we retry,
538 			 * so just get out now if this is the case.
539 			 */
540 			if (schedctl_cancel_pending())
541 				break;
542 			/* FALLTHROUGH */
543 		case EAGAIN:    /* process may be forking */
544 			/*
545 			 * Back off for a bit
546 			 */
547 			delay(hz);
548 			retry = 1;
549 			break;
550 		case EBADF:	/* Invalid door */
551 		case EINVAL:    /* Not a door, wrong target */
552 			/*
553 			 * A fatal door error, if our failing door
554 			 * handle is the current door handle, clean
555 			 * up our state.
556 			 */
557 			mutex_enter(&fngp->fng_autofs_daemon_lock);
558 			if (dh == fngp->fng_autofs_daemon_dh) {
559 				door_ki_rele(fngp->fng_autofs_daemon_dh);
560 				fngp->fng_autofs_daemon_dh = NULL;
561 			}
562 			mutex_exit(&fngp->fng_autofs_daemon_lock);
563 			AUTOFS_DPRINT((5, "auto_calldaemon error=%d\n", error));
564 			if (hard) {
565 				if (!fngp->fng_printed_not_running_msg) {
566 					fngp->fng_printed_not_running_msg = 1;
567 					zprintf(zoneid, "automountd not "
568 					    "running, retrying\n");
569 				}
570 				delay(hz);
571 				retry = 1;
572 				break;
573 			} else {
574 				error = ECONNREFUSED;
575 				kmem_free(xdr_argsp,
576 				    xdr_len + sizeof (*xdr_argsp));
577 				if (orp)
578 					kmem_free(orp, orl);
579 				return (error);
580 			}
581 		default:	/* Unknown must be fatal */
582 			error = ENOENT;
583 			kmem_free(xdr_argsp, xdr_len + sizeof (*xdr_argsp));
584 			if (orp)
585 				kmem_free(orp, orl);
586 			return (error);
587 		}
588 	} while (retry);
589 
590 	if (fngp->fng_printed_not_running_msg == 1) {
591 		fngp->fng_printed_not_running_msg = 0;
592 		zprintf(zoneid, "automountd OK\n");
593 	}
594 
595 	if (orp && orl) {
596 		autofs_door_res_t	*door_resp;
597 		door_resp = (autofs_door_res_t *)door_args.rbuf;
598 
599 		if ((void *)door_args.rbuf != orp)
600 			kmem_free(orp, orl);
601 
602 		xdrmem_create(&xdrres, (char *)&door_resp->xdr_res,
603 		    door_resp->xdr_len, XDR_DECODE);
604 
605 		if (!((*xresp_func)(&xdrres, resp)))
606 			error = EINVAL;
607 		kmem_free(door_args.rbuf, door_args.rsize);
608 	}
609 	kmem_free(xdr_argsp, xdr_len + sizeof (*xdr_argsp));
610 	return (error);
611 }
612 
613 static int
auto_null_request(zoneid_t zoneid,bool_t hard)614 auto_null_request(zoneid_t zoneid, bool_t hard)
615 {
616 	int error;
617 
618 	AUTOFS_DPRINT((4, "\tauto_null_request\n"));
619 
620 	error = auto_calldaemon(zoneid, NULLPROC,
621 	    xdr_void, NULL, xdr_void, NULL, 0, hard);
622 
623 	AUTOFS_DPRINT((5, "\tauto_null_request: error=%d\n", error));
624 	return (error);
625 }
626 
627 static int
auto_lookup_request(fninfo_t * fnip,char * key,struct linka * lnp,bool_t hard,bool_t * mountreq,cred_t * cred)628 auto_lookup_request(
629 	fninfo_t *fnip,
630 	char *key,
631 	struct linka *lnp,
632 	bool_t hard,
633 	bool_t *mountreq,
634 	cred_t *cred)
635 {
636 	int 				error;
637 	struct autofs_globals 		*fngp;
638 	struct autofs_lookupargs	 reqst;
639 	autofs_lookupres 		*resp;
640 	struct linka 			*p;
641 
642 
643 	AUTOFS_DPRINT((4, "auto_lookup_equest: path=%s name=%s\n",
644 	    fnip->fi_path, key));
645 
646 	fngp = vntofn(fnip->fi_rootvp)->fn_globals;
647 
648 	reqst.map = fnip->fi_map;
649 	reqst.path = fnip->fi_path;
650 
651 	if (fnip->fi_flags & MF_DIRECT)
652 		reqst.name = fnip->fi_key;
653 	else
654 		reqst.name = key;
655 	AUTOFS_DPRINT((4, "auto_lookup_request: using key=%s\n", reqst.name));
656 
657 	reqst.subdir = fnip->fi_subdir;
658 	reqst.opts = fnip->fi_opts;
659 	reqst.isdirect = fnip->fi_flags & MF_DIRECT ? TRUE : FALSE;
660 	reqst.uid = crgetuid(cred);
661 
662 	resp = kmem_zalloc(sizeof (*resp), KM_SLEEP);
663 
664 	error = auto_calldaemon(fngp->fng_zoneid, AUTOFS_LOOKUP,
665 	    xdr_autofs_lookupargs, &reqst, xdr_autofs_lookupres,
666 	    (void *)resp, sizeof (autofs_lookupres), hard);
667 
668 	if (error) {
669 		xdr_free(xdr_autofs_lookupres, (char *)resp);
670 		kmem_free(resp, sizeof (*resp));
671 		return (error);
672 	}
673 
674 	if (!error) {
675 		fngp->fng_verbose = resp->lu_verbose;
676 		switch (resp->lu_res) {
677 		case AUTOFS_OK:
678 			switch (resp->lu_type.action) {
679 			case AUTOFS_MOUNT_RQ:
680 				lnp->link = NULL;
681 				lnp->dir = NULL;
682 				*mountreq = TRUE;
683 				break;
684 
685 			case AUTOFS_LINK_RQ:
686 			p = &resp->lu_type.lookup_result_type_u.lt_linka;
687 				lnp->dir = kmem_alloc(strlen(p->dir) + 1,
688 				    KM_SLEEP);
689 				(void) strcpy(lnp->dir, p->dir);
690 				lnp->link = kmem_alloc(strlen(p->link) + 1,
691 				    KM_SLEEP);
692 				(void) strcpy(lnp->link, p->link);
693 				break;
694 
695 			case AUTOFS_NONE:
696 				lnp->link = NULL;
697 				lnp->dir = NULL;
698 				break;
699 
700 			default:
701 				auto_log(fngp->fng_verbose, fngp->fng_zoneid,
702 				    CE_WARN, "auto_lookup_request: bad action "
703 				    "type %d", resp->lu_res);
704 				error = ENOENT;
705 			}
706 			break;
707 
708 		case AUTOFS_NOENT:
709 			error = ENOENT;
710 			break;
711 
712 		default:
713 			error = ENOENT;
714 			auto_log(fngp->fng_verbose, fngp->fng_zoneid, CE_WARN,
715 			    "auto_lookup_request: unknown result: %d",
716 			    resp->lu_res);
717 			break;
718 		}
719 	}
720 
721 	xdr_free(xdr_autofs_lookupres, (char *)resp);
722 	kmem_free(resp, sizeof (*resp));
723 	AUTOFS_DPRINT((5, "auto_lookup_request: path=%s name=%s error=%d\n",
724 	    fnip->fi_path, key, error));
725 	return (error);
726 }
727 
728 static int
auto_mount_request(fninfo_t * fnip,char * key,action_list ** alpp,cred_t * cred,bool_t hard)729 auto_mount_request(
730 	fninfo_t *fnip,
731 	char *key,
732 	action_list **alpp,
733 	cred_t *cred,
734 	bool_t hard)
735 {
736 	int 			error;
737 	struct autofs_globals 	*fngp;
738 	autofs_lookupargs 	reqst;
739 	autofs_mountres		*xdrres = NULL;
740 
741 	AUTOFS_DPRINT((4, "auto_mount_request: path=%s name=%s\n",
742 	    fnip->fi_path, key));
743 
744 	fngp = vntofn(fnip->fi_rootvp)->fn_globals;
745 	reqst.map = fnip->fi_map;
746 	reqst.path = fnip->fi_path;
747 
748 	if (fnip->fi_flags & MF_DIRECT)
749 		reqst.name = fnip->fi_key;
750 	else
751 		reqst.name = key;
752 
753 	AUTOFS_DPRINT((4, "auto_mount_request: using key=%s\n", reqst.name));
754 
755 	reqst.subdir = fnip->fi_subdir;
756 	reqst.opts = fnip->fi_opts;
757 	reqst.isdirect = fnip->fi_flags & MF_DIRECT ? TRUE : FALSE;
758 	reqst.uid = crgetuid(cred);
759 
760 	xdrres = kmem_zalloc(sizeof (*xdrres), KM_SLEEP);
761 
762 	error = auto_calldaemon(fngp->fng_zoneid, AUTOFS_MNTINFO,
763 	    xdr_autofs_lookupargs, &reqst, xdr_autofs_mountres,
764 	    (void *)xdrres, sizeof (autofs_mountres), hard);
765 
766 	if (!error) {
767 		fngp->fng_verbose = xdrres->mr_verbose;
768 		switch (xdrres->mr_type.status) {
769 		case AUTOFS_ACTION:
770 			error = 0;
771 			/*
772 			 * Save the action list since it is used by
773 			 * the caller. We NULL the action list pointer
774 			 * in 'result' so that xdr_free() will not free
775 			 * the list.
776 			 */
777 			*alpp = xdrres->mr_type.mount_result_type_u.list;
778 			xdrres->mr_type.mount_result_type_u.list = NULL;
779 			break;
780 		case AUTOFS_DONE:
781 			error = xdrres->mr_type.mount_result_type_u.error;
782 			break;
783 		default:
784 			error = ENOENT;
785 			auto_log(fngp->fng_verbose, fngp->fng_zoneid, CE_WARN,
786 			    "auto_mount_request: unknown status %d",
787 			    xdrres->mr_type.status);
788 			break;
789 		}
790 	}
791 
792 	xdr_free(xdr_autofs_mountres, (char *)xdrres);
793 	kmem_free(xdrres, sizeof (*xdrres));
794 
795 
796 	AUTOFS_DPRINT((5, "auto_mount_request: path=%s name=%s error=%d\n",
797 	    fnip->fi_path, key, error));
798 	return (error);
799 }
800 
801 
802 static int
auto_send_unmount_request(fninfo_t * fnip,umntrequest * ul,bool_t hard)803 auto_send_unmount_request(
804 	fninfo_t *fnip,
805 	umntrequest *ul,
806 	bool_t hard)
807 {
808 	int 	error;
809 	umntres	xdrres;
810 
811 	struct autofs_globals *fngp = vntofn(fnip->fi_rootvp)->fn_globals;
812 
813 	AUTOFS_DPRINT((4, "\tauto_send_unmount_request: fstype=%s "
814 	    " mntpnt=%s\n", ul->fstype, ul->mntpnt));
815 
816 	bzero(&xdrres, sizeof (umntres));
817 	error = auto_calldaemon(fngp->fng_zoneid, AUTOFS_UNMOUNT,
818 	    xdr_umntrequest, (void *)ul, xdr_umntres, (void *)&xdrres,
819 	    sizeof (umntres), hard);
820 
821 	if (!error)
822 		error = xdrres.status;
823 
824 	AUTOFS_DPRINT((5, "\tauto_send_unmount_request: error=%d\n", error));
825 
826 	return (error);
827 }
828 
829 static int
auto_perform_link(fnnode_t * fnp,struct linka * linkp,cred_t * cred)830 auto_perform_link(fnnode_t *fnp, struct linka *linkp, cred_t *cred)
831 {
832 	vnode_t *vp;
833 	size_t len;
834 	char *tmp;
835 
836 	AUTOFS_DPRINT((3, "auto_perform_link: fnp=%p dir=%s link=%s\n",
837 	    (void *)fnp, linkp->dir, linkp->link));
838 
839 	len = strlen(linkp->link) + 1;		/* include '\0' */
840 	tmp = kmem_zalloc(len, KM_SLEEP);
841 	(void) kcopy(linkp->link, tmp, len);
842 	mutex_enter(&fnp->fn_lock);
843 	fnp->fn_symlink = tmp;
844 	fnp->fn_symlinklen = (uint_t)len;
845 	fnp->fn_flags |= MF_THISUID_MATCH_RQD;
846 	crhold(cred);
847 	fnp->fn_cred = cred;
848 	mutex_exit(&fnp->fn_lock);
849 
850 	vp = fntovn(fnp);
851 	vp->v_type = VLNK;
852 
853 	return (0);
854 }
855 
856 static void
auto_free_autofs_args(struct mounta * m)857 auto_free_autofs_args(struct mounta *m)
858 {
859 	autofs_args	*aargs = (autofs_args *)m->dataptr;
860 
861 	if (aargs->addr.buf)
862 		kmem_free(aargs->addr.buf, aargs->addr.len);
863 	if (aargs->path)
864 		kmem_free(aargs->path, strlen(aargs->path) + 1);
865 	if (aargs->opts)
866 		kmem_free(aargs->opts, strlen(aargs->opts) + 1);
867 	if (aargs->map)
868 		kmem_free(aargs->map, strlen(aargs->map) + 1);
869 	if (aargs->subdir)
870 		kmem_free(aargs->subdir, strlen(aargs->subdir) + 1);
871 	if (aargs->key)
872 		kmem_free(aargs->key, strlen(aargs->key) + 1);
873 	kmem_free(aargs, sizeof (*aargs));
874 }
875 
876 static void
auto_free_action_list(action_list * alp)877 auto_free_action_list(action_list *alp)
878 {
879 	struct	mounta	*m;
880 	action_list	*lastalp;
881 	char		*fstype;
882 
883 	m = &alp->action.action_list_entry_u.mounta;
884 	while (alp != NULL) {
885 		fstype = alp->action.action_list_entry_u.mounta.fstype;
886 		m = &alp->action.action_list_entry_u.mounta;
887 		if (m->dataptr) {
888 			if (strcmp(fstype, "autofs") == 0) {
889 				auto_free_autofs_args(m);
890 			}
891 		}
892 		if (m->spec)
893 			kmem_free(m->spec, strlen(m->spec) + 1);
894 		if (m->dir)
895 			kmem_free(m->dir, strlen(m->dir) + 1);
896 		if (m->fstype)
897 			kmem_free(m->fstype, strlen(m->fstype) + 1);
898 		if (m->optptr)
899 			kmem_free(m->optptr, m->optlen);
900 		lastalp = alp;
901 		alp = alp->next;
902 		kmem_free(lastalp, sizeof (*lastalp));
903 	}
904 }
905 
906 static boolean_t
auto_invalid_autofs(fninfo_t * dfnip,fnnode_t * dfnp,action_list * p)907 auto_invalid_autofs(fninfo_t *dfnip, fnnode_t *dfnp, action_list *p)
908 {
909 	struct mounta *m;
910 	struct autofs_args *argsp;
911 	vnode_t *dvp;
912 	char buff[AUTOFS_MAXPATHLEN];
913 	size_t len;
914 	struct autofs_globals *fngp;
915 
916 	fngp = dfnp->fn_globals;
917 	dvp = fntovn(dfnp);
918 
919 	m = &p->action.action_list_entry_u.mounta;
920 	/*
921 	 * Make sure we aren't geting passed NULL values or a "dir" that
922 	 * isn't "." and doesn't begin with "./".
923 	 *
924 	 * We also only want to perform autofs mounts, so make sure
925 	 * no-one is trying to trick us into doing anything else.
926 	 */
927 	if (m->spec == NULL || m->dir == NULL || m->dir[0] != '.' ||
928 	    (m->dir[1] != '/' && m->dir[1] != '\0') ||
929 	    m->fstype == NULL || strcmp(m->fstype, "autofs") != 0 ||
930 	    m->dataptr == NULL || m->datalen != sizeof (struct autofs_args) ||
931 	    m->optptr == NULL)
932 		return (B_TRUE);
933 	/*
934 	 * We also don't like ".."s in the pathname.  Symlinks are
935 	 * handled by the fact that we'll use NOFOLLOW when we do
936 	 * lookup()s.
937 	 */
938 	if (strstr(m->dir, "/../") != NULL ||
939 	    (len = strlen(m->dir)) > sizeof ("/..") - 1 &&
940 	    m->dir[len] == '.' && m->dir[len - 1] == '.' &&
941 	    m->dir[len - 2] == '/')
942 		return (B_TRUE);
943 	argsp = (struct autofs_args *)m->dataptr;
944 	/*
945 	 * We don't want NULL values here either.
946 	 */
947 	if (argsp->addr.buf == NULL || argsp->path == NULL ||
948 	    argsp->opts == NULL || argsp->map == NULL || argsp->subdir == NULL)
949 		return (B_TRUE);
950 	/*
951 	 * We know what the claimed pathname *should* look like:
952 	 *
953 	 * If the parent (dfnp) is a mount point (VROOT), then
954 	 * the path should be (dfnip->fi_path + m->dir).
955 	 *
956 	 * Else, we know we're only two levels deep, so we use
957 	 * (dfnip->fi_path + dfnp->fn_name + m->dir).
958 	 *
959 	 * Furthermore, "." only makes sense if dfnp is a
960 	 * trigger node.
961 	 *
962 	 * At this point it seems like the passed-in path is
963 	 * redundant.
964 	 */
965 	if (dvp->v_flag & VROOT) {
966 		if (m->dir[1] == '\0' && !(dfnp->fn_flags & MF_TRIGGER))
967 			return (B_TRUE);
968 		(void) snprintf(buff, sizeof (buff), "%s%s",
969 		    dfnip->fi_path, m->dir + 1);
970 	} else {
971 		(void) snprintf(buff, sizeof (buff), "%s/%s%s",
972 		    dfnip->fi_path, dfnp->fn_name, m->dir + 1);
973 	}
974 	if (strcmp(argsp->path, buff) != 0) {
975 		auto_log(fngp->fng_verbose, fngp->fng_zoneid,
976 		    CE_WARN, "autofs: expected path of '%s', "
977 		    "got '%s' instead.", buff, argsp->path);
978 		return (B_TRUE);
979 	}
980 	return (B_FALSE); /* looks OK */
981 }
982 
983 /*
984  * auto_invalid_action will validate the action_list received.  If all is good
985  * this function returns FALSE, if there is a problem it returns TRUE.
986  */
987 static boolean_t
auto_invalid_action(fninfo_t * dfnip,fnnode_t * dfnp,action_list * alistpp)988 auto_invalid_action(fninfo_t *dfnip, fnnode_t *dfnp, action_list *alistpp)
989 {
990 
991 	/*
992 	 * Before we go any further, this better be a mount request.
993 	 */
994 	if (alistpp->action.action != AUTOFS_MOUNT_RQ)
995 		return (B_TRUE);
996 	return (auto_invalid_autofs(dfnip, dfnp, alistpp));
997 
998 }
999 
1000 static int
auto_perform_actions(fninfo_t * dfnip,fnnode_t * dfnp,action_list * alp,cred_t * cred)1001 auto_perform_actions(
1002 	fninfo_t *dfnip,
1003 	fnnode_t *dfnp,
1004 	action_list *alp,
1005 	cred_t *cred)	/* Credentials of the caller */
1006 {
1007 
1008 	action_list *p;
1009 	struct mounta		*m, margs;
1010 	struct autofs_args 		*argsp;
1011 	int 			error, success = 0;
1012 	vnode_t 		*mvp, *dvp, *newvp;
1013 	fnnode_t 		*newfnp, *mfnp;
1014 	int 			auto_mount = 0;
1015 	int 			save_triggers = 0;
1016 	int 			update_times = 0;
1017 	char 			*mntpnt;
1018 	char 			buff[AUTOFS_MAXPATHLEN];
1019 	timestruc_t 		now;
1020 	struct autofs_globals 	*fngp;
1021 	cred_t 			*zcred;
1022 
1023 	AUTOFS_DPRINT((4, "auto_perform_actions: alp=%p\n", (void *)alp));
1024 
1025 	fngp = dfnp->fn_globals;
1026 	dvp = fntovn(dfnp);
1027 
1028 	/*
1029 	 * As automountd running in a zone may be compromised, and this may be
1030 	 * an attack, we can't trust everything passed in by automountd, and we
1031 	 * need to do argument verification.  We'll issue a warning and drop
1032 	 * the request if it doesn't seem right.
1033 	 */
1034 
1035 	for (p = alp; p != NULL; p = p->next) {
1036 		if (auto_invalid_action(dfnip, dfnp, p)) {
1037 			/*
1038 			 * This warning should be sent to the global zone,
1039 			 * since presumably the zone administrator is the same
1040 			 * as the attacker.
1041 			 */
1042 			cmn_err(CE_WARN, "autofs: invalid action list received "
1043 			    "by automountd in zone %s.",
1044 			    curproc->p_zone->zone_name);
1045 			/*
1046 			 * This conversation is over.
1047 			 */
1048 			xdr_free(xdr_action_list, (char *)alp);
1049 			return (EINVAL);
1050 		}
1051 	}
1052 
1053 	zcred = zone_get_kcred(getzoneid());
1054 	ASSERT(zcred != NULL);
1055 
1056 	if (vn_mountedvfs(dvp) != NULL) {
1057 		/*
1058 		 * The daemon successfully mounted a filesystem
1059 		 * on the AUTOFS root node.
1060 		 */
1061 		mutex_enter(&dfnp->fn_lock);
1062 		dfnp->fn_flags |= MF_MOUNTPOINT;
1063 		ASSERT(dfnp->fn_dirents == NULL);
1064 		mutex_exit(&dfnp->fn_lock);
1065 		success++;
1066 	} else {
1067 		/*
1068 		 * Clear MF_MOUNTPOINT.
1069 		 */
1070 		mutex_enter(&dfnp->fn_lock);
1071 		if (dfnp->fn_flags & MF_MOUNTPOINT) {
1072 			AUTOFS_DPRINT((10, "autofs: clearing mountpoint "
1073 			    "flag on %s.", dfnp->fn_name));
1074 			ASSERT(dfnp->fn_dirents == NULL);
1075 			ASSERT(dfnp->fn_trigger == NULL);
1076 		}
1077 		dfnp->fn_flags &= ~MF_MOUNTPOINT;
1078 		mutex_exit(&dfnp->fn_lock);
1079 	}
1080 
1081 	for (p = alp; p != NULL; p = p->next) {
1082 
1083 		vfs_t *vfsp;	/* dummy argument */
1084 		vfs_t *mvfsp;
1085 
1086 		auto_mount = 0;
1087 
1088 		m = &p->action.action_list_entry_u.mounta;
1089 		argsp = (struct autofs_args *)m->dataptr;
1090 		ASSERT(strcmp(m->fstype, "autofs") == 0);
1091 		/*
1092 		 * use the parent directory's timeout since it's the
1093 		 * one specified/inherited by automount.
1094 		 */
1095 		argsp->mount_to = dfnip->fi_mount_to;
1096 		/*
1097 		 * The mountpoint is relative, and it is guaranteed to
1098 		 * begin with "."
1099 		 *
1100 		 */
1101 		ASSERT(m->dir[0] == '.');
1102 		if (m->dir[0] == '.' && m->dir[1] == '\0') {
1103 			/*
1104 			 * mounting on the trigger node
1105 			 */
1106 			mvp = dvp;
1107 			VN_HOLD(mvp);
1108 			goto mount;
1109 		}
1110 		/*
1111 		 * ignore "./" in front of mountpoint
1112 		 */
1113 		ASSERT(m->dir[1] == '/');
1114 		mntpnt = m->dir + 2;
1115 
1116 		AUTOFS_DPRINT((10, "\tdfnip->fi_path=%s\n", dfnip->fi_path));
1117 		AUTOFS_DPRINT((10, "\tdfnip->fi_flags=%x\n", dfnip->fi_flags));
1118 		AUTOFS_DPRINT((10, "\tmntpnt=%s\n", mntpnt));
1119 
1120 		if (dfnip->fi_flags & MF_DIRECT) {
1121 			AUTOFS_DPRINT((10, "\tDIRECT\n"));
1122 			(void) sprintf(buff, "%s/%s", dfnip->fi_path, mntpnt);
1123 		} else {
1124 			AUTOFS_DPRINT((10, "\tINDIRECT\n"));
1125 			(void) sprintf(buff, "%s/%s/%s",
1126 			    dfnip->fi_path, dfnp->fn_name, mntpnt);
1127 		}
1128 
1129 		if (vn_mountedvfs(dvp) == NULL) {
1130 			/*
1131 			 * Daemon didn't mount anything on the root
1132 			 * We have to create the mountpoint if it
1133 			 * doesn't exist already
1134 			 *
1135 			 * We use the caller's credentials in case a
1136 			 * UID-match is required
1137 			 * (MF_THISUID_MATCH_RQD).
1138 			 */
1139 			rw_enter(&dfnp->fn_rwlock, RW_WRITER);
1140 			error = auto_search(dfnp, mntpnt, &mfnp, cred);
1141 			if (error == 0) {
1142 				/*
1143 				 * AUTOFS mountpoint exists
1144 				 */
1145 				if (vn_mountedvfs(fntovn(mfnp)) != NULL) {
1146 					cmn_err(CE_PANIC,
1147 					    "auto_perform_actions:"
1148 					    " mfnp=%p covered", (void *)mfnp);
1149 				}
1150 			} else {
1151 				/*
1152 				 * Create AUTOFS mountpoint
1153 				 */
1154 				ASSERT((dfnp->fn_flags & MF_MOUNTPOINT) == 0);
1155 				error = auto_enter(dfnp, mntpnt, &mfnp, cred);
1156 				ASSERT(mfnp->fn_linkcnt == 1);
1157 				mfnp->fn_linkcnt++;
1158 			}
1159 			if (!error)
1160 				update_times = 1;
1161 			rw_exit(&dfnp->fn_rwlock);
1162 			ASSERT(error != EEXIST);
1163 			if (!error) {
1164 				/*
1165 				 * mfnp is already held.
1166 				 */
1167 				mvp = fntovn(mfnp);
1168 			} else {
1169 				auto_log(fngp->fng_verbose, fngp->fng_zoneid,
1170 				    CE_WARN, "autofs: mount of %s "
1171 				    "failed - can't create"
1172 				    " mountpoint.", buff);
1173 				continue;
1174 			}
1175 		} else {
1176 			/*
1177 			 * Find mountpoint in VFS mounted here. If not
1178 			 * found, fail the submount, though the overall
1179 			 * mount has succeeded since the root is
1180 			 * mounted.
1181 			 */
1182 			if (error = auto_getmntpnt(dvp, mntpnt, &mvp, kcred)) {
1183 				auto_log(fngp->fng_verbose, fngp->fng_zoneid,
1184 				    CE_WARN, "autofs: mount of %s "
1185 				    "failed - mountpoint doesn't"
1186 				    " exist.", buff);
1187 				continue;
1188 			}
1189 			if (mvp->v_type == VLNK) {
1190 				auto_log(fngp->fng_verbose, fngp->fng_zoneid,
1191 				    CE_WARN, "autofs: %s symbolic "
1192 				    "link: not a valid mountpoint "
1193 				    "- mount failed", buff);
1194 				VN_RELE(mvp);
1195 				error = ENOENT;
1196 				continue;
1197 			}
1198 		}
1199 mount:
1200 		m->flags |= MS_SYSSPACE | MS_OPTIONSTR;
1201 
1202 		/*
1203 		 * Copy mounta struct here so we can substitute a
1204 		 * buffer that is large enough to hold the returned
1205 		 * option string, if that string is longer than the
1206 		 * input option string.
1207 		 * This can happen if there are default options enabled
1208 		 * that were not in the input option string.
1209 		 */
1210 		bcopy(m, &margs, sizeof (*m));
1211 		margs.optptr = kmem_alloc(MAX_MNTOPT_STR, KM_SLEEP);
1212 		margs.optlen = MAX_MNTOPT_STR;
1213 		(void) strcpy(margs.optptr, m->optptr);
1214 		margs.dir = argsp->path;
1215 
1216 		/*
1217 		 * We use the zone's kcred because we don't want the
1218 		 * zone to be able to thus do something it wouldn't
1219 		 * normally be able to.
1220 		 */
1221 		error = domount(NULL, &margs, mvp, zcred, &vfsp);
1222 		kmem_free(margs.optptr, MAX_MNTOPT_STR);
1223 		if (error != 0) {
1224 			auto_log(fngp->fng_verbose, fngp->fng_zoneid,
1225 			    CE_WARN, "autofs: domount of %s failed "
1226 			    "error=%d", buff, error);
1227 			VN_RELE(mvp);
1228 			continue;
1229 		}
1230 		VFS_RELE(vfsp);
1231 
1232 		/*
1233 		 * If mountpoint is an AUTOFS node, then I'm going to
1234 		 * flag it that the Filesystem mounted on top was
1235 		 * mounted in the kernel so that the unmount can be
1236 		 * done inside the kernel as well.
1237 		 * I don't care to flag non-AUTOFS mountpoints when an
1238 		 * AUTOFS in-kernel mount was done on top, because the
1239 		 * unmount routine already knows that such case was
1240 		 * done in the kernel.
1241 		 */
1242 		if (vfs_matchops(dvp->v_vfsp, vfs_getops(mvp->v_vfsp))) {
1243 			mfnp = vntofn(mvp);
1244 			mutex_enter(&mfnp->fn_lock);
1245 			mfnp->fn_flags |= MF_IK_MOUNT;
1246 			mutex_exit(&mfnp->fn_lock);
1247 		}
1248 
1249 		(void) vn_vfswlock_wait(mvp);
1250 		mvfsp = vn_mountedvfs(mvp);
1251 		if (mvfsp != NULL) {
1252 			vfs_lock_wait(mvfsp);
1253 			vn_vfsunlock(mvp);
1254 			error = VFS_ROOT(mvfsp, &newvp);
1255 			vfs_unlock(mvfsp);
1256 			if (error) {
1257 				/*
1258 				 * We've dropped the locks, so let's
1259 				 * get the mounted vfs again in case
1260 				 * it changed.
1261 				 */
1262 				(void) vn_vfswlock_wait(mvp);
1263 				mvfsp = vn_mountedvfs(mvp);
1264 				if (mvfsp != NULL) {
1265 					error = dounmount(mvfsp, 0, CRED());
1266 					if (error) {
1267 						cmn_err(CE_WARN,
1268 						    "autofs: could not unmount"
1269 						    " vfs=%p", (void *)mvfsp);
1270 					}
1271 				} else
1272 					vn_vfsunlock(mvp);
1273 				VN_RELE(mvp);
1274 				continue;
1275 			}
1276 		} else {
1277 			vn_vfsunlock(mvp);
1278 			VN_RELE(mvp);
1279 			continue;
1280 		}
1281 
1282 		auto_mount = vfs_matchops(dvp->v_vfsp,
1283 		    vfs_getops(newvp->v_vfsp));
1284 		newfnp = vntofn(newvp);
1285 		newfnp->fn_parent = dfnp;
1286 
1287 		/*
1288 		 * At this time we want to save the AUTOFS filesystem
1289 		 * as a trigger node. (We only do this if the mount
1290 		 * occurred on a node different from the root.
1291 		 * We look at the trigger nodes during
1292 		 * the automatic unmounting to make sure we remove them
1293 		 * as a unit and remount them as a unit if the
1294 		 * filesystem mounted at the root could not be
1295 		 * unmounted.
1296 		 */
1297 		if (auto_mount && (error == 0) && (mvp != dvp)) {
1298 			save_triggers++;
1299 			/*
1300 			 * Add AUTOFS mount to hierarchy
1301 			 */
1302 			newfnp->fn_flags |= MF_TRIGGER;
1303 			rw_enter(&newfnp->fn_rwlock, RW_WRITER);
1304 			newfnp->fn_next = dfnp->fn_trigger;
1305 			rw_exit(&newfnp->fn_rwlock);
1306 			rw_enter(&dfnp->fn_rwlock, RW_WRITER);
1307 			dfnp->fn_trigger = newfnp;
1308 			rw_exit(&dfnp->fn_rwlock);
1309 			/*
1310 			 * Don't VN_RELE(newvp) here since dfnp now
1311 			 * holds reference to it as its trigger node.
1312 			 */
1313 			AUTOFS_DPRINT((10, "\tadding trigger %s to %s\n",
1314 			    newfnp->fn_name, dfnp->fn_name));
1315 			AUTOFS_DPRINT((10, "\tfirst trigger is %s\n",
1316 			    dfnp->fn_trigger->fn_name));
1317 			if (newfnp->fn_next != NULL)
1318 				AUTOFS_DPRINT((10, "\tnext trigger is %s\n",
1319 				    newfnp->fn_next->fn_name));
1320 			else
1321 				AUTOFS_DPRINT((10, "\tno next trigger\n"));
1322 		} else
1323 			VN_RELE(newvp);
1324 
1325 		if (!error)
1326 			success++;
1327 
1328 		if (update_times) {
1329 			gethrestime(&now);
1330 			dfnp->fn_atime = dfnp->fn_mtime = now;
1331 		}
1332 
1333 		VN_RELE(mvp);
1334 	}
1335 
1336 	if (save_triggers) {
1337 		/*
1338 		 * Make sure the parent can't be freed while it has triggers.
1339 		 */
1340 		VN_HOLD(dvp);
1341 	}
1342 
1343 	crfree(zcred);
1344 
1345 	/*
1346 	 * Return failure if daemon didn't mount anything, and all
1347 	 * kernel mounts attempted failed.
1348 	 */
1349 	error = success ? 0 : ENOENT;
1350 
1351 	if (alp != NULL) {
1352 		if ((error == 0) && save_triggers) {
1353 			/*
1354 			 * Save action_list information, so that we can use it
1355 			 * when it comes time to remount the trigger nodes
1356 			 * The action list is freed when the directory node
1357 			 * containing the reference to it is unmounted in
1358 			 * unmount_tree().
1359 			 */
1360 			mutex_enter(&dfnp->fn_lock);
1361 			ASSERT(dfnp->fn_alp == NULL);
1362 			dfnp->fn_alp = alp;
1363 			mutex_exit(&dfnp->fn_lock);
1364 		} else {
1365 			/*
1366 			 * free the action list now,
1367 			 */
1368 			xdr_free(xdr_action_list, (char *)alp);
1369 		}
1370 	}
1371 	AUTOFS_DPRINT((5, "auto_perform_actions: error=%d\n", error));
1372 	return (error);
1373 }
1374 
1375 fnnode_t *
auto_makefnnode(vtype_t type,vfs_t * vfsp,char * name,cred_t * cred,struct autofs_globals * fngp)1376 auto_makefnnode(
1377 	vtype_t type,
1378 	vfs_t *vfsp,
1379 	char *name,
1380 	cred_t *cred,
1381 	struct autofs_globals *fngp)
1382 {
1383 	fnnode_t *fnp;
1384 	vnode_t *vp;
1385 	char *tmpname;
1386 	timestruc_t now;
1387 	/*
1388 	 * autofs uses odd inode numbers
1389 	 * automountd uses even inode numbers
1390 	 *
1391 	 * To preserve the age-old semantics that inum+devid is unique across
1392 	 * the system, this variable must be global across zones.
1393 	 */
1394 	static ino_t nodeid = 3;
1395 
1396 	fnp = kmem_zalloc(sizeof (*fnp), KM_SLEEP);
1397 	fnp->fn_vnode = vn_alloc(KM_SLEEP);
1398 
1399 	vp = fntovn(fnp);
1400 	tmpname = kmem_alloc(strlen(name) + 1, KM_SLEEP);
1401 	(void) strcpy(tmpname, name);
1402 	fnp->fn_name = &tmpname[0];
1403 	fnp->fn_namelen = (int)strlen(tmpname) + 1;	/* include '\0' */
1404 	fnp->fn_uid = crgetuid(cred);
1405 	fnp->fn_gid = crgetgid(cred);
1406 	/*
1407 	 * ".." is added in auto_enter and auto_mount.
1408 	 * "." is added in auto_mkdir and auto_mount.
1409 	 */
1410 	/*
1411 	 * Note that fn_size and fn_linkcnt are already 0 since
1412 	 * we used kmem_zalloc to allocated fnp
1413 	 */
1414 	fnp->fn_mode = AUTOFS_MODE;
1415 	gethrestime(&now);
1416 	fnp->fn_atime = fnp->fn_mtime = fnp->fn_ctime = now;
1417 	fnp->fn_ref_time = now.tv_sec;
1418 	mutex_enter(&autofs_nodeid_lock);
1419 	fnp->fn_nodeid = nodeid;
1420 	nodeid += 2;
1421 	fnp->fn_globals = fngp;
1422 	fngp->fng_fnnode_count++;
1423 	mutex_exit(&autofs_nodeid_lock);
1424 	vn_setops(vp, auto_vnodeops);
1425 	vp->v_type = type;
1426 	vp->v_data = (void *)fnp;
1427 	vp->v_vfsp = vfsp;
1428 	mutex_init(&fnp->fn_lock, NULL, MUTEX_DEFAULT, NULL);
1429 	rw_init(&fnp->fn_rwlock, NULL, RW_DEFAULT, NULL);
1430 	cv_init(&fnp->fn_cv_mount, NULL, CV_DEFAULT, NULL);
1431 	vn_exists(vp);
1432 	return (fnp);
1433 }
1434 
1435 
1436 void
auto_freefnnode(fnnode_t * fnp)1437 auto_freefnnode(fnnode_t *fnp)
1438 {
1439 	vnode_t *vp = fntovn(fnp);
1440 
1441 	AUTOFS_DPRINT((4, "auto_freefnnode: fnp=%p\n", (void *)fnp));
1442 
1443 	ASSERT(fnp->fn_linkcnt == 0);
1444 	ASSERT(vp->v_count == 0);
1445 	ASSERT(fnp->fn_dirents == NULL);
1446 	ASSERT(fnp->fn_parent == NULL);
1447 
1448 	vn_invalid(vp);
1449 	kmem_free(fnp->fn_name, fnp->fn_namelen);
1450 	if (fnp->fn_symlink) {
1451 		ASSERT(fnp->fn_flags & MF_THISUID_MATCH_RQD);
1452 		kmem_free(fnp->fn_symlink, fnp->fn_symlinklen);
1453 	}
1454 	if (fnp->fn_cred)
1455 		crfree(fnp->fn_cred);
1456 	mutex_destroy(&fnp->fn_lock);
1457 	rw_destroy(&fnp->fn_rwlock);
1458 	cv_destroy(&fnp->fn_cv_mount);
1459 	vn_free(vp);
1460 
1461 	mutex_enter(&autofs_nodeid_lock);
1462 	fnp->fn_globals->fng_fnnode_count--;
1463 	mutex_exit(&autofs_nodeid_lock);
1464 	kmem_free(fnp, sizeof (*fnp));
1465 }
1466 
1467 void
auto_disconnect(fnnode_t * dfnp,fnnode_t * fnp)1468 auto_disconnect(
1469 	fnnode_t *dfnp,
1470 	fnnode_t *fnp)
1471 {
1472 	fnnode_t *tmp, **fnpp;
1473 	vnode_t *vp = fntovn(fnp);
1474 	timestruc_t now;
1475 
1476 	AUTOFS_DPRINT((4,
1477 	    "auto_disconnect: dfnp=%p fnp=%p linkcnt=%d\n v_count=%d",
1478 	    (void *)dfnp, (void *)fnp, fnp->fn_linkcnt, vp->v_count));
1479 
1480 	ASSERT(RW_WRITE_HELD(&dfnp->fn_rwlock));
1481 	ASSERT(fnp->fn_linkcnt == 1);
1482 
1483 	if (vn_mountedvfs(vp) != NULL) {
1484 		cmn_err(CE_PANIC, "auto_disconnect: vp %p mounted on",
1485 		    (void *)vp);
1486 	}
1487 
1488 	/*
1489 	 * Decrement by 1 because we're removing the entry in dfnp.
1490 	 */
1491 	fnp->fn_linkcnt--;
1492 	fnp->fn_size--;
1493 
1494 	/*
1495 	 * only changed while holding parent's (dfnp) rw_lock
1496 	 */
1497 	fnp->fn_parent = NULL;
1498 
1499 	fnpp = &dfnp->fn_dirents;
1500 	for (;;) {
1501 		tmp = *fnpp;
1502 		if (tmp == NULL) {
1503 			cmn_err(CE_PANIC,
1504 			    "auto_disconnect: %p not in %p dirent list",
1505 			    (void *)fnp, (void *)dfnp);
1506 		}
1507 		if (tmp == fnp) {
1508 			*fnpp = tmp->fn_next; 	/* remove it from the list */
1509 			ASSERT(vp->v_count == 0);
1510 			/* child had a pointer to parent ".." */
1511 			dfnp->fn_linkcnt--;
1512 			dfnp->fn_size--;
1513 			break;
1514 		}
1515 		fnpp = &tmp->fn_next;
1516 	}
1517 
1518 	mutex_enter(&fnp->fn_lock);
1519 	gethrestime(&now);
1520 	fnp->fn_atime = fnp->fn_mtime = now;
1521 	mutex_exit(&fnp->fn_lock);
1522 
1523 	AUTOFS_DPRINT((5, "auto_disconnect: done\n"));
1524 }
1525 
1526 int
auto_enter(fnnode_t * dfnp,char * name,fnnode_t ** fnpp,cred_t * cred)1527 auto_enter(fnnode_t *dfnp, char *name, fnnode_t **fnpp, cred_t *cred)
1528 {
1529 	struct fnnode *cfnp, **spp;
1530 	vnode_t *dvp = fntovn(dfnp);
1531 	ushort_t offset = 0;
1532 	ushort_t diff;
1533 
1534 	AUTOFS_DPRINT((4, "auto_enter: dfnp=%p, name=%s ", (void *)dfnp, name));
1535 
1536 	ASSERT(RW_WRITE_HELD(&dfnp->fn_rwlock));
1537 
1538 	cfnp = dfnp->fn_dirents;
1539 	if (cfnp == NULL) {
1540 		/*
1541 		 * offset = 0 for '.' and offset = 1 for '..'
1542 		 */
1543 		spp = &dfnp->fn_dirents;
1544 		offset = 2;
1545 	}
1546 
1547 	for (; cfnp; cfnp = cfnp->fn_next) {
1548 		if (strcmp(cfnp->fn_name, name) == 0) {
1549 			mutex_enter(&cfnp->fn_lock);
1550 			if (cfnp->fn_flags & MF_THISUID_MATCH_RQD) {
1551 				/*
1552 				 * "thisuser" kind of node, need to
1553 				 * match CREDs as well
1554 				 */
1555 				mutex_exit(&cfnp->fn_lock);
1556 				if (crcmp(cfnp->fn_cred, cred) == 0)
1557 					return (EEXIST);
1558 			} else {
1559 				mutex_exit(&cfnp->fn_lock);
1560 				return (EEXIST);
1561 			}
1562 		}
1563 
1564 		if (cfnp->fn_next != NULL) {
1565 			diff = (ushort_t)
1566 			    (cfnp->fn_next->fn_offset - cfnp->fn_offset);
1567 			ASSERT(diff != 0);
1568 			if (diff > 1 && offset == 0) {
1569 				offset = (ushort_t)cfnp->fn_offset + 1;
1570 				spp = &cfnp->fn_next;
1571 			}
1572 		} else if (offset == 0) {
1573 			offset = (ushort_t)cfnp->fn_offset + 1;
1574 			spp = &cfnp->fn_next;
1575 		}
1576 	}
1577 
1578 	*fnpp = auto_makefnnode(VDIR, dvp->v_vfsp, name, cred,
1579 	    dfnp->fn_globals);
1580 	if (*fnpp == NULL)
1581 		return (ENOMEM);
1582 
1583 	/*
1584 	 * I don't hold the mutex on fnpp because I created it, and
1585 	 * I'm already holding the writers lock for it's parent
1586 	 * directory, therefore nobody can reference it without me first
1587 	 * releasing the writers lock.
1588 	 */
1589 	(*fnpp)->fn_offset = offset;
1590 	(*fnpp)->fn_next = *spp;
1591 	*spp = *fnpp;
1592 	(*fnpp)->fn_parent = dfnp;
1593 	(*fnpp)->fn_linkcnt++;	/* parent now holds reference to entry */
1594 	(*fnpp)->fn_size++;
1595 
1596 	/*
1597 	 * dfnp->fn_linkcnt and dfnp->fn_size protected by dfnp->rw_lock
1598 	 */
1599 	dfnp->fn_linkcnt++;	/* child now holds reference to parent '..' */
1600 	dfnp->fn_size++;
1601 
1602 	dfnp->fn_ref_time = gethrestime_sec();
1603 
1604 	AUTOFS_DPRINT((5, "*fnpp=%p\n", (void *)*fnpp));
1605 	return (0);
1606 }
1607 
1608 int
auto_search(fnnode_t * dfnp,char * name,fnnode_t ** fnpp,cred_t * cred)1609 auto_search(fnnode_t *dfnp, char *name, fnnode_t **fnpp, cred_t *cred)
1610 {
1611 	vnode_t *dvp;
1612 	fnnode_t *p;
1613 	int error = ENOENT, match = 0;
1614 
1615 	AUTOFS_DPRINT((4, "auto_search: dfnp=%p, name=%s...\n",
1616 	    (void *)dfnp, name));
1617 
1618 	dvp = fntovn(dfnp);
1619 	if (dvp->v_type != VDIR) {
1620 		cmn_err(CE_PANIC, "auto_search: dvp=%p not a directory",
1621 		    (void *)dvp);
1622 	}
1623 
1624 	ASSERT(RW_LOCK_HELD(&dfnp->fn_rwlock));
1625 	for (p = dfnp->fn_dirents; p != NULL; p = p->fn_next) {
1626 		if (strcmp(p->fn_name, name) == 0) {
1627 			mutex_enter(&p->fn_lock);
1628 			if (p->fn_flags & MF_THISUID_MATCH_RQD) {
1629 				/*
1630 				 * "thisuser" kind of node
1631 				 * Need to match CREDs as well
1632 				 */
1633 				mutex_exit(&p->fn_lock);
1634 				match = crcmp(p->fn_cred, cred) == 0;
1635 			} else {
1636 				/*
1637 				 * No need to check CRED
1638 				 */
1639 				mutex_exit(&p->fn_lock);
1640 				match = 1;
1641 			}
1642 		}
1643 		if (match) {
1644 			error = 0;
1645 			if (fnpp) {
1646 				*fnpp = p;
1647 				VN_HOLD(fntovn(*fnpp));
1648 			}
1649 			break;
1650 		}
1651 	}
1652 
1653 	AUTOFS_DPRINT((5, "auto_search: error=%d\n", error));
1654 	return (error);
1655 }
1656 
1657 /*
1658  * If dvp is mounted on, get path's vnode in the mounted on
1659  * filesystem.  Path is relative to dvp, ie "./path".
1660  * If successful, *mvp points to a the held mountpoint vnode.
1661  */
1662 /* ARGSUSED */
1663 static int
auto_getmntpnt(vnode_t * dvp,char * path,vnode_t ** mvpp,cred_t * cred)1664 auto_getmntpnt(
1665 	vnode_t *dvp,
1666 	char *path,
1667 	vnode_t **mvpp,		/* vnode for mountpoint */
1668 	cred_t *cred)
1669 {
1670 	int error = 0;
1671 	vnode_t *newvp;
1672 	char namebuf[TYPICALMAXPATHLEN];
1673 	struct pathname lookpn;
1674 	vfs_t *vfsp;
1675 
1676 	AUTOFS_DPRINT((4, "auto_getmntpnt: path=%s\n", path));
1677 
1678 	if (error = vn_vfsrlock_wait(dvp))
1679 		return (error);
1680 
1681 	/*
1682 	 * Now that we have the vfswlock, check to see if dvp
1683 	 * is still mounted on.  If not, then just bail out as
1684 	 * there is no need to remount the triggers since the
1685 	 * higher level mount point has gotten unmounted.
1686 	 */
1687 	vfsp = vn_mountedvfs(dvp);
1688 	if (vfsp == NULL) {
1689 		vn_vfsunlock(dvp);
1690 		error = EBUSY;
1691 		goto done;
1692 	}
1693 	/*
1694 	 * Since mounted on, lookup "path" in the new filesystem,
1695 	 * it is important that we do the filesystem jump here to
1696 	 * avoid lookuppn() calling auto_lookup on dvp and deadlock.
1697 	 */
1698 	error = VFS_ROOT(vfsp, &newvp);
1699 	vn_vfsunlock(dvp);
1700 	if (error)
1701 		goto done;
1702 
1703 	/*
1704 	 * We do a VN_HOLD on newvp just in case the first call to
1705 	 * lookuppnvp() fails with ENAMETOOLONG.  We should still have a
1706 	 * reference to this vnode for the second call to lookuppnvp().
1707 	 */
1708 	VN_HOLD(newvp);
1709 
1710 	/*
1711 	 * Now create the pathname struct so we can make use of lookuppnvp,
1712 	 * and pn_getcomponent.
1713 	 * This code is similar to lookupname() in fs/lookup.c.
1714 	 */
1715 	error = pn_get_buf(path, UIO_SYSSPACE, &lookpn,
1716 	    namebuf, sizeof (namebuf));
1717 	if (error == 0) {
1718 		error = lookuppnvp(&lookpn, NULL, NO_FOLLOW, NULLVPP,
1719 		    mvpp, rootdir, newvp, cred);
1720 	} else
1721 		VN_RELE(newvp);
1722 	if (error == ENAMETOOLONG) {
1723 		/*
1724 		 * This thread used a pathname > TYPICALMAXPATHLEN bytes long.
1725 		 * newvp is VN_RELE'd by this call to lookuppnvp.
1726 		 *
1727 		 * Using 'rootdir' in a zone's context is OK here: we already
1728 		 * ascertained that there are no '..'s in the path, and we're
1729 		 * not following symlinks.
1730 		 */
1731 		if ((error = pn_get(path, UIO_SYSSPACE, &lookpn)) == 0) {
1732 			error = lookuppnvp(&lookpn, NULL, NO_FOLLOW, NULLVPP,
1733 			    mvpp, rootdir, newvp, cred);
1734 			pn_free(&lookpn);
1735 		} else
1736 			VN_RELE(newvp);
1737 	} else {
1738 		/*
1739 		 * Need to release newvp here since we held it.
1740 		 */
1741 		VN_RELE(newvp);
1742 	}
1743 
1744 done:
1745 	AUTOFS_DPRINT((5, "auto_getmntpnt: path=%s *mvpp=%p error=%d\n",
1746 	    path, (void *)*mvpp, error));
1747 	return (error);
1748 }
1749 
1750 #define	DEEPER(x) (((x)->fn_dirents != NULL) || \
1751 			(vn_mountedvfs(fntovn((x)))) != NULL)
1752 
1753 /*
1754  * The caller, should have already VN_RELE'd its reference to the
1755  * root vnode of this filesystem.
1756  */
1757 static int
auto_inkernel_unmount(vfs_t * vfsp)1758 auto_inkernel_unmount(vfs_t *vfsp)
1759 {
1760 	vnode_t *cvp = vfsp->vfs_vnodecovered;
1761 	int error;
1762 
1763 	AUTOFS_DPRINT((4,
1764 	    "auto_inkernel_unmount: devid=%lx mntpnt(%p) count %u\n",
1765 	    vfsp->vfs_dev, (void *)cvp, cvp->v_count));
1766 
1767 	ASSERT(vn_vfswlock_held(cvp));
1768 
1769 	/*
1770 	 * Perform the unmount
1771 	 * The mountpoint has already been locked by the caller.
1772 	 */
1773 	error = dounmount(vfsp, 0, kcred);
1774 
1775 	AUTOFS_DPRINT((5, "auto_inkernel_unmount: exit count %u\n",
1776 	    cvp->v_count));
1777 	return (error);
1778 }
1779 
1780 /*
1781  * unmounts trigger nodes in the kernel.
1782  */
1783 static void
unmount_triggers(fnnode_t * fnp,action_list ** alp)1784 unmount_triggers(fnnode_t *fnp, action_list **alp)
1785 {
1786 	fnnode_t *tp, *next;
1787 	int error = 0;
1788 	vfs_t *vfsp;
1789 	vnode_t *tvp;
1790 
1791 	AUTOFS_DPRINT((4, "unmount_triggers: fnp=%p\n", (void *)fnp));
1792 	ASSERT(RW_WRITE_HELD(&fnp->fn_rwlock));
1793 
1794 	*alp = fnp->fn_alp;
1795 	next = fnp->fn_trigger;
1796 	while ((tp = next) != NULL) {
1797 		tvp = fntovn(tp);
1798 		ASSERT(tvp->v_count >= 2);
1799 		next = tp->fn_next;
1800 		/*
1801 		 * drop writer's lock since the unmount will end up
1802 		 * disconnecting this node from fnp and needs to acquire
1803 		 * the writer's lock again.
1804 		 * next has at least a reference count >= 2 since it's
1805 		 * a trigger node, therefore can not be accidentally freed
1806 		 * by a VN_RELE
1807 		 */
1808 		rw_exit(&fnp->fn_rwlock);
1809 
1810 		vfsp = tvp->v_vfsp;
1811 
1812 		/*
1813 		 * Its parent was holding a reference to it, since this
1814 		 * is a trigger vnode.
1815 		 */
1816 		VN_RELE(tvp);
1817 		if (error = auto_inkernel_unmount(vfsp)) {
1818 			cmn_err(CE_PANIC, "unmount_triggers: "
1819 			    "unmount of vp=%p failed error=%d",
1820 			    (void *)tvp, error);
1821 		}
1822 		/*
1823 		 * reacquire writer's lock
1824 		 */
1825 		rw_enter(&fnp->fn_rwlock, RW_WRITER);
1826 	}
1827 
1828 	/*
1829 	 * We were holding a reference to our parent.  Drop that.
1830 	 */
1831 	VN_RELE(fntovn(fnp));
1832 	fnp->fn_trigger = NULL;
1833 	fnp->fn_alp = NULL;
1834 
1835 	AUTOFS_DPRINT((5, "unmount_triggers: finished\n"));
1836 }
1837 
1838 /*
1839  * This routine locks the mountpoint of every trigger node if they're
1840  * not busy, or returns EBUSY if any node is busy.
1841  */
1842 static boolean_t
triggers_busy(fnnode_t * fnp)1843 triggers_busy(fnnode_t *fnp)
1844 {
1845 	int done;
1846 	int lck_error = 0;
1847 	fnnode_t *tp, *t1p;
1848 	vfs_t *vfsp;
1849 
1850 	ASSERT(RW_WRITE_HELD(&fnp->fn_rwlock));
1851 
1852 	for (tp = fnp->fn_trigger; tp != NULL; tp = tp->fn_next) {
1853 		AUTOFS_DPRINT((10, "\ttrigger: %s\n", tp->fn_name));
1854 		/* MF_LOOKUP should never be set on trigger nodes */
1855 		ASSERT((tp->fn_flags & MF_LOOKUP) == 0);
1856 		vfsp = fntovn(tp)->v_vfsp;
1857 
1858 		/*
1859 		 * The vn_vfsunlock will be done in auto_inkernel_unmount.
1860 		 */
1861 		lck_error = vn_vfswlock(vfsp->vfs_vnodecovered);
1862 
1863 		if (lck_error != 0 || (tp->fn_flags & MF_INPROG) ||
1864 		    DEEPER(tp) || ((fntovn(tp))->v_count) > 2) {
1865 			/*
1866 			 * couldn't lock it because it's busy,
1867 			 * It is mounted on or has dirents?
1868 			 * If reference count is greater than two, then
1869 			 * somebody else is holding a reference to this vnode.
1870 			 * One reference is for the mountpoint, and the second
1871 			 * is for the trigger node.
1872 			 */
1873 			AUTOFS_DPRINT((10, "\ttrigger busy\n"));
1874 
1875 			/*
1876 			 * Unlock previously locked mountpoints
1877 			 */
1878 			for (done = 0, t1p = fnp->fn_trigger; !done;
1879 			    t1p = t1p->fn_next) {
1880 				/*
1881 				 * Unlock all nodes previously
1882 				 * locked. All nodes up to 'tp'
1883 				 * were successfully locked. If 'lck_err' is
1884 				 * set, then 'tp' was not locked, and thus
1885 				 * should not be unlocked. If
1886 				 * 'lck_err' is not set, then 'tp' was
1887 				 * successfully locked, and it should
1888 				 * be unlocked.
1889 				 */
1890 				if (t1p != tp || !lck_error) {
1891 					vfsp = fntovn(t1p)->v_vfsp;
1892 					vn_vfsunlock(vfsp->vfs_vnodecovered);
1893 				}
1894 				done = (t1p == tp);
1895 			}
1896 			return (B_TRUE);
1897 		}
1898 	}
1899 
1900 	return (B_FALSE);
1901 }
1902 
1903 /*
1904  * It is the caller's responsibility to grab the VVFSLOCK.
1905  * Releases the VVFSLOCK upon return.
1906  */
1907 static int
unmount_node(vnode_t * cvp,int force)1908 unmount_node(vnode_t *cvp, int force)
1909 {
1910 	int error = 0;
1911 	fnnode_t *cfnp;
1912 	vfs_t *vfsp;
1913 	umntrequest ul;
1914 	fninfo_t *fnip;
1915 
1916 	AUTOFS_DPRINT((4, "\tunmount_node cvp=%p\n", (void *)cvp));
1917 
1918 	ASSERT(vn_vfswlock_held(cvp));
1919 	cfnp = vntofn(cvp);
1920 	vfsp = vn_mountedvfs(cvp);
1921 
1922 	if (force || cfnp->fn_flags & MF_IK_MOUNT) {
1923 		/*
1924 		 * Mount was performed in the kernel, so
1925 		 * do an in-kernel unmount. auto_inkernel_unmount()
1926 		 * will vn_vfsunlock(cvp).
1927 		 */
1928 		error = auto_inkernel_unmount(vfsp);
1929 	} else {
1930 		zone_t *zone = NULL;
1931 		refstr_t *mntpt, *resource;
1932 		size_t mntoptslen;
1933 
1934 		/*
1935 		 * Get the mnttab information of the node
1936 		 * and ask the daemon to unmount it.
1937 		 */
1938 		bzero(&ul, sizeof (ul));
1939 		mntfs_getmntopts(vfsp, &ul.mntopts, &mntoptslen);
1940 		if (ul.mntopts == NULL) {
1941 			auto_log(cfnp->fn_globals->fng_verbose,
1942 			    cfnp->fn_globals->fng_zoneid, CE_WARN,
1943 			    "unmount_node: no memory");
1944 			vn_vfsunlock(cvp);
1945 			error = ENOMEM;
1946 			goto done;
1947 		}
1948 		if (mntoptslen > AUTOFS_MAXOPTSLEN)
1949 			ul.mntopts[AUTOFS_MAXOPTSLEN - 1] = '\0';
1950 
1951 		mntpt = vfs_getmntpoint(vfsp);
1952 		ul.mntpnt = (char *)refstr_value(mntpt);
1953 		resource = vfs_getresource(vfsp);
1954 		ul.mntresource = (char *)refstr_value(resource);
1955 
1956 		fnip = vfstofni(cvp->v_vfsp);
1957 		ul.isdirect = fnip->fi_flags & MF_DIRECT ? TRUE : FALSE;
1958 
1959 		/*
1960 		 * Since a zone'd automountd's view of the autofs mount points
1961 		 * differs from those in the kernel, we need to make sure we
1962 		 * give it consistent mount points.
1963 		 */
1964 		ASSERT(fnip->fi_zoneid == getzoneid());
1965 		zone = curproc->p_zone;
1966 
1967 		if (fnip->fi_zoneid != GLOBAL_ZONEID) {
1968 			if (ZONE_PATH_VISIBLE(ul.mntpnt, zone)) {
1969 				ul.mntpnt =
1970 				    ZONE_PATH_TRANSLATE(ul.mntpnt, zone);
1971 			}
1972 			if (ZONE_PATH_VISIBLE(ul.mntresource, zone)) {
1973 				ul.mntresource =
1974 				    ZONE_PATH_TRANSLATE(ul.mntresource, zone);
1975 			}
1976 		}
1977 
1978 		ul.fstype = vfssw[vfsp->vfs_fstype].vsw_name;
1979 		vn_vfsunlock(cvp);
1980 
1981 		error = auto_send_unmount_request(fnip, &ul, FALSE);
1982 		kmem_free(ul.mntopts, mntoptslen);
1983 		refstr_rele(mntpt);
1984 		refstr_rele(resource);
1985 	}
1986 
1987 done:
1988 	AUTOFS_DPRINT((5, "\tunmount_node cvp=%p error=%d\n", (void *)cvp,
1989 	    error));
1990 	return (error);
1991 }
1992 
1993 /*
1994  * return EBUSY if any thread is holding a reference to this vnode
1995  * other than us. Result of this function cannot be relied on, since
1996  * it doesn't follow proper locking rules (i.e. vp->v_vfsmountedhere
1997  * and fnp->fn_trigger can change throughout this function). However
1998  * it's good enough for rough estimation.
1999  */
2000 static int
check_auto_node(vnode_t * vp)2001 check_auto_node(vnode_t *vp)
2002 {
2003 	fnnode_t *fnp;
2004 	int error = 0;
2005 	/*
2006 	 * number of references to expect for
2007 	 * a non-busy vnode.
2008 	 */
2009 	uint_t count;
2010 
2011 	AUTOFS_DPRINT((4, "\tcheck_auto_node vp=%p ", (void *)vp));
2012 	fnp = vntofn(vp);
2013 
2014 	count = 1;		/* we are holding a reference to vp */
2015 	if (fnp->fn_flags & MF_TRIGGER) {
2016 		/*
2017 		 * parent holds a pointer to us (trigger)
2018 		 */
2019 		count++;
2020 	}
2021 	if (fnp->fn_trigger != NULL) {
2022 		/*
2023 		 * The trigger nodes have a hold on us.
2024 		 */
2025 		count++;
2026 	}
2027 	if (vn_ismntpt(vp)) {
2028 		/*
2029 		 * File system is mounted on us.
2030 		 */
2031 		count++;
2032 	}
2033 	mutex_enter(&vp->v_lock);
2034 	ASSERT(vp->v_count > 0);
2035 	if (vp->v_flag & VROOT)
2036 		count++;
2037 	AUTOFS_DPRINT((10, "\tcount=%u ", vp->v_count));
2038 	if (vp->v_count > count)
2039 		error = EBUSY;
2040 	mutex_exit(&vp->v_lock);
2041 
2042 	AUTOFS_DPRINT((5, "\tcheck_auto_node error=%d ", error));
2043 	return (error);
2044 }
2045 
2046 /*
2047  * rootvp is the root of the AUTOFS filesystem.
2048  * If rootvp is busy (v_count > 1) returns EBUSY.
2049  * else removes every vnode under this tree.
2050  * ASSUMPTION: Assumes that the only node which can be busy is
2051  * the root vnode. This filesystem better be two levels deep only,
2052  * the root and its immediate subdirs.
2053  * The daemon will "AUTOFS direct-mount" only one level below the root.
2054  */
2055 static void
unmount_autofs(vnode_t * rootvp)2056 unmount_autofs(vnode_t *rootvp)
2057 {
2058 	fnnode_t *fnp, *rootfnp, *nfnp;
2059 
2060 	AUTOFS_DPRINT((4, "\tunmount_autofs rootvp=%p ", (void *)rootvp));
2061 
2062 	/*
2063 	 * Remove all its immediate subdirectories.
2064 	 */
2065 	rootfnp = vntofn(rootvp);
2066 	rw_enter(&rootfnp->fn_rwlock, RW_WRITER);
2067 	for (fnp = rootfnp->fn_dirents; fnp != NULL; fnp = nfnp) {
2068 		ASSERT(fntovn(fnp)->v_count == 0);
2069 		ASSERT(fnp->fn_dirents == NULL);
2070 		ASSERT(fnp->fn_linkcnt == 2);
2071 		fnp->fn_linkcnt--;
2072 		auto_disconnect(rootfnp, fnp);
2073 		nfnp = fnp->fn_next;
2074 		auto_freefnnode(fnp);
2075 	}
2076 	rw_exit(&rootfnp->fn_rwlock);
2077 }
2078 
2079 /*
2080  * If a node matches all unmount criteria, do:
2081  *     destroy subordinate trigger node(s) if there is any
2082  *     unmount filesystem mounted on top of the node if there is any
2083  *
2084  * Function should be called with locked fnp's mutex. The mutex is
2085  * unlocked before return from function.
2086  */
2087 static int
try_unmount_node(fnnode_t * fnp,boolean_t force)2088 try_unmount_node(fnnode_t *fnp, boolean_t force)
2089 {
2090 	boolean_t	trigger_unmount = B_FALSE;
2091 	action_list	*alp = NULL;
2092 	vnode_t		*vp;
2093 	int		error = 0;
2094 	fninfo_t	*fnip;
2095 	vfs_t		*vfsp;
2096 	struct autofs_globals *fngp;
2097 
2098 	AUTOFS_DPRINT((10, "\ttry_unmount_node: processing node %p\n",
2099 	    (void *)fnp));
2100 
2101 	ASSERT(MUTEX_HELD(&fnp->fn_lock));
2102 
2103 	fngp = fnp->fn_globals;
2104 	vp = fntovn(fnp);
2105 	fnip = vfstofni(vp->v_vfsp);
2106 
2107 	/*
2108 	 * If either a mount, lookup or another unmount of this subtree is in
2109 	 * progress, don't attempt to unmount at this time.
2110 	 */
2111 	if (fnp->fn_flags & (MF_INPROG | MF_LOOKUP)) {
2112 		mutex_exit(&fnp->fn_lock);
2113 		return (EBUSY);
2114 	}
2115 
2116 	/*
2117 	 * Bail out if someone else is holding reference to this vnode.
2118 	 * This check isn't just an optimization (someone is probably
2119 	 * just about to trigger mount). It is necessary to prevent a deadlock
2120 	 * in domount() called from auto_perform_actions() if unmount of
2121 	 * trigger parent fails. domount() calls lookupname() to resolve
2122 	 * special in mount arguments. Special is set to a map name in case
2123 	 * of autofs triggers (i.e. auto_ws.sun.com). Thus if current
2124 	 * working directory is set to currently processed node, lookupname()
2125 	 * calls into autofs vnops in order to resolve special, which deadlocks
2126 	 * the process.
2127 	 *
2128 	 * Note: This should be fixed. Autofs shouldn't pass the map name
2129 	 * in special and avoid useless lookup with potentially disasterous
2130 	 * consequence.
2131 	 */
2132 	if (check_auto_node(vp) == EBUSY) {
2133 		mutex_exit(&fnp->fn_lock);
2134 		return (EBUSY);
2135 	}
2136 
2137 	/*
2138 	 * If not forced operation, back out if node has been referenced
2139 	 * recently.
2140 	 */
2141 	if (!force &&
2142 	    fnp->fn_ref_time + fnip->fi_mount_to > gethrestime_sec()) {
2143 		mutex_exit(&fnp->fn_lock);
2144 		return (EBUSY);
2145 	}
2146 
2147 	/* block mounts/unmounts on the node */
2148 	AUTOFS_BLOCK_OTHERS(fnp, MF_INPROG);
2149 	fnp->fn_error = 0;
2150 	mutex_exit(&fnp->fn_lock);
2151 
2152 	/* unmount next level triggers if there are any */
2153 	rw_enter(&fnp->fn_rwlock, RW_WRITER);
2154 	if (fnp->fn_trigger != NULL) {
2155 		trigger_unmount = B_TRUE;
2156 
2157 		if (triggers_busy(fnp)) {
2158 			rw_exit(&fnp->fn_rwlock);
2159 			mutex_enter(&fnp->fn_lock);
2160 			AUTOFS_UNBLOCK_OTHERS(fnp, MF_INPROG);
2161 			mutex_exit(&fnp->fn_lock);
2162 			return (EBUSY);
2163 		}
2164 
2165 		/*
2166 		 * At this point, we know all trigger nodes are locked,
2167 		 * and they're not busy or mounted on.
2168 		 *
2169 		 * Attempt to unmount all trigger nodes, save the
2170 		 * action_list in case we need to remount them later.
2171 		 * The action_list will be freed later if there was no
2172 		 * need to remount the trigger nodes.
2173 		 */
2174 		unmount_triggers(fnp, &alp);
2175 	}
2176 	rw_exit(&fnp->fn_rwlock);
2177 
2178 	(void) vn_vfswlock_wait(vp);
2179 
2180 	vfsp = vn_mountedvfs(vp);
2181 	if (vfsp != NULL) {
2182 		/* vn_vfsunlock(vp) is done inside unmount_node() */
2183 		error = unmount_node(vp, force);
2184 		if (error == ECONNRESET) {
2185 			if (vn_mountedvfs(vp) == NULL) {
2186 				/*
2187 				 * The filesystem was unmounted before the
2188 				 * daemon died. Unfortunately we can not
2189 				 * determine whether all the cleanup work was
2190 				 * successfully finished (i.e. update mnttab,
2191 				 * or notify NFS server of the unmount).
2192 				 * We should not retry the operation since the
2193 				 * filesystem has already been unmounted, and
2194 				 * may have already been removed from mnttab,
2195 				 * in such case the devid/rdevid we send to
2196 				 * the daemon will not be matched. So we have
2197 				 * to be content with the partial unmount.
2198 				 * Since the mountpoint is no longer covered, we
2199 				 * clear the error condition.
2200 				 */
2201 				error = 0;
2202 				auto_log(fngp->fng_verbose, fngp->fng_zoneid,
2203 				    CE_WARN, "autofs: automountd "
2204 				    "connection dropped when unmounting %s/%s",
2205 				    fnip->fi_path, (fnip->fi_flags & MF_DIRECT)
2206 				    ? "" : fnp->fn_name);
2207 			}
2208 		}
2209 	} else {
2210 		vn_vfsunlock(vp);
2211 		/* Destroy all dirents of fnp if we unmounted its triggers */
2212 		if (trigger_unmount)
2213 			unmount_autofs(vp);
2214 	}
2215 
2216 	/* If unmount failed, we got to remount triggers */
2217 	if (error != 0) {
2218 		if (trigger_unmount) {
2219 			int	ret;
2220 
2221 			ASSERT((fnp->fn_flags & MF_THISUID_MATCH_RQD) == 0);
2222 
2223 			/*
2224 			 * The action list was free'd by auto_perform_actions
2225 			 */
2226 			ret = auto_perform_actions(fnip, fnp, alp, CRED());
2227 			if (ret != 0) {
2228 				auto_log(fngp->fng_verbose, fngp->fng_zoneid,
2229 				    CE_WARN, "autofs: can't remount triggers "
2230 				    "fnp=%p error=%d", (void *)fnp, ret);
2231 			}
2232 		}
2233 		mutex_enter(&fnp->fn_lock);
2234 		AUTOFS_UNBLOCK_OTHERS(fnp, MF_INPROG);
2235 		mutex_exit(&fnp->fn_lock);
2236 	} else {
2237 		/* Free the action list here */
2238 		if (trigger_unmount)
2239 			xdr_free(xdr_action_list, (char *)alp);
2240 
2241 		/*
2242 		 * Other threads may be waiting for this unmount to
2243 		 * finish. We must let it know that in order to
2244 		 * proceed, it must trigger the mount itself.
2245 		 */
2246 		mutex_enter(&fnp->fn_lock);
2247 		fnp->fn_flags &= ~MF_IK_MOUNT;
2248 		if (fnp->fn_flags & MF_WAITING)
2249 			fnp->fn_error = EAGAIN;
2250 		AUTOFS_UNBLOCK_OTHERS(fnp, MF_INPROG);
2251 		mutex_exit(&fnp->fn_lock);
2252 	}
2253 
2254 	return (error);
2255 }
2256 
2257 /*
2258  * This is an implementation of depth-first search in a tree rooted by
2259  * start_fnp and composed from fnnodes. Links between tree levels are
2260  * fn_dirents, fn_trigger in fnnode_t and v_mountedvfs in vnode_t (if
2261  * mounted vfs is autofs). The algorithm keeps track of visited nodes
2262  * by means of a timestamp (fn_unmount_ref_time).
2263  *
2264  * Upon top-down traversal of the tree we apply following locking scheme:
2265  *	lock fn_rwlock of current node
2266  *	grab reference to child's vnode (VN_HOLD)
2267  *	unlock fn_rwlock
2268  *	free reference to current vnode (VN_RELE)
2269  * Similar locking scheme is used for down-top and left-right traversal.
2270  *
2271  * Algorithm examines the most down-left node in tree, which hasn't been
2272  * visited yet. From this follows that nodes are processed in bottom-up
2273  * fashion.
2274  *
2275  * Function returns either zero if unmount of root node was successful
2276  * or error code (mostly EBUSY).
2277  */
2278 int
unmount_subtree(fnnode_t * rootfnp,boolean_t force)2279 unmount_subtree(fnnode_t *rootfnp, boolean_t force)
2280 {
2281 	fnnode_t	*currfnp; /* currently examined node in the tree */
2282 	fnnode_t	*lastfnp; /* previously processed node */
2283 	fnnode_t	*nextfnp; /* next examined node in the tree */
2284 	vnode_t		*curvp;
2285 	vnode_t		*newvp;
2286 	vfs_t		*vfsp;
2287 	time_t		timestamp;
2288 
2289 	ASSERT(fntovn(rootfnp)->v_type != VLNK);
2290 	AUTOFS_DPRINT((10, "unmount_subtree: root=%p (%s)\n", (void *)rootfnp,
2291 	    rootfnp->fn_name));
2292 
2293 	/*
2294 	 * Timestamp, which visited nodes are marked with, to distinguish them
2295 	 * from unvisited nodes.
2296 	 */
2297 	timestamp = gethrestime_sec();
2298 	currfnp = lastfnp = rootfnp;
2299 
2300 	/* Loop until we examine all nodes in the tree */
2301 	mutex_enter(&currfnp->fn_lock);
2302 	while (currfnp != rootfnp || rootfnp->fn_unmount_ref_time < timestamp) {
2303 		curvp = fntovn(currfnp);
2304 		AUTOFS_DPRINT((10, "\tunmount_subtree: entering node %p (%s)\n",
2305 		    (void *)currfnp, currfnp->fn_name));
2306 
2307 		/*
2308 		 * New candidate for processing must have been already visited,
2309 		 * by us because we want to process tree nodes in bottom-up
2310 		 * order.
2311 		 */
2312 		if (currfnp->fn_unmount_ref_time == timestamp &&
2313 		    currfnp != lastfnp) {
2314 			(void) try_unmount_node(currfnp, force);
2315 			lastfnp = currfnp;
2316 			mutex_enter(&currfnp->fn_lock);
2317 			/*
2318 			 * Fall through to next if-branch to pick
2319 			 * sibling or parent of this node.
2320 			 */
2321 		}
2322 
2323 		/*
2324 		 * If this node has been already visited, it means that it's
2325 		 * dead end and we need to pick sibling or parent as next node.
2326 		 */
2327 		if (currfnp->fn_unmount_ref_time >= timestamp ||
2328 		    curvp->v_type == VLNK) {
2329 			mutex_exit(&currfnp->fn_lock);
2330 			/*
2331 			 * Obtain parent's readers lock before grabbing
2332 			 * reference to sibling.
2333 			 */
2334 			rw_enter(&currfnp->fn_parent->fn_rwlock, RW_READER);
2335 			if ((nextfnp = currfnp->fn_next) != NULL) {
2336 				VN_HOLD(fntovn(nextfnp));
2337 				rw_exit(&currfnp->fn_parent->fn_rwlock);
2338 				VN_RELE(curvp);
2339 				currfnp = nextfnp;
2340 				mutex_enter(&currfnp->fn_lock);
2341 				continue;
2342 			}
2343 			rw_exit(&currfnp->fn_parent->fn_rwlock);
2344 
2345 			/*
2346 			 * All descendants and siblings were visited. Perform
2347 			 * bottom-up move.
2348 			 */
2349 			nextfnp = currfnp->fn_parent;
2350 			VN_HOLD(fntovn(nextfnp));
2351 			VN_RELE(curvp);
2352 			currfnp = nextfnp;
2353 			mutex_enter(&currfnp->fn_lock);
2354 			continue;
2355 		}
2356 
2357 		/*
2358 		 * Mark node as visited. Note that the timestamp could have
2359 		 * been updated by somebody else in the meantime.
2360 		 */
2361 		if (currfnp->fn_unmount_ref_time < timestamp)
2362 			currfnp->fn_unmount_ref_time = timestamp;
2363 
2364 		/*
2365 		 * Don't descent below nodes, which are being unmounted/mounted.
2366 		 *
2367 		 * We need to hold both locks at once: fn_lock because we need
2368 		 * to read MF_INPROG and fn_rwlock to prevent anybody from
2369 		 * modifying fn_trigger until its used to traverse triggers
2370 		 * below.
2371 		 *
2372 		 * Acquire fn_rwlock in non-blocking mode to avoid deadlock.
2373 		 * If it can't be acquired, then acquire locks in correct
2374 		 * order.
2375 		 */
2376 		if (!rw_tryenter(&currfnp->fn_rwlock, RW_READER)) {
2377 			mutex_exit(&currfnp->fn_lock);
2378 			rw_enter(&currfnp->fn_rwlock, RW_READER);
2379 			mutex_enter(&currfnp->fn_lock);
2380 		}
2381 		if (currfnp->fn_flags & MF_INPROG) {
2382 			rw_exit(&currfnp->fn_rwlock);
2383 			continue;
2384 		}
2385 		mutex_exit(&currfnp->fn_lock);
2386 
2387 		/*
2388 		 * Examine descendants in this order: triggers, dirents, autofs
2389 		 * mounts.
2390 		 */
2391 
2392 		if ((nextfnp = currfnp->fn_trigger) != NULL) {
2393 			VN_HOLD(fntovn(nextfnp));
2394 			rw_exit(&currfnp->fn_rwlock);
2395 			VN_RELE(curvp);
2396 			currfnp = nextfnp;
2397 			mutex_enter(&currfnp->fn_lock);
2398 			continue;
2399 		}
2400 
2401 		if ((nextfnp = currfnp->fn_dirents) != NULL) {
2402 			VN_HOLD(fntovn(nextfnp));
2403 			rw_exit(&currfnp->fn_rwlock);
2404 			VN_RELE(curvp);
2405 			currfnp = nextfnp;
2406 			mutex_enter(&currfnp->fn_lock);
2407 			continue;
2408 		}
2409 		rw_exit(&currfnp->fn_rwlock);
2410 
2411 		(void) vn_vfswlock_wait(curvp);
2412 		vfsp = vn_mountedvfs(curvp);
2413 		if (vfsp != NULL &&
2414 		    vfs_matchops(vfsp, vfs_getops(curvp->v_vfsp))) {
2415 			/*
2416 			 * Deal with /xfn/host/jurassic alikes here...
2417 			 *
2418 			 * We know this call to VFS_ROOT is safe to call while
2419 			 * holding VVFSLOCK, since it resolves to a call to
2420 			 * auto_root().
2421 			 */
2422 			if (VFS_ROOT(vfsp, &newvp)) {
2423 				cmn_err(CE_PANIC,
2424 				    "autofs: VFS_ROOT(vfs=%p) failed",
2425 				    (void *)vfsp);
2426 			}
2427 			vn_vfsunlock(curvp);
2428 			VN_RELE(curvp);
2429 			currfnp = vntofn(newvp);
2430 			mutex_enter(&currfnp->fn_lock);
2431 			continue;
2432 		}
2433 		vn_vfsunlock(curvp);
2434 		mutex_enter(&currfnp->fn_lock);
2435 	}
2436 
2437 	/*
2438 	 * Now we deal with the root node (currfnp's mutex is unlocked
2439 	 * in try_unmount_node()).
2440 	 */
2441 	return (try_unmount_node(currfnp, force));
2442 }
2443 
2444 /*
2445  * XXX unmount_tree() is not suspend-safe within the scope of
2446  * the present model defined for cpr to suspend the system. Calls made
2447  * by the unmount_tree() that have been identified to be unsafe are
2448  * (1) RPC client handle setup and client calls to automountd which can
2449  * block deep down in the RPC library, (2) kmem_alloc() calls with the
2450  * KM_SLEEP flag which can block if memory is low, and (3) VFS_*() and
2451  * VOP_*() calls which can result in over the wire calls to servers.
2452  * The thread should be completely reevaluated to make it suspend-safe in
2453  * case of future updates to the cpr model.
2454  */
2455 void
unmount_tree(struct autofs_globals * fngp,boolean_t force)2456 unmount_tree(struct autofs_globals *fngp, boolean_t force)
2457 {
2458 	callb_cpr_t	cprinfo;
2459 	kmutex_t	unmount_tree_cpr_lock;
2460 	fnnode_t	*root, *fnp, *next;
2461 
2462 	mutex_init(&unmount_tree_cpr_lock, NULL, MUTEX_DEFAULT, NULL);
2463 	CALLB_CPR_INIT(&cprinfo, &unmount_tree_cpr_lock, callb_generic_cpr,
2464 	    "unmount_tree");
2465 
2466 	/*
2467 	 * autofssys() will be calling in from the global zone and doing
2468 	 * work on the behalf of the given zone, hence we can't always
2469 	 * assert that we have the right credentials, nor that the
2470 	 * caller is always in the correct zone.
2471 	 *
2472 	 * We do, however, know that if this is a "forced unmount"
2473 	 * operation (which autofssys() does), then we won't go down to
2474 	 * the krpc layers, so we don't need to fudge with the
2475 	 * credentials.
2476 	 */
2477 	ASSERT(force || fngp->fng_zoneid == getzoneid());
2478 
2479 	/*
2480 	 * If automountd is not running in this zone,
2481 	 * don't attempt unmounting this round.
2482 	 */
2483 	if (force || auto_null_request(fngp->fng_zoneid, FALSE) == 0) {
2484 		/*
2485 		 * Iterate over top level autofs filesystems and call
2486 		 * unmount_subtree() for each of them.
2487 		 */
2488 		root = fngp->fng_rootfnnodep;
2489 		rw_enter(&root->fn_rwlock, RW_READER);
2490 		for (fnp = root->fn_dirents; fnp != NULL; fnp = next) {
2491 			VN_HOLD(fntovn(fnp));
2492 			rw_exit(&root->fn_rwlock);
2493 			(void) unmount_subtree(fnp, force);
2494 			rw_enter(&root->fn_rwlock, RW_READER);
2495 			next = fnp->fn_next;
2496 			VN_RELE(fntovn(fnp));
2497 		}
2498 		rw_exit(&root->fn_rwlock);
2499 	}
2500 
2501 	mutex_enter(&unmount_tree_cpr_lock);
2502 	CALLB_CPR_EXIT(&cprinfo);
2503 	mutex_destroy(&unmount_tree_cpr_lock);
2504 }
2505 
2506 static void
unmount_zone_tree(struct autofs_globals * fngp)2507 unmount_zone_tree(struct autofs_globals *fngp)
2508 {
2509 	AUTOFS_DPRINT((5, "unmount_zone_tree started. Thread created.\n"));
2510 
2511 	unmount_tree(fngp, B_FALSE);
2512 	mutex_enter(&fngp->fng_unmount_threads_lock);
2513 	fngp->fng_unmount_threads--;
2514 	mutex_exit(&fngp->fng_unmount_threads_lock);
2515 
2516 	AUTOFS_DPRINT((5, "unmount_zone_tree done. Thread exiting.\n"));
2517 
2518 	zthread_exit();
2519 	/* NOTREACHED */
2520 }
2521 
2522 void
auto_do_unmount(struct autofs_globals * fngp)2523 auto_do_unmount(struct autofs_globals *fngp)
2524 {
2525 	callb_cpr_t cprinfo;
2526 	clock_t timeleft;
2527 	zone_t *zone = curproc->p_zone;
2528 
2529 	CALLB_CPR_INIT(&cprinfo, &fngp->fng_unmount_threads_lock,
2530 	    callb_generic_cpr, "auto_do_unmount");
2531 
2532 	for (;;) {	/* forever */
2533 		mutex_enter(&fngp->fng_unmount_threads_lock);
2534 		CALLB_CPR_SAFE_BEGIN(&cprinfo);
2535 newthread:
2536 		mutex_exit(&fngp->fng_unmount_threads_lock);
2537 		timeleft = zone_status_timedwait(zone, ddi_get_lbolt() +
2538 		    autofs_unmount_thread_timer * hz, ZONE_IS_SHUTTING_DOWN);
2539 		mutex_enter(&fngp->fng_unmount_threads_lock);
2540 
2541 		if (timeleft != -1) {	/* didn't time out */
2542 			ASSERT(zone_status_get(zone) >= ZONE_IS_SHUTTING_DOWN);
2543 			/*
2544 			 * zone is exiting... don't create any new threads.
2545 			 * fng_unmount_threads_lock is released implicitly by
2546 			 * the below.
2547 			 */
2548 			CALLB_CPR_SAFE_END(&cprinfo,
2549 			    &fngp->fng_unmount_threads_lock);
2550 			CALLB_CPR_EXIT(&cprinfo);
2551 			zthread_exit();
2552 			/* NOTREACHED */
2553 		}
2554 		if (fngp->fng_unmount_threads < autofs_unmount_threads) {
2555 			fngp->fng_unmount_threads++;
2556 			CALLB_CPR_SAFE_END(&cprinfo,
2557 			    &fngp->fng_unmount_threads_lock);
2558 			mutex_exit(&fngp->fng_unmount_threads_lock);
2559 
2560 			(void) zthread_create(NULL, 0, unmount_zone_tree, fngp,
2561 			    0, minclsyspri);
2562 		} else
2563 			goto newthread;
2564 	}
2565 	/* NOTREACHED */
2566 }
2567 
2568 /*
2569  * Is nobrowse specified in option string?
2570  * opts should be a null ('\0') terminated string.
2571  * Returns non-zero if nobrowse has been specified.
2572  */
2573 int
auto_nobrowse_option(char * opts)2574 auto_nobrowse_option(char *opts)
2575 {
2576 	char *buf;
2577 	char *p;
2578 	char *t;
2579 	int nobrowse = 0;
2580 	int last_opt = 0;
2581 	size_t len;
2582 
2583 	len = strlen(opts) + 1;
2584 	p = buf = kmem_alloc(len, KM_SLEEP);
2585 	(void) strcpy(buf, opts);
2586 	do {
2587 		if (t = strchr(p, ','))
2588 			*t++ = '\0';
2589 		else
2590 			last_opt++;
2591 		if (strcmp(p, MNTOPT_NOBROWSE) == 0)
2592 			nobrowse = 1;
2593 		else if (strcmp(p, MNTOPT_BROWSE) == 0)
2594 			nobrowse = 0;
2595 		p = t;
2596 	} while (!last_opt);
2597 	kmem_free(buf, len);
2598 
2599 	return (nobrowse);
2600 }
2601 
2602 /*
2603  * used to log warnings only if automountd is running
2604  * with verbose mode set
2605  */
2606 
2607 void
auto_log(int verbose,zoneid_t zoneid,int level,const char * fmt,...)2608 auto_log(int verbose, zoneid_t zoneid, int level, const char *fmt, ...)
2609 {
2610 	va_list	args;
2611 
2612 	if (verbose) {
2613 		va_start(args, fmt);
2614 		vzcmn_err(zoneid, level, fmt, args);
2615 		va_end(args);
2616 	}
2617 }
2618 
2619 #ifdef DEBUG
2620 static int autofs_debug = 0;
2621 
2622 /*
2623  * Utilities used by both client and server
2624  * Standard levels:
2625  * 0) no debugging
2626  * 1) hard failures
2627  * 2) soft failures
2628  * 3) current test software
2629  * 4) main procedure entry points
2630  * 5) main procedure exit points
2631  * 6) utility procedure entry points
2632  * 7) utility procedure exit points
2633  * 8) obscure procedure entry points
2634  * 9) obscure procedure exit points
2635  * 10) random stuff
2636  * 11) all <= 1
2637  * 12) all <= 2
2638  * 13) all <= 3
2639  * ...
2640  */
2641 /* PRINTFLIKE2 */
2642 void
auto_dprint(int level,const char * fmt,...)2643 auto_dprint(int level, const char *fmt, ...)
2644 {
2645 	va_list args;
2646 
2647 	if (autofs_debug == level ||
2648 	    (autofs_debug > 10 && (autofs_debug - 10) >= level)) {
2649 		va_start(args, fmt);
2650 		(void) vprintf(fmt, args);
2651 		va_end(args);
2652 	}
2653 }
2654 #endif /* DEBUG */
2655