OSDN Git Service

xfs: don't overflow xattr listent buffer
authorDarrick J. Wong <darrick.wong@oracle.com>
Wed, 13 Feb 2019 19:15:17 +0000 (11:15 -0800)
committerDarrick J. Wong <darrick.wong@oracle.com>
Thu, 14 Feb 2019 17:36:52 +0000 (09:36 -0800)
For VFS listxattr calls, xfs_xattr_put_listent calls
__xfs_xattr_put_listent twice if it sees an attribute
"trusted.SGI_ACL_FILE": once for that name, and again for
"system.posix_acl_access".  Unfortunately, if we happen to run out of
buffer space while emitting the first name, we set count to -1 (so that
we can feed ERANGE to the caller).  The second invocation doesn't check that
the context parameters make sense and overwrites the byte before the
buffer, triggering a KASAN report:

==================================================================
BUG: KASAN: slab-out-of-bounds in strncpy+0xb3/0xd0
Write of size 1 at addr ffff88807fbd317f by task syz/1113

CPU: 3 PID: 1113 Comm: syz Not tainted 5.0.0-rc6-xfsx #rc6
Hardware name: QEMU Standard PC (Q35 + ICH9, 2009), BIOS 1.10.2-1ubuntu1 04/01/2014
Call Trace:
 dump_stack+0xcc/0x180
 print_address_description+0x6c/0x23c
 kasan_report.cold.3+0x1c/0x35
 strncpy+0xb3/0xd0
 __xfs_xattr_put_listent+0x1a9/0x2c0 [xfs]
 xfs_attr_list_int_ilocked+0x11af/0x1800 [xfs]
 xfs_attr_list_int+0x20c/0x2e0 [xfs]
 xfs_vn_listxattr+0x225/0x320 [xfs]
 listxattr+0x11f/0x1b0
 path_listxattr+0xbd/0x130
 do_syscall_64+0x139/0x560

While we're at it we add an assert to the other put_listent to avoid
this sort of thing ever happening to the attrlist_by_handle code.

Signed-off-by: Darrick J. Wong <darrick.wong@oracle.com>
Reviewed-by: Christoph Hellwig <hch@lst.de>
fs/xfs/xfs_attr_list.c
fs/xfs/xfs_xattr.c

index a580340..3d213a7 100644 (file)
@@ -555,6 +555,7 @@ xfs_attr_put_listent(
        attrlist_ent_t *aep;
        int arraytop;
 
+       ASSERT(!context->seen_enough);
        ASSERT(!(context->flags & ATTR_KERNOVAL));
        ASSERT(context->count >= 0);
        ASSERT(context->count < (ATTR_MAX_VALUELEN/8));
index 63ee1d5..9a63016 100644 (file)
@@ -129,6 +129,9 @@ __xfs_xattr_put_listent(
        char *offset;
        int arraytop;
 
+       if (context->count < 0 || context->seen_enough)
+               return;
+
        if (!context->alist)
                goto compute_size;