cifs: redefine NUM_SUBAUTH constant from 5 to 15
[pandora-kernel.git] / fs / cifs / cifsacl.c
index fc783e2..dd8d3df 100644 (file)
@@ -210,7 +210,7 @@ sid_to_str(struct cifs_sid *sidptr, char *sidstr)
        sprintf(strptr, "-%d", sidptr->revision);
        strptr = sidstr + strlen(sidstr);
 
-       for (i = 0; i < 6; ++i) {
+       for (i = 0; i < NUM_AUTHS; ++i) {
                if (sidptr->authority[i]) {
                        sprintf(strptr, "-%d", sidptr->authority[i]);
                        strptr = sidstr + strlen(sidstr);
@@ -224,6 +224,69 @@ sid_to_str(struct cifs_sid *sidptr, char *sidstr)
        }
 }
 
+/*
+ * if the two SIDs (roughly equivalent to a UUID for a user or group) are
+ * the same returns zero, if they do not match returns non-zero.
+ */
+static int
+compare_sids(const struct cifs_sid *ctsid, const struct cifs_sid *cwsid)
+{
+       int i;
+       int num_subauth, num_sat, num_saw;
+
+       if ((!ctsid) || (!cwsid))
+               return 1;
+
+       /* compare the revision */
+       if (ctsid->revision != cwsid->revision) {
+               if (ctsid->revision > cwsid->revision)
+                       return 1;
+               else
+                       return -1;
+       }
+
+       /* compare all of the six auth values */
+       for (i = 0; i < NUM_AUTHS; ++i) {
+               if (ctsid->authority[i] != cwsid->authority[i]) {
+                       if (ctsid->authority[i] > cwsid->authority[i])
+                               return 1;
+                       else
+                               return -1;
+               }
+       }
+
+       /* compare all of the subauth values if any */
+       num_sat = ctsid->num_subauth;
+       num_saw = cwsid->num_subauth;
+       num_subauth = num_sat < num_saw ? num_sat : num_saw;
+       if (num_subauth) {
+               for (i = 0; i < num_subauth; ++i) {
+                       if (ctsid->sub_auth[i] != cwsid->sub_auth[i]) {
+                               if (le32_to_cpu(ctsid->sub_auth[i]) >
+                                       le32_to_cpu(cwsid->sub_auth[i]))
+                                       return 1;
+                               else
+                                       return -1;
+                       }
+               }
+       }
+
+       return 0; /* sids compare/match */
+}
+
+static void
+cifs_copy_sid(struct cifs_sid *dst, const struct cifs_sid *src)
+{
+       int i;
+
+       dst->revision = src->revision;
+       dst->num_subauth = min_t(u8, src->num_subauth, SID_MAX_SUB_AUTHORITIES);
+       for (i = 0; i < NUM_AUTHS; ++i)
+               dst->authority[i] = src->authority[i];
+       for (i = 0; i < dst->num_subauth; ++i)
+               dst->sub_auth[i] = src->sub_auth[i];
+}
+
 static void
 id_rb_insert(struct rb_root *root, struct cifs_sid *sidptr,
                struct cifs_sid_id **psidid, char *typestr)
@@ -248,7 +311,7 @@ id_rb_insert(struct rb_root *root, struct cifs_sid *sidptr,
                }
        }
 
-       memcpy(&(*psidid)->sid, sidptr, sizeof(struct cifs_sid));
+       cifs_copy_sid(&(*psidid)->sid, sidptr);
        (*psidid)->time = jiffies - (SID_MAP_RETRY + 1);
        (*psidid)->refcount = 0;
 
@@ -320,7 +383,7 @@ id_to_sid(unsigned long cid, uint sidtype, struct cifs_sid *ssid)
                if (!npsidid)
                        return -ENOMEM;
 
-               npsidid->sidstr = kmalloc(SIDLEN, GFP_KERNEL);
+               npsidid->sidstr = kmalloc(SID_STRING_MAX, GFP_KERNEL);
                if (!npsidid->sidstr) {
                        kfree(npsidid);
                        return -ENOMEM;
@@ -354,7 +417,7 @@ id_to_sid(unsigned long cid, uint sidtype, struct cifs_sid *ssid)
         * any fields of the node after a reference is put .
         */
        if (test_bit(SID_ID_MAPPED, &psidid->state)) {
-               memcpy(ssid, &psidid->sid, sizeof(struct cifs_sid));
+               cifs_copy_sid(ssid, &psidid->sid);
                psidid->time = jiffies; /* update ts for accessing */
                goto id_sid_out;
        }
@@ -370,14 +433,14 @@ id_to_sid(unsigned long cid, uint sidtype, struct cifs_sid *ssid)
                if (IS_ERR(sidkey)) {
                        rc = -EINVAL;
                        cFYI(1, "%s: Can't map and id to a SID", __func__);
+               } else if (sidkey->datalen < CIFS_SID_BASE_SIZE) {
+                       rc = -EIO;
+                       cFYI(1, "%s: Downcall contained malformed key "
+                               "(datalen=%hu)", __func__, sidkey->datalen);
                } else {
                        lsid = (struct cifs_sid *)sidkey->payload.data;
-                       memcpy(&psidid->sid, lsid,
-                               sidkey->datalen < sizeof(struct cifs_sid) ?
-                               sidkey->datalen : sizeof(struct cifs_sid));
-                       memcpy(ssid, &psidid->sid,
-                               sidkey->datalen < sizeof(struct cifs_sid) ?
-                               sidkey->datalen : sizeof(struct cifs_sid));
+                       cifs_copy_sid(&psidid->sid, lsid);
+                       cifs_copy_sid(ssid, &psidid->sid);
                        set_bit(SID_ID_MAPPED, &psidid->state);
                        key_put(sidkey);
                        kfree(psidid->sidstr);
@@ -396,7 +459,7 @@ id_to_sid(unsigned long cid, uint sidtype, struct cifs_sid *ssid)
                        return rc;
                }
                if (test_bit(SID_ID_MAPPED, &psidid->state))
-                       memcpy(ssid, &psidid->sid, sizeof(struct cifs_sid));
+                       cifs_copy_sid(ssid, &psidid->sid);
                else
                        rc = -EINVAL;
        }
@@ -437,7 +500,7 @@ sid_to_id(struct cifs_sb_info *cifs_sb, struct cifs_sid *psid,
                if (!npsidid)
                        return -ENOMEM;
 
-               npsidid->sidstr = kmalloc(SIDLEN, GFP_KERNEL);
+               npsidid->sidstr = kmalloc(SID_STRING_MAX, GFP_KERNEL);
                if (!npsidid->sidstr) {
                        kfree(npsidid);
                        return -ENOMEM;
@@ -623,60 +686,10 @@ cifs_destroy_idmaptrees(void)
        spin_unlock(&gidsidlock);
 }
 
-/* if the two SIDs (roughly equivalent to a UUID for a user or group) are
-   the same returns 1, if they do not match returns 0 */
-int compare_sids(const struct cifs_sid *ctsid, const struct cifs_sid *cwsid)
-{
-       int i;
-       int num_subauth, num_sat, num_saw;
-
-       if ((!ctsid) || (!cwsid))
-               return 1;
-
-       /* compare the revision */
-       if (ctsid->revision != cwsid->revision) {
-               if (ctsid->revision > cwsid->revision)
-                       return 1;
-               else
-                       return -1;
-       }
-
-       /* compare all of the six auth values */
-       for (i = 0; i < 6; ++i) {
-               if (ctsid->authority[i] != cwsid->authority[i]) {
-                       if (ctsid->authority[i] > cwsid->authority[i])
-                               return 1;
-                       else
-                               return -1;
-               }
-       }
-
-       /* compare all of the subauth values if any */
-       num_sat = ctsid->num_subauth;
-       num_saw = cwsid->num_subauth;
-       num_subauth = num_sat < num_saw ? num_sat : num_saw;
-       if (num_subauth) {
-               for (i = 0; i < num_subauth; ++i) {
-                       if (ctsid->sub_auth[i] != cwsid->sub_auth[i]) {
-                               if (le32_to_cpu(ctsid->sub_auth[i]) >
-                                       le32_to_cpu(cwsid->sub_auth[i]))
-                                       return 1;
-                               else
-                                       return -1;
-                       }
-               }
-       }
-
-       return 0; /* sids compare/match */
-}
-
-
 /* copy ntsd, owner sid, and group sid from a security descriptor to another */
 static void copy_sec_desc(const struct cifs_ntsd *pntsd,
                                struct cifs_ntsd *pnntsd, __u32 sidsoffset)
 {
-       int i;
-
        struct cifs_sid *owner_sid_ptr, *group_sid_ptr;
        struct cifs_sid *nowner_sid_ptr, *ngroup_sid_ptr;
 
@@ -692,26 +705,14 @@ static void copy_sec_desc(const struct cifs_ntsd *pntsd,
        owner_sid_ptr = (struct cifs_sid *)((char *)pntsd +
                                le32_to_cpu(pntsd->osidoffset));
        nowner_sid_ptr = (struct cifs_sid *)((char *)pnntsd + sidsoffset);
-
-       nowner_sid_ptr->revision = owner_sid_ptr->revision;
-       nowner_sid_ptr->num_subauth = owner_sid_ptr->num_subauth;
-       for (i = 0; i < 6; i++)
-               nowner_sid_ptr->authority[i] = owner_sid_ptr->authority[i];
-       for (i = 0; i < 5; i++)
-               nowner_sid_ptr->sub_auth[i] = owner_sid_ptr->sub_auth[i];
+       cifs_copy_sid(nowner_sid_ptr, owner_sid_ptr);
 
        /* copy group sid */
        group_sid_ptr = (struct cifs_sid *)((char *)pntsd +
                                le32_to_cpu(pntsd->gsidoffset));
        ngroup_sid_ptr = (struct cifs_sid *)((char *)pnntsd + sidsoffset +
                                        sizeof(struct cifs_sid));
-
-       ngroup_sid_ptr->revision = group_sid_ptr->revision;
-       ngroup_sid_ptr->num_subauth = group_sid_ptr->num_subauth;
-       for (i = 0; i < 6; i++)
-               ngroup_sid_ptr->authority[i] = group_sid_ptr->authority[i];
-       for (i = 0; i < 5; i++)
-               ngroup_sid_ptr->sub_auth[i] = group_sid_ptr->sub_auth[i];
+       cifs_copy_sid(ngroup_sid_ptr, group_sid_ptr);
 
        return;
 }
@@ -818,7 +819,7 @@ static __u16 fill_ace_for_sid(struct cifs_ace *pntace,
 
        pntace->sid.revision = psid->revision;
        pntace->sid.num_subauth = psid->num_subauth;
-       for (i = 0; i < 6; i++)
+       for (i = 0; i < NUM_AUTHS; i++)
                pntace->sid.authority[i] = psid->authority[i];
        for (i = 0; i < psid->num_subauth; i++)
                pntace->sid.sub_auth[i] = psid->sub_auth[i];
@@ -994,8 +995,8 @@ static int parse_sid(struct cifs_sid *psid, char *end_of_acl)
                return -EINVAL;
        }
 
-       if (psid->num_subauth) {
 #ifdef CONFIG_CIFS_DEBUG2
+       if (psid->num_subauth) {
                int i;
                cFYI(1, "SID revision %d num_auth %d",
                        psid->revision, psid->num_subauth);
@@ -1009,8 +1010,8 @@ static int parse_sid(struct cifs_sid *psid, char *end_of_acl)
                        num auths and therefore go off the end */
                cFYI(1, "RID 0x%x",
                        le32_to_cpu(psid->sub_auth[psid->num_subauth-1]));
-#endif
        }
+#endif
 
        return 0;
 }
@@ -1120,8 +1121,7 @@ static int build_sec_desc(struct cifs_ntsd *pntsd, struct cifs_ntsd *pnntsd,
                                kfree(nowner_sid_ptr);
                                return rc;
                        }
-                       memcpy(owner_sid_ptr, nowner_sid_ptr,
-                                       sizeof(struct cifs_sid));
+                       cifs_copy_sid(owner_sid_ptr, nowner_sid_ptr);
                        kfree(nowner_sid_ptr);
                        *aclflag = CIFS_ACL_OWNER;
                }
@@ -1139,8 +1139,7 @@ static int build_sec_desc(struct cifs_ntsd *pntsd, struct cifs_ntsd *pnntsd,
                                kfree(ngroup_sid_ptr);
                                return rc;
                        }
-                       memcpy(group_sid_ptr, ngroup_sid_ptr,
-                                       sizeof(struct cifs_sid));
+                       cifs_copy_sid(group_sid_ptr, ngroup_sid_ptr);
                        kfree(ngroup_sid_ptr);
                        *aclflag = CIFS_ACL_GROUP;
                }
@@ -1316,42 +1315,39 @@ id_mode_to_cifs_acl(struct inode *inode, const char *path, __u64 nmode,
 
        /* Get the security descriptor */
        pntsd = get_cifs_acl(CIFS_SB(inode->i_sb), inode, path, &secdesclen);
-
-       /* Add three ACEs for owner, group, everyone getting rid of
-          other ACEs as chmod disables ACEs and set the security descriptor */
-
        if (IS_ERR(pntsd)) {
                rc = PTR_ERR(pntsd);
                cERROR(1, "%s: error %d getting sec desc", __func__, rc);
-       } else {
-               /* allocate memory for the smb header,
-                  set security descriptor request security descriptor
-                  parameters, and secuirty descriptor itself */
-
-               secdesclen = secdesclen < DEFSECDESCLEN ?
-                                       DEFSECDESCLEN : secdesclen;
-               pnntsd = kmalloc(secdesclen, GFP_KERNEL);
-               if (!pnntsd) {
-                       cERROR(1, "Unable to allocate security descriptor");
-                       kfree(pntsd);
-                       return -ENOMEM;
-               }
+               goto out;
+       }
 
-               rc = build_sec_desc(pntsd, pnntsd, secdesclen, nmode, uid, gid,
-                                       &aclflag);
+       /*
+        * Add three ACEs for owner, group, everyone getting rid of other ACEs
+        * as chmod disables ACEs and set the security descriptor. Allocate
+        * memory for the smb header, set security descriptor request security
+        * descriptor parameters, and secuirty descriptor itself
+        */
+       secdesclen = max_t(u32, secdesclen, DEFSECDESCLEN);
+       pnntsd = kmalloc(secdesclen, GFP_KERNEL);
+       if (!pnntsd) {
+               cERROR(1, "Unable to allocate security descriptor");
+               kfree(pntsd);
+               return -ENOMEM;
+       }
 
-               cFYI(DBG2, "build_sec_desc rc: %d", rc);
+       rc = build_sec_desc(pntsd, pnntsd, secdesclen, nmode, uid, gid,
+                               &aclflag);
 
-               if (!rc) {
-                       /* Set the security descriptor */
-                       rc = set_cifs_acl(pnntsd, secdesclen, inode,
-                                               path, aclflag);
-                       cFYI(DBG2, "set_cifs_acl rc: %d", rc);
-               }
+       cFYI(DBG2, "build_sec_desc rc: %d", rc);
 
-               kfree(pnntsd);
-               kfree(pntsd);
+       if (!rc) {
+               /* Set the security descriptor */
+               rc = set_cifs_acl(pnntsd, secdesclen, inode, path, aclflag);
+               cFYI(DBG2, "set_cifs_acl rc: %d", rc);
        }
 
+       kfree(pnntsd);
+       kfree(pntsd);
+out:
        return rc;
 }