security review and patches for libpurple
Chris Palmer
chris at eff.org
Tue Jul 19 00:26:20 EDT 2011
Regarding strlcpy, sizeof, malloc, et c. There are a few issues, and techniques we can use for increased love and happiness.
1. C99 (and C++) allows us to declare dynamically-sized arrays on the stack. This allows us to use sizeof (since it's a Foo [] and not a Foo *) and allows us to not have to manually free(3). Of course, we can't return this value; it's only for temporary storage.
boolean are_things_awesome(..., size_t thing_count) {
Thing things[thing_count];
// Blah...
// Make use of sizeof(things) if necessary
// No need to free(things)
return ...;
}
A caveat is that I don't know how this dynamic stack allocation interacts with stack smashing protection; that's worth looking into. Also, you may or may not be limited by the stack size limit (some implementations may revert to heap allocation in case of stack size overflow and then handle the freeing implicitly — I saw alloca(3) do this at least once).
A good implementation checks for integer overflow. Don't know if any actually do...
2. With malloc(3) and realloc(3), integer overflow is a big problem (e.g. foo = malloc(sizeof(Foo) * count)). For this reason, I prefer to use calloc(3), whose interface allows the implementation to check for overflow (and any good implementation does do the check, and many do). If you are worried about the overhead of calloc's zero-it-out behavior, (a) profile; (b) some implementations back all heap allocation from /dev/zero anyway; and (c) you can write a new two-argument wrapper that does the integer overflow check and then passes the product to malloc if profiling really shows a problem.
3. FreeBSD 7.0+ provides malloc_usable_size(const void *):
The malloc_usable_size() function returns the usable size of the alloca-
tion pointed to by ptr. The return value may be larger than the size
that was requested during allocation. The malloc_usable_size() function
is not a mechanism for in-place realloc(); rather it is provided solely
as a tool for introspection purposes. Any discrepancy between the
requested allocation size and the size reported by malloc_usable_size()
should not be depended on, since such behavior is entirely implementa-
tion-dependent.
I wonder if there is an equivalent function for other libc implementations, and if we could thereby create a wrapper to give us "sizeof for heap allocations". I think most implementations require this for their own purposes anyway, so I bet some equivalent is generally available. GNU libc has mallopt(3) and malloc_usable_size. Maybe Windows and the other BSDs and... have similar interfaces.
Obviously, it is guaranteed to work to have the caller keep track of the allocation size, especially if the caller can easily check integer overflow. But I have this urge to push the boundaries of C's primitivism...
--
Chris Palmer
Technology Director, Electronic Frontier Foundation
https://www.eff.org/code
More information about the security
mailing list