git: 7c5146da1286 - main - mountd: Add support for spaces in exported directories

From: Rick Macklem <rmacklem_at_FreeBSD.org>
Date: Sat, 04 Nov 2023 22:10:55 UTC
The branch main has been updated by rmacklem:

URL: https://cgit.FreeBSD.org/src/commit/?id=7c5146da128688ba2bb6bdad5e98716087a47281

commit 7c5146da128688ba2bb6bdad5e98716087a47281
Author:     Dan Mcgregor <dan.mcgregor_usask.ca>
AuthorDate: 2023-11-04 22:07:56 +0000
Commit:     Rick Macklem <rmacklem@FreeBSD.org>
CommitDate: 2023-11-04 22:07:56 +0000

    mountd: Add support for spaces in exported directories
    
    The previous code would correctly parse strings including quotation
    marks (") or backslash (/), but the tests when creating the export
    includes them in the final string. This prevents exporting paths
    with embedded spaces, for example "/exports/with space". Trying
    results in log lines resembling:
    
    mountd[1337]: bad exports list line '/exports/with\ space':
        /exports/with\ space: lstat() failed: No such file or directory.
    
    Turns out that when creating its exports list, zfs escapes strings
    in a format compatible with vis(3). Since I expect that zfs sharenfs
    is the dominating use case for generating an exports list, use
    strunvis(3) to parse the export path. The result is lines like the
    following allowing spaces:
    
    /exports/with\040space -network 192.168.0 -mask 255.255.255.0
    
    A man page update will be done as a separate commit.
    
    MFC after:      1 month
    Reviewed by:    rmacklem
    Differential Revision:  https://reviews.freebsd.org/D42432
---
 usr.sbin/mountd/mountd.c | 32 +++++++++++++++++++++++---------
 1 file changed, 23 insertions(+), 9 deletions(-)

diff --git a/usr.sbin/mountd/mountd.c b/usr.sbin/mountd/mountd.c
index 6602dbc09aa0..33c19a81a0cf 100644
--- a/usr.sbin/mountd/mountd.c
+++ b/usr.sbin/mountd/mountd.c
@@ -83,6 +83,7 @@ static char sccsid[] = "@(#)mountd.c	8.15 (Berkeley) 5/1/95";
 #include <stdlib.h>
 #include <string.h>
 #include <unistd.h>
+#include <vis.h>
 #include "pathnames.h"
 #include "mntopts.h"
 
@@ -1561,10 +1562,13 @@ get_exportlist_one(int passno)
 	char *err_msg = NULL;
 	int len, has_host, got_nondir, dirplen, netgrp;
 	uint64_t exflags;
+	char unvis_dir[PATH_MAX + 1];
+	int unvis_len;
 
 	v4root_phase = 0;
 	anon.cr_groups = NULL;
 	dirhead = (struct dirlist *)NULL;
+	unvis_dir[0] = '\0';
 	while (get_line()) {
 		if (debug)
 			warnx("got line %s", line);
@@ -1631,17 +1635,25 @@ get_exportlist_one(int passno)
 			} else if (*cp == '/') {
 			    savedc = *endcp;
 			    *endcp = '\0';
+			    unvis_len = strnunvis(unvis_dir, sizeof(unvis_dir),
+				cp);
+			    if (unvis_len <= 0) {
+				getexp_err(ep, tgrp, "Cannot strunvis "
+				    "decode dir");
+				goto nextline;
+			    }
 			    if (v4root_phase > 1) {
 				    if (dirp != NULL) {
 					getexp_err(ep, tgrp, "Multiple V4 dirs");
 					goto nextline;
 				    }
 			    }
-			    if (check_dirpath(cp, &err_msg) &&
-				check_statfs(cp, &fsb, &err_msg)) {
+			    if (check_dirpath(unvis_dir, &err_msg) &&
+				check_statfs(unvis_dir, &fsb, &err_msg)) {
 				if ((fsb.f_flags & MNT_AUTOMOUNTED) != 0)
 				    syslog(LOG_ERR, "Warning: exporting of "
-					"automounted fs %s not supported", cp);
+					"automounted fs %s not supported",
+					unvis_dir);
 				if (got_nondir) {
 				    getexp_err(ep, tgrp, "dirs must be first");
 				    goto nextline;
@@ -1652,16 +1664,17 @@ get_exportlist_one(int passno)
 					goto nextline;
 				    }
 				    if (strlen(v4root_dirpath) == 0) {
-					strlcpy(v4root_dirpath, cp,
+					strlcpy(v4root_dirpath, unvis_dir,
 					    sizeof (v4root_dirpath));
-				    } else if (strcmp(v4root_dirpath, cp)
+				    } else if (strcmp(v4root_dirpath, unvis_dir)
 					!= 0) {
 					syslog(LOG_ERR,
-					    "different V4 dirpath %s", cp);
+					    "different V4 dirpath %s",
+					    unvis_dir);
 					getexp_err(ep, tgrp, NULL);
 					goto nextline;
 				    }
-				    dirp = cp;
+				    dirp = unvis_dir;
 				    v4root_phase = 2;
 				    got_nondir = 1;
 				    ep = get_exp();
@@ -1699,8 +1712,9 @@ get_exportlist_one(int passno)
 				    /*
 				     * Add dirpath to export mount point.
 				     */
-				    dirp = add_expdir(&dirhead, cp, len);
-				    dirplen = len;
+				    dirp = add_expdir(&dirhead, unvis_dir,
+					unvis_len);
+				    dirplen = unvis_len;
 				}
 			    } else {
 				if (err_msg != NULL) {