From nobody@FreeBSD.org  Wed Nov 28 21:59:39 2007
Return-Path: <nobody@FreeBSD.org>
Received: from mx1.freebsd.org (mx1.freebsd.org [IPv6:2001:4f8:fff6::34])
	by hub.freebsd.org (Postfix) with ESMTP id 143E916A419
	for <freebsd-gnats-submit@FreeBSD.org>; Wed, 28 Nov 2007 21:59:39 +0000 (UTC)
	(envelope-from nobody@FreeBSD.org)
Received: from www.freebsd.org (www.freebsd.org [IPv6:2001:4f8:fff6::21])
	by mx1.freebsd.org (Postfix) with ESMTP id 0D4B313C44B
	for <freebsd-gnats-submit@FreeBSD.org>; Wed, 28 Nov 2007 21:59:39 +0000 (UTC)
	(envelope-from nobody@FreeBSD.org)
Received: from www.freebsd.org (localhost [127.0.0.1])
	by www.freebsd.org (8.14.2/8.14.2) with ESMTP id lASLxTnn008202
	for <freebsd-gnats-submit@FreeBSD.org>; Wed, 28 Nov 2007 21:59:29 GMT
	(envelope-from nobody@www.freebsd.org)
Received: (from nobody@localhost)
	by www.freebsd.org (8.14.2/8.14.1/Submit) id lASLxTbZ008201;
	Wed, 28 Nov 2007 21:59:29 GMT
	(envelope-from nobody)
Message-Id: <200711282159.lASLxTbZ008201@www.freebsd.org>
Date: Wed, 28 Nov 2007 21:59:29 GMT
From: "mark thompson <"<info-gentoo@mark.thompson.bz>
To: freebsd-gnats-submit@FreeBSD.org
Subject: [patch] NFS SETATTR sometimes fails to set file mode on ZFS partition
X-Send-Pr-Version: www-3.1
X-GNATS-Notify:

>Number:         118320
>Category:       kern
>Synopsis:       [zfs] [patch] NFS SETATTR sometimes fails to set file mode on ZFS partition
>Confidential:   no
>Severity:       serious
>Priority:       medium
>Responsible:    pjd
>State:          closed
>Quarter:        
>Keywords:       
>Date-Required:  
>Class:          sw-bug
>Submitter-Id:   current-users
>Arrival-Date:   Wed Nov 28 22:00:07 UTC 2007
>Closed-Date:    Mon Oct 12 20:43:20 UTC 2009
>Last-Modified:  Mon Oct 12 20:43:20 UTC 2009
>Originator:     mark thompson
>Release:        7.0 BETA 3
>Organization:
tgsoft.com
>Environment:
FreeBSD moose.tgsoft.com 7.0-BETA3 FreeBSD 7.0-BETA3 #6: Wed Nov 28 13:24:23 PST 2007     mark@moose.tgsoft.com:/usr/obj/usr/src/sys/ASUS  amd64

>Description:
ZFS partition exported with NFS, using a MacOS X (Tiger) client. Finder
has problems creating files (they are created, but have a mode of zero,
so cannot be opened). Trace shows that an NFS SETATTR call that should
set uid, gid, and mode fails to set the mode. Similar trace on a UFS
partition works as expected.

Examination shows that secpolicy_vnode_setattr is smashing the mode
argument. Attached patch to zfs_setattr saves and restores the argument
in this one case.


>How-To-Repeat:
NFS export ZFS partition, import on MacOS X. Try to drag a file into the folder on the imported drive using the Finder. In some cases, it will fail.
>Fix:
In /usr/src/sys/contrib/opensolaris/uts/common/fs/zfs/zfs_vnops.c:
*** zfs_vnops.c-orig	Wed Nov 28 09:20:23 2007
--- zfs_vnops.c	Wed Nov 28 13:39:07 2007
***************
*** 2080,2085 ****
--- 2080,2086 ----
  	vattr_t		oldva;
  	uint_t		mask = vap->va_mask;
  	uint_t		saved_mask;
+ 	uint64_t	saved_mode;
  	int		trim_mask = 0;
  	uint64_t	new_mode;
  	znode_t		*attrzp;
***************
*** 2214,2219 ****
--- 2215,2221 ----
  
  		if (trim_mask) {
  			saved_mask = vap->va_mask;
+ 			saved_mode = vap->va_mode; /* secpolicy.. smashes */
  			vap->va_mask &= ~trim_mask;
  
  		}
***************
*** 2224,2231 ****
  			return (err);
  		}
  
! 		if (trim_mask)
  			vap->va_mask |= saved_mask;
  	}
  
  	/*
--- 2226,2236 ----
  			return (err);
  		}
  
! 		if (trim_mask) {
  			vap->va_mask |= saved_mask;
+ 			if (trim_mask & AT_MODE)
+ 				vap->va_mode = saved_mode;
+ 		}
  	}
  
  	/*


>Release-Note:
>Audit-Trail:
Responsible-Changed-From-To: freebsd-bugs->pjd 
Responsible-Changed-By: linimon 
Responsible-Changed-When: Wed Nov 28 22:17:38 UTC 2007 
Responsible-Changed-Why:  
pjd, sounds like this one might be for you? 

http://www.freebsd.org/cgi/query-pr.cgi?pr=118320 
Responsible-Changed-From-To: pjd->freebsd-fs 
Responsible-Changed-By: linimon 
Responsible-Changed-When: Thu May 28 22:21:17 UTC 2009 
Responsible-Changed-Why:  
With pjd's permission, reassing ZFS-related PRs to freebsd-fs. 

http://www.freebsd.org/cgi/query-pr.cgi?pr=118320 
State-Changed-From-To: open->feedback 
State-Changed-By: pjd 
State-Changed-When: ndz 13 wrz 2009 16:08:52 UTC 
State-Changed-Why:  
Is this still a problem with FreeBSD 8? 


Responsible-Changed-From-To: freebsd-fs->pjd 
Responsible-Changed-By: pjd 
Responsible-Changed-When: ndz 13 wrz 2009 16:08:52 UTC 
Responsible-Changed-Why:  
I'll take this one. 

http://www.freebsd.org/cgi/query-pr.cgi?pr=118320 
State-Changed-From-To: feedback->patched 
State-Changed-By: pjd 
State-Changed-When: ro 7 pa 2009 12:38:39 UTC 
State-Changed-Why:  
I found a way to reproduce the problem and committed a fix to HEAD. 
Thank you for the report! 

http://www.freebsd.org/cgi/query-pr.cgi?pr=118320 

From: dfilter@FreeBSD.ORG (dfilter service)
To: bug-followup@FreeBSD.org
Cc:  
Subject: Re: kern/118320: commit references a PR
Date: Wed,  7 Oct 2009 12:38:33 +0000 (UTC)

 Author: pjd
 Date: Wed Oct  7 12:38:19 2009
 New Revision: 197831
 URL: http://svn.freebsd.org/changeset/base/197831
 
 Log:
   Fix situation where Mac OS X NFS client creates a file and when it tries
   to set ownership and mode in the same setattr operation, the mode was
   overwritten by secpolicy_vnode_setattr().
   
   PR:		kern/118320
   Submitted by:	Mark Thompson <info-gentoo@mark.thompson.bz>
   MFC after:	3 days
 
 Modified:
   head/sys/cddl/contrib/opensolaris/uts/common/fs/zfs/zfs_vnops.c
 
 Modified: head/sys/cddl/contrib/opensolaris/uts/common/fs/zfs/zfs_vnops.c
 ==============================================================================
 --- head/sys/cddl/contrib/opensolaris/uts/common/fs/zfs/zfs_vnops.c	Wed Oct  7 09:22:27 2009	(r197830)
 +++ head/sys/cddl/contrib/opensolaris/uts/common/fs/zfs/zfs_vnops.c	Wed Oct  7 12:38:19 2009	(r197831)
 @@ -2538,6 +2538,7 @@ zfs_setattr(vnode_t *vp, vattr_t *vap, i
  	vattr_t		oldva;
  	uint_t		mask = vap->va_mask;
  	uint_t		saved_mask;
 +	uint64_t	saved_mode;
  	int		trim_mask = 0;
  	uint64_t	new_mode;
  	znode_t		*attrzp;
 @@ -2766,6 +2767,13 @@ top:
  		if (trim_mask) {
  			saved_mask = vap->va_mask;
  			vap->va_mask &= ~trim_mask;
 +			if (trim_mask & AT_MODE) {
 +				/*
 +				 * Save the mode, as secpolicy_vnode_setattr()
 +				 * will overwrite it with ova.va_mode.
 +				 */
 +				saved_mode = vap->va_mode;
 +			}
  		}
  		err = secpolicy_vnode_setattr(cr, vp, vap, &oldva, flags,
  		    (int (*)(void *, int, cred_t *))zfs_zaccess_unix, zp);
 @@ -2774,8 +2782,16 @@ top:
  			return (err);
  		}
  
 -		if (trim_mask)
 +		if (trim_mask) {
  			vap->va_mask |= saved_mask;
 +			if (trim_mask & AT_MODE) {
 +				/*
 +				 * Recover the mode after
 +				 * secpolicy_vnode_setattr().
 +				 */
 +				vap->va_mode = saved_mode;
 +			}
 +		}
  	}
  
  	/*
 _______________________________________________
 svn-src-all@freebsd.org mailing list
 http://lists.freebsd.org/mailman/listinfo/svn-src-all
 To unsubscribe, send any mail to "svn-src-all-unsubscribe@freebsd.org"
 

From: dfilter@FreeBSD.ORG (dfilter service)
To: bug-followup@FreeBSD.org
Cc:  
Subject: Re: kern/118320: commit references a PR
Date: Mon, 12 Oct 2009 20:37:09 +0000 (UTC)

 Author: pjd
 Date: Mon Oct 12 20:36:55 2009
 New Revision: 198001
 URL: http://svn.freebsd.org/changeset/base/198001
 
 Log:
   MFC r197831,r197842,r197843,r197860,r197861:
   
   r197831:
   
   Fix situation where Mac OS X NFS client creates a file and when it tries
   to set ownership and mode in the same setattr operation, the mode was
   overwritten by secpolicy_vnode_setattr().
   
   PR:	kern/118320
   Submitted by:	Mark Thompson <info-gentoo@mark.thompson.bz>
   
   r197842:
   
   Fix white-spaces.
   
   r197843:
   
   On FreeBSD it is enough to report provider removal when orphan event is
   received, we don't have to do it on every ENXIO error in I/O path.
   Solaris has no GEOM so they have to handle it in a less clean way.
   
   r197860:
   
   File system owner is when uid matches and jail matches.
   
   r197861:
   
   Allow file system owner to modify system flags if securelevel permits.
   
   Approved by:	re (kib)
 
 Modified:
   stable/8/sys/   (props changed)
   stable/8/sys/amd64/include/xen/   (props changed)
   stable/8/sys/cddl/compat/opensolaris/kern/opensolaris_policy.c
   stable/8/sys/cddl/compat/opensolaris/sys/policy.h
   stable/8/sys/cddl/contrib/opensolaris/   (props changed)
   stable/8/sys/cddl/contrib/opensolaris/uts/common/fs/zfs/vdev_geom.c
   stable/8/sys/cddl/contrib/opensolaris/uts/common/fs/zfs/zfs_vnops.c
   stable/8/sys/contrib/dev/acpica/   (props changed)
   stable/8/sys/contrib/pf/   (props changed)
   stable/8/sys/dev/xen/xenpci/   (props changed)
 
 Modified: stable/8/sys/cddl/compat/opensolaris/kern/opensolaris_policy.c
 ==============================================================================
 --- stable/8/sys/cddl/compat/opensolaris/kern/opensolaris_policy.c	Mon Oct 12 19:41:57 2009	(r198000)
 +++ stable/8/sys/cddl/compat/opensolaris/kern/opensolaris_policy.c	Mon Oct 12 20:36:55 2009	(r198001)
 @@ -78,12 +78,11 @@ secpolicy_fs_owner(struct mount *mp, str
  
  	if (zfs_super_owner) {
  		if (cred->cr_uid == mp->mnt_cred->cr_uid &&
 -		    (!jailed(cred) ||
 -		     cred->cr_prison == mp->mnt_cred->cr_prison)) {
 +		    cred->cr_prison == mp->mnt_cred->cr_prison) {
  			return (0);
  		}
  	}
 -	return (priv_check_cred(cred, PRIV_VFS_MOUNT_OWNER, 0));
 +	return (EPERM);
  }
  
  /*
 @@ -359,8 +358,11 @@ secpolicy_fs_mount_clearopts(cred_t *cr,
   * Check privileges for setting xvattr attributes
   */
  int
 -secpolicy_xvattr(xvattr_t *xvap, uid_t owner, cred_t *cr, vtype_t vtype)
 +secpolicy_xvattr(struct vnode *vp, xvattr_t *xvap, uid_t owner, cred_t *cr,
 +    vtype_t vtype)
  {
  
 +	if (secpolicy_fs_owner(vp->v_mount, cr) == 0)
 +		return (0);
  	return (priv_check_cred(cr, PRIV_VFS_SYSFLAGS, 0));
  }
 
 Modified: stable/8/sys/cddl/compat/opensolaris/sys/policy.h
 ==============================================================================
 --- stable/8/sys/cddl/compat/opensolaris/sys/policy.h	Mon Oct 12 19:41:57 2009	(r198000)
 +++ stable/8/sys/cddl/compat/opensolaris/sys/policy.h	Mon Oct 12 20:36:55 2009	(r198001)
 @@ -70,7 +70,8 @@ int	secpolicy_setid_setsticky_clear(stru
  int	secpolicy_fs_owner(struct mount *vfsp, struct ucred *cred);
  int	secpolicy_fs_mount(cred_t *cr, vnode_t *mvp, struct mount *vfsp);
  void	secpolicy_fs_mount_clearopts(cred_t *cr, struct mount *vfsp);
 -int	secpolicy_xvattr(xvattr_t *xvap, uid_t owner, cred_t *cr, vtype_t vtype);
 +int	secpolicy_xvattr(struct vnode *vp, xvattr_t *xvap, uid_t owner,
 +	    cred_t *cr, vtype_t vtype);
  
  #endif	/* _KERNEL */
  
 
 Modified: stable/8/sys/cddl/contrib/opensolaris/uts/common/fs/zfs/vdev_geom.c
 ==============================================================================
 --- stable/8/sys/cddl/contrib/opensolaris/uts/common/fs/zfs/vdev_geom.c	Mon Oct 12 19:41:57 2009	(r198000)
 +++ stable/8/sys/cddl/contrib/opensolaris/uts/common/fs/zfs/vdev_geom.c	Mon Oct 12 20:36:55 2009	(r198001)
 @@ -433,7 +433,7 @@ vdev_geom_open_by_guid(vdev_t *vd)
  	if (cp != NULL) {
  		len = strlen(cp->provider->name) + strlen("/dev/") + 1;
  		buf = kmem_alloc(len, KM_SLEEP);
 -	
 +
  		snprintf(buf, len, "/dev/%s", cp->provider->name);
  		spa_strfree(vd->vdev_path);
  		vd->vdev_path = buf;
 @@ -662,26 +662,6 @@ sendreq:
  static void
  vdev_geom_io_done(zio_t *zio)
  {
 -
 -	/*																						    
 -	 * If the device returned ENXIO, then attempt we should verify if GEOM														
 -	 * provider has been removed. If this is the case, then we trigger an														 
 -	 * asynchronous removal of the device.																		
 -	 */																						   
 -	if (zio->io_error == ENXIO) {
 -		vdev_t *vd = zio->io_vd;
 -		vdev_geom_ctx_t *ctx;
 -		struct g_provider *pp = NULL;
 -
 -		ctx = vd->vdev_tsd;
 -		if (ctx != NULL && ctx->gc_consumer != NULL)
 -			pp = ctx->gc_consumer->provider;
 -
 -		if (pp == NULL || (pp->flags & G_PF_ORPHAN)) {
 -			vd->vdev_remove_wanted = B_TRUE;
 -			spa_async_request(zio->io_spa, SPA_ASYNC_REMOVE);
 -		}
 -	}
  }
  
  vdev_ops_t vdev_geom_ops = {
 
 Modified: stable/8/sys/cddl/contrib/opensolaris/uts/common/fs/zfs/zfs_vnops.c
 ==============================================================================
 --- stable/8/sys/cddl/contrib/opensolaris/uts/common/fs/zfs/zfs_vnops.c	Mon Oct 12 19:41:57 2009	(r198000)
 +++ stable/8/sys/cddl/contrib/opensolaris/uts/common/fs/zfs/zfs_vnops.c	Mon Oct 12 20:36:55 2009	(r198001)
 @@ -1306,7 +1306,7 @@ zfs_create(vnode_t *dvp, char *name, vat
  	}
  
  	if (vap->va_mask & AT_XVATTR) {
 -		if ((error = secpolicy_xvattr((xvattr_t *)vap,
 +		if ((error = secpolicy_xvattr(dvp, (xvattr_t *)vap,
  		    crgetuid(cr), cr, vap->va_type)) != 0) {
  			ZFS_EXIT(zfsvfs);
  			return (error);
 @@ -1758,7 +1758,7 @@ zfs_mkdir(vnode_t *dvp, char *dirname, v
  		zf |= ZCILOOK;
  
  	if (vap->va_mask & AT_XVATTR)
 -		if ((error = secpolicy_xvattr((xvattr_t *)vap,
 +		if ((error = secpolicy_xvattr(dvp, (xvattr_t *)vap,
  		    crgetuid(cr), cr, vap->va_type)) != 0) {
  			ZFS_EXIT(zfsvfs);
  			return (error);
 @@ -2538,6 +2538,7 @@ zfs_setattr(vnode_t *vp, vattr_t *vap, i
  	vattr_t		oldva;
  	uint_t		mask = vap->va_mask;
  	uint_t		saved_mask;
 +	uint64_t	saved_mode;
  	int		trim_mask = 0;
  	uint64_t	new_mode;
  	znode_t		*attrzp;
 @@ -2766,6 +2767,13 @@ top:
  		if (trim_mask) {
  			saved_mask = vap->va_mask;
  			vap->va_mask &= ~trim_mask;
 +			if (trim_mask & AT_MODE) {
 +				/*
 +				 * Save the mode, as secpolicy_vnode_setattr()
 +				 * will overwrite it with ova.va_mode.
 +				 */
 +				saved_mode = vap->va_mode;
 +			}
  		}
  		err = secpolicy_vnode_setattr(cr, vp, vap, &oldva, flags,
  		    (int (*)(void *, int, cred_t *))zfs_zaccess_unix, zp);
 @@ -2774,8 +2782,16 @@ top:
  			return (err);
  		}
  
 -		if (trim_mask)
 +		if (trim_mask) {
  			vap->va_mask |= saved_mask;
 +			if (trim_mask & AT_MODE) {
 +				/*
 +				 * Recover the mode after
 +				 * secpolicy_vnode_setattr().
 +				 */
 +				vap->va_mode = saved_mode;
 +			}
 +		}
  	}
  
  	/*
 @@ -4182,12 +4198,6 @@ zfs_freebsd_setattr(ap)
  		if ((fflags & ~(SF_IMMUTABLE|SF_APPEND|SF_NOUNLINK|UF_NODUMP)) != 0)
  			return (EOPNOTSUPP);
  		/*
 -		 * Callers may only modify the file flags on objects they
 -		 * have VADMIN rights for.
 -		 */
 -		if ((error = VOP_ACCESS(vp, VADMIN, cred, curthread)) != 0)
 -			return (error);
 -		/*
  		 * Unprivileged processes are not permitted to unset system
  		 * flags, or modify flags if any system flags are set.
  		 * Privileged non-jail processes may not modify system flags
 @@ -4197,14 +4207,21 @@ zfs_freebsd_setattr(ap)
  		 * is non-zero; otherwise, they behave like unprivileged
  		 * processes.
  		 */
 -		if (priv_check_cred(cred, PRIV_VFS_SYSFLAGS, 0) == 0) {
 +		if (secpolicy_fs_owner(vp->v_mount, cred) == 0 ||
 +		    priv_check_cred(cred, PRIV_VFS_SYSFLAGS, 0) == 0) {
  			if (zflags &
  			    (ZFS_IMMUTABLE | ZFS_APPENDONLY | ZFS_NOUNLINK)) {
  				error = securelevel_gt(cred, 0);
 -				if (error)
 +				if (error != 0)
  					return (error);
  			}
  		} else {
 +			/*
 +			 * Callers may only modify the file flags on objects they
 +			 * have VADMIN rights for.
 +			 */
 +			if ((error = VOP_ACCESS(vp, VADMIN, cred, curthread)) != 0)
 +				return (error);
  			if (zflags &
  			    (ZFS_IMMUTABLE | ZFS_APPENDONLY | ZFS_NOUNLINK)) {
  				return (EPERM);
 _______________________________________________
 svn-src-all@freebsd.org mailing list
 http://lists.freebsd.org/mailman/listinfo/svn-src-all
 To unsubscribe, send any mail to "svn-src-all-unsubscribe@freebsd.org"
 
State-Changed-From-To: patched->closed 
State-Changed-By: pjd 
State-Changed-When: pon 12 pa 2009 20:42:57 UTC 
State-Changed-Why:  
Fix merged to stable/8. 

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