FreeBSD fmtmsg(3) Typo
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.

haha, this is a great bug. Good find.
anon
November 12, 2009 at 23:54