Re: bin/60493: autofs does not handle chroot

Taylor R Campbell <[email protected]>
Newsgroups gmane.os.netbsd.bugs
Message-ID <[email protected]>
Updated patch -- this one initializes chrootpath as the somewhat
sharp-edged getcwd_common expects, so it doesn't lead to immediate
null pointer dereference.
pr60493-autofschroot-v2.patch (text/plain, 4.2 KB)
# HG changeset patch
# User Taylor R Campbell <[email protected]>
# Date 1784864508 0
#      Fri Jul 24 03:41:48 2026 +0000
# Branch trunk
# Node ID 6a1f5812e6f2eea24edafcaceba580dea93e45e2
# Parent  b125bad3265e13dfd5a772b3676744fca85ce488
# EXP-Topic riastradh-pr60493-autofschroot
WIP: autofs: Support running inside a chroot.

PR kern/60493: autofs does not handle chroot

diff -r b125bad3265e -r 6a1f5812e6f2 sys/fs/autofs/autofs.c
--- a/sys/fs/autofs/autofs.c	Mon Aug 03 19:24:48 2026 +0000
+++ b/sys/fs/autofs/autofs.c	Fri Jul 24 03:41:48 2026 +0000
@@ -75,6 +75,7 @@
 #include "ioconf.h"
 
 #include <sys/atomic.h>
+#include <sys/filedesc.h>
 #include <sys/queue.h>
 #include <sys/signalvar.h>
 
@@ -451,16 +452,70 @@ autofs_trigger(struct autofs_node *anp, 
 static int
 autofs_ioctl_request(struct autofs_daemon_request *adr)
 {
+	struct lwp *l = curlwp;
+	struct proc *p = curproc;
+	struct cwdinfo *cwdi = p->p_cwdi;
 	struct autofs_request *ar;
+	char *chrootpathbuf = NULL, *chrootpath = NULL;
+	size_t chrootpathlen = 0;
+	const char *path;
+	int error;
 
+	/*
+	 * If we're chrooted, find the prefix to match in requests and
+	 * strip off.
+	 *
+	 * If we're not chrooted, don't bother with any of it: no need
+	 * to allocate a pathbuf and compute getcwd().  If another
+	 * thread chroots while we're working, tough.
+	 */
+	if (atomic_load_relaxed(&cwdi->cwdi_rdir) != NULL) {
+		/*
+		 * getcwd_common builds a path backwards from the end
+		 * in a given buffer.  So allocate a buffer,
+		 * NUL-terminate it at the end, and start with a
+		 * pointer to the NUL byte.  Even though PNBUF_GET
+		 * allocates a buffer of MAXPATHLEN bytes (including
+		 * NUL), we clamp the length of the chroot prefix
+		 * somewhat arbitrarily to MAXPATHLEN/2 just like
+		 * statvfs(2) and getvfsstat(2).
+		 */
+		chrootpathbuf = PNBUF_GET();
+		chrootpath = chrootpathbuf + MAXPATHLEN;
+		*--chrootpath = '\0';
+
+		rw_enter(&cwdi->cwdi_lock, RW_READER);
+		error = getcwd_common(cwdi->cwdi_rdir, rootvnode, &chrootpath,
+		    chrootpathbuf, MAXPATHLEN/2, 0, l);
+		rw_exit(&cwdi->cwdi_lock);
+		if (error)
+			goto out;
+		chrootpathlen = strlen(chrootpath);
+	}
+
+	/*
+	 * Wait until there is a request that is:
+	 *
+	 * (a) not done,
+	 * (b) not in progress by another thread,
+	 * (c) if we're chrooted, within our chroot.
+	 *
+	 * Once we have one, mark it in progress so other threads don't
+	 * take it.
+	 */
 	mutex_enter(&autofs_softc->sc_lock);
 	for (;;) {
-		int error;
 		TAILQ_FOREACH(ar, &autofs_softc->sc_requests, ar_next) {
 			if (ar->ar_done)
 				continue;
 			if (ar->ar_in_progress)
 				continue;
+			if (chrootpathlen > 1 &&
+			    (strncmp(ar->ar_path, chrootpath, chrootpathlen)
+				!= 0 ||
+				(ar->ar_path[chrootpathlen] != '/' &&
+				    ar->ar_path[chrootpathlen] != '\0')))
+				continue;
 			break;
 		}
 
@@ -471,16 +526,34 @@ autofs_ioctl_request(struct autofs_daemo
 		    &autofs_softc->sc_lock);
 		if (error) {
 			mutex_exit(&autofs_softc->sc_lock);
-			return error;
+			goto out;
 		}
 	}
 
 	ar->ar_in_progress = true;
 	mutex_exit(&autofs_softc->sc_lock);
 
+	/*
+	 * If we're chrooted, strip the chroot prefix off ar->ar_path.
+	 * Otherwise, just use ar->ar_path as is for the adr->adr_path
+	 * we return to userland.
+	 */
+	if (chrootpathlen > 1) {
+		KASSERT(strncmp(ar->ar_path, chrootpath, chrootpathlen) == 0);
+		KASSERT(ar->ar_path[chrootpathlen] == '/' ||
+		    ar->ar_path[chrootpathlen] == '\0');
+		if (ar->ar_path[chrootpathlen] == '\0')
+			path = "/";
+		else
+			path = ar->ar_path + chrootpathlen;
+		KASSERT(path[0] == '/');
+	} else {
+		path = ar->ar_path;
+	}
+
 	adr->adr_id = ar->ar_id;
 	strlcpy(adr->adr_from, ar->ar_from, sizeof(adr->adr_from));
-	strlcpy(adr->adr_path, ar->ar_path, sizeof(adr->adr_path));
+	strlcpy(adr->adr_path, path, sizeof(adr->adr_path));
 	strlcpy(adr->adr_prefix, ar->ar_prefix, sizeof(adr->adr_prefix));
 	strlcpy(adr->adr_key, ar->ar_key, sizeof(adr->adr_key));
 	strlcpy(adr->adr_options, ar->ar_options, sizeof(adr->adr_options));
@@ -489,7 +562,11 @@ autofs_ioctl_request(struct autofs_daemo
 	autofs_softc->sc_dev_sid = curproc->p_pgrp->pg_id;
 	mutex_exit(&proc_lock);
 
-	return 0;
+	error = 0;
+
+out:	if (chrootpathbuf)
+		PNBUF_PUT(chrootpathbuf);
+	return error;
 }
 
 static int
lmpx.com only provides a reader for public news (NNTP) servers. It is not affiliated with the servers or forums shown here and is not responsible for the content of articles, which is written by their respective authors.