Recently gcc (4.5) improved its ability to see the size of various structures. As a result, the FORTIFY protections have suddenly gotten a bit stricter. In the past, you used to be able to do things like this:
struct thingy { int magic; char data[4]; } void work(char *input) { char buffer[1000]; int length; struct thingy *header; header = (struct thingy *)buffer; length = strlen(input); if (length > sizeof(buffer) - sizeof(*header) - 1) abort(); strcpy(header->data, input); header->magic = 42; do_something_fun(header); }
The problem here is that gcc thinks that header->data
is only 4 bytes long. But gcc doesn’t know we intentionally overruled this (and even did length checking), so due to -D_FORTIFY_SOURCE=2
, the strcpy()
checks kick in when input
is more than 4 bytes.
The fix, in this case, is to use memcpy()
instead, since we actually know how long our destination is, we can replace the strcpy(...)
line with:
memcpy(header->data, input, length + 1); /* take 0-term too */
This kind of header and then data stuff is common for protocol handlers. So far, things like Wine, TFTP, and others have been experiencing problems with the change. Please keep an eye out for it when doing testing.
© 2010, Kees Cook. This work is licensed under a Creative Commons Attribution-ShareAlike 4.0 License.