xorl %eax, %eax

FreeBSD fmtmsg(3) Typo

with one comment

This is a funny bug reported by soulcatcher to the FreeBSD project. The vulnerable code resides in gen/fmtmsg.c and specifically in printfmt() routine as you can see below.

 * Returns NULL on memory allocation failure, otherwise returns a pointer to
 * a newly malloc()'d output buffer.
static char *
printfmt(char *msgverb, long class, const char *label, int sev,
    const char *text, const char *act, const char *tag)
        size_t size;
        char *comp, *output;
        const char *sevname;
        size = 32;
        if (text != MM_NULLTXT)
                size += strlen(text);
        if (text != MM_NULLACT)
                size += strlen(act);
        if ((output = malloc(size)) == NULL)
        return (output);

This could be reached directly using fmtmsg(3).
The problem here is in the ‘MM_NULLACT’ case (which checks if ‘act’ is set to “NULL” or not), which is incorrectly using ‘text’ argument even though it updates the size variable using ‘act’. The advisory included a small PoC trigger C code which you can see here.

#include <fmtmsg.h>

int main(int argc, char * argv[])
fmtmsg(MM_UTIL | MM_PRINT, "BSD:ls", MM_ERROR,
"illegal option -- z", MM_NULLACT, "BSD:ls:001");
return 0;

It is quite simple, it has a ‘text’ argument set to “illegal option — z” and ‘act’ set to MM_NULLACT. This will attempt to add the length of that ‘MM_NULLACT’ to the ‘size’ and eventually, result in a segmentation fault.
The fix was, as you might have guessed…

         if (text != MM_NULLTXT)
                 size += strlen(text);
-        if (text != MM_NULLACT)
+        if (act != MM_NULLACT)
                 size += strlen(act);

It just checks the correct argument before updating the size that will be later allocated.

Written by xorl

November 12, 2009 at 23:09

One Response

Subscribe to comments with RSS.

  1. haha, this is a great bug. Good find.


    November 12, 2009 at 23:54

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 )

Google+ photo

You are commenting using your Google+ 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 )


Connecting to %s