6650192 zfs ACL/fuid code could use some minor cleanup
6650223 zdb znode output should include uid/gid and possible SID information
6657644 zfs_fuid_init() panic
--- a/usr/src/cmd/zdb/zdb.c Fri Feb 01 10:11:12 2008 -0800
+++ b/usr/src/cmd/zdb/zdb.c Fri Feb 01 12:13:54 2008 -0800
@@ -19,7 +19,7 @@
* CDDL HEADER END
*/
/*
- * Copyright 2007 Sun Microsystems, Inc. All rights reserved.
+ * Copyright 2008 Sun Microsystems, Inc. All rights reserved.
* Use is subject to license terms.
*/
@@ -51,6 +51,7 @@
#include <sys/dmu_traverse.h>
#include <sys/zio_checksum.h>
#include <sys/zio_compress.h>
+#include <sys/zfs_fuid.h>
#undef ZFS_MAXNAMELEN
#undef verify
#include <libzfs.h>
@@ -848,6 +849,64 @@
mutex_destroy(&bpl.bpl_lock);
}
+static avl_tree_t idx_tree;
+static avl_tree_t domain_tree;
+static boolean_t fuid_table_loaded;
+
+static void
+fuid_table_destroy()
+{
+ if (fuid_table_loaded) {
+ zfs_fuid_table_destroy(&idx_tree, &domain_tree);
+ fuid_table_loaded = B_FALSE;
+ }
+}
+
+/*
+ * print uid or gid information.
+ * For normal POSIX id just the id is printed in decimal format.
+ * For CIFS files with FUID the fuid is printed in hex followed by
+ * the doman-rid string.
+ */
+static void
+print_idstr(uint64_t id, const char *id_type)
+{
+ if (FUID_INDEX(id)) {
+ char *domain;
+
+ domain = zfs_fuid_idx_domain(&idx_tree, FUID_INDEX(id));
+ (void) printf("\t%s %llx [%s-%d]\n", id_type,
+ (u_longlong_t)id, domain, (int)FUID_RID(id));
+ } else {
+ (void) printf("\t%s %llu\n", id_type, (u_longlong_t)id);
+ }
+
+}
+
+static void
+dump_uidgid(objset_t *os, znode_phys_t *zp)
+{
+ uint32_t uid_idx, gid_idx;
+
+ uid_idx = FUID_INDEX(zp->zp_uid);
+ gid_idx = FUID_INDEX(zp->zp_gid);
+
+ /* Load domain table, if not already loaded */
+ if (!fuid_table_loaded && (uid_idx || gid_idx)) {
+ uint64_t fuid_obj;
+
+ /* first find the fuid object. It lives in the master node */
+ VERIFY(zap_lookup(os, MASTER_NODE_OBJ, ZFS_FUID_TABLES,
+ 8, 1, &fuid_obj) == 0);
+ (void) zfs_fuid_table_load(os, fuid_obj,
+ &idx_tree, &domain_tree);
+ fuid_table_loaded = B_TRUE;
+ }
+
+ print_idstr(zp->zp_uid, "uid");
+ print_idstr(zp->zp_gid, "gid");
+}
+
/*ARGSUSED*/
static void
dump_znode(objset_t *os, uint64_t object, void *data, size_t size)
@@ -876,6 +935,7 @@
z_ctime = (time_t)zp->zp_ctime[0];
(void) printf("\tpath %s\n", path);
+ dump_uidgid(os, zp);
(void) printf("\tatime %s", ctime(&z_atime));
(void) printf("\tmtime %s", ctime(&z_mtime));
(void) printf("\tctime %s", ctime(&z_ctime));
@@ -1230,6 +1290,7 @@
}
dump_dir(os);
dmu_objset_close(os);
+ fuid_table_destroy();
return (0);
}
@@ -2408,6 +2469,8 @@
spa_close(spa, FTAG);
}
+ fuid_table_destroy();
+
libzfs_fini(g_zfs);
kernel_fini();
--- a/usr/src/lib/libzpool/common/kernel.c Fri Feb 01 10:11:12 2008 -0800
+++ b/usr/src/lib/libzpool/common/kernel.c Fri Feb 01 12:13:54 2008 -0800
@@ -19,7 +19,7 @@
* CDDL HEADER END
*/
/*
- * Copyright 2007 Sun Microsystems, Inc. All rights reserved.
+ * Copyright 2008 Sun Microsystems, Inc. All rights reserved.
* Use is subject to license terms.
*/
@@ -874,3 +874,20 @@
{
return (0);
}
+
+ksiddomain_t *
+ksid_lookupdomain(const char *dom)
+{
+ ksiddomain_t *kd;
+
+ kd = umem_zalloc(sizeof (ksiddomain_t), UMEM_NOFAIL);
+ kd->kd_name = spa_strdup(dom);
+ return (kd);
+}
+
+void
+ksiddomain_rele(ksiddomain_t *ksid)
+{
+ spa_strfree(ksid->kd_name);
+ umem_free(ksid, sizeof (ksiddomain_t));
+}
--- a/usr/src/lib/libzpool/common/sys/zfs_context.h Fri Feb 01 10:11:12 2008 -0800
+++ b/usr/src/lib/libzpool/common/sys/zfs_context.h Fri Feb 01 12:13:54 2008 -0800
@@ -19,7 +19,7 @@
* CDDL HEADER END
*/
/*
- * Copyright 2007 Sun Microsystems, Inc. All rights reserved.
+ * Copyright 2008 Sun Microsystems, Inc. All rights reserved.
* Use is subject to license terms.
*/
@@ -521,6 +521,16 @@
extern int zfs_secpolicy_destroy_perms(const char *name, cred_t *cr);
extern zoneid_t getzoneid(void);
+/* SID stuff */
+typedef struct ksiddomain {
+ uint_t kd_ref;
+ uint_t kd_len;
+ char *kd_name;
+} ksiddomain_t;
+
+ksiddomain_t *ksid_lookupdomain(const char *);
+void ksiddomain_rele(ksiddomain_t *);
+
#ifdef __cplusplus
}
#endif
--- a/usr/src/uts/common/Makefile.files Fri Feb 01 10:11:12 2008 -0800
+++ b/usr/src/uts/common/Makefile.files Fri Feb 01 12:13:54 2008 -0800
@@ -1115,6 +1115,7 @@
zap_micro.o \
zfs_byteswap.o \
zfs_fm.o \
+ zfs_fuid.o \
zfs_znode.o \
zil.o \
zio.o \
@@ -1137,7 +1138,6 @@
zfs_acl.o \
zfs_ctldir.o \
zfs_dir.o \
- zfs_fuid.o \
zfs_ioctl.o \
zfs_log.o \
zfs_replay.o \
--- a/usr/src/uts/common/fs/zfs/sys/zfs_fuid.h Fri Feb 01 10:11:12 2008 -0800
+++ b/usr/src/uts/common/fs/zfs/sys/zfs_fuid.h Fri Feb 01 12:13:54 2008 -0800
@@ -28,21 +28,17 @@
#pragma ident "%Z%%M% %I% %E% SMI"
-#include <sys/isa_defs.h>
-#include <sys/types32.h>
#ifdef _KERNEL
#include <sys/kidmap.h>
#include <sys/sid.h>
#include <sys/dmu.h>
#include <sys/zfs_vfsops.h>
#endif
+#include <sys/avl.h>
-#ifdef _KERNEL
-typedef struct zfs_fuid_hdl {
- idmap_get_handle_t *z_hdl;
- boolean_t z_map_needed; /* is mapping required */
- idmap_stat z_status; /* needed for kidmap interface */
-} zfs_fuid_hdl_t;
+#ifdef __cplusplus
+extern "C" {
+#endif
typedef enum {
ZFS_OWNER,
@@ -51,8 +47,6 @@
ZFS_ACE_GROUP
} zfs_fuid_type_t;
-#endif
-
/*
* Estimate space needed for one more fuid table entry.
* for now assume its current size + 1K
@@ -107,29 +101,22 @@
#ifdef _KERNEL
struct znode;
-extern void zfs_fuid_map_id(zfsvfs_t *, uint64_t, cred_t *, zfs_fuid_type_t,
- uid_t *);
+extern uid_t zfs_fuid_map_id(zfsvfs_t *, uint64_t, cred_t *, zfs_fuid_type_t);
extern void zfs_fuid_destroy(zfsvfs_t *);
-extern uint64_t zfs_fuid_create_cred(zfsvfs_t *, uint64_t, zfs_fuid_type_t,
+extern uint64_t zfs_fuid_create_cred(zfsvfs_t *, zfs_fuid_type_t,
dmu_tx_t *, cred_t *, zfs_fuid_info_t **);
extern uint64_t zfs_fuid_create(zfsvfs_t *, uint64_t, cred_t *, zfs_fuid_type_t,
dmu_tx_t *, zfs_fuid_info_t **);
-extern void zfs_fuid_queue_map_id(zfsvfs_t *zfsvfs, zfs_fuid_hdl_t *,
- uint64_t, cred_t *, zfs_fuid_type_t, uid_t *);
extern void zfs_fuid_map_ids(struct znode *zp, cred_t *cr, uid_t *uid,
uid_t *gid);
-extern void zfs_fuid_get_mappings(zfs_fuid_hdl_t *);
-extern char *zfs_fuid_find_by_idx(zfsvfs_t *, uint64_t);
-int zfs_fuid_find_by_domain(zfsvfs_t *, const char *, char **, dmu_tx_t *);
extern zfs_fuid_info_t *zfs_fuid_info_alloc(void);
extern void zfs_fuid_info_free();
extern boolean_t zfs_groupmember(zfsvfs_t *, uint64_t, cred_t *);
-
#endif
-#ifdef __cplusplus
-extern "C" {
-#endif
+char *zfs_fuid_idx_domain(avl_tree_t *, uint32_t);
+uint64_t zfs_fuid_table_load(objset_t *, uint64_t, avl_tree_t *, avl_tree_t *);
+void zfs_fuid_table_destroy(avl_tree_t *, avl_tree_t *);
#ifdef __cplusplus
}
--- a/usr/src/uts/common/fs/zfs/zfs_acl.c Fri Feb 01 10:11:12 2008 -0800
+++ b/usr/src/uts/common/fs/zfs/zfs_acl.c Fri Feb 01 12:13:54 2008 -0800
@@ -545,8 +545,7 @@
if (entry_type != ACE_OWNER && entry_type != OWNING_GROUP &&
entry_type != ACE_EVERYONE) {
if (!aclp->z_has_fuids)
- aclp->z_has_fuids = IS_EPHEMERAL(acep->a_who) ?
- B_TRUE : B_FALSE;
+ aclp->z_has_fuids = IS_EPHEMERAL(acep->a_who);
aceptr->z_fuid = (uint64_t)acep->a_who;
}
@@ -599,7 +598,6 @@
ace_t *acep = datap;
ace_object_t *objacep;
zfs_object_ace_t *zobjacep;
- zfs_fuid_hdl_t hdl = { 0 };
size_t ace_size;
uint16_t entry_type;
@@ -632,18 +630,18 @@
entry_type = (iflags & ACE_TYPE_FLAGS);
if ((entry_type != ACE_OWNER &&
entry_type != (ACE_GROUP | ACE_IDENTIFIER_GROUP) &&
- entry_type != ACE_EVERYONE))
- zfs_fuid_queue_map_id(zfsvfs, &hdl, who, cr,
- (entry_type & ACE_IDENTIFIER_GROUP) ?
- ZFS_ACE_GROUP : ZFS_ACE_USER, &acep->a_who);
- else
+ entry_type != ACE_EVERYONE)) {
+ acep->a_who = zfs_fuid_map_id(zfsvfs, who,
+ cr, (entry_type & ACE_IDENTIFIER_GROUP) ?
+ ZFS_ACE_GROUP : ZFS_ACE_USER);
+ } else {
acep->a_who = (uid_t)(int64_t)who;
+ }
acep->a_access_mask = access_mask;
acep->a_flags = iflags;
acep->a_type = type;
acep = (ace_t *)((caddr_t)acep + ace_size);
}
- zfs_fuid_get_mappings(&hdl);
}
static int
@@ -897,8 +895,8 @@
if (entry_type == 0 || entry_type == ACE_IDENTIFIER_GROUP) {
aclp->z_ops.ace_who_set(acep,
zfs_fuid_create(zp->z_zfsvfs, who, cr,
- entry_type == 0 ? ZFS_ACE_USER : ZFS_ACE_GROUP, tx,
- fuidp));
+ (entry_type == 0) ? ZFS_ACE_USER : ZFS_ACE_GROUP,
+ tx, fuidp));
}
}
return (mode);
@@ -1535,7 +1533,7 @@
reuse_deny = zfs_reuse_deny(aclp, acep,
prevacep);
- if (reuse_deny == B_FALSE) {
+ if (!reuse_deny) {
prevacep =
zfs_acl_prepend_deny(zp,
aclp, acep, mode);
@@ -1766,15 +1764,13 @@
vattr_t *vap, dmu_tx_t *tx, cred_t *cr,
zfs_acl_t *setaclp, zfs_fuid_info_t **fuidp)
{
- uint64_t mode;
- uint64_t uid;
- uint64_t gid;
+ uint64_t mode, fuid, fgid;
int error;
- int pull_down;
zfsvfs_t *zfsvfs = zp->z_zfsvfs;
zfs_acl_t *aclp = NULL;
zfs_acl_t *paclp;
xvattr_t *xvap = (xvattr_t *)vap;
+ gid_t gid;
if (setaclp)
aclp = setaclp;
@@ -1786,24 +1782,33 @@
*/
if ((flag & (IS_ROOT_NODE | IS_REPLAY)) ||
((flag & IS_XATTR) && (vap->va_type == VDIR))) {
- uid = zfs_fuid_create(zfsvfs, vap->va_uid, cr,
+ fuid = zfs_fuid_create(zfsvfs, vap->va_uid, cr,
ZFS_OWNER, tx, fuidp);
- gid = zfs_fuid_create(zfsvfs, vap->va_gid, cr,
+ fgid = zfs_fuid_create(zfsvfs, vap->va_gid, cr,
ZFS_GROUP, tx, fuidp);
+ gid = vap->va_gid;
} else {
- uid = zfs_fuid_create_cred(zfsvfs, crgetuid(cr),
- ZFS_OWNER, tx, cr, fuidp);
- if ((vap->va_mask & AT_GID) &&
- ((vap->va_gid == parent->z_phys->zp_gid) ||
- groupmember(vap->va_gid, cr) ||
- secpolicy_vnode_create_gid(cr) == 0)) {
- gid = zfs_fuid_create_cred(zfsvfs, vap->va_gid,
- ZFS_GROUP, tx, cr, fuidp);
- } else {
- gid = (parent->z_phys->zp_mode & S_ISGID) ?
- parent->z_phys->zp_gid : crgetgid(cr);
- gid = zfs_fuid_create_cred(zfsvfs, gid,
- ZFS_GROUP, tx, cr, fuidp);
+ fuid = zfs_fuid_create_cred(zfsvfs, ZFS_OWNER, tx, cr, fuidp);
+ fgid = 0;
+ if (vap->va_mask & AT_GID) {
+ fgid = zfs_fuid_create(zfsvfs, vap->va_gid, cr,
+ ZFS_GROUP, tx, fuidp);
+ gid = vap->va_gid;
+ if (fgid != parent->z_phys->zp_gid &&
+ !groupmember(vap->va_gid, cr) &&
+ secpolicy_vnode_create_gid(cr) != 0)
+ fgid = 0;
+ }
+ if (fgid == 0) {
+ if (parent->z_phys->zp_mode & S_ISGID) {
+ fgid = parent->z_phys->zp_gid;
+ gid = zfs_fuid_map_id(zfsvfs, fgid,
+ cr, ZFS_GROUP);
+ } else {
+ fgid = zfs_fuid_create_cred(zfsvfs,
+ ZFS_GROUP, tx, cr, fuidp);
+ gid = crgetgid(cr);
+ }
}
}
@@ -1814,22 +1819,21 @@
* file's new group, clear the file's set-GID bit.
*/
- if ((parent->z_phys->zp_mode & S_ISGID) && (vap->va_type == VDIR))
+ if ((parent->z_phys->zp_mode & S_ISGID) && (vap->va_type == VDIR)) {
mode |= S_ISGID;
- else {
+ } else {
if ((mode & S_ISGID) &&
secpolicy_vnode_setids_setgids(cr, gid) != 0)
mode &= ~S_ISGID;
}
- zp->z_phys->zp_uid = uid;
- zp->z_phys->zp_gid = gid;
+ zp->z_phys->zp_uid = fuid;
+ zp->z_phys->zp_gid = fgid;
zp->z_phys->zp_mode = mode;
if (aclp == NULL) {
mutex_enter(&parent->z_lock);
- pull_down = (parent->z_phys->zp_flags & ZFS_INHERIT_ACE);
- if (pull_down) {
+ if (parent->z_phys->zp_flags & ZFS_INHERIT_ACE) {
mutex_enter(&parent->z_acl_lock);
VERIFY(0 == zfs_acl_node_read(parent, &paclp, B_FALSE));
mutex_exit(&parent->z_acl_lock);
@@ -1861,9 +1865,8 @@
mutex_exit(&zp->z_acl_lock);
ASSERT3U(error, ==, 0);
- if (aclp != setaclp) {
+ if (aclp != setaclp)
zfs_acl_free(aclp);
- }
}
/*
@@ -2242,8 +2245,8 @@
if (entry_type == 0) {
uid_t newid;
- zfs_fuid_map_id(zfsvfs, who, cr,
- ZFS_ACE_USER, &newid);
+ newid = zfs_fuid_map_id(zfsvfs, who, cr,
+ ZFS_ACE_USER);
if (newid != IDMAP_WK_CREATOR_OWNER_UID &&
uid == newid)
checkit = B_TRUE;
@@ -2341,7 +2344,7 @@
return (0);
}
- if (error && check_privs == B_FALSE) {
+ if (error && !check_privs) {
if (is_attr)
VN_RELE(ZTOV(xzp));
return (error);
@@ -2355,8 +2358,8 @@
uid_t owner;
mode_t checkmode = 0;
- zfs_fuid_map_id(zfsvfs, check_zp->z_phys->zp_uid, cr,
- ZFS_OWNER, &owner);
+ owner = zfs_fuid_map_id(zfsvfs, check_zp->z_phys->zp_uid, cr,
+ ZFS_OWNER);
/*
* First check for implicit owner permission on
@@ -2440,7 +2443,7 @@
uid_t downer;
zfsvfs_t *zfsvfs = zp->z_zfsvfs;
- zfs_fuid_map_id(zfsvfs, dzp->z_phys->zp_uid, cr, ZFS_OWNER, &downer);
+ downer = zfs_fuid_map_id(zfsvfs, dzp->z_phys->zp_uid, cr, ZFS_OWNER);
error = secpolicy_vnode_access(cr, ZTOV(zp), downer, S_IWRITE|S_IEXEC);
@@ -2513,8 +2516,7 @@
zp_error = zfs_zaccess_common(zp, ACE_DELETE, &zp_working_mode,
&zpcheck_privs, B_FALSE, cr);
- if ((dzp_error && dzpcheck_privs == B_FALSE) ||
- (zp_error && zpcheck_privs == B_FALSE))
+ if ((dzp_error && !dzpcheck_privs) || (zp_error && !zpcheck_privs))
return (dzp_error);
/*
@@ -2557,7 +2559,7 @@
dzp_error = zfs_zaccess_common(dzp, ACE_WRITE_DATA|ACE_EXECUTE,
&dzp_working_mode, &dzpcheck_privs, B_FALSE, cr);
- if (dzp_error && dzpcheck_privs == B_FALSE)
+ if (dzp_error && !dzpcheck_privs)
return (dzp_error);
if ((dzp_working_mode & (ACE_WRITE_DATA|ACE_EXECUTE)) == 0)
--- a/usr/src/uts/common/fs/zfs/zfs_dir.c Fri Feb 01 10:11:12 2008 -0800
+++ b/usr/src/uts/common/fs/zfs/zfs_dir.c Fri Feb 01 12:13:54 2008 -0800
@@ -956,8 +956,8 @@
if ((zdp->z_phys->zp_mode & S_ISVTX) == 0)
return (0);
- zfs_fuid_map_id(zfsvfs, zdp->z_phys->zp_uid, cr, ZFS_OWNER, &downer);
- zfs_fuid_map_id(zfsvfs, zp->z_phys->zp_uid, cr, ZFS_OWNER, &fowner);
+ downer = zfs_fuid_map_id(zfsvfs, zdp->z_phys->zp_uid, cr, ZFS_OWNER);
+ fowner = zfs_fuid_map_id(zfsvfs, zp->z_phys->zp_uid, cr, ZFS_OWNER);
if ((uid = crgetuid(cr)) == downer || uid == fowner ||
(ZTOV(zp)->v_type == VREG &&
--- a/usr/src/uts/common/fs/zfs/zfs_fuid.c Fri Feb 01 10:11:12 2008 -0800
+++ b/usr/src/uts/common/fs/zfs/zfs_fuid.c Fri Feb 01 12:13:54 2008 -0800
@@ -25,20 +25,20 @@
#pragma ident "%Z%%M% %I% %E% SMI"
-#include <sys/types.h>
-#include <sys/unistd.h>
-#include <sys/sysmacros.h>
+#include <sys/zfs_context.h>
#include <sys/sunddi.h>
+#include <sys/dmu.h>
+#include <sys/avl.h>
+#include <sys/zap.h>
+#include <sys/refcount.h>
+#include <sys/nvpair.h>
+#ifdef _KERNEL
+#include <sys/kidmap.h>
+#include <sys/sid.h>
#include <sys/zfs_vfsops.h>
#include <sys/zfs_znode.h>
+#endif
#include <sys/zfs_fuid.h>
-#include <sys/dmu.h>
-#include <sys/refcount.h>
-#include <sys/avl.h>
-#include <sys/zap.h>
-#include <sys/nvpair.h>
-#include <sys/kidmap.h>
-#include <sys/sid.h>
/*
* FUID Domain table(s).
@@ -59,26 +59,20 @@
#define FUID_NVP_ARRAY "fuid_nvlist"
typedef struct fuid_domain {
- avl_node_t f_node;
+ avl_node_t f_domnode;
+ avl_node_t f_idxnode;
ksiddomain_t *f_ksid;
- int f_idx;
- uint32_t f_offset;
+ uint64_t f_idx;
} fuid_domain_t;
-typedef struct fuid_idx {
- avl_node_t f_node;
- int f_idx;
- fuid_domain_t *f_domain;
-} fuid_idx_t;
-
/*
* Compare two indexes.
*/
static int
idx_compare(const void *arg1, const void *arg2)
{
- const fuid_idx_t *node1 = arg1;
- const fuid_idx_t *node2 = arg2;
+ const fuid_domain_t *node1 = arg1;
+ const fuid_domain_t *node2 = arg2;
if (node1->f_idx < node2->f_idx)
return (-1);
@@ -104,15 +98,100 @@
}
/*
+ * load initial fuid domain and idx trees. This function is used by
+ * both the kernel and zdb.
+ */
+uint64_t
+zfs_fuid_table_load(objset_t *os, uint64_t fuid_obj, avl_tree_t *idx_tree,
+ avl_tree_t *domain_tree)
+{
+ dmu_buf_t *db;
+ uint64_t fuid_size;
+
+ avl_create(idx_tree, idx_compare,
+ sizeof (fuid_domain_t), offsetof(fuid_domain_t, f_idxnode));
+ avl_create(domain_tree, domain_compare,
+ sizeof (fuid_domain_t), offsetof(fuid_domain_t, f_domnode));
+
+ VERIFY(0 == dmu_bonus_hold(os, fuid_obj, FTAG, &db));
+ fuid_size = *(uint64_t *)db->db_data;
+ dmu_buf_rele(db, FTAG);
+
+ if (fuid_size) {
+ nvlist_t **fuidnvp;
+ nvlist_t *nvp = NULL;
+ uint_t count;
+ char *packed;
+ int i;
+
+ packed = kmem_alloc(fuid_size, KM_SLEEP);
+ VERIFY(dmu_read(os, fuid_obj, 0, fuid_size, packed) == 0);
+ VERIFY(nvlist_unpack(packed, fuid_size,
+ &nvp, 0) == 0);
+ VERIFY(nvlist_lookup_nvlist_array(nvp, FUID_NVP_ARRAY,
+ &fuidnvp, &count) == 0);
+
+ for (i = 0; i != count; i++) {
+ fuid_domain_t *domnode;
+ char *domain;
+ uint64_t idx;
+
+ VERIFY(nvlist_lookup_string(fuidnvp[i], FUID_DOMAIN,
+ &domain) == 0);
+ VERIFY(nvlist_lookup_uint64(fuidnvp[i], FUID_IDX,
+ &idx) == 0);
+
+ domnode = kmem_alloc(sizeof (fuid_domain_t), KM_SLEEP);
+
+ domnode->f_idx = idx;
+ domnode->f_ksid = ksid_lookupdomain(domain);
+ avl_add(idx_tree, domnode);
+ avl_add(domain_tree, domnode);
+ }
+ nvlist_free(nvp);
+ kmem_free(packed, fuid_size);
+ }
+ return (fuid_size);
+}
+
+void
+zfs_fuid_table_destroy(avl_tree_t *idx_tree, avl_tree_t *domain_tree)
+{
+ fuid_domain_t *domnode;
+ void *cookie;
+
+ cookie = NULL;
+ while (domnode = avl_destroy_nodes(domain_tree, &cookie))
+ ksiddomain_rele(domnode->f_ksid);
+
+ avl_destroy(domain_tree);
+ cookie = NULL;
+ while (domnode = avl_destroy_nodes(idx_tree, &cookie))
+ kmem_free(domnode, sizeof (fuid_domain_t));
+ avl_destroy(idx_tree);
+}
+
+char *
+zfs_fuid_idx_domain(avl_tree_t *idx_tree, uint32_t idx)
+{
+ fuid_domain_t searchnode, *findnode;
+ avl_index_t loc;
+
+ searchnode.f_idx = idx;
+
+ findnode = avl_find(idx_tree, &searchnode, &loc);
+
+ return (findnode->f_ksid->kd_name);
+}
+
+#ifdef _KERNEL
+/*
* Load the fuid table(s) into memory.
*/
static void
zfs_fuid_init(zfsvfs_t *zfsvfs, dmu_tx_t *tx)
{
- dmu_buf_t *db;
- char *packed;
int error = 0;
- int i;
rw_enter(&zfsvfs->z_fuid_lock, RW_WRITER);
@@ -137,70 +216,9 @@
}
}
- avl_create(&zfsvfs->z_fuid_idx, idx_compare,
- sizeof (fuid_idx_t), offsetof(fuid_idx_t, f_node));
- avl_create(&zfsvfs->z_fuid_domain, domain_compare,
- sizeof (fuid_domain_t), offsetof(fuid_domain_t, f_node));
-
- if (zfsvfs->z_fuid_obj) {
- VERIFY(0 == dmu_bonus_hold(zfsvfs->z_os, zfsvfs->z_fuid_obj,
- FTAG, &db));
- zfsvfs->z_fuid_size = *(uint64_t *)db->db_data;
- dmu_buf_rele(db, FTAG);
- }
-
- if (zfsvfs->z_fuid_size == 0)
- goto initialized;
-
- packed = kmem_alloc(zfsvfs->z_fuid_size, KM_SLEEP);
- error = dmu_read(zfsvfs->z_os, zfsvfs->z_fuid_obj, 0,
- zfsvfs->z_fuid_size, packed);
- if (error == 0) {
- nvlist_t **fuidnvp;
- nvlist_t *nvp = NULL;
- uint_t count;
-
- VERIFY(nvlist_unpack(packed, zfsvfs->z_fuid_size,
- &nvp, 0) == 0);
- VERIFY((error = nvlist_lookup_nvlist_array(nvp, FUID_NVP_ARRAY,
- &fuidnvp, &count)) == 0);
+ zfsvfs->z_fuid_size = zfs_fuid_table_load(zfsvfs->z_os,
+ zfsvfs->z_fuid_obj, &zfsvfs->z_fuid_idx, &zfsvfs->z_fuid_domain);
- for (i = 0; i != count; i++) {
- fuid_idx_t *idxnode;
- fuid_domain_t *domnode;
- char *domain;
- avl_index_t loc;
- uint64_t idx, offset;
-
- VERIFY(nvlist_lookup_string(fuidnvp[i], FUID_DOMAIN,
- &domain) == 0);
- VERIFY(nvlist_lookup_uint64(fuidnvp[i], FUID_IDX,
- &idx) == 0);
- VERIFY(nvlist_lookup_uint64(fuidnvp[i], FUID_OFFSET,
- &offset) == 0);
-
- idxnode = kmem_alloc(sizeof (fuid_idx_t), KM_SLEEP);
- domnode = kmem_alloc(sizeof (fuid_domain_t), KM_SLEEP);
-
- domnode->f_idx = idxnode->f_idx = idx;
- domnode->f_ksid = ksid_lookupdomain(domain);
- idxnode->f_domain = domnode;
- domnode->f_offset = offset;
- if (avl_find(&zfsvfs->z_fuid_idx,
- idxnode, &loc) == NULL) {
- avl_insert(&zfsvfs->z_fuid_idx, idxnode, loc);
- }
- if (avl_find(&zfsvfs->z_fuid_domain,
- domnode, &loc) == NULL) {
- avl_insert(&zfsvfs->z_fuid_domain,
- domnode, loc);
- }
- }
- nvlist_free(nvp);
- }
- kmem_free(packed, zfsvfs->z_fuid_size);
-
-initialized:
zfsvfs->z_fuid_loaded = B_TRUE;
rw_exit(&zfsvfs->z_fuid_lock);
}
@@ -232,7 +250,7 @@
if (retdomain) {
*retdomain = searchnode.f_ksid->kd_name;
}
- if (zfsvfs->z_fuid_loaded == B_FALSE)
+ if (!zfsvfs->z_fuid_loaded)
zfs_fuid_init(zfsvfs, tx);
rw_enter(&zfsvfs->z_fuid_lock, RW_READER);
@@ -244,7 +262,6 @@
return (findnode->f_idx);
} else {
fuid_domain_t *domnode;
- fuid_idx_t *newidxnode;
nvlist_t *nvp;
nvlist_t **fuids;
uint64_t retidx;
@@ -255,17 +272,12 @@
domnode = kmem_alloc(sizeof (fuid_domain_t), KM_SLEEP);
domnode->f_ksid = searchnode.f_ksid;
- domnode->f_offset = 0;
-
- newidxnode = kmem_alloc(sizeof (fuid_idx_t), KM_SLEEP);
- newidxnode->f_domain = domnode;
rw_enter(&zfsvfs->z_fuid_lock, RW_WRITER);
- retidx = domnode->f_idx = newidxnode->f_idx =
- avl_numnodes(&zfsvfs->z_fuid_idx) + 1;
+ retidx = domnode->f_idx = avl_numnodes(&zfsvfs->z_fuid_idx) + 1;
avl_add(&zfsvfs->z_fuid_domain, domnode);
- avl_add(&zfsvfs->z_fuid_idx, newidxnode);
+ avl_add(&zfsvfs->z_fuid_idx, domnode);
/*
* Now resync the on-disk nvlist.
*/
@@ -278,8 +290,8 @@
NV_UNIQUE_NAME, KM_SLEEP) == 0);
VERIFY(nvlist_add_uint64(fuids[i], FUID_IDX,
domnode->f_idx) == 0);
- VERIFY(nvlist_add_uint64(fuids[i], FUID_OFFSET,
- domnode->f_offset) == 0);
+ VERIFY(nvlist_add_uint64(fuids[i],
+ FUID_OFFSET, 0) == 0);
VERIFY(nvlist_add_string(fuids[i++], FUID_DOMAIN,
domnode->f_ksid->kd_name) == 0);
domnode = AVL_NEXT(&zfsvfs->z_fuid_domain, domnode);
@@ -315,119 +327,56 @@
* Returns a pointer from an avl node of the domain string.
*
*/
-char *
-zfs_fuid_find_by_idx(zfsvfs_t *zfsvfs, uint64_t idx)
+static char *
+zfs_fuid_find_by_idx(zfsvfs_t *zfsvfs, uint32_t idx)
{
- fuid_idx_t searchnode, *findnode;
- avl_index_t loc;
+ char *domain;
- if (idx == 0 || zfsvfs->z_use_fuids == B_FALSE)
+ if (idx == 0 || !zfsvfs->z_use_fuids)
return (NULL);
- if (zfsvfs->z_fuid_loaded == B_FALSE)
+ if (!zfsvfs->z_fuid_loaded)
zfs_fuid_init(zfsvfs, NULL);
- searchnode.f_idx = idx;
-
rw_enter(&zfsvfs->z_fuid_lock, RW_READER);
- findnode = avl_find(&zfsvfs->z_fuid_idx, &searchnode, &loc);
+ domain = zfs_fuid_idx_domain(&zfsvfs->z_fuid_idx, idx);
rw_exit(&zfsvfs->z_fuid_lock);
- ASSERT(findnode);
- return (findnode->f_domain->f_ksid->kd_name);
+ ASSERT(domain);
+ return (domain);
}
void
-zfs_fuid_get_mappings(zfs_fuid_hdl_t *hdl)
+zfs_fuid_map_ids(znode_t *zp, cred_t *cr, uid_t *uidp, uid_t *gidp)
{
- VERIFY(hdl != NULL);
- if (hdl->z_map_needed == B_FALSE)
- return;
-
- (void) kidmap_get_mappings(hdl->z_hdl);
-
- kidmap_get_destroy(hdl->z_hdl);
- hdl->z_hdl = NULL;
- hdl->z_map_needed = B_FALSE;
+ *uidp = zfs_fuid_map_id(zp->z_zfsvfs, zp->z_phys->zp_uid,
+ cr, ZFS_OWNER);
+ *gidp = zfs_fuid_map_id(zp->z_zfsvfs, zp->z_phys->zp_gid,
+ cr, ZFS_GROUP);
}
-void
-zfs_fuid_queue_map_id(zfsvfs_t *zfsvfs, zfs_fuid_hdl_t *hdl,
- uint64_t fuid, cred_t *cr, zfs_fuid_type_t type, uid_t *id)
+uid_t
+zfs_fuid_map_id(zfsvfs_t *zfsvfs, uint64_t fuid,
+ cred_t *cr, zfs_fuid_type_t type)
{
uint32_t index = FUID_INDEX(fuid);
char *domain;
- int status;
-
- VERIFY(hdl);
+ uid_t id;
- if (index == 0 || zfsvfs->z_use_fuids == B_FALSE) {
- *id = (uid_t)fuid;
- return;
- }
-
- if (hdl->z_hdl == NULL) {
- hdl->z_hdl = kidmap_get_create(crgetzone(cr));
- hdl->z_map_needed = B_TRUE;
- }
+ if (index == 0)
+ return (fuid);
domain = zfs_fuid_find_by_idx(zfsvfs, index);
ASSERT(domain != NULL);
- if (type == ZFS_OWNER || type == ZFS_ACE_USER)
- status = kidmap_batch_getuidbysid(hdl->z_hdl, domain,
- FUID_RID(fuid), id, &hdl->z_status);
- else
- status = kidmap_batch_getgidbysid(hdl->z_hdl, domain,
- FUID_RID(fuid), id, &hdl->z_status);
- ASSERT(status == 0);
-}
-
-void
-zfs_fuid_map_ids(znode_t *zp, cred_t *cr, uid_t *uid, uid_t *gid)
-{
- uint32_t uid_index = FUID_INDEX(zp->z_phys->zp_uid);
- uint32_t gid_index = FUID_INDEX(zp->z_phys->zp_gid);
-
- /* Favor the common case, neither will be ephemeral */
- if (uid_index == 0 && gid_index == 0) {
- *uid = zp->z_phys->zp_uid;
- *gid = zp->z_phys->zp_gid;
- return;
+ if (type == ZFS_OWNER || type == ZFS_ACE_USER) {
+ (void) kidmap_getuidbysid(crgetzone(cr), domain,
+ FUID_RID(fuid), &id);
} else {
- zfs_fuid_hdl_t hdl = { 0 };
-
- zfs_fuid_queue_map_id(zp->z_zfsvfs, &hdl,
- zp->z_phys->zp_uid, cr, ZFS_OWNER, uid);
-
- zfs_fuid_queue_map_id(zp->z_zfsvfs, &hdl,
- zp->z_phys->zp_gid, cr, ZFS_GROUP, gid);
-
- zfs_fuid_get_mappings(&hdl);
+ (void) kidmap_getgidbysid(crgetzone(cr), domain,
+ FUID_RID(fuid), &id);
}
-}
-
-void
-zfs_fuid_map_id(zfsvfs_t *zfsvfs, uint64_t fuid,
- cred_t *cr, zfs_fuid_type_t type, uid_t *id)
-{
- uint32_t index = FUID_INDEX(fuid);
- char *domain;
-
- if (index == 0) {
- *id = (uid_t)fuid;
- return;
- }
-
- domain = zfs_fuid_find_by_idx(zfsvfs, index);
- ASSERT(domain != NULL);
-
- if (type == ZFS_OWNER || type == ZFS_ACE_USER)
- (void) kidmap_getuidbysid(crgetzone(cr), domain,
- FUID_RID(fuid), id);
- else
- (void) kidmap_getgidbysid(crgetzone(cr), domain,
- FUID_RID(fuid), id);
+ return (id);
}
/*
@@ -466,7 +415,7 @@
}
}
- if (found == B_FALSE) {
+ if (!found) {
fuid_domain = kmem_alloc(sizeof (zfs_fuid_domain_t), KM_SLEEP);
fuid_domain->z_domain = domain;
fuid_domain->z_domidx = idx;
@@ -499,18 +448,24 @@
* Create a file system FUID, based on information in the users cred
*/
uint64_t
-zfs_fuid_create_cred(zfsvfs_t *zfsvfs, uint64_t id,
- zfs_fuid_type_t type, dmu_tx_t *tx, cred_t *cr, zfs_fuid_info_t **fuidp)
+zfs_fuid_create_cred(zfsvfs_t *zfsvfs, zfs_fuid_type_t type,
+ dmu_tx_t *tx, cred_t *cr, zfs_fuid_info_t **fuidp)
{
uint64_t idx;
ksid_t *ksid;
uint32_t rid;
char *kdomain;
const char *domain;
+ uid_t id;
VERIFY(type == ZFS_OWNER || type == ZFS_GROUP);
- if (zfsvfs->z_use_fuids == B_FALSE || !IS_EPHEMERAL(id))
+ if (type == ZFS_OWNER)
+ id = crgetuid(cr);
+ else
+ id = crgetgid(cr);
+
+ if (!zfsvfs->z_use_fuids || !IS_EPHEMERAL(id))
return ((uint64_t)id);
ksid = crgetsid(cr, (type == ZFS_OWNER) ? KSID_OWNER : KSID_GROUP);
@@ -555,8 +510,12 @@
/*
* If POSIX ID, or entry is already a FUID then
* just return the id
+ *
+ * We may also be handed an already FUID'ized id via
+ * chmod.
*/
- if (!IS_EPHEMERAL(id) || fuid_idx != 0)
+
+ if (!zfsvfs->z_use_fuids || !IS_EPHEMERAL(id) || fuid_idx != 0)
return (id);
if (is_replay) {
@@ -605,12 +564,11 @@
rid = UID_NOBODY;
domain = "";
}
-
}
idx = zfs_fuid_find_by_domain(zfsvfs, domain, &kdomain, tx);
- if (is_replay == B_FALSE)
+ if (!is_replay)
zfs_fuid_node_add(fuidpp, kdomain, rid, idx, id, type);
else if (zfuid != NULL) {
list_remove(&fuidp->z_fuids, zfuid);
@@ -622,25 +580,12 @@
void
zfs_fuid_destroy(zfsvfs_t *zfsvfs)
{
- fuid_domain_t *domnode;
- fuid_idx_t *idxnode;
- void *cookie;
-
rw_enter(&zfsvfs->z_fuid_lock, RW_WRITER);
- if (zfsvfs->z_fuid_loaded == B_FALSE) {
+ if (!zfsvfs->z_fuid_loaded) {
rw_exit(&zfsvfs->z_fuid_lock);
return;
}
- cookie = NULL;
- while (domnode = avl_destroy_nodes(&zfsvfs->z_fuid_domain, &cookie)) {
- ksiddomain_rele(domnode->f_ksid);
- kmem_free(domnode, sizeof (fuid_domain_t));
- }
- avl_destroy(&zfsvfs->z_fuid_domain);
- cookie = NULL;
- while (idxnode = avl_destroy_nodes(&zfsvfs->z_fuid_idx, &cookie))
- kmem_free(idxnode, sizeof (fuid_idx_t));
- avl_destroy(&zfsvfs->z_fuid_idx);
+ zfs_fuid_table_destroy(&zfsvfs->z_fuid_idx, &zfsvfs->z_fuid_domain);
rw_exit(&zfsvfs->z_fuid_lock);
}
@@ -723,15 +668,13 @@
ASSERT(domain != NULL);
if (strcmp(domain,
- IDMAP_WK_CREATOR_SID_AUTHORITY) == 0) {
+ IDMAP_WK_CREATOR_SID_AUTHORITY) == 0)
return (B_FALSE);
- }
if ((strcmp(domain,
ksid_groups[i].ks_domain->kd_name) == 0) &&
- rid == ksid_groups[i].ks_rid) {
+ rid == ksid_groups[i].ks_rid)
return (B_TRUE);
- }
}
}
}
@@ -739,6 +682,7 @@
/*
* Not found in ksidlist, check posix groups
*/
- zfs_fuid_map_id(zfsvfs, id, cr, ZFS_GROUP, &gid);
+ gid = zfs_fuid_map_id(zfsvfs, id, cr, ZFS_GROUP);
return (groupmember(gid, cr));
}
+#endif
--- a/usr/src/uts/common/fs/zfs/zfs_vnops.c Fri Feb 01 10:11:12 2008 -0800
+++ b/usr/src/uts/common/fs/zfs/zfs_vnops.c Fri Feb 01 12:13:54 2008 -0800
@@ -1219,7 +1219,8 @@
tx = dmu_tx_create(os);
dmu_tx_hold_bonus(tx, DMU_NEW_OBJECT);
- if (aclp && aclp->z_has_fuids) {
+ if ((aclp && aclp->z_has_fuids) || IS_EPHEMERAL(crgetuid(cr)) ||
+ IS_EPHEMERAL(crgetgid(cr))) {
if (zfsvfs->z_fuid_obj == 0) {
dmu_tx_hold_bonus(tx, DMU_NEW_OBJECT);
dmu_tx_hold_write(tx, DMU_NEW_OBJECT, 0,
@@ -1640,7 +1641,8 @@
tx = dmu_tx_create(zfsvfs->z_os);
dmu_tx_hold_zap(tx, dzp->z_id, TRUE, dirname);
dmu_tx_hold_zap(tx, DMU_NEW_OBJECT, FALSE, NULL);
- if (aclp && aclp->z_has_fuids) {
+ if ((aclp && aclp->z_has_fuids) || IS_EPHEMERAL(crgetuid(cr)) ||
+ IS_EPHEMERAL(crgetgid(cr))) {
if (zfsvfs->z_fuid_obj == 0) {
dmu_tx_hold_bonus(tx, DMU_NEW_OBJECT);
dmu_tx_hold_write(tx, DMU_NEW_OBJECT, 0,
@@ -3420,7 +3422,7 @@
return (EPERM);
}
- zfs_fuid_map_id(zfsvfs, szp->z_phys->zp_uid, cr, ZFS_OWNER, &owner);
+ owner = zfs_fuid_map_id(zfsvfs, szp->z_phys->zp_uid, cr, ZFS_OWNER);
if (owner != crgetuid(cr) &&
secpolicy_basic_link(cr) != 0) {
ZFS_EXIT(zfsvfs);