summaryrefslogtreecommitdiffstats
path: root/module/zfs/zfs_fuid.c
diff options
context:
space:
mode:
Diffstat (limited to 'module/zfs/zfs_fuid.c')
-rw-r--r--module/zfs/zfs_fuid.c62
1 files changed, 45 insertions, 17 deletions
diff --git a/module/zfs/zfs_fuid.c b/module/zfs/zfs_fuid.c
index e704b1ca9..8c0424e84 100644
--- a/module/zfs/zfs_fuid.c
+++ b/module/zfs/zfs_fuid.c
@@ -19,12 +19,10 @@
* CDDL HEADER END
*/
/*
- * Copyright 2009 Sun Microsystems, Inc. All rights reserved.
- * Use is subject to license terms.
+ * Copyright (c) 2007, 2010, Oracle and/or its affiliates. All rights reserved.
*/
#include <sys/zfs_context.h>
-#include <sys/sunddi.h>
#include <sys/dmu.h>
#include <sys/avl.h>
#include <sys/zap.h>
@@ -377,7 +375,7 @@ zfs_fuid_find_by_idx(zfsvfs_t *zfsvfs, uint32_t idx)
rw_enter(&zfsvfs->z_fuid_lock, RW_READER);
- if (zfsvfs->z_fuid_obj)
+ if (zfsvfs->z_fuid_obj || zfsvfs->z_fuid_dirty)
domain = zfs_fuid_idx_domain(&zfsvfs->z_fuid_idx, idx);
else
domain = nulldomain;
@@ -390,10 +388,26 @@ zfs_fuid_find_by_idx(zfsvfs_t *zfsvfs, uint32_t idx)
void
zfs_fuid_map_ids(znode_t *zp, cred_t *cr, uid_t *uidp, uid_t *gidp)
{
- *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);
+ uint64_t fuid, fgid;
+ sa_bulk_attr_t bulk[2];
+ int count = 0;
+
+ if (IS_EPHEMERAL(zp->z_uid) || IS_EPHEMERAL(zp->z_gid)) {
+ SA_ADD_BULK_ATTR(bulk, count, SA_ZPL_UID(zp->z_zfsvfs),
+ NULL, &fuid, 8);
+ SA_ADD_BULK_ATTR(bulk, count, SA_ZPL_GID(zp->z_zfsvfs),
+ NULL, &fgid, 8);
+ VERIFY(0 == sa_bulk_lookup(zp->z_sa_hdl, bulk, count));
+ }
+ if (IS_EPHEMERAL(zp->z_uid))
+ *uidp = zfs_fuid_map_id(zp->z_zfsvfs, zp->z_uid, cr, ZFS_OWNER);
+ else
+ *uidp = zp->z_uid;
+ if (IS_EPHEMERAL(zp->z_gid))
+ *gidp = zfs_fuid_map_id(zp->z_zfsvfs,
+ zp->z_gid, cr, ZFS_GROUP);
+ else
+ *gidp = zp->z_gid;
}
uid_t
@@ -427,7 +441,7 @@ zfs_fuid_map_id(zfsvfs_t *zfsvfs, uint64_t fuid,
* If ACL has multiple domains, then keep only one copy of each unique
* domain.
*/
-static void
+void
zfs_fuid_node_add(zfs_fuid_info_t **fuidpp, const char *domain, uint32_t rid,
uint64_t idx, uint64_t id, zfs_fuid_type_t type)
{
@@ -488,6 +502,11 @@ zfs_fuid_node_add(zfs_fuid_info_t **fuidpp, const char *domain, uint32_t rid,
/*
* Create a file system FUID, based on information in the users cred
+ *
+ * If cred contains KSID_OWNER then it should be used to determine
+ * the uid otherwise cred's uid will be used. By default cred's gid
+ * is used unless it's an ephemeral ID in which case KSID_GROUP will
+ * be used if it exists.
*/
uint64_t
zfs_fuid_create_cred(zfsvfs_t *zfsvfs, zfs_fuid_type_t type,
@@ -503,18 +522,27 @@ zfs_fuid_create_cred(zfsvfs_t *zfsvfs, zfs_fuid_type_t type,
VERIFY(type == ZFS_OWNER || type == ZFS_GROUP);
ksid = crgetsid(cr, (type == ZFS_OWNER) ? KSID_OWNER : KSID_GROUP);
- if (ksid) {
- id = ksid_getid(ksid);
- } else {
- if (type == ZFS_OWNER)
- id = crgetuid(cr);
- else
- id = crgetgid(cr);
+
+ if (!zfsvfs->z_use_fuids || (ksid == NULL)) {
+ id = (type == ZFS_OWNER) ? crgetuid(cr) : crgetgid(cr);
+
+ if (IS_EPHEMERAL(id))
+ return ((type == ZFS_OWNER) ? UID_NOBODY : GID_NOBODY);
+
+ return ((uint64_t)id);
}
- if (!zfsvfs->z_use_fuids || (!IS_EPHEMERAL(id)))
+ /*
+ * ksid is present and FUID is supported
+ */
+ id = (type == ZFS_OWNER) ? ksid_getid(ksid) : crgetgid(cr);
+
+ if (!IS_EPHEMERAL(id))
return ((uint64_t)id);
+ if (type == ZFS_GROUP)
+ id = ksid_getid(ksid);
+
rid = ksid_getrid(ksid);
domain = ksid_getdomain(ksid);