changeset 13178:5f70b43d6386

6977619 NULL pointer deference in sa_handle_get_from_db()
author Mark Shellenbaum <Mark.Shellenbaum@Oracle.COM>
date Wed, 18 Aug 2010 13:59:31 -0600
parents f3dd638d3435
children 7f829eb09eb7
files usr/src/uts/common/fs/vfs.c usr/src/uts/common/fs/zfs/zfs_vfsops.c usr/src/uts/common/sys/vfs.h
diffstat 3 files changed, 48 insertions(+), 16 deletions(-) [+]
line wrap: on
line diff
--- a/usr/src/uts/common/fs/vfs.c	Wed Aug 18 12:47:36 2010 -0700
+++ b/usr/src/uts/common/fs/vfs.c	Wed Aug 18 13:59:31 2010 -0600
@@ -4718,6 +4718,15 @@
 	vfsp->vfs_featureset[VFTINDEX(feature)] |= VFTBITS(feature);
 }
 
+void
+vfs_clear_feature(vfs_t *vfsp, vfs_feature_t feature)
+{
+	/* Note that vfs_featureset[] is found in *vfsp->vfs_implp */
+	if (vfsp->vfs_implp == NULL)
+		return;
+	vfsp->vfs_featureset[VFTINDEX(feature)] &= VFTBITS(~feature);
+}
+
 /*
  * Query a vfs for a feature.
  * Returns 1 if feature is present, 0 if not
--- a/usr/src/uts/common/fs/zfs/zfs_vfsops.c	Wed Aug 18 12:47:36 2010 -0700
+++ b/usr/src/uts/common/fs/zfs/zfs_vfsops.c	Wed Aug 18 13:59:31 2010 -0600
@@ -1086,13 +1086,22 @@
 zfs_set_fuid_feature(zfsvfs_t *zfsvfs)
 {
 	zfsvfs->z_use_fuids = USE_FUIDS(zfsvfs->z_version, zfsvfs->z_os);
-	if (zfsvfs->z_use_fuids && zfsvfs->z_vfs) {
-		vfs_set_feature(zfsvfs->z_vfs, VFSFT_XVATTR);
-		vfs_set_feature(zfsvfs->z_vfs, VFSFT_SYSATTR_VIEWS);
-		vfs_set_feature(zfsvfs->z_vfs, VFSFT_ACEMASKONACCESS);
-		vfs_set_feature(zfsvfs->z_vfs, VFSFT_ACLONCREATE);
-		vfs_set_feature(zfsvfs->z_vfs, VFSFT_ACCESS_FILTER);
-		vfs_set_feature(zfsvfs->z_vfs, VFSFT_REPARSE);
+	if (zfsvfs->z_vfs) {
+		if (zfsvfs->z_use_fuids) {
+			vfs_set_feature(zfsvfs->z_vfs, VFSFT_XVATTR);
+			vfs_set_feature(zfsvfs->z_vfs, VFSFT_SYSATTR_VIEWS);
+			vfs_set_feature(zfsvfs->z_vfs, VFSFT_ACEMASKONACCESS);
+			vfs_set_feature(zfsvfs->z_vfs, VFSFT_ACLONCREATE);
+			vfs_set_feature(zfsvfs->z_vfs, VFSFT_ACCESS_FILTER);
+			vfs_set_feature(zfsvfs->z_vfs, VFSFT_REPARSE);
+		} else {
+			vfs_clear_feature(zfsvfs->z_vfs, VFSFT_XVATTR);
+			vfs_clear_feature(zfsvfs->z_vfs, VFSFT_SYSATTR_VIEWS);
+			vfs_clear_feature(zfsvfs->z_vfs, VFSFT_ACEMASKONACCESS);
+			vfs_clear_feature(zfsvfs->z_vfs, VFSFT_ACLONCREATE);
+			vfs_clear_feature(zfsvfs->z_vfs, VFSFT_ACCESS_FILTER);
+			vfs_clear_feature(zfsvfs->z_vfs, VFSFT_REPARSE);
+		}
 	}
 	zfsvfs->z_use_sa = USE_SA(zfsvfs->z_version, zfsvfs->z_os);
 }
@@ -2010,7 +2019,7 @@
 int
 zfs_resume_fs(zfsvfs_t *zfsvfs, const char *osname)
 {
-	int err, err2;
+	int err;
 
 	ASSERT(RRW_WRITE_HELD(&zfsvfs->z_teardown_lock));
 	ASSERT(RW_WRITE_HELD(&zfsvfs->z_teardown_inactive_lock));
@@ -2023,19 +2032,34 @@
 		znode_t *zp;
 		uint64_t sa_obj = 0;
 
-		err2 = zap_lookup(zfsvfs->z_os, MASTER_NODE_OBJ,
+		/*
+		 * Make sure version hasn't changed
+		 */
+
+		err = zfs_get_zplprop(zfsvfs->z_os, ZFS_PROP_VERSION,
+		    &zfsvfs->z_version);
+
+		if (err)
+			goto bail;
+
+		err = zap_lookup(zfsvfs->z_os, MASTER_NODE_OBJ,
 		    ZFS_SA_ATTRS, 8, 1, &sa_obj);
 
-		if ((err || err2) && zfsvfs->z_version >= ZPL_VERSION_SA)
+		if (err && zfsvfs->z_version >= ZPL_VERSION_SA)
 			goto bail;
 
-
 		if ((err = sa_setup(zfsvfs->z_os, sa_obj,
 		    zfs_attr_table,  ZPL_END, &zfsvfs->z_attr_table)) != 0)
 			goto bail;
 
+		if (zfsvfs->z_version >= ZPL_VERSION_SA)
+			sa_register_update_callback(zfsvfs->z_os,
+			    zfs_sa_upgrade);
+
 		VERIFY(zfsvfs_setup(zfsvfs, B_FALSE) == 0);
 
+		zfs_set_fuid_feature(zfsvfs);
+
 		/*
 		 * Attempt to re-establish all the active znodes with
 		 * their dbufs.  If a zfs_rezget() fails, then we'll let
@@ -2048,7 +2072,6 @@
 			(void) zfs_rezget(zp);
 		}
 		mutex_exit(&zfsvfs->z_znodes_lock);
-
 	}
 
 bail:
@@ -2058,8 +2081,8 @@
 
 	if (err) {
 		/*
-		 * Since we couldn't reopen zfsvfs::z_os, force
-		 * unmount this file system.
+		 * Since we couldn't reopen zfsvfs::z_os, or
+		 * setup the sa framework force unmount this file system.
 		 */
 		if (vn_vfswlock(zfsvfs->z_vfs->vfs_vnodecovered) == 0)
 			(void) dounmount(zfsvfs->z_vfs, MS_FORCE, CRED());
@@ -2219,8 +2242,7 @@
 
 	zfsvfs->z_version = newvers;
 
-	if (zfsvfs->z_version >= ZPL_VERSION_FUID)
-		zfs_set_fuid_feature(zfsvfs);
+	zfs_set_fuid_feature(zfsvfs);
 
 	return (0);
 }
--- a/usr/src/uts/common/sys/vfs.h	Wed Aug 18 12:47:36 2010 -0700
+++ b/usr/src/uts/common/sys/vfs.h	Wed Aug 18 13:59:31 2010 -0600
@@ -494,6 +494,7 @@
 
 /* VFS feature routines */
 void	vfs_set_feature(vfs_t *, vfs_feature_t);
+void	vfs_clear_feature(vfs_t *, vfs_feature_t);
 int	vfs_has_feature(vfs_t *, vfs_feature_t);
 void	vfs_propagate_features(vfs_t *, vfs_t *);