Mercurial > illumos > git > illumos-omnios
changeset 21396:a1dd191628fc
10991 Allow user ACE in ACL to match SID in token extra SIDs
Reviewed by: Roman Strashkin <roman.strashkin@nexenta.com>
Reviewed by: Sanjay Nadkarni <sanjay.nadkarni@nexenta.com>
Reviewed by: Evan Layton <evan.layton@nexenta.com>
Reviewed by: Rick McNeal <rick.mcneal@nexenta.com>
Reviewed by: Joyce McIntosh <joyce.mcintosh@nexenta.com>
Reviewed by: Garrett D'Amore <garrett@damore.org>
Reviewed by: Gergő Doma <domag02@gmail.com>
Approved by: Dan McDonald <danmcd@joyent.com>
author | Gordon Ross <gwr@nexenta.com> |
---|---|
date | Tue, 17 Oct 2017 10:04:43 -0400 |
parents | b2bf0d068923 |
children | cc6857011980 |
files | usr/src/uts/common/fs/zfs/sys/zfs_fuid.h usr/src/uts/common/fs/zfs/zfs_acl.c usr/src/uts/common/fs/zfs/zfs_fuid.c |
diffstat | 3 files changed, 72 insertions(+), 28 deletions(-) [+] |
line wrap: on
line diff
--- a/usr/src/uts/common/fs/zfs/sys/zfs_fuid.h Thu May 23 22:54:25 2019 +0000 +++ b/usr/src/uts/common/fs/zfs/sys/zfs_fuid.h Tue Oct 17 10:04:43 2017 -0400 @@ -21,6 +21,8 @@ /* * Copyright 2010 Sun Microsystems, Inc. All rights reserved. * Use is subject to license terms. + * + * Copyright 2017 Nexenta Systems, Inc. All rights reserved. */ #ifndef _SYS_FS_ZFS_FUID_H @@ -70,8 +72,8 @@ * Used for mapping ephemeral uid/gid during ACL setting to FUIDs */ typedef struct zfs_fuid { - list_node_t z_next; - uint64_t z_id; /* uid/gid being converted to fuid */ + list_node_t z_next; + uint64_t z_id; /* uid/gid being converted to fuid */ uint64_t z_domidx; /* index in AVL domain table */ uint64_t z_logfuid; /* index for domain in log */ } zfs_fuid_t; @@ -111,6 +113,7 @@ uid_t *uid, uid_t *gid); extern zfs_fuid_info_t *zfs_fuid_info_alloc(void); extern void zfs_fuid_info_free(zfs_fuid_info_t *); +extern boolean_t zfs_user_in_cred(zfsvfs_t *, uint64_t, cred_t *); extern boolean_t zfs_groupmember(zfsvfs_t *, uint64_t, cred_t *); void zfs_fuid_sync(zfsvfs_t *, dmu_tx_t *); extern int zfs_fuid_find_by_domain(zfsvfs_t *, const char *domain,
--- a/usr/src/uts/common/fs/zfs/zfs_acl.c Thu May 23 22:54:25 2019 +0000 +++ b/usr/src/uts/common/fs/zfs/zfs_acl.c Tue Oct 17 10:04:43 2017 -0400 @@ -2106,18 +2106,13 @@ zfsvfs_t *zfsvfs = zp->z_zfsvfs; zfs_acl_t *aclp; int error; - uid_t uid = crgetuid(cr); - uint64_t who; + uint64_t who; /* FUID from the ACE */ uint16_t type, iflags; uint16_t entry_type; uint32_t access_mask; uint32_t deny_mask = 0; zfs_ace_hdr_t *acep = NULL; - boolean_t checkit; - uid_t gowner; - uid_t fowner; - - zfs_fuid_map_ids(zp, cr, &fowner, &gowner); + boolean_t checkit; /* ACE ID matches */ mutex_enter(&zp->z_acl_lock); @@ -2150,11 +2145,13 @@ switch (entry_type) { case ACE_OWNER: - if (uid == fowner) - checkit = B_TRUE; + who = zp->z_uid; + /*FALLTHROUGH*/ + case 0: /* USER Entry */ + checkit = zfs_user_in_cred(zfsvfs, who, cr); break; case OWNING_GROUP: - who = gowner; + who = zp->z_gid; /*FALLTHROUGH*/ case ACE_IDENTIFIER_GROUP: checkit = zfs_groupmember(zfsvfs, who, cr); @@ -2163,21 +2160,13 @@ checkit = B_TRUE; break; - /* USER Entry */ default: - if (entry_type == 0) { - uid_t newid; - - newid = zfs_fuid_map_id(zfsvfs, who, cr, - ZFS_ACE_USER); - if (newid != IDMAP_WK_CREATOR_OWNER_UID && - uid == newid) - checkit = B_TRUE; - break; - } else { - mutex_exit(&zp->z_acl_lock); - return (SET_ERROR(EIO)); - } + /* + * The zfs_acl_valid_ace_type check above + * should make this case impossible. + */ + mutex_exit(&zp->z_acl_lock); + return (SET_ERROR(EIO)); } if (checkit) {
--- a/usr/src/uts/common/fs/zfs/zfs_fuid.c Thu May 23 22:54:25 2019 +0000 +++ b/usr/src/uts/common/fs/zfs/zfs_fuid.c Tue Oct 17 10:04:43 2017 -0400 @@ -20,6 +20,7 @@ */ /* * Copyright (c) 2007, 2010, Oracle and/or its affiliates. All rights reserved. + * Copyright 2018 Nexenta Systems, Inc. All rights reserved. */ #include <sys/zfs_context.h> @@ -492,7 +493,7 @@ uint64_t idx; ksid_t *ksid; uint32_t rid; - char *kdomain; + char *kdomain; const char *domain; uid_t id; @@ -685,6 +686,57 @@ } /* + * Check to see if user ID is in the list of SIDs in CR. + */ +boolean_t +zfs_user_in_cred(zfsvfs_t *zfsvfs, uint64_t id, cred_t *cr) +{ + ksid_t *ksid = crgetsid(cr, KSID_USER); + ksidlist_t *ksidlist = crgetsidlist(cr); + uid_t uid; + + /* Check for match with cred->cr_uid */ + uid = zfs_fuid_map_id(zfsvfs, id, cr, ZFS_ACE_USER); + if (uid != IDMAP_WK_CREATOR_OWNER_UID && + uid == crgetuid(cr)) + return (B_TRUE); + + /* Check for any match in the ksidlist */ + if (ksid && ksidlist) { + int i; + ksid_t *ksid_vec; + uint32_t idx = FUID_INDEX(id); + uint32_t rid = FUID_RID(id); + const char *domain; + + if (idx == 0) { + /* + * The ID passed in has idx zero, which means + * it's just a Unix UID. That can never match + * anything in ksid_vec[] because those all + * have ksid->ks_id set to a Group ID. + */ + return (B_FALSE); + } + + domain = zfs_fuid_find_by_idx(zfsvfs, idx); + ASSERT(domain != NULL); + + if (strcmp(domain, IDMAP_WK_CREATOR_SID_AUTHORITY) == 0) + return (B_FALSE); + + ksid_vec = ksidlist->ksl_sids; + for (i = 0; i != ksidlist->ksl_nsid; i++) { + if ((strcmp(domain, + ksid_vec[i].ks_domain->kd_name) == 0) && + rid == ksid_vec[i].ks_rid) + return (B_TRUE); + } + } + return (B_FALSE); +} + +/* * Check to see if id is a groupmember. If cred * has ksid info then sidlist is checked first * and if still not found then POSIX groups are checked @@ -699,7 +751,7 @@ uid_t gid; if (ksid && ksidlist) { - int i; + int i; ksid_t *ksid_groups; uint32_t idx = FUID_INDEX(id); uint32_t rid = FUID_RID(id);