]> asedeno.scripts.mit.edu Git - linux.git/commitdiff
xfs: namecheck attribute names before listing them
authorDarrick J. Wong <darrick.wong@oracle.com>
Mon, 28 Oct 2019 23:12:33 +0000 (16:12 -0700)
committerDarrick J. Wong <darrick.wong@oracle.com>
Tue, 29 Oct 2019 16:50:11 +0000 (09:50 -0700)
Actually call namecheck on attribute names before we hand them over to
userspace.

Signed-off-by: Darrick J. Wong <darrick.wong@oracle.com>
Reviewed-by: Brian Foster <bfoster@redhat.com>
fs/xfs/libxfs/xfs_attr_leaf.h
fs/xfs/xfs_attr_list.c

index 7b74e18becff79950778a62faf0a9a31b2becdc6..bb0880057ee30d902cf9c2eaf2eaaebcf2fef7e4 100644 (file)
@@ -67,8 +67,8 @@ int   xfs_attr3_leaf_add(struct xfs_buf *leaf_buffer,
                                 struct xfs_da_args *args);
 int    xfs_attr3_leaf_remove(struct xfs_buf *leaf_buffer,
                                    struct xfs_da_args *args);
-void   xfs_attr3_leaf_list_int(struct xfs_buf *bp,
-                                     struct xfs_attr_list_context *context);
+int    xfs_attr3_leaf_list_int(struct xfs_buf *bp,
+                               struct xfs_attr_list_context *context);
 
 /*
  * Routines used for shrinking the Btree.
index 00758fdc2fecf58eac5795a781023a8837452dc5..c02f22d50e45808bc90bf847d6113bc98f132efc 100644 (file)
@@ -49,14 +49,16 @@ xfs_attr_shortform_compare(const void *a, const void *b)
  * we can begin returning them to the user.
  */
 static int
-xfs_attr_shortform_list(xfs_attr_list_context_t *context)
+xfs_attr_shortform_list(
+       struct xfs_attr_list_context    *context)
 {
-       attrlist_cursor_kern_t *cursor;
-       xfs_attr_sf_sort_t *sbuf, *sbp;
-       xfs_attr_shortform_t *sf;
-       xfs_attr_sf_entry_t *sfe;
-       xfs_inode_t *dp;
-       int sbsize, nsbuf, count, i;
+       struct attrlist_cursor_kern     *cursor;
+       struct xfs_attr_sf_sort         *sbuf, *sbp;
+       struct xfs_attr_shortform       *sf;
+       struct xfs_attr_sf_entry        *sfe;
+       struct xfs_inode                *dp;
+       int                             sbsize, nsbuf, count, i;
+       int                             error = 0;
 
        ASSERT(context != NULL);
        dp = context->dp;
@@ -84,6 +86,11 @@ xfs_attr_shortform_list(xfs_attr_list_context_t *context)
            (XFS_ISRESET_CURSOR(cursor) &&
             (dp->i_afp->if_bytes + sf->hdr.count * 16) < context->bufsize)) {
                for (i = 0, sfe = &sf->list[0]; i < sf->hdr.count; i++) {
+                       if (!xfs_attr_namecheck(sfe->nameval, sfe->namelen)) {
+                               XFS_ERROR_REPORT(__func__, XFS_ERRLEVEL_LOW,
+                                                context->dp->i_mount);
+                               return -EFSCORRUPTED;
+                       }
                        context->put_listent(context,
                                             sfe->flags,
                                             sfe->nameval,
@@ -161,10 +168,8 @@ xfs_attr_shortform_list(xfs_attr_list_context_t *context)
                        break;
                }
        }
-       if (i == nsbuf) {
-               kmem_free(sbuf);
-               return 0;
-       }
+       if (i == nsbuf)
+               goto out;
 
        /*
         * Loop putting entries into the user buffer.
@@ -174,6 +179,12 @@ xfs_attr_shortform_list(xfs_attr_list_context_t *context)
                        cursor->hashval = sbp->hash;
                        cursor->offset = 0;
                }
+               if (!xfs_attr_namecheck(sbp->name, sbp->namelen)) {
+                       XFS_ERROR_REPORT(__func__, XFS_ERRLEVEL_LOW,
+                                        context->dp->i_mount);
+                       error = -EFSCORRUPTED;
+                       goto out;
+               }
                context->put_listent(context,
                                     sbp->flags,
                                     sbp->name,
@@ -183,9 +194,9 @@ xfs_attr_shortform_list(xfs_attr_list_context_t *context)
                        break;
                cursor->offset++;
        }
-
+out:
        kmem_free(sbuf);
-       return 0;
+       return error;
 }
 
 /*
@@ -284,7 +295,7 @@ xfs_attr_node_list(
        struct xfs_buf                  *bp;
        struct xfs_inode                *dp = context->dp;
        struct xfs_mount                *mp = dp->i_mount;
-       int                             error;
+       int                             error = 0;
 
        trace_xfs_attr_node_list(context);
 
@@ -358,7 +369,9 @@ xfs_attr_node_list(
         */
        for (;;) {
                leaf = bp->b_addr;
-               xfs_attr3_leaf_list_int(bp, context);
+               error = xfs_attr3_leaf_list_int(bp, context);
+               if (error)
+                       break;
                xfs_attr3_leaf_hdr_from_disk(mp->m_attr_geo, &leafhdr, leaf);
                if (context->seen_enough || leafhdr.forw == 0)
                        break;
@@ -369,13 +382,13 @@ xfs_attr_node_list(
                        return error;
        }
        xfs_trans_brelse(context->tp, bp);
-       return 0;
+       return error;
 }
 
 /*
  * Copy out attribute list entries for attr_list(), for leaf attribute lists.
  */
-void
+int
 xfs_attr3_leaf_list_int(
        struct xfs_buf                  *bp,
        struct xfs_attr_list_context    *context)
@@ -417,7 +430,7 @@ xfs_attr3_leaf_list_int(
                }
                if (i == ichdr.count) {
                        trace_xfs_attr_list_notfound(context);
-                       return;
+                       return 0;
                }
        } else {
                entry = &entries[0];
@@ -457,6 +470,11 @@ xfs_attr3_leaf_list_int(
                        valuelen = be32_to_cpu(name_rmt->valuelen);
                }
 
+               if (!xfs_attr_namecheck(name, namelen)) {
+                       XFS_ERROR_REPORT(__func__, XFS_ERRLEVEL_LOW,
+                                        context->dp->i_mount);
+                       return -EFSCORRUPTED;
+               }
                context->put_listent(context, entry->flags,
                                              name, namelen, valuelen);
                if (context->seen_enough)
@@ -464,7 +482,7 @@ xfs_attr3_leaf_list_int(
                cursor->offset++;
        }
        trace_xfs_attr_list_leaf_end(context);
-       return;
+       return 0;
 }
 
 /*
@@ -483,9 +501,9 @@ xfs_attr_leaf_list(xfs_attr_list_context_t *context)
        if (error)
                return error;
 
-       xfs_attr3_leaf_list_int(bp, context);
+       error = xfs_attr3_leaf_list_int(bp, context);
        xfs_trans_brelse(context->tp, bp);
-       return 0;
+       return error;
 }
 
 int