Skip site navigation (1)Skip section navigation (2)
Date:      Sat, 22 Nov 2008 13:24:44 +0000 (UTC)
From:      Pawel Jakub Dawidek <pjd@FreeBSD.org>
To:        src-committers@freebsd.org, svn-src-all@freebsd.org, svn-src-head@freebsd.org
Subject:   svn commit: r185172 - head/sys/cddl/contrib/opensolaris/uts/common/fs/zfs
Message-ID:  <200811221324.mAMDOiTc018904@svn.freebsd.org>

next in thread | raw e-mail | index | archive | help
Author: pjd
Date: Sat Nov 22 13:24:44 2008
New Revision: 185172
URL: http://svn.freebsd.org/changeset/base/185172

Log:
  IFp4: Finish implemnetation of chflags(2) for ZFS. While doing this I found
  that zfs_access() can only handle VREAD, VWRITE and VEXEC, for the rest we need
  to use vaccess(9).

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	Sat Nov 22 13:22:24 2008	(r185171)
+++ head/sys/cddl/contrib/opensolaris/uts/common/fs/zfs/zfs_vnops.c	Sat Nov 22 13:24:44 2008	(r185172)
@@ -3955,6 +3955,19 @@ zfs_freebsd_access(ap)
 	} */ *ap;
 {
 
+	/*
+	 * ZFS itself only knowns about VREAD, VWRITE and VEXEC, the rest
+	 * we have to handle by calling vaccess().
+	 */
+	if ((ap->a_accmode & ~(VREAD|VWRITE|VEXEC)) != 0) {
+		vnode_t *vp = ap->a_vp;
+		znode_t *zp = VTOZ(vp);
+		znode_phys_t *zphys = zp->z_phys;
+
+		return (vaccess(vp->v_type, zphys->zp_mode, zphys->zp_uid,
+		    zphys->zp_gid, ap->a_accmode, ap->a_cred, NULL));
+	}
+
 	return (zfs_access(ap->a_vp, ap->a_accmode, 0, ap->a_cred, NULL));
 }
 
@@ -4132,7 +4145,9 @@ zfs_freebsd_setattr(ap)
 		struct thread *a_td;
 	} */ *ap;
 {
+	vnode_t *vp = ap->a_vp;
 	vattr_t *vap = ap->a_vap;
+	cred_t *cred = ap->a_cred;
 	xvattr_t xvap;
 	u_long fflags;
 	uint64_t zflags;
@@ -4143,11 +4158,47 @@ zfs_freebsd_setattr(ap)
 	xva_init(&xvap);
 	xvap.xva_vattr = *vap;
 
+	zflags = VTOZ(vp)->z_phys->zp_flags;
+
 	if (vap->va_flags != VNOVAL) {
+		int error;
+
 		fflags = vap->va_flags;
 		if ((fflags & ~(SF_IMMUTABLE|SF_APPEND|SF_NOUNLINK|UF_NODUMP)) != 0)
 			return (EOPNOTSUPP);
-		zflags = VTOZ(ap->a_vp)->z_phys->zp_flags;
+		/*
+		 * 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
+		 * if securelevel > 0 and any existing system flags are set.
+		 * Privileged jail processes behave like privileged non-jail
+		 * processes if the security.jail.chflags_allowed sysctl is
+		 * is non-zero; otherwise, they behave like unprivileged
+		 * processes.
+		 */
+		if (priv_check_cred(cred, PRIV_VFS_SYSFLAGS, 0) == 0) {
+			if (zflags &
+			    (ZFS_IMMUTABLE | ZFS_APPENDONLY | ZFS_NOUNLINK)) {
+				error = securelevel_gt(cred, 0);
+				if (error)
+					return (error);
+			}
+		} else {
+			if (zflags &
+			    (ZFS_IMMUTABLE | ZFS_APPENDONLY | ZFS_NOUNLINK)) {
+				return (EPERM);
+			}
+			if (fflags &
+			    (SF_IMMUTABLE | SF_APPEND | SF_NOUNLINK)) {
+				return (EPERM);
+			}
+		}
 
 #define	FLAG_CHANGE(fflag, zflag, xflag, xfield)	do {		\
 	if (((fflags & (fflag)) && !(zflags & (zflag))) ||		\
@@ -4165,10 +4216,10 @@ zfs_freebsd_setattr(ap)
 		FLAG_CHANGE(SF_NOUNLINK, ZFS_NOUNLINK, XAT_NOUNLINK,
 		    xvap.xva_xoptattrs.xoa_nounlink);
 		FLAG_CHANGE(UF_NODUMP, ZFS_NODUMP, XAT_NODUMP,
-		    xvap.xva_xoptattrs.xoa_nounlink);
+		    xvap.xva_xoptattrs.xoa_nodump);
 #undef	FLAG_CHANGE
 	}
-	return (zfs_setattr(ap->a_vp, (vattr_t *)&xvap, 0, ap->a_cred, NULL));
+	return (zfs_setattr(vp, (vattr_t *)&xvap, 0, cred, NULL));
 }
 
 static int



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