From eugen@grosbein.pp.ru  Sat Oct  6 19:26:53 2007
Return-Path: <eugen@grosbein.pp.ru>
Received: from mx1.freebsd.org (mx1.freebsd.org [IPv6:2001:4f8:fff6::34])
	by hub.freebsd.org (Postfix) with ESMTP id A641016A417
	for <FreeBSD-gnats-submit@freebsd.org>; Sat,  6 Oct 2007 19:26:53 +0000 (UTC)
	(envelope-from eugen@grosbein.pp.ru)
Received: from grosbein.pp.ru (grgw.svzserv.kemerovo.su [213.184.64.166])
	by mx1.freebsd.org (Postfix) with ESMTP id C9AA313C45D
	for <FreeBSD-gnats-submit@freebsd.org>; Sat,  6 Oct 2007 19:26:51 +0000 (UTC)
	(envelope-from eugen@grosbein.pp.ru)
Received: from grosbein.pp.ru (localhost [127.0.0.1])
	by grosbein.pp.ru (8.14.1/8.14.1) with ESMTP id l96JQmhF036307
	for <FreeBSD-gnats-submit@freebsd.org>; Sun, 7 Oct 2007 03:26:48 +0800 (KRAST)
	(envelope-from eugen@grosbein.pp.ru)
Received: (from eugen@localhost)
	by grosbein.pp.ru (8.14.1/8.14.1/Submit) id l96JQmtE036306;
	Sun, 7 Oct 2007 03:26:48 +0800 (KRAST)
	(envelope-from eugen)
Message-Id: <200710061926.l96JQmtE036306@grosbein.pp.ru>
Date: Sun, 7 Oct 2007 03:26:48 +0800 (KRAST)
From: Eugene Grosbein <eugen@grosbein.pp.ru>
To: FreeBSD-gnats-submit@freebsd.org
Cc:
Subject: [patch] [msdosfs] mount_msdosfs(8) resets some flags for 'update' mount
X-Send-Pr-Version: 3.113
X-GNATS-Notify:

>Number:         116980
>Category:       bin
>Synopsis:       [msdosfs] [patch] mount_msdosfs(8) resets some flags for 'update' mount
>Confidential:   no
>Severity:       non-critical
>Priority:       low
>Responsible:    freebsd-fs
>State:          open
>Quarter:        
>Keywords:       
>Date-Required:  
>Class:          sw-bug
>Submitter-Id:   current-users
>Arrival-Date:   Sat Oct 06 19:30:00 GMT 2007
>Closed-Date:    
>Last-Modified:  Mon May 18 04:29:09 UTC 2009
>Originator:     Eugene Grosbein
>Release:        FreeBSD 6.2-STABLE i386
>Organization:
Svyaz-Service JSC
>Environment:
System: FreeBSD grosbein.pp.ru 6.2-STABLE FreeBSD 6.2-STABLE #2: Sun Sep 16 16:54:23 KRAST 2007 eu@grosbein.pp.ru:/home/obj/usr/local/src/sys/DADV i386

>Description:
	"mount -t msdosfs -u -o rw" resets uid, gid, mask and dirmask
	to defauls but should keep current values.

>How-To-Repeat:

	1. Create FS with a file:

# dd if=/dev/zero bs=1k count=1440 of=image
# mdconfig -a -t vnode -f image
# newfs_msdos -f 1440 /dev/md0
# mount_msdosfs /dev/md0 /mnt/tmp
# touch /mnt/tmp/file
# umount /mnt/tmp

	2. Mount it with convenient flags, so directories are searchable
	and files are not executable, and read-only:

# mount_msdosfs -o ro -M 755 -m 644 /dev/md0 /mnt/tmp

	Make sure it works, file is not executable:

# ls -l /mnt/tmp
total 0
-rw-r--r--  1 root  wheel  0 Oct  7 03:05 file

	Now remount it read-write and see that mask has been reset:

# mount -u -o rw /mnt/tmp
# ls -l /mnt/tmp
total 0
-rwxr-xr-x  1 root  wheel  0 Oct  7 03:05 file

>Fix:

	mount_msdosfs(8) should not set defaults for update.

--- sbin/mount_msdosfs/mount_msdosfs.c.orig	2007-09-24 20:36:51.000000000 +0800
+++ sbin/mount_msdosfs/mount_msdosfs.c	2007-10-07 03:15:40.000000000 +0800
@@ -69,7 +69,7 @@
 	struct iovec *iov = NULL;
 	int iovlen = 0;
 	struct stat sb;
-	int c, mntflags, set_gid, set_uid, set_mask, set_dirmask;
+	int c, mntflags, set_gid, set_uid, set_mask, set_dirmask, update = 0;
 	char *dev, *dir, mntpath[MAXPATHLEN], *csp;
 	char fstype[] = "msdosfs";
 	char *cs_dos = NULL;
@@ -133,6 +133,7 @@
 				*p = '\0';
 				val = p + 1;
 			}
+			update = update || !strcmp(optarg, "update");
 			build_iovec(&iov, &iovlen, optarg, val, -1);
 			}
 			break;
@@ -165,13 +166,15 @@
 	if (optind + 2 != argc)
 		usage();
 
-	if (set_mask && !set_dirmask) {
-		dirmask = mask;
-		set_dirmask = 1;
-	}
-	else if (set_dirmask && !set_mask) {
-		mask = dirmask;
-		set_mask = 1;
+	if (!update) {
+		if (set_mask && !set_dirmask) {
+			dirmask = mask;
+			set_dirmask = 1;
+		}
+		else if (set_dirmask && !set_mask) {
+			mask = dirmask;
+			set_mask = 1;
+		}
 	}
 
 	dev = argv[optind];
@@ -195,26 +198,36 @@
 	(void)checkpath(dir, mntpath);
 	(void)rmslashes(dev, dev);
 
-	if (!set_gid || !set_uid || !set_mask) {
+	if (!update && (!set_gid || !set_uid || !set_mask)) {
 		if (stat(mntpath, &sb) == -1)
 			err(EX_OSERR, "stat %s", mntpath);
-
-		if (!set_uid)
+		if (!set_uid) {
 			uid = sb.st_uid;
-		if (!set_gid)
+			set_uid = 1;
+		}
+		if (!set_gid) {
 			gid = sb.st_gid;
-		if (!set_mask)
+			set_gid = 1;
+		}
+		if (!set_mask) {
 			mask = dirmask =
 				sb.st_mode & (S_IRWXU | S_IRWXG | S_IRWXO);
+			set_mask = set_dirmask = 1;
+		}
 	}
 
 	build_iovec(&iov, &iovlen, "fstype", fstype, -1);
 	build_iovec(&iov, &iovlen, "fspath", mntpath, -1);
 	build_iovec(&iov, &iovlen, "from", dev, -1);
-	build_iovec_argf(&iov, &iovlen, "uid", "%d", uid);
-	build_iovec_argf(&iov, &iovlen, "gid", "%u", gid);
-	build_iovec_argf(&iov, &iovlen, "mask", "%u", mask);
-	build_iovec_argf(&iov, &iovlen, "dirmask", "%u", dirmask);
+	
+	if (set_uid)
+		build_iovec_argf(&iov, &iovlen, "uid", "%d", uid);
+	if (set_gid)
+		build_iovec_argf(&iov, &iovlen, "gid", "%u", gid);
+	if (set_mask)
+		build_iovec_argf(&iov, &iovlen, "mask", "%u", mask);
+	if (set_dirmask)
+		build_iovec_argf(&iov, &iovlen, "dirmask", "%u", dirmask);
 
 	if (nmount(iov, iovlen, mntflags) < 0)
 		err(1, "%s", dev);


>Release-Note:
>Audit-Trail:

From: EugeneGrosbein@grosbein.pp.ru
To: bug-followup@freebsd.org
Cc:  
Subject: Re: bin/116980: [patch] [msdosfs] mount_msdosfs(8) resets some flags for 'update' mount
Date: Sun, 14 Oct 2007 22:48:55 +0800

 Hi!
 
 Same patch, suitable for 7.0-PRERELEASE:
 
 --- sbin/mount_msdosfs/mount_msdosfs.c.orig	2007-01-29 08:49:08.000000000 +0700
 +++ sbin/mount_msdosfs/mount_msdosfs.c	2007-10-14 18:37:08.000000000 +0800
 @@ -69,7 +69,7 @@
  	struct iovec *iov = NULL;
  	int iovlen = 0;
  	struct stat sb;
 -	int c, mntflags, set_gid, set_uid, set_mask, set_dirmask;
 +	int c, mntflags, set_gid, set_uid, set_mask, set_dirmask, update = 0;
  	char *dev, *dir, mntpath[MAXPATHLEN], *csp;
  	char fstype[] = "msdosfs";
  	char errmsg[255] = {0};
 @@ -134,6 +134,7 @@
  				*p = '\0';
  				val = p + 1;
  			}
 +			update = update || !strcmp(optarg, "update");
  			build_iovec(&iov, &iovlen, optarg, val, (size_t)-1);
  			}
  			break;
 @@ -166,13 +167,15 @@
  	if (optind + 2 != argc)
  		usage();
  
 -	if (set_mask && !set_dirmask) {
 -		dirmask = mask;
 -		set_dirmask = 1;
 -	}
 -	else if (set_dirmask && !set_mask) {
 -		mask = dirmask;
 -		set_mask = 1;
 +	if (!update) {
 +		if (set_mask && !set_dirmask) {
 +			dirmask = mask;
 +			set_dirmask = 1;
 +		}
 +		else if (set_dirmask && !set_mask) {
 +			mask = dirmask;
 +			set_mask = 1;
 +		}
  	}
  
  	dev = argv[optind];
 @@ -196,27 +199,37 @@
  	(void)checkpath(dir, mntpath);
  	(void)rmslashes(dev, dev);
  
 -	if (!set_gid || !set_uid || !set_mask) {
 + 	if (!update && (!set_gid || !set_uid || !set_mask)) {
  		if (stat(mntpath, &sb) == -1)
  			err(EX_OSERR, "stat %s", mntpath);
 -
 -		if (!set_uid)
 + 		if (!set_uid) {
  			uid = sb.st_uid;
 -		if (!set_gid)
 + 			set_uid = 1;
 + 		}
 + 		if (!set_gid) {
  			gid = sb.st_gid;
 -		if (!set_mask)
 + 			set_gid = 1;
 + 		}
 + 		if (!set_mask) {
  			mask = dirmask =
  				sb.st_mode & (S_IRWXU | S_IRWXG | S_IRWXO);
 + 			set_mask = set_dirmask = 1;
 + 		}
  	}
  
  	build_iovec(&iov, &iovlen, "fstype", fstype, (size_t)-1);
  	build_iovec(&iov, &iovlen, "fspath", mntpath, (size_t)-1);
  	build_iovec(&iov, &iovlen, "from", dev, (size_t)-1);
  	build_iovec(&iov, &iovlen, "errmsg", errmsg, sizeof(errmsg));
 -	build_iovec_argf(&iov, &iovlen, "uid", "%d", uid);
 -	build_iovec_argf(&iov, &iovlen, "gid", "%u", gid);
 -	build_iovec_argf(&iov, &iovlen, "mask", "%u", mask);
 -	build_iovec_argf(&iov, &iovlen, "dirmask", "%u", dirmask);
 +
 + 	if (set_uid)
 + 		build_iovec_argf(&iov, &iovlen, "uid", "%d", uid);
 + 	if (set_gid)
 + 		build_iovec_argf(&iov, &iovlen, "gid", "%u", gid);
 + 	if (set_mask)
 + 		build_iovec_argf(&iov, &iovlen, "mask", "%u", mask);
 + 	if (set_dirmask)
 + 		build_iovec_argf(&iov, &iovlen, "dirmask", "%u", dirmask);
  
  	if (nmount(iov, iovlen, mntflags) < 0)
  		err(1, "%s: %s", dev, errmsg);

From: Bruce Evans <brde@optusnet.com.au>
To: EugeneGrosbein@grosbein.pp.ru
Cc: freebsd-gnats-submit@freebsd.org, jkoshy@freebsd.org, dwmalone@freebsd.org
Subject: Re: bin/116980: [patch] [msdosfs] mount_msdosfs(8) resets some flags
 for 'update' mount
Date: Mon, 15 Oct 2007 15:37:43 +1000 (EST)

 On Sun, 14 Oct 2007 EugeneGrosbein@grosbein.pp.ru wrote:
 
 > Subject: Re: bin/116980: [patch] [msdosfs] mount_msdosfs(8) resets some flags for 'update' mount
 
 > Same patch, suitable for 7.0-PRERELEASE:
 
 You should be using -ocurrent.  Without -ocurrent, all flags not
 explicily mentioned in the options list are supposed to be reset.
 However, -ocurrent has apparently never actually worked except for
 generic flags, since the generic level of mount(1) cannot determine
 the current settings of non-generic flags itself and has no way to
 pass the -current option to the fs-specific mount utilities.  This
 also breaks the display of the current settings when no mount point
 is specified.
 
 This problem affects all file systems, and its fix shouldn't involve
 changing the semantics of mount without -ocurrent, so it cannot be
 fixed as in the submitted patch.
 
 > --- sbin/mount_msdosfs/mount_msdosfs.c.orig	2007-01-29 08:49:08.000000000 +0700
 > +++ sbin/mount_msdosfs/mount_msdosfs.c	2007-10-14 18:37:08.000000000 +0800
 > @@ -69,7 +69,7 @@
 >  	struct iovec *iov = NULL;
 >  	int iovlen = 0;
 >  	struct stat sb;
 > -	int c, mntflags, set_gid, set_uid, set_mask, set_dirmask;
 > +	int c, mntflags, set_gid, set_uid, set_mask, set_dirmask, update = 0;
 >  	char *dev, *dir, mntpath[MAXPATHLEN], *csp;
 >  	char fstype[] = "msdosfs";
 >  	char errmsg[255] = {0};
 
 Style bug: initialization in declaration.  Some nearby lines have the same
 style bug, but style bugs on the changed line were limited to disorder.
 
 > @@ -134,6 +134,7 @@
 >  				*p = '\0';
 >  				val = p + 1;
 >  			}
 > +			update = update || !strcmp(optarg, "update");
 >  			build_iovec(&iov, &iovlen, optarg, val, (size_t)-1);
 >  			}
 >  			break;
 
 This and the following changes might be correct with a test of "current"
 instead of "update".
 
 Style bug: boolean comparison of non-boolean `strcmp()'.  This style bug is
 missing for all other instances of strcmp() in this file.
 
 The (old) logic for resetting to defaults also has problems.  Defaults
 for uids, gids and masks are taken from the current values for the mount
 point.  However, previous overrides of the defaults affect the current
 value, so it is difficult to determine the values to reset to.  This
 causes strange behaviour like the following:
 
  	# mount_msdosfs /dev/foo /foo
  	# # mode is now 555 for /foo and for regular files under /foo, say
  	# mount -u -o -M755,-m644 /foo  # set nicer masks
  	# mount -u /foo  # try to reset
  	# # mode is now 755 for /foo and for regular files under /foo
  	# # The -M setting is apparently preserved, but that is an illusion --
  	# # the setting is the default and the default is wrong (it is
  	# # taken from the current value for the mount point but should be
  	# # taken from the current value for the mounted-on point.
  	# # The -m setting is neither reset nor apparently-preserved --
  	# # again, it is the default and the default is wrong (same as for
  	# # -M since the directory perms are used for regular files unless
  	# # -m is specified.
 
 I think I saw problems caused by this for nfs yesterday.  I was toggling
 -T and async, and thought that mount -u doesn't support toggling -T,
 so I was remounting to toggle -T.  Then toggling async using mount -u
 caused mysterious hangs if I forgot to match the current setting of
 -T in the option list for -u.  I think the hangs are new -- apparently,
 toggling -T used to work but now causes hangs.
 
 Bruce
Responsible-Changed-From-To: freebsd-bugs->freebsd-fs 
Responsible-Changed-By: linimon 
Responsible-Changed-When: Mon May 18 04:28:52 UTC 2009 
Responsible-Changed-Why:  
Over to maintainer(s). 

http://www.freebsd.org/cgi/query-pr.cgi?pr=116980 
>Unformatted:
