Subject: Re: CVS commit: syssrc/sys/ufs/ffs
To: None <christos@netbsd.org>
From: enami tsugutomo <enami@sm.sony.co.jp>
List: source-changes
Date: 04/01/2002 10:16:43
Christos Zoulas <christos@netbsd.org> writes:

> Module Name:	syssrc
> Committed By:	christos
> Date:		Sun Mar 31 20:53:26 UTC 2002
> 
> Modified Files:
> 	syssrc/sys/ufs/ffs: ffs_vfsops.c
> 
> Log Message:
> PR/16136: Chris Jepeway: Bogus entry in /etc/fstab can panic kernel.
> 
> 
> To generate a diff of this commit:
> cvs rdiff -r1.94 -r1.95 syssrc/sys/ufs/ffs/ffs_vfsops.c
> 
> Please note that diffs are not public domain; they are subject to the
> copyright notices on the relevant files.

I suspect how well this change is reviewed.  It at least introduces
one bug and one bogus check and points out some ambiguity.

- If VOP_ACCESS fails when updating mount, we will vrele() twice.

- The check for update-only flags in mp->mnt_flag when not updating
  case is bogus.  If we really want to check, we need to see flags in
  ufs_args, but I'm not sure if it is really necessary.

- The credential passed to ffs_reload was credential of when looking
  up mount point, but now it is credential of when looking up device
  node.  Anyway, it may be current process's credential.

enami.

c.f.:

Index: ffs_vfsops.c
===================================================================
RCS file: /cvsroot/syssrc/sys/ufs/ffs/ffs_vfsops.c,v
retrieving revision 1.95
diff -u -r1.95 ffs_vfsops.c
--- ffs_vfsops.c	2002/03/31 20:53:25	1.95
+++ ffs_vfsops.c	2002/04/01 01:03:53
@@ -207,27 +207,9 @@
 	} else {
 		/* New mounts must have a filename for the device */
 		if (args.fspec == NULL)
-			return EINVAL;
-
-		/* Check for update-only flags */
-		if (mp->mnt_flag &
-		    (MNT_WANTRDWR |	/*
-					 * Upgrading from read-only to
-					 * read-write can only occur after
-					 * the initial mount
-					 */
-		     MNT_EXRDONLY |
-		     MNT_DEFEXPORTED |
-		     MNT_EXPORTANON |
-		     MNT_EXKERB |	/* Only update mounts are allowed */
-		     MNT_EXNORESPORT |  /* to affect exporting		  */
-		     MNT_EXPUBLIC |
-		     MNT_DELEXPORT))
-		return EINVAL;
+			return (EINVAL);
 	}
 
-	error = 0;
-
 	if (args.fspec) {
 		/*
 		 * Look up the name and verify that it's sane.
@@ -252,13 +234,6 @@
 			 */
 			if (devvp != ump->um_devvp)
 				error = EINVAL;
-			else
-				/*
-				 * The initial mount got a reference on this
-				 * device, so drop the one obtained via
-				 * namei(), above
-				 */
-				vrele(devvp);
 		}
 	}
 
@@ -268,8 +243,9 @@
 	 */
 	if (error == 0 && p->p_ucred->cr_uid != 0) {
 		accessmode = VREAD;
-		if ((!update && (mp->mnt_flag & MNT_RDONLY) == 0) ||
-		     (update && (mp->mnt_flag & MNT_WANTRDWR)))
+		if (update ?
+		    (mp->mnt_flag & MNT_WANTRDWR) != 0 :
+		    (mp->mnt_flag & MNT_RDONLY) == 0)
 			accessmode |= VWRITE;
 		vn_lock(devvp, LK_EXCLUSIVE | LK_RETRY);
 		error = VOP_ACCESS(devvp, accessmode, p->p_ucred, p);
@@ -293,14 +269,22 @@
 		if ((mp->mnt_flag & (MNT_SOFTDEP | MNT_ASYNC)) ==
 		    (MNT_SOFTDEP | MNT_ASYNC)) {
 			printf("%s fs uses soft updates, "
-			       "ignoring async mode\n",
-			       fs->fs_fsmnt);
+			    "ignoring async mode\n",
+			    fs->fs_fsmnt);
 			mp->mnt_flag &= ~MNT_ASYNC;
 		}
 	} else {
+		/*
+		 * Update the mount.
+		 */
+
 		/*
-		 * Update the mount
+		 * The initial mount got a reference on this
+		 * device, so drop the one obtained via
+		 * namei(), above.
 		 */
+		vrele(devvp);
+
 		fs = ump->um_fs;
 		if (fs->fs_ronly == 0 && (mp->mnt_flag & MNT_RDONLY)) {
 			/*
@@ -372,7 +356,7 @@
 		}
 
 		if (mp->mnt_flag & MNT_RELOAD) {
-			error = ffs_reload(mp, ndp->ni_cnd.cn_cred, p);
+			error = ffs_reload(mp, p->p_ucred, p);
 			if (error)
 				return (error);
 		}