Re: [PATCH 2/2] Retrieve uid and gid from special sid if enabled

[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]

 



On Fri, 2016-10-14 at 10:10 -0500, Steve French wrote:
> New mount option "idsfromsid" indicates to cifs.ko that
> it should try to retrieve the uid and gid owner fields
> from special sids.  This patch adds the code to parse the owner
> sids in the ACL to see if they match, and if so populate the
> uid and/or gid from them.  This is faster than upcalling for
> them and asking winbind, and is a fairly common case, and is
> also helpful when cifs.upcall and idmapping is not configured.
> 
> Signed-off-by: Steve French <steve.french@xxxxxxxxxxxxxxx>
> Reviewed-by:  Shirish Pargaonkar <shirishpargaonkar@xxxxxxxxx>
> ---
>  fs/cifs/cifsacl.c | 123 ++++++++++++++++++++++++++++++++++++++++++++++++++++++
>  1 file changed, 123 insertions(+)
> 
> diff --git a/fs/cifs/cifsacl.c b/fs/cifs/cifsacl.c
> index 71e8a56..15bac39 100644
> --- a/fs/cifs/cifsacl.c
> +++ b/fs/cifs/cifsacl.c
> @@ -42,6 +42,35 @@
>  /* group users */
>  static const struct cifs_sid sid_user = {1, 2 , {0, 0, 0, 0, 0, 5}, {} };
>  
> +/* S-1-22-1 Unmapped Unix users */
> +static const struct cifs_sid sid_unix_users = {1, 1, {0, 0, 0, 0, 0, 22},
> +		{cpu_to_le32(1), 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0} };
> +
> +/* S-1-22-2 Unmapped Unix groups */
> +static const struct cifs_sid sid_unix_groups = { 1, 1, {0, 0, 0, 0, 0, 22},
> +		{cpu_to_le32(2), 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0} };
> +
> +/*
> + * See http://technet.microsoft.com/en-us/library/hh509017(v=ws.10).aspx
> + */
> +
> +/* S-1-5-88 MS NFS and Apple style UID/GID/mode */
> +
> +/* S-1-5-88-1 Unix uid */
> +static const struct cifs_sid sid_unix_NFS_users = { 1, 2, {0, 0, 0, 0, 0, 5},
> +	{cpu_to_le32(88),
> +	 cpu_to_le32(1), 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0} };
> +
> +/* S-1-5-88-2 Unix gid */
> +static const struct cifs_sid sid_unix_NFS_groups = { 1, 2, {0, 0, 0, 0, 0, 5},
> +	{cpu_to_le32(88),
> +	 cpu_to_le32(2), 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0} };
> +
> +/* S-1-5-88-3 Unix mode */
> +static const struct cifs_sid sid_unix_NFS_mode = { 1, 2, {0, 0, 0, 0, 0, 5},
> +	{cpu_to_le32(88),
> +	 cpu_to_le32(3), 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0} };
> +
>  static const struct cred *root_cred;
>  
>  static int
> @@ -183,6 +212,62 @@
>  	return 0; /* sids compare/match */
>  }
>  
> +static bool
> +is_well_known_sid(const struct cifs_sid *psid, uint32_t *puid, bool is_group)
> +{
> +	int i;
> +	int num_subauth;
> +	const struct cifs_sid *pwell_known_sid;
> +
> +	if (!psid || (puid == NULL))
> +		return false;
> +
> +	num_subauth = psid->num_subauth;
> +
> +	/* check if Mac (or Windows NFS) vs. Samba format for Unix owner SID */
> +	if (num_subauth == 2) {
> +		if (is_group)
> +			pwell_known_sid = &sid_unix_groups;
> +		else
> +			pwell_known_sid = &sid_unix_users;
> +	} else if (num_subauth == 3) {
> +		if (is_group)
> +			pwell_known_sid = &sid_unix_NFS_groups;
> +		else
> +			pwell_known_sid = &sid_unix_NFS_users;
> +	} else
> +		return false;
> +
> +	/* compare the revision */
> +	if (psid->revision != pwell_known_sid->revision)
> +		return false;
> +
> +	/* compare all of the six auth values */
> +	for (i = 0; i < NUM_AUTHS; ++i) {
> +		if (psid->authority[i] != pwell_known_sid->authority[i]) {
> +			cifs_dbg(FYI, "auth %d did not match\n", i);
> +			return false;
> +		}
> +	}
> +
> +	if (num_subauth == 2) {
> +		if (psid->sub_auth[0] != pwell_known_sid->sub_auth[0])
> +			return false;
> +
> +		*puid = le32_to_cpu(psid->sub_auth[1]);
> +	} else /* 3 subauths, ie Windows/Mac style */ {
> +		*puid = le32_to_cpu(psid->sub_auth[0]);
> +		if ((psid->sub_auth[0] != pwell_known_sid->sub_auth[0]) ||
> +		    (psid->sub_auth[1] != pwell_known_sid->sub_auth[1]))
> +			return false;
> +
> +		*puid = le32_to_cpu(psid->sub_auth[2]);
> +	}
> +
> +	cifs_dbg(FYI, "Unix UID %d returned from SID\n", *puid);
> +	return true; /* well known sid found, uid returned */
> +}
> +
>  static void
>  cifs_copy_sid(struct cifs_sid *dst, const struct cifs_sid *src)
>  {
> @@ -276,6 +361,43 @@
>  		return -EIO;
>  	}
>  
> +	if (cifs_sb->mnt_cifs_flags & CIFS_MOUNT_UID_FROM_ACL) {
> +		uint32_t unix_id;
> +		bool is_group;
> +
> +		if (sidtype != SIDOWNER)
> +			is_group = true;
> +		else
> +			is_group = false;
> +
> +		if (is_well_known_sid(psid, &unix_id, is_group) == false)
> +			goto try_upcall_to_get_id;
> +
> +		if (is_group) {
> +			kgid_t gid;
> +			gid_t id;
> +
> +			id = (gid_t)unix_id;
> +			gid = make_kgid(&init_user_ns, id);
> +			if (gid_valid(gid)) {
> +				fgid = gid;
> +				goto got_valid_id;
> +			}
> +		} else {
> +			kuid_t uid;
> +			uid_t id;
> +
> +			id = (uid_t)unix_id;
> +			uid = make_kuid(&init_user_ns, id);
> +			if (uid_valid(uid)) {
> +				fuid = uid;
> +				goto got_valid_id;
> +			}
> +		}
> +		/* If unable to find uid/gid easily from SID try via upcall */
> +	}
> +
> +try_upcall_to_get_id:
>  	sidstr = sid_to_key_str(psid, sidtype);
>  	if (!sidstr)
>  		return -ENOMEM;
> @@ -329,6 +451,7 @@
>  	 * Note that we return 0 here unconditionally. If the mapping
>  	 * fails then we just fall back to using the mnt_uid/mnt_gid.
>  	 */
> +got_valid_id:
>  	if (sidtype == SIDOWNER)
>  		fattr->cf_uid = fuid;
>  	else

Nice! Good idea:

Reviewed-by: Jeff Layton <jlayton@xxxxxxxxxx>
--
To unsubscribe from this list: send the line "unsubscribe linux-cifs" in
the body of a message to majordomo@xxxxxxxxxxxxxxx
More majordomo info at  http://vger.kernel.org/majordomo-info.html



[Linux USB Devel]     [Video for Linux]     [Linux Audio Users]     [Yosemite News]     [Linux Kernel]     [Linux SCSI]

  Powered by Linux