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]

 



I planned to use the NFS mode in the future (since apparently it can
be set in ACL in Windows case - not sure about Mac) but I didn't have
time to test it yet, and in any case want to get the SMB3 cifsacl
enablement in first.

On Fri, Oct 14, 2016 at 2:12 PM, Pavel Shilovsky <piastryyy@xxxxxxxxx> wrote:
> 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



-- 
Thanks,

Steve
--
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