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]

 



2016-10-14 8:10 GMT-07:00 Steve French <smfrench@xxxxxxxxx>:
> 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
> --
> 1.9.1
>
> --
> 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

It seems like sid_unix_NFS_mode variable is not used.

Other than the notice above, the patch looks good:

Reviewed-by: Pavel Shilovsky <pshilov@xxxxxxxxxxxxx>

-- 
Best regards,
Pavel Shilovsky
--
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