Skip site navigation (1)Skip section navigation (2)
Date:      Sat, 15 Dec 2001 00:34:35 +0000
From:      Ian Dowse <iedowse@maths.tcd.ie>
To:        current@freebsd.org
Subject:   mountd(8) leaving filesystems exported
Message-ID:   <200112150034.aa63895@salmon.maths.tcd.ie>

next in thread | raw e-mail | index | archive | help

There are quite a few assumptions in mountd(8) about the layout of
the per-filesystem mount(2) `data' struct, which make the code quite
ugly. It uses a union to ensure that it supplies a large enough
structure to mount(2), but regardless of the filesystem type, it
always initialises the UFS version.

One nasty bug is that the code for un-exporting filesystems checks
to see if the filesystem is among a list of supported types, but
the code for exporting doesn't. This list of supported filesystems
does not include ext2fs or hpfs, so you can successfully export
these filesystems, but they remain exported even when the /etc/exports
entry is removed and mountd is restarted or sent a SIGHUP, and no
errors are logged...

The patch below should address this issue by checking the same list
of filesystems in both cases, and adding ext2fs and hpfs to the
filesystem list. It also avoids the need to assume that all xxx_args
have the export_args in the same place by storing the offsets in a
table. I am aware that there is work ongoing in the area of mount(2),
so maybe the patch is overkill at this time. Any comments?

Ian

Index: mountd.c
===================================================================
RCS file: /dump/FreeBSD-CVS/src/sbin/mountd/mountd.c,v
retrieving revision 1.59
diff -u -r1.59 mountd.c
--- mountd.c	20 Sep 2001 02:15:17 -0000	1.59
+++ mountd.c	15 Dec 2001 00:10:47 -0000
@@ -76,6 +76,7 @@
 #include <netdb.h>
 #include <pwd.h>
 #include <signal.h>
+#include <stddef.h>
 #include <stdio.h>
 #include <stdlib.h>
 #include <string.h>
@@ -157,6 +158,29 @@
 	nfsfh_t	fhr_fh;
 };
 
+/* Union of mount(2) `data' structs for supported filesystems. */
+union mountdata {
+	struct ufs_args ua;
+	struct iso_args ia;
+	struct msdosfs_args da;
+	struct ntfs_args na;
+};
+
+/* Find the offset into the mountdata union of a filesystem's export_args. */
+struct ea_off {
+	char *fsname;
+	int exportargs_off;
+} ea_offtable[] = {
+	{"ufs", offsetof(union mountdata, ua.export)},
+	{"ifs", offsetof(union mountdata, ua.export)},
+	{"ext2fs", offsetof(union mountdata, ua.export)},
+	{"cd9660", offsetof(union mountdata, ia.export)},
+	{"msdosfs", offsetof(union mountdata, da.export)},
+	{"ntfs", offsetof(union mountdata, na.export)},
+	{"hpfs", offsetof(union mountdata, ua.export)}, /* XXX */
+	{NULL, 0}
+};
+
 /* Global defs */
 char	*add_expdir __P((struct dirlist **, char *, int));
 void	add_dlist __P((struct dirlist **, struct dirlist *,
@@ -191,6 +215,7 @@
 void	huphandler(int sig);
 int	makemask(struct sockaddr_storage *ssp, int bitlen);
 void	mntsrv __P((struct svc_req *, SVCXPRT *));
+struct export_args *mountdata_to_eap __P((union mountdata *, struct statfs *));
 void	nextfield __P((char **, char **));
 void	out_of_mem __P((void));
 void	parsecred __P((char *, struct xucred *));
@@ -884,6 +909,8 @@
 void
 get_exportlist()
 {
+	union mountdata args;
+	struct export_args *eap;
 	struct exportlist *ep, *ep2;
 	struct grouplist *grp, *tgrp;
 	struct exportlist **epp;
@@ -918,26 +945,16 @@
 	/*
 	 * And delete exports that are in the kernel for all local
 	 * file systems.
-	 * XXX: Should know how to handle all local exportable file systems
-	 *      instead of just "ufs".
 	 */
 	num = getmntinfo(&fsp, MNT_NOWAIT);
 	for (i = 0; i < num; i++) {
-		union {
-			struct ufs_args ua;
-			struct iso_args ia;
-			struct msdosfs_args da;
-			struct ntfs_args na;
-		} targs;
-
-		if (!strcmp(fsp->f_fstypename, "ufs") ||
-		    !strcmp(fsp->f_fstypename, "msdosfs") ||
-		    !strcmp(fsp->f_fstypename, "ntfs") ||
-		    !strcmp(fsp->f_fstypename, "cd9660")) {
-			targs.ua.fspec = NULL;
-			targs.ua.export.ex_flags = MNT_DELEXPORT;
+		eap = mountdata_to_eap(&args, fsp);
+		if (eap != NULL) {
+			/* This is a filesystem that supports NFS exports. */
+			bzero(&args, sizeof(args));
+			eap->ex_flags = MNT_DELEXPORT;
 			if (mount(fsp->f_fstypename, fsp->f_mntonname,
-			    fsp->f_flags | MNT_UPDATE, (caddr_t)&targs) < 0 &&
+			    fsp->f_flags | MNT_UPDATE, &args) < 0 &&
 			    errno != ENOENT)
 				syslog(LOG_ERR,
 				    "can't delete exports for %s: %m",
@@ -1711,23 +1728,23 @@
 	int dirplen;
 	struct statfs *fsb;
 {
+	union mountdata args;
 	struct statfs fsb1;
 	struct addrinfo *ai;
 	struct export_args *eap;
 	char *cp = NULL;
 	int done;
 	char savedc = '\0';
-	union {
-		struct ufs_args ua;
-		struct iso_args ia;
-		struct msdosfs_args da;
-		struct ntfs_args na;
-	} args;
 
 	bzero(&args, sizeof args);
-	/* XXX, we assume that all xx_args look like ufs_args. */
-	args.ua.fspec = 0;
-	eap = &args.ua.export;
+	if ((eap = mountdata_to_eap(&args, fsb)) == NULL) {
+		if (debug)
+			warnx("%s: cannot export %s filesystems", dirp,
+			    fsb->f_fstypename);
+		syslog(LOG_ERR, "%s: cannot export %s filesystems", dirp,
+		    fsb->f_fstypename);
+		return (1);
+	}
 
 	eap->ex_flags = exflags;
 	eap->ex_anon = *anoncrp;
@@ -1777,8 +1794,6 @@
 		 * XXX:
 		 * Maybe I should just use the fsb->f_mntonname path instead
 		 * of looping back up the dirp to the mount point??
-		 * Also, needs to know how to export all types of local
-		 * exportable file systems and not just "ufs".
 		 */
 		while (mount(fsb->f_fstypename, dirp,
 		    fsb->f_flags | MNT_UPDATE, (caddr_t)&args) < 0) {
@@ -1829,6 +1844,25 @@
 	if (cp)
 		*cp = savedc;
 	return (0);
+}
+
+/*
+ * For the filesystem specified by fsp, return a pointer to the
+ * export_args structure within the mountdata union. If the filesystem
+ * does not support NFS exports, NULL is returned instead.
+ */
+struct export_args *
+mountdata_to_eap(mntdata, fsp)
+	union mountdata *mntdata;
+	struct statfs *fsp;
+{
+	struct ea_off *p;
+
+	for (p = ea_offtable; p->fsname != NULL; p++)
+		if (strcmp(fsp->f_fstypename, p->fsname) == 0)
+			return (struct export_args *)((char *)mntdata +
+			    p->exportargs_off);
+	return (NULL);
 }
 
 /*

To Unsubscribe: send mail to majordomo@FreeBSD.org
with "unsubscribe freebsd-current" in the body of the message




Want to link to this message? Use this URL: <https://mail-archive.FreeBSD.org/cgi/mid.cgi? <200112150034.aa63895>