NetBSD-Bugs archive

[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index][Old Index]

Re: bin/60493: autofs does not handle chroot



Would you like to try the attached patch?

(Warning: totally untested; I have only verified it builds.)
# HG changeset patch
# User Taylor R Campbell <riastradh%NetBSD.org@localhost>
# Date 1784864508 0
#      Fri Jul 24 03:41:48 2026 +0000
# Branch trunk
# Node ID 195a46d49d734f1334b6e99c472d6d12173d98c9
# Parent  f75c5d43d5f2deed5b47bb74589a480ad6b7cd66
# EXP-Topic riastradh-pr60493-autofschroot
WIP: autofs: Support running inside a chroot.

PR kern/60493: autofs does not handle chroot

diff -r f75c5d43d5f2 -r 195a46d49d73 sys/fs/autofs/autofs.c
--- a/sys/fs/autofs/autofs.c	Thu Jul 23 22:07:04 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,58 @@ 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) {
+		chrootpathbuf = PNBUF_GET();
+
+		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;
 		}
 
@@ -478,9 +521,27 @@ autofs_ioctl_request(struct autofs_daemo
 	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 +550,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


Home | Main Index | Thread Index | Old Index