Subject: statfs changes
To: None <tech-kern@netbsd.org>
From: Christos Zoulas <christos@zoulas.com>
List: tech-kern
Date: 04/15/2003 20:42:32
Inspired by pr 1796 I decided to fix statfs under chrooted environments.
It does not make any sense to display the full mount list, and it should
display an appropriate root entry. In addition, mount calls that happen
under the chroot environment should be able to be unmounted outside the
chroot environment. To fix this I introduced a nse function set_statfs_info()
which normalizes the f_mntonnname to the canonical non chrooted path,
eliminating a lot of code and fixing a bug in ext2fs, and a dostatfs()
wrapper that deals with providing proper chrooted paths. Finally I
fixed a locking bug in vfs_getfsstat(). Please let me know what you think, 
because I am planning to commit the changes soon.

christos

Index: fs/adosfs/advfsops.c
===================================================================
RCS file: /cvsroot/src/sys/fs/adosfs/advfsops.c,v
retrieving revision 1.3
diff -u -u -r1.3 advfsops.c
--- fs/adosfs/advfsops.c	2003/03/21 23:11:24	1.3
+++ fs/adosfs/advfsops.c	2003/04/16 00:36:57
@@ -103,7 +103,6 @@
 	struct vnode *devvp;
 	struct adosfs_args args;
 	struct adosfsmount *amp;
-	size_t size;
 	int error;
 	mode_t accessmode;
 
@@ -175,12 +174,7 @@
 	amp->uid = args.uid;
 	amp->gid = args.gid;
 	amp->mask = args.mask;
-	(void) copyinstr(path, mp->mnt_stat.f_mntonname, MNAMELEN - 1, &size);
-	memset(mp->mnt_stat.f_mntonname + size, 0, MNAMELEN - size);
-	(void) copyinstr(args.fspec, mp->mnt_stat.f_mntfromname, MNAMELEN - 1,
-	    &size);
-	memset(mp->mnt_stat.f_mntfromname + size, 0, MNAMELEN - size);
-	return (0);
+	return set_statfs_info(0, path, args.fspec, mp, p);
 }
 
 int
Index: fs/cd9660/cd9660_vfsops.c
===================================================================
RCS file: /cvsroot/src/sys/fs/cd9660/cd9660_vfsops.c,v
retrieving revision 1.4
diff -u -u -r1.4 cd9660_vfsops.c
--- fs/cd9660/cd9660_vfsops.c	2003/04/03 15:37:55	1.4
+++ fs/cd9660/cd9660_vfsops.c	2003/04/16 00:36:58
@@ -177,7 +177,6 @@
 {
 	struct vnode *devvp;
 	struct iso_args args;
-	size_t size;
 	int error;
 	struct iso_mnt *imp = NULL;
 	
@@ -249,12 +248,7 @@
 		return error;
 	}
 	imp = VFSTOISOFS(mp);
-	(void) copyinstr(path, mp->mnt_stat.f_mntonname, MNAMELEN - 1, &size);
-	memset(mp->mnt_stat.f_mntonname + size, 0, MNAMELEN - size);
-	(void) copyinstr(args.fspec, mp->mnt_stat.f_mntfromname, MNAMELEN - 1,
-	    &size);
-	memset(mp->mnt_stat.f_mntfromname + size, 0, MNAMELEN - size);
-	return 0;
+	return set_statfs_info(0, path, args.fspec, mp, p);
 }
 
 /*
Index: fs/filecorefs/filecore_vfsops.c
===================================================================
RCS file: /cvsroot/src/sys/fs/filecorefs/filecore_vfsops.c,v
retrieving revision 1.2
diff -u -u -r1.2 filecore_vfsops.c
--- fs/filecorefs/filecore_vfsops.c	2003/02/01 06:23:41	1.2
+++ fs/filecorefs/filecore_vfsops.c	2003/04/16 00:36:58
@@ -159,7 +159,6 @@
 {
 	struct vnode *devvp;
 	struct filecore_args args;
-	size_t size;
 	int error;
 	struct filecore_mnt *fcmp = NULL;
 	
@@ -233,12 +232,7 @@
 		return error;
 	}
 	fcmp = VFSTOFILECORE(mp);
-	(void) copyinstr(path, mp->mnt_stat.f_mntonname, MNAMELEN - 1, &size);
-	memset(mp->mnt_stat.f_mntonname + size, 0, MNAMELEN - size);
-	(void) copyinstr(args.fspec, mp->mnt_stat.f_mntfromname, MNAMELEN - 1,
-	    &size);
-	memset(mp->mnt_stat.f_mntfromname + size, 0, MNAMELEN - size);
-	return 0;
+	return set_statfs_info(0, path, args.fspec, mp, p);
 }
 
 /*
Index: fs/msdosfs/msdosfs_vfsops.c
===================================================================
RCS file: /cvsroot/src/sys/fs/msdosfs/msdosfs_vfsops.c,v
retrieving revision 1.3
diff -u -u -r1.3 msdosfs_vfsops.c
--- fs/msdosfs/msdosfs_vfsops.c	2003/03/21 23:11:25	1.3
+++ fs/msdosfs/msdosfs_vfsops.c	2003/04/16 00:36:59
@@ -245,7 +245,6 @@
 	struct msdosfs_args args; /* will hold data from mount request */
 	/* msdosfs specific mount control block */
 	struct msdosfsmount *pmp = NULL;
-	size_t size;
 	int error, flags;
 	mode_t accessmode;
 
@@ -367,15 +366,10 @@
 		return error;
 	}
 
-	(void) copyinstr(path, mp->mnt_stat.f_mntonname, MNAMELEN - 1, &size);
-	memset(mp->mnt_stat.f_mntonname + size, 0, MNAMELEN - size);
-	(void) copyinstr(args.fspec, mp->mnt_stat.f_mntfromname, MNAMELEN - 1,
-	    &size);
-	memset(mp->mnt_stat.f_mntfromname + size, 0, MNAMELEN - size);
 #ifdef MSDOSFS_DEBUG
 	printf("msdosfs_mount(): mp %p, pmp %p, inusemap %p\n", mp, pmp, pmp->pm_inusemap);
 #endif
-	return (0);
+	return set_statfs_info(0, path, args.fspec, mp, p);
 }
 
 int
Index: fs/ntfs/ntfs_vfsops.c
===================================================================
RCS file: /cvsroot/src/sys/fs/ntfs/ntfs_vfsops.c,v
retrieving revision 1.3
diff -u -u -r1.3 ntfs_vfsops.c
--- fs/ntfs/ntfs_vfsops.c	2003/04/09 16:18:17	1.3
+++ fs/ntfs/ntfs_vfsops.c	2003/04/16 00:36:59
@@ -246,7 +246,6 @@
 	struct nameidata *ndp,
 	struct proc *p )
 {
-	size_t		size;
 	int		err = 0;
 	struct vnode	*devvp;
 	struct ntfs_args args;
@@ -369,12 +368,7 @@
 		 * Update device name only on success
 		 */
 		if( !err) {
-			/* Save "mounted from" info for mount point (NULL pad)*/
-			copyinstr(	args.fspec,
-					mp->mnt_stat.f_mntfromname,
-					MNAMELEN - 1,
-					&size);
-			bzero( mp->mnt_stat.f_mntfromname + size, MNAMELEN - size);
+			err = set_statfs_info(0, NULL, args.fspec, mp, p);
 		}
 #endif
 	} else {
@@ -391,20 +385,10 @@
 		 * upper level code.
 		 */
 		/* Save "last mounted on" info for mount point (NULL pad)*/
-		copyinstr(	path,				/* mount point*/
-				mp->mnt_stat.f_mntonname,	/* save area*/
-				MNAMELEN - 1,			/* max size*/
-				&size);				/* real size*/
-		bzero( mp->mnt_stat.f_mntonname + size, MNAMELEN - size);
-
-		/* Save "mounted from" info for mount point (NULL pad)*/
-		copyinstr(	args.fspec,			/* device name*/
-				mp->mnt_stat.f_mntfromname,	/* save area*/
-				MNAMELEN - 1,			/* max size*/
-				&size);				/* real size*/
-		bzero( mp->mnt_stat.f_mntfromname + size, MNAMELEN - size);
-
-		err = ntfs_mountfs(devvp, mp, &args, p);
+		err = set_statfs_info(0, path, args.fspec, mp, p);
+		if ( !err) {
+			err = ntfs_mountfs(devvp, mp, &args, p);
+		}
 	}
 	if (err) {
 		goto error_2;
Index: fs/smbfs/smbfs_vfsops.c
===================================================================
RCS file: /cvsroot/src/sys/fs/smbfs/smbfs_vfsops.c,v
retrieving revision 1.24
diff -u -u -r1.24 smbfs_vfsops.c
--- fs/smbfs/smbfs_vfsops.c	2003/04/08 16:26:31	1.24
+++ fs/smbfs/smbfs_vfsops.c	2003/04/16 00:36:59
@@ -122,7 +122,6 @@
 	struct smb_vc *vcp;
 	struct smb_share *ssp = NULL;
 	struct smb_cred scred;
-	size_t size;
 	int error;
 
 	if (mp->mnt_flag & MNT_GETARGS) {
@@ -171,17 +170,12 @@
 	smp->sm_args.dir_mode  = (smp->sm_args.dir_mode &
 			    (S_IRWXU|S_IRWXG|S_IRWXO)) | S_IFDIR;
 
-	error = copyinstr(path, mp->mnt_stat.f_mntonname, MNAMELEN - 1, &size);
+	error = set_statfs_info(0, path, NULL, mp, p);
 	if (error)
 		goto bad;
-	memset(mp->mnt_stat.f_mntonname + size, 0, MNAMELEN - size);
-
 	memset(mp->mnt_stat.f_mntfromname, 0, MNAMELEN);
 	snprintf(mp->mnt_stat.f_mntfromname, MNAMELEN,
-		"//%s@%s/%s",
-		vcp->vc_username,
-		vcp->vc_srvname,
-		ssp->ss_name);
+	    "//%s@%s/%s", vcp->vc_username, vcp->vc_srvname, ssp->ss_name);
 
 	vfs_getnewfsid(mp);
 	return (0);
Index: fs/union/union_vfsops.c
===================================================================
RCS file: /cvsroot/src/sys/fs/union/union_vfsops.c,v
retrieving revision 1.3
diff -u -u -r1.3 union_vfsops.c
--- fs/union/union_vfsops.c	2003/03/17 10:28:41	1.3
+++ fs/union/union_vfsops.c	2003/04/16 00:37:00
@@ -226,8 +226,7 @@
 	mp->mnt_data = um;
 	vfs_getnewfsid(mp);
 
-	(void) copyinstr(path, mp->mnt_stat.f_mntonname, MNAMELEN - 1, &size);
-	memset(mp->mnt_stat.f_mntonname + size, 0, MNAMELEN - size);
+	(void)set_statfs_info(0, path, NULL, mp, p);
 
 	switch (um->um_op) {
 	case UNMNT_ABOVE:
Index: kern/vfs_getcwd.c
===================================================================
RCS file: /cvsroot/src/sys/kern/vfs_getcwd.c,v
retrieving revision 1.16
diff -u -u -r1.16 vfs_getcwd.c
--- kern/vfs_getcwd.c	2003/01/18 10:06:37	1.16
+++ kern/vfs_getcwd.c	2003/04/16 00:37:00
@@ -63,9 +63,6 @@
 static int
 getcwd_getcache __P((struct vnode **, struct vnode **,
     char **, char *));
-int
-getcwd_common __P((struct vnode *, struct vnode *,
-		   char **, char *, int, int, struct proc *));
 
 #define DIRENT_MINSIZE (sizeof(struct dirent) - (MAXNAMLEN+1) + 4)
 
@@ -370,8 +367,6 @@
 /*
  * common routine shared by sys___getcwd() and vn_isunder()
  */
-
-#define GETCWD_CHECK_ACCESS 0x0001
 
 int 
 getcwd_common (lvp, rvp, bpp, bufp, limit, flags, p)
Index: kern/vfs_subr.c
===================================================================
RCS file: /cvsroot/src/sys/kern/vfs_subr.c,v
retrieving revision 1.191
diff -u -u -r1.191 vfs_subr.c
--- kern/vfs_subr.c	2003/04/03 09:13:10	1.191
+++ kern/vfs_subr.c	2003/04/16 00:37:01
@@ -109,6 +109,7 @@
 #include <sys/syscallargs.h>
 #include <sys/device.h>
 #include <sys/dirent.h>
+#include <sys/filedesc.h>
 
 #include <miscfs/specfs/specdev.h>
 #include <miscfs/genfs/genfs.h>
@@ -2770,6 +2771,72 @@
 			(*vfs->vfs_reinit)();
 		}
 	}
+}
+
+int
+set_statfs_info(int uk, const char *onp, const char *fromp, struct mount *mp,
+    struct proc *p)
+{
+	int error;
+	size_t size;
+	struct statfs *sfs = &mp->mnt_stat;
+	int (*fun)(const void *, void *, size_t, size_t *);
+
+	if (onp) {
+		struct cwdinfo *cwdi = p->p_cwdi;
+		fun = (uk & 1) ? copystr : copyinstr;
+		if (cwdi->cwdi_rdir != NULL) {
+			size_t len;
+			char *bp;
+			char *path = malloc(MAXPATHLEN, M_TEMP, M_WAITOK);
+
+			if (!path)
+				return ENOMEM;
+
+			bp = path + MAXPATHLEN;
+			*--bp = '\0';
+			error = getcwd_common(cwdi->cwdi_rdir, rootvnode, &bp,
+			    path, MAXPATHLEN / 2, 0, p);
+			if (error) {
+				free(path, M_TEMP);
+				return error;
+			}
+
+			len = strlen(bp);
+			if (len > sizeof(sfs->f_mntonname) - 1)
+				len = sizeof(sfs->f_mntonname) - 1;
+			(void)strncpy(sfs->f_mntonname, bp, len);
+			free(path, M_TEMP);
+
+			if (len < sizeof(sfs->f_mntonname) - 1) {
+				error = (*fun)(onp, &sfs->f_mntonname[len],
+				    len - sizeof(sfs->f_mntonname) - 1, &size);
+				if (error)
+					return error;
+				size += len;
+			} else {
+				size = len;
+			}
+		} else {
+			error = (*fun)(onp, &sfs->f_mntonname,
+			    sizeof(sfs->f_mntonname) - 1, &size);
+			if (error)
+				return error;
+		}
+		(void)memset(sfs->f_mntonname + size, 0,
+		    sizeof(sfs->f_mntonname) - size);
+	}
+
+	if (fromp) {
+		fun = (uk & 2) ? copystr : copyinstr;
+		error = (*fun)(fromp, sfs->f_mntfromname,
+		    sizeof(sfs->f_mntfromname) - 1, &size);
+		if (error)
+			return error;
+		(void)memset(sfs->f_mntfromname + size, 0,
+		    sizeof(sfs->f_mntfromname) - size);
+	}
+	return 0;
 }
 
 #ifdef DDB
Index: kern/vfs_syscalls.c
===================================================================
RCS file: /cvsroot/src/sys/kern/vfs_syscalls.c,v
retrieving revision 1.184
diff -u -u -r1.184 vfs_syscalls.c
--- kern/vfs_syscalls.c	2003/03/21 23:11:25	1.184
+++ kern/vfs_syscalls.c	2003/04/16 00:37:02
@@ -76,6 +76,8 @@
 static int change_utimes __P((struct vnode *vp, const struct timeval *,
 	       struct proc *p));
 static int rename_files __P((const char *, const char *, struct proc *, int));
+static int dostatfs __P((struct mount *, struct statfs *, struct proc *, int,
+    int));
 
 void checkdirs __P((struct vnode *));
 
@@ -141,7 +143,7 @@
 	/*
 	 * Get vnode to be covered
 	 */
-	NDINIT(&nd, LOOKUP, FOLLOW , UIO_USERSPACE,
+	NDINIT(&nd, LOOKUP, FOLLOW, UIO_USERSPACE,
 	    SCARG(uap, path), p);
 	if ((error = namei(&nd)) != 0)
 		return (error);
@@ -635,6 +637,70 @@
 	    SCARG(uap, arg), p));
 }
 
+static int
+dostatfs(struct mount *mp, struct statfs *sp, struct proc *p, int flags,
+    int root)
+{
+	struct cwdinfo *cwdi = p->p_cwdi;
+	int error = 0;
+
+	/*
+	 * If MNT_NOWAIT or MNT_LAZY is specified, do not
+	 * refresh the fsstat cache. MNT_WAIT or MNT_LAXY
+	 * overrides MNT_NOWAIT.
+	 */
+	if (flags == MNT_NOWAIT	|| flags == MNT_LAZY ||
+	    (flags != MNT_WAIT && flags != 0)) {
+		memcpy(sp, &mp->mnt_stat, sizeof(*sp));
+		goto done;
+	}
+		
+	if ((error = VFS_STATFS(mp, sp, p)) != 0) {
+		return error;
+	}
+
+	if (cwdi->cwdi_rdir == NULL)
+		(void)memcpy(&mp->mnt_stat, sp, sizeof(mp->mnt_stat));
+done:
+	if (cwdi->cwdi_rdir != NULL) {
+		size_t len;
+		char *bp;
+		char *path = malloc(MAXPATHLEN, M_TEMP, M_WAITOK);
+		if (!path)
+			return ENOMEM;
+
+		bp = path + MAXPATHLEN;
+		*--bp = '\0';
+		error = getcwd_common(cwdi->cwdi_rdir, rootvnode, &bp, path,
+		    MAXPATHLEN / 2, 0, p);
+		if (error) {
+			free(path, M_TEMP);
+			return error;
+		}
+		len = strlen(bp);
+		/*
+		 * for mount points that are below our root, we can see
+		 * them, so we fix up the pathname and return them. The
+		 * rest we cannot see, so we don't allow viewing the
+		 * data.
+		 */
+		if (strncmp(bp, sp->f_mntonname, len) == 0) {
+			strcpy(sp->f_mntonname, &sp->f_mntonname[len]);
+			if (sp->f_mntonname[0] == '\0')
+			    (void)strcpy(sp->f_mntonname, "/");
+		} else {
+			if (root)
+				(void)strcpy(sp->f_mntonname, "/");
+			else
+				error = EPERM;
+		}
+		free(path, M_TEMP);
+	}
+	sp->f_flags = mp->mnt_flag & MNT_VISFLAGMASK;
+	sp->f_oflags = sp->f_flags & 0xffff;
+	return error;
+}
+
 /*
  * Get filesystem statistics.
  */
@@ -651,21 +717,18 @@
 	} */ *uap = v;
 	struct proc *p = l->l_proc;
 	struct mount *mp;
-	struct statfs *sp;
+	struct statfs sbuf;
 	int error;
 	struct nameidata nd;
 
 	NDINIT(&nd, LOOKUP, FOLLOW, UIO_USERSPACE, SCARG(uap, path), p);
 	if ((error = namei(&nd)) != 0)
-		return (error);
+		return error;
 	mp = nd.ni_vp->v_mount;
-	sp = &mp->mnt_stat;
 	vrele(nd.ni_vp);
-	if ((error = VFS_STATFS(mp, sp, p)) != 0)
-		return (error);
-	sp->f_flags = mp->mnt_flag & MNT_VISFLAGMASK;
-	sp->f_oflags = sp->f_flags & 0xffff;
-	return (copyout(sp, SCARG(uap, buf), sizeof(*sp)));
+	if ((error = dostatfs(mp, &sbuf, p, 0, 1)) != 0)
+		return error;
+	return copyout(&sbuf, SCARG(uap, buf), sizeof(sbuf));
 }
 
 /*
@@ -685,24 +748,22 @@
 	struct proc *p = l->l_proc;
 	struct file *fp;
 	struct mount *mp;
-	struct statfs *sp;
+	struct statfs sbuf;
 	int error;
 
 	/* getvnode() will use the descriptor for us */
 	if ((error = getvnode(p->p_fd, SCARG(uap, fd), &fp)) != 0)
 		return (error);
 	mp = ((struct vnode *)fp->f_data)->v_mount;
-	sp = &mp->mnt_stat;
-	if ((error = VFS_STATFS(mp, sp, p)) != 0)
+	if ((error = dostatfs(mp, &sbuf, p, 0, 1)) != 0)
 		goto out;
-	sp->f_flags = mp->mnt_flag & MNT_VISFLAGMASK;
-	sp->f_oflags = sp->f_flags & 0xffff;
-	error = copyout(sp, SCARG(uap, buf), sizeof(*sp));
+	error = copyout(&sbuf, SCARG(uap, buf), sizeof(sbuf));
  out:
 	FILE_UNUSE(fp, p);
-	return (error);
+	return error;
 }
 
+
 /*
  * Get statistics on all filesystems.
  */
@@ -717,11 +778,12 @@
 		syscallarg(long) bufsize;
 		syscallarg(int) flags;
 	} */ *uap = v;
+	int root = 0;
 	struct proc *p = l->l_proc;
 	struct mount *mp, *nmp;
-	struct statfs *sp;
+	struct statfs sbuf;
 	caddr_t sfsp;
-	long count, maxcount, error;
+	long count, maxcount, error = 0;
 
 	maxcount = SCARG(uap, bufsize) / sizeof(struct statfs);
 	sfsp = (caddr_t)SCARG(uap, buf);
@@ -734,42 +796,41 @@
 			continue;
 		}
 		if (sfsp && count < maxcount) {
-			sp = &mp->mnt_stat;
-			/*
-			 * If MNT_NOWAIT or MNT_LAZY is specified, do not
-			 * refresh the fsstat cache. MNT_WAIT or MNT_LAXY
-			 * overrides MNT_NOWAIT.
-			 */
-			if (SCARG(uap, flags) != MNT_NOWAIT &&
-			    SCARG(uap, flags) != MNT_LAZY &&
-			    (SCARG(uap, flags) == MNT_WAIT ||
-			     SCARG(uap, flags) == 0) &&
-			    (error = VFS_STATFS(mp, sp, p)) != 0) {
-				simple_lock(&mountlist_slock);
+			error = dostatfs(mp, &sbuf, p, SCARG(uap, flags), 0);
+			if (error) {
 				nmp = CIRCLEQ_NEXT(mp, mnt_list);
 				vfs_unbusy(mp);
 				continue;
 			}
-			sp->f_flags = mp->mnt_flag & MNT_VISFLAGMASK;
-			sp->f_oflags = sp->f_flags & 0xffff;
-			error = copyout(sp, sfsp, sizeof(*sp));
+			error = copyout(&sbuf, sfsp, sizeof(sbuf));
 			if (error) {
 				vfs_unbusy(mp);
 				return (error);
 			}
-			sfsp += sizeof(*sp);
+			sfsp += sizeof(sbuf);
+			root |= strcmp(sbuf.f_mntonname, "/") == 0;
 		}
 		count++;
-		simple_lock(&mountlist_slock);
 		nmp = CIRCLEQ_NEXT(mp, mnt_list);
 		vfs_unbusy(mp);
 	}
 	simple_unlock(&mountlist_slock);
+	if (root == 0 && p->p_cwdi->cwdi_rdir) {
+		/*
+		 * fake a root entry
+		 */
+		if ((error = dostatfs(p->p_cwdi->cwdi_rdir->v_mount, &sbuf, p,
+		    SCARG(uap, flags), 1)) != 0)
+			return error;
+		if (sfsp)
+			error = copyout(&sbuf, sfsp, sizeof(sbuf));
+		count++;
+	}
 	if (sfsp && count > maxcount)
 		*retval = maxcount;
 	else
 		*retval = count;
-	return (0);
+	return error;
 }
 
 /*
@@ -1313,7 +1374,7 @@
 		syscallarg(struct statfs *) buf;
 	} */ *uap = v;
 	struct proc *p = l->l_proc;
-	struct statfs sp;
+	struct statfs sbuf;
 	fhandle_t fh;
 	struct mount *mp;
 	struct vnode *vp;
@@ -1334,11 +1395,9 @@
 		return (error);
 	mp = vp->v_mount;
 	vput(vp);
-	if ((error = VFS_STATFS(mp, &sp, p)) != 0)
+	if ((error = VFS_STATFS(mp, &sbuf, p)) != 0)
 		return (error);
-	sp.f_flags = mp->mnt_flag & MNT_VISFLAGMASK;
-	sp.f_oflags = sp.f_flags & 0xffff;
-	return (copyout(&sp, SCARG(uap, buf), sizeof(sp)));
+	return (copyout(&sbuf, SCARG(uap, buf), sizeof(sbuf)));
 }
 
 /*
Index: miscfs/fdesc/fdesc_vfsops.c
===================================================================
RCS file: /cvsroot/src/sys/miscfs/fdesc/fdesc_vfsops.c,v
retrieving revision 1.38
diff -u -u -r1.38 fdesc_vfsops.c
--- miscfs/fdesc/fdesc_vfsops.c	2002/09/21 18:09:27	1.38
+++ miscfs/fdesc/fdesc_vfsops.c	2003/04/16 00:37:05
@@ -91,7 +91,6 @@
 	struct proc *p;
 {
 	int error = 0;
-	size_t size;
 	struct fdescmount *fmp;
 	struct vnode *rvp;
 
@@ -116,12 +115,9 @@
 	mp->mnt_data = fmp;
 	vfs_getnewfsid(mp);
 
-	(void) copyinstr(path, mp->mnt_stat.f_mntonname, MNAMELEN - 1, &size);
-	memset(mp->mnt_stat.f_mntonname + size, 0, MNAMELEN - size);
-	memset(mp->mnt_stat.f_mntfromname, 0, MNAMELEN);
-	memcpy(mp->mnt_stat.f_mntfromname, "fdesc", sizeof("fdesc"));
+	error = set_statfs_info(2, path, "fdesc", mp, p);
 	VOP_UNLOCK(rvp, 0);
-	return (0);
+	return error;
 }
 
 int
Index: miscfs/kernfs/kernfs_vfsops.c
===================================================================
RCS file: /cvsroot/src/sys/miscfs/kernfs/kernfs_vfsops.c,v
retrieving revision 1.47
diff -u -u -r1.47 kernfs_vfsops.c
--- miscfs/kernfs/kernfs_vfsops.c	2003/02/01 06:23:46	1.47
+++ miscfs/kernfs/kernfs_vfsops.c	2003/04/16 00:37:05
@@ -132,7 +132,6 @@
 	struct proc *p;
 {
 	int error = 0;
-	size_t size;
 	struct kernfs_mount *fmp;
 	struct vnode *rvp;
 
@@ -164,16 +163,13 @@
 	mp->mnt_data = fmp;
 	vfs_getnewfsid(mp);
 
-	(void) copyinstr(path, mp->mnt_stat.f_mntonname, MNAMELEN - 1, &size);
-	memset(mp->mnt_stat.f_mntonname + size, 0, MNAMELEN - size);
-	memset(mp->mnt_stat.f_mntfromname, 0, MNAMELEN);
-	memcpy(mp->mnt_stat.f_mntfromname, "kernfs", sizeof("kernfs"));
+	error = set_statfs_info(2, path, "kernfs", mp, p);
 #ifdef KERNFS_DIAGNOSTIC
 	printf("kernfs_mount: at %s\n", mp->mnt_stat.f_mntonname);
 #endif
 
 	kernfs_get_rrootdev();
-	return (0);
+	return error;
 }
 
 int
Index: miscfs/nullfs/null_vfsops.c
===================================================================
RCS file: /cvsroot/src/sys/miscfs/nullfs/null_vfsops.c,v
retrieving revision 1.38
diff -u -u -r1.38 null_vfsops.c
--- miscfs/nullfs/null_vfsops.c	2002/09/21 18:09:29	1.38
+++ miscfs/nullfs/null_vfsops.c	2003/04/16 00:37:06
@@ -111,7 +111,6 @@
 	struct vnode *lowerrootvp, *vp;
 	struct null_mount *nmp;
 	struct layer_mount *lmp;
-	size_t size;
 	int error = 0;
 
 #ifdef NULLFS_DIAGNOSTIC
@@ -210,16 +209,12 @@
 	vp->v_flag |= VROOT;
 	nmp->nullm_rootvp = vp;
 
-	(void) copyinstr(path, mp->mnt_stat.f_mntonname, MNAMELEN - 1, &size);
-	memset(mp->mnt_stat.f_mntonname + size, 0, MNAMELEN - size);
-	(void) copyinstr(args.la.target, mp->mnt_stat.f_mntfromname,
-	    MNAMELEN - 1, &size);
-	memset(mp->mnt_stat.f_mntfromname + size, 0, MNAMELEN - size);
+	error = set_statfs_info(0, path, args.la.target, mp, p);
 #ifdef NULLFS_DIAGNOSTIC
 	printf("nullfs_mount: lower %s, alias at %s\n",
 	    mp->mnt_stat.f_mntfromname, mp->mnt_stat.f_mntonname);
 #endif
-	return (0);
+	return error; 
 }
 
 /*
Index: miscfs/overlay/overlay_vfsops.c
===================================================================
RCS file: /cvsroot/src/sys/miscfs/overlay/overlay_vfsops.c,v
retrieving revision 1.12
diff -u -u -r1.12 overlay_vfsops.c
--- miscfs/overlay/overlay_vfsops.c	2002/09/21 18:09:29	1.12
+++ miscfs/overlay/overlay_vfsops.c	2003/04/16 00:37:06
@@ -113,7 +113,6 @@
 	struct vnode *lowerrootvp, *vp;
 	struct overlay_mount *nmp;
 	struct layer_mount *lmp;
-	size_t size;
 
 #ifdef OVERLAYFS_DIAGNOSTIC
 	printf("ov_mount(mp = %p)\n", mp);
@@ -204,16 +203,12 @@
 	vp->v_flag |= VROOT;
 	nmp->ovm_rootvp = vp;
 
-	(void) copyinstr(path, mp->mnt_stat.f_mntonname, MNAMELEN - 1, &size);
-	memset(mp->mnt_stat.f_mntonname + size, 0, MNAMELEN - size);
-	(void) copyinstr(args.la.target, mp->mnt_stat.f_mntfromname, MNAMELEN - 1, 
-	    &size);
-	memset(mp->mnt_stat.f_mntfromname + size, 0, MNAMELEN - size);
+	error = set_statfs_info(0, path, args.la.target, mp, p);
 #ifdef OVERLAYFS_DIAGNOSTIC
 	printf("ov_mount: lower %s, alias at %s\n",
 	    mp->mnt_stat.f_mntfromname, mp->mnt_stat.f_mntonname);
 #endif
-	return (0);
+	return error;
 }
 
 /*
Index: miscfs/portal/portal_vfsops.c
===================================================================
RCS file: /cvsroot/src/sys/miscfs/portal/portal_vfsops.c,v
retrieving revision 1.32
diff -u -u -r1.32 portal_vfsops.c
--- miscfs/portal/portal_vfsops.c	2003/02/23 14:37:37	1.32
+++ miscfs/portal/portal_vfsops.c	2003/04/16 00:37:06
@@ -113,7 +113,6 @@
 	struct portalmount *fmp;
 	struct socket *so;
 	struct vnode *rvp;
-	size_t size;
 	int error;
 
 	if (mp->mnt_flag & MNT_GETARGS) {
@@ -165,12 +164,7 @@
 	mp->mnt_data = fmp;
 	vfs_getnewfsid(mp);
 
-	(void) copyinstr(path, mp->mnt_stat.f_mntonname, MNAMELEN - 1, &size);
-	memset(mp->mnt_stat.f_mntonname + size, 0, MNAMELEN - size);
-	(void) copyinstr(args.pa_config, mp->mnt_stat.f_mntfromname,
-	    MNAMELEN - 1, &size);
-	memset(mp->mnt_stat.f_mntfromname + size, 0, MNAMELEN - size);
-	return (0);
+	return set_statfs_info(0, path, args.pa_config, mp, p);
 }
 
 int
Index: miscfs/procfs/procfs_vfsops.c
===================================================================
RCS file: /cvsroot/src/sys/miscfs/procfs/procfs_vfsops.c,v
retrieving revision 1.44
diff -u -u -r1.44 procfs_vfsops.c
--- miscfs/procfs/procfs_vfsops.c	2003/01/03 13:21:18	1.44
+++ miscfs/procfs/procfs_vfsops.c	2003/04/16 00:37:06
@@ -98,7 +98,6 @@
 	struct nameidata *ndp;
 	struct proc *p;
 {
-	size_t size;
 	struct procfsmount *pmnt;
 	struct procfs_args args;
 	int error;
@@ -137,15 +136,11 @@
 	mp->mnt_data = pmnt;
 	vfs_getnewfsid(mp);
 
-	(void) copyinstr(path, mp->mnt_stat.f_mntonname, MNAMELEN, &size);
-	memset(mp->mnt_stat.f_mntonname + size, 0, MNAMELEN - size);
-	memset(mp->mnt_stat.f_mntfromname, 0, MNAMELEN);
-	memcpy(mp->mnt_stat.f_mntfromname, "procfs", sizeof("procfs"));
-
+	error = set_statfs_info(2, path, "procfs", mp, p);
 	pmnt->pmnt_exechook = exechook_establish(procfs_revoke_vnodes, mp);
 	pmnt->pmnt_flags = args.flags;
 
-	return (0);
+	return error;
 }
 
 /*
Index: miscfs/umapfs/umap_vfsops.c
===================================================================
RCS file: /cvsroot/src/sys/miscfs/umapfs/umap_vfsops.c,v
retrieving revision 1.35
diff -u -u -r1.35 umap_vfsops.c
--- miscfs/umapfs/umap_vfsops.c	2002/09/21 18:09:31	1.35
+++ miscfs/umapfs/umap_vfsops.c	2003/04/16 00:37:06
@@ -76,7 +76,6 @@
 	struct umap_args args;
 	struct vnode *lowerrootvp, *vp;
 	struct umap_mount *amp;
-	size_t size;
 	int error;
 #ifdef UMAPFS_DIAGNOSTIC
 	int i;
@@ -231,16 +230,12 @@
 	vp->v_flag |= VROOT;
 	amp->umapm_rootvp = vp;
 
-	(void) copyinstr(path, mp->mnt_stat.f_mntonname, MNAMELEN - 1, &size);
-	memset(mp->mnt_stat.f_mntonname + size, 0, MNAMELEN - size);
-	(void) copyinstr(args.umap_target, mp->mnt_stat.f_mntfromname,
-		MNAMELEN - 1, &size);
-	memset(mp->mnt_stat.f_mntfromname + size, 0, MNAMELEN - size);
+	error = set_statfs_info(0, path, args.umap_target, mp, p);
 #ifdef UMAPFS_DIAGNOSTIC
 	printf("umapfs_mount: lower %s, alias at %s\n",
 		mp->mnt_stat.f_mntfromname, mp->mnt_stat.f_mntonname);
 #endif
-	return (0);
+	return error;
 }
 
 /*
Index: nfs/nfs_vfsops.c
===================================================================
RCS file: /cvsroot/src/sys/nfs/nfs_vfsops.c,v
retrieving revision 1.124
diff -u -u -r1.124 nfs_vfsops.c
--- nfs/nfs_vfsops.c	2003/04/02 15:14:24	1.124
+++ nfs/nfs_vfsops.c	2003/04/16 00:37:08
@@ -745,8 +745,7 @@
 #endif
 	strncpy(&mp->mnt_stat.f_fstypename[0], mp->mnt_op->vfs_name,
 	    MFSNAMELEN);
-	memcpy(mp->mnt_stat.f_mntfromname, hst, MNAMELEN);
-	memcpy(mp->mnt_stat.f_mntonname, pth, MNAMELEN);
+	(void)set_statfs_info(3, pth, hst, mp, p);
 	nmp->nm_nam = nam;
 
 	/* Set up the sockets and per-host congestion */
Index: sys/filedesc.h
===================================================================
RCS file: /cvsroot/src/sys/sys/filedesc.h,v
retrieving revision 1.25
diff -u -u -r1.25 filedesc.h
--- sys/filedesc.h	2002/10/23 09:14:58	1.25
+++ sys/filedesc.h	2003/04/16 00:37:08
@@ -135,6 +135,9 @@
 void	cwdshare(struct proc *, struct proc *);
 void	cwdunshare(struct proc *);
 void	cwdfree(struct proc *);
+#define GETCWD_CHECK_ACCESS 0x0001
+int	getcwd_common(struct vnode *, struct vnode *, char **, char *, int,
+    int, struct proc *);
 
 int	closef(struct file *, struct proc *);
 int	getsock(struct filedesc *, int, struct file **);
Index: sys/mount.h
===================================================================
RCS file: /cvsroot/src/sys/sys/mount.h,v
retrieving revision 1.100
diff -u -u -r1.100 mount.h
--- sys/mount.h	2003/04/06 07:04:42	1.100
+++ sys/mount.h	2003/04/16 00:37:08
@@ -502,6 +502,9 @@
 LIST_HEAD(vfs_list_head, vfsops);
 extern struct vfs_list_head vfs_list;
 
+int	set_statfs_info __P((int, const char *, const char *, struct mount *,
+    struct proc *p));
+
 #else /* _KERNEL */
 
 #include <sys/cdefs.h>
Index: ufs/ext2fs/ext2fs_vfsops.c
===================================================================
RCS file: /cvsroot/src/sys/ufs/ext2fs/ext2fs_vfsops.c,v
retrieving revision 1.56
diff -u -u -r1.56 ext2fs_vfsops.c
--- ufs/ext2fs/ext2fs_vfsops.c	2003/04/05 14:01:56	1.56
+++ ufs/ext2fs/ext2fs_vfsops.c	2003/04/16 00:37:09
@@ -342,8 +342,9 @@
 	}
 	ump = VFSTOUFS(mp);
 	fs = ump->um_e2fs;
-	(void) copyinstr(path, fs->e2fs_fsmnt, sizeof(fs->e2fs_fsmnt) - 1,
-	    &size);
+	error = set_statfs_info(0, path, args.fspec, mp, p);
+	(void) copystr(mp->mnt_stat.f_mntonname, fs->e2fs_fsmnt,
+	    sizeof(fs->e2fs_fsmnt) - 1, &size);
 	memset(fs->e2fs_fsmnt + size, 0, sizeof(fs->e2fs_fsmnt) - size);
 	if (fs->e2fs.e2fs_rev > E2FS_REV0) {
 		(void) copystr(mp->mnt_stat.f_mntonname, fs->e2fs.e2fs_fsmnt,
@@ -351,10 +352,6 @@
 		memset(fs->e2fs.e2fs_fsmnt, 0,
 		    sizeof(fs->e2fs.e2fs_fsmnt) - size);
 	}
-	memcpy(mp->mnt_stat.f_mntonname, fs->e2fs_fsmnt, MNAMELEN);
-	(void) copyinstr(args.fspec, mp->mnt_stat.f_mntfromname, MNAMELEN - 1, 
-		&size);
-	memset(mp->mnt_stat.f_mntfromname + size, 0, MNAMELEN - size);
 	if (fs->e2fs_fmod != 0) {	/* XXX */
 		fs->e2fs_fmod = 0;
 		if (fs->e2fs.e2fs_state == 0)
@@ -364,7 +361,7 @@
 				mp->mnt_stat.f_mntfromname);
 		(void) ext2fs_cgupdate(ump, MNT_WAIT);
 	}
-	return (0);
+	return error;
 }
 
 /*
Index: ufs/ffs/ffs_vfsops.c
===================================================================
RCS file: /cvsroot/src/sys/ufs/ffs/ffs_vfsops.c,v
retrieving revision 1.112
diff -u -u -r1.112 ffs_vfsops.c
--- ufs/ffs/ffs_vfsops.c	2003/04/12 10:35:58	1.112
+++ ufs/ffs/ffs_vfsops.c	2003/04/16 00:37:09
@@ -192,7 +192,6 @@
 	struct ufs_args args;
 	struct ufsmount *ump = NULL;
 	struct fs *fs;
-	size_t size;
 	int error, flags, update;
 	mode_t accessmode;
 
@@ -407,12 +406,7 @@
 		}
 	}
 
-	(void) copyinstr(path, fs->fs_fsmnt, sizeof(fs->fs_fsmnt) - 1, &size);
-	memset(fs->fs_fsmnt + size, 0, sizeof(fs->fs_fsmnt) - size);
-	memcpy(mp->mnt_stat.f_mntonname, fs->fs_fsmnt, MNAMELEN);
-	(void) copyinstr(args.fspec, mp->mnt_stat.f_mntfromname, MNAMELEN - 1, 
-	    &size);
-	memset(mp->mnt_stat.f_mntfromname + size, 0, MNAMELEN - size);
+	error = set_statfs_info(0, path, args.fspec, mp, p);
 	if (mp->mnt_flag & MNT_SOFTDEP)
 		fs->fs_flags |= FS_DOSOFTDEP;
 	else
@@ -430,7 +424,7 @@
 		}
 		(void) ffs_cgupdate(ump, MNT_WAIT);
 	}
-	return (0);
+	return error;
 }
 
 /*
Index: ufs/lfs/lfs_vfsops.c
===================================================================
RCS file: /cvsroot/src/sys/ufs/lfs/lfs_vfsops.c,v
retrieving revision 1.113
diff -u -u -r1.113 lfs_vfsops.c
--- ufs/lfs/lfs_vfsops.c	2003/04/02 10:39:42	1.113
+++ ufs/lfs/lfs_vfsops.c	2003/04/16 00:37:10
@@ -349,7 +349,6 @@
 	struct ufs_args args;
 	struct ufsmount *ump = NULL;
 	struct lfs *fs = NULL;				/* LFS */
-	size_t size;
 	int error;
 	mode_t accessmode;
 
@@ -446,13 +445,7 @@
 	}
 	ump = VFSTOUFS(mp);
 	fs = ump->um_lfs;					/* LFS */
-	(void)copyinstr(path, fs->lfs_fsmnt, sizeof(fs->lfs_fsmnt) - 1, &size);
-	bzero(fs->lfs_fsmnt + size, sizeof(fs->lfs_fsmnt) - size);
-	bcopy(fs->lfs_fsmnt, mp->mnt_stat.f_mntonname, MNAMELEN);
-	(void) copyinstr(args.fspec, mp->mnt_stat.f_mntfromname, MNAMELEN - 1,
-			 &size);
-	bzero(mp->mnt_stat.f_mntfromname + size, MNAMELEN - size);
-	return (0);
+	return set_statfs_info(0, path, args.fspec, mp, p);
 }
 
 /*
Index: ufs/mfs/mfs_vfsops.c
===================================================================
RCS file: /cvsroot/src/sys/ufs/mfs/mfs_vfsops.c,v
retrieving revision 1.45
diff -u -u -r1.45 mfs_vfsops.c
--- ufs/mfs/mfs_vfsops.c	2003/04/02 10:39:43	1.45
+++ ufs/mfs/mfs_vfsops.c	2003/04/16 00:37:11
@@ -236,7 +236,6 @@
 	struct ufsmount *ump;
 	struct fs *fs;
 	struct mfsnode *mfsp;
-	size_t size;
 	int flags, error;
 
 	if (mp->mnt_flag & MNT_GETARGS) {
@@ -319,13 +318,10 @@
 	}
 	ump = VFSTOUFS(mp);
 	fs = ump->um_fs;
-	(void) copyinstr(path, fs->fs_fsmnt, sizeof(fs->fs_fsmnt) - 1, &size);
-	memset(fs->fs_fsmnt + size, 0, sizeof(fs->fs_fsmnt) - size);
-	memcpy(mp->mnt_stat.f_mntonname, fs->fs_fsmnt, MNAMELEN);
-	(void) copyinstr(args.fspec, mp->mnt_stat.f_mntfromname, MNAMELEN - 1,
-	    &size);
-	memset(mp->mnt_stat.f_mntfromname + size, 0, MNAMELEN - size);
-	return (0);
+	error = set_statfs_info(0, path, args.fspec, mp, p);
+	(void)memcpy(fs->fs_fsmnt, mp->mnt_stat.f_mntonname,
+	    sizeof(fs->fs_fsmnt));
+	return error;
 }
 
 int	mfs_pri = PWAIT | PCATCH;		/* XXX prob. temp */