summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorMark Shellenbaum <Mark.Shellenbaum@Oracle.COM>2010-08-18 13:59:31 -0600
committerMark Shellenbaum <Mark.Shellenbaum@Oracle.COM>2010-08-18 13:59:31 -0600
commit44bffe012cad6481c82ad67bacd6b40bd29def2b (patch)
tree02ac403d4fa8ec419c2e6046000b5eb6020f6f32
parente291592ab12a560fc73b0610963bb3fe66aab341 (diff)
downloadillumos-joyent-44bffe012cad6481c82ad67bacd6b40bd29def2b.tar.gz
6977619 NULL pointer deference in sa_handle_get_from_db()
-rw-r--r--usr/src/uts/common/fs/vfs.c9
-rw-r--r--usr/src/uts/common/fs/zfs/zfs_vfsops.c54
-rw-r--r--usr/src/uts/common/sys/vfs.h1
3 files changed, 48 insertions, 16 deletions
diff --git a/usr/src/uts/common/fs/vfs.c b/usr/src/uts/common/fs/vfs.c
index cbb2adfb37..e24f2d3b32 100644
--- a/usr/src/uts/common/fs/vfs.c
+++ b/usr/src/uts/common/fs/vfs.c
@@ -4718,6 +4718,15 @@ vfs_set_feature(vfs_t *vfsp, vfs_feature_t feature)
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
diff --git a/usr/src/uts/common/fs/zfs/zfs_vfsops.c b/usr/src/uts/common/fs/zfs/zfs_vfsops.c
index cb8c1d086e..4970552d0c 100644
--- a/usr/src/uts/common/fs/zfs/zfs_vfsops.c
+++ b/usr/src/uts/common/fs/zfs/zfs_vfsops.c
@@ -1086,13 +1086,22 @@ static void
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 @@ zfs_suspend_fs(zfsvfs_t *zfsvfs)
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 @@ zfs_resume_fs(zfsvfs_t *zfsvfs, const char *osname)
znode_t *zp;
uint64_t sa_obj = 0;
- err2 = zap_lookup(zfsvfs->z_os, MASTER_NODE_OBJ,
- ZFS_SA_ATTRS, 8, 1, &sa_obj);
+ /*
+ * Make sure version hasn't changed
+ */
+
+ err = zfs_get_zplprop(zfsvfs->z_os, ZFS_PROP_VERSION,
+ &zfsvfs->z_version);
- if ((err || err2) && zfsvfs->z_version >= ZPL_VERSION_SA)
+ if (err)
goto bail;
+ err = zap_lookup(zfsvfs->z_os, MASTER_NODE_OBJ,
+ ZFS_SA_ATTRS, 8, 1, &sa_obj);
+
+ 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 @@ zfs_resume_fs(zfsvfs_t *zfsvfs, const char *osname)
(void) zfs_rezget(zp);
}
mutex_exit(&zfsvfs->z_znodes_lock);
-
}
bail:
@@ -2058,8 +2081,8 @@ bail:
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 @@ zfs_set_version(zfsvfs_t *zfsvfs, uint64_t newvers)
zfsvfs->z_version = newvers;
- if (zfsvfs->z_version >= ZPL_VERSION_FUID)
- zfs_set_fuid_feature(zfsvfs);
+ zfs_set_fuid_feature(zfsvfs);
return (0);
}
diff --git a/usr/src/uts/common/sys/vfs.h b/usr/src/uts/common/sys/vfs.h
index ba013a0eda..879f2aad09 100644
--- a/usr/src/uts/common/sys/vfs.h
+++ b/usr/src/uts/common/sys/vfs.h
@@ -494,6 +494,7 @@ void vfs_remove(struct vfs *);
/* 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 *);