xorl %eax, %eax

FreeBSD vfs_mountroot_try() Heap off-by-one Overwrite

leave a comment »

On 27 December 2009, Jakub Klama made a bug report on freebsd-bugs mailing list. The issue affects FreeBSD 7.0-RELEASE-p5 and probably other versions too and it is located at kern/vfs_mount.c file and specifically, in the following code.

/*
 * Mount (mountfrom) as the root filesystem.
 */
static int
vfs_mountroot_try(const char *mountfrom)
{
        struct mount    *mp;
        char            *vfsname, *path;
        time_t          timebase;
        int             error;
        char            patt[32];
     ...
        /* parse vfs name and path */
        vfsname = malloc(MFSNAMELEN, M_MOUNT, M_WAITOK);
        path = malloc(MNAMELEN, M_MOUNT, M_WAITOK);
        vfsname[0] = path[0] = 0;
        sprintf(patt, "%%%d[a-z0-9]:%%%ds", MFSNAMELEN, MNAMELEN);
        if (sscanf(mountfrom, patt, vfsname, path) < 1)
                goto out;
 
        if (path[0] == '\0')
                strcpy(path, ROOTNAME);
     ...
out:
        free(path, M_MOUNT);
        free(vfsname, M_MOUNT);
        return (error);
}

So, this code uses malloc() to allocate ‘MFSNAMELEN’ bytes which is 16 as we can read at sys/mount.h header file:

/*
 * filesystem statistics
 */
#define MFSNAMELEN      16              /* length of type name including null */
#define MNAMELEN        88              /* size of on/from name bufs */
#define STATFS_VERSION  0x20030518      /* current version number */

And then 88 more (you can see the definition of ‘MNAMELEN’ above), then it creates the appropriate format string and stores it in ‘patt’ using sprintf() and at last, it copies the ‘mountfrom’ string using the previously constructed format string in order to retrieve the VFS name (represented by ‘vfsname’ string) and the equivalent path (which is stored in ‘path’ string). Now, if you read the format string that is being used you can easily see that it leaves no space for string’s NULL termination since it’s using the maximum available values for both the VFS name and the path.
As J. Klama said, to reproduce this you can do the following (in his own words):

Enter any string longer than 16 characters without ":" in 
it with WITNESS kernel option enabled in mountroot prompt.

He later corrected this by saying:

sorry for mentioning WITNESS, i was of course thinking of DEBUG_MEMGUARD.

However, since this routine is used to mount the root filesystem I don’t know if it’s a security related bug, for example this is called numerous times from vfs_mountroot() and vfs_mountroot_ask() as seen in kern/vfs_mount.c but I personally didn’t find a code path from which I could consider this a vulnerability. In any case, it’s an interesting bug and who knows… there might be a way to exploit it…

Written by xorl

January 2, 2010 at 06:42

Posted in bugs, freebsd

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