xfs: Validate the length of on-disk ACLs
authorAndreas Gruenbacher <agruenba@redhat.com>
Tue, 3 Nov 2015 01:41:59 +0000 (12:41 +1100)
committerDave Chinner <david@fromorbit.com>
Tue, 3 Nov 2015 01:41:59 +0000 (12:41 +1100)
In xfs_acl_from_disk, instead of trusting that xfs_acl.acl_cnt is correct,
make sure that the length of the attributes is correct as well.  Also, turn
the aclp parameter into a const pointer.

Signed-off-by: Andreas Gruenbacher <agruenba@redhat.com>
Reviewed-by: Dave Chinner <dchinner@redhat.com>
Signed-off-by: Dave Chinner <david@fromorbit.com>
fs/xfs/libxfs/xfs_format.h
fs/xfs/xfs_acl.c

index 9590a06..0e62682 100644 (file)
@@ -1487,9 +1487,13 @@ struct xfs_acl {
                                                sizeof(struct xfs_acl_entry) \
                : 25)
 
-#define XFS_ACL_MAX_SIZE(mp) \
+#define XFS_ACL_SIZE(cnt) \
        (sizeof(struct xfs_acl) + \
-               sizeof(struct xfs_acl_entry) * XFS_ACL_MAX_ENTRIES((mp)))
+               sizeof(struct xfs_acl_entry) * cnt)
+
+#define XFS_ACL_MAX_SIZE(mp) \
+       XFS_ACL_SIZE(XFS_ACL_MAX_ENTRIES((mp)))
+
 
 /* On-disk XFS extended attribute names */
 #define SGI_ACL_FILE           "SGI_ACL_FILE"
index 4b64167..763e365 100644 (file)
 
 STATIC struct posix_acl *
 xfs_acl_from_disk(
-       struct xfs_acl  *aclp,
-       int             max_entries)
+       const struct xfs_acl    *aclp,
+       int                     len,
+       int                     max_entries)
 {
        struct posix_acl_entry *acl_e;
        struct posix_acl *acl;
-       struct xfs_acl_entry *ace;
+       const struct xfs_acl_entry *ace;
        unsigned int count, i;
 
+       if (len < sizeof(*aclp))
+               return ERR_PTR(-EFSCORRUPTED);
        count = be32_to_cpu(aclp->acl_cnt);
-       if (count > max_entries)
+       if (count > max_entries || XFS_ACL_SIZE(count) != len)
                return ERR_PTR(-EFSCORRUPTED);
 
        acl = posix_acl_alloc(count, GFP_KERNEL);
@@ -163,7 +166,7 @@ xfs_get_acl(struct inode *inode, int type)
                goto out;
        }
 
-       acl = xfs_acl_from_disk(xfs_acl, XFS_ACL_MAX_ENTRIES(ip->i_mount));
+       acl = xfs_acl_from_disk(xfs_acl, len, XFS_ACL_MAX_ENTRIES(ip->i_mount));
        if (IS_ERR(acl))
                goto out;