xorl %eax, %eax

CVE-2010-3078: Linux kernel XFS IOCTL 12-Bytes Information Leak

leave a comment »

This vulnerability was reported and fixed by Dan Rosenberg as we can read in this email to xfs-masters mailing list. Specifically, here is the buggy code as seen at fs/xfs/linux-2.6/xfs_ioctl.c of 2.6.35 release of the Linux kernel…

        xfs_inode_t             *ip,
        int                     attr,
        void                    __user *arg)
        struct fsxattr          fa;
        fa.fsx_xflags = xfs_ip2xflags(ip);
        fa.fsx_extsize = ip->i_d.di_extsize << ip->i_mount->m_sb.sb_blocklog;
        fa.fsx_projid = ip->i_d.di_projid;
                        fa.fsx_nextents = ip->i_d.di_nextents;

        if (copy_to_user(arg, &fa, sizeof(fa)))
                return -EFAULT;
        return 0;

For convenience, here is the ‘fsxattr’ structure as it is defined in fs/xfs/xfs_fs.h:

struct fsxattr {
        __u32           fsx_xflags;     /* xflags field value (get/set) */
        __u32           fsx_extsize;    /* extsize field value (get/set)*/
        __u32           fsx_nextents;   /* nextents field value (get)   */
        __u32           fsx_projid;     /* project identifier (get/set) */
        unsigned char   fsx_pad[12];

Back to xfs_ioc_fsgetxattr() we can see that all of the members are initialized properly apart from the padding of the structure which is an array of 12 Bytes named ‘fsx_pad’. Since xfs_ioc_fsgetxattr() is using its stack to store the ‘fsxattr’ structure, the memory will be uninitialized and thus the subsequent copy to userspace using copy_to_user() will result in leaking 12-Bytes of unitialized memory to userspace.
To make things even better, this code could be easily reached through an IOCTL call as you can read at fs/xfs/linux-2.6/xfs_ioctl.c:

        struct file             *filp,
        unsigned int            cmd,
        unsigned long           p)
        struct inode            *inode = filp->f_path.dentry->d_inode;
        struct xfs_inode        *ip = XFS_I(inode);
        struct xfs_mount        *mp = ip->i_mount;
        void                    __user *arg = (void __user *)p;
        int                     ioflags = 0;
        int                     error;
        switch (cmd) {
                return xfs_ioc_fsgetxattr(ip, 1, arg);

Clearly, to fix this vulnerability the patch was to simply zero out the structure before using it using memset() like this:

        struct fsxattr          fa;

+       memset(&fa, 0, sizeof(struct fsxattr));
        xfs_ilock(ip, XFS_ILOCK_SHARED);

Written by xorl

September 13, 2010 at 23:14

Posted in linux, vulnerabilities

Leave a Reply

Fill in your details below or click an icon to log in:

WordPress.com Logo

You are commenting using your WordPress.com account. Log Out / Change )

Twitter picture

You are commenting using your Twitter account. Log Out / Change )

Facebook photo

You are commenting using your Facebook account. Log Out / Change )

Google+ photo

You are commenting using your Google+ account. Log Out / Change )

Connecting to %s