So my daily travels around the intertubes landed me on a very interesting blog post by Microsoft’s Security Development Lifecycle team (which they call SDL, not to be confused with the arguably more useful Simple DirectMedia Layer library). The post centered around them adding memcpy() to the banned functions list in favor of their more “secure” variant, memcpy_s(), which takes and checks the size of the destination buffer.
Before I explain why I think this is another example of Microsoft spending their time doing something incredibly useless instead of innovating, let me explain that all these blasted _s functions are one of the reasons I detest the Windows API so much.
I had the unfortunate “pleasure” of digging rather deep into the Windows API for a project I was working on this past spring quarter. For those of you who haven’t ventured into the Windows API, let me say this: It’s so incredibly confusing that it doesn’t even look like C anymore.
Almost everything uses custom types, even when there’s no logical reason to do so. The Linux API does this to some extent, but not nearly as bad as Microsoft.
Secondly, there seems to be no rhyme or reason as to what these types are named. Some are named as ALL_CAPITALS_TYPE, others _use_this_strange_underscore_prefix, and some use the standard type_t. If you start to use almost any standard library C function, you’ll inevitably be told by the compiler that you’re doing it wrong, and should use strcpy_s(), or _strcpy_s(), or _s_t_r_c_p_y_s_(). Seriously, their API has got more underscores than Bill Gates has dollar bills.
What this gives you is this strange, alien language that vaguely resembles C, but is so ugly and hideous that you’re afraid to touch it. Apple has Objective-C. Microsoft has Franken-C.
So let me back up and explain this blog post I mentioned earlier. I’m a bit behind on this one (I’ll admit I’m not often found venturing into the MSDN blogs) but back in May the SDL announced that they were adding memcpy() to their banned functions list, to join strcpy(), strcat(), strncpy(), strncat(), gets(), and others.
They announced it’s replacement, memcpy_s() (soon to be replaced by _memcpy_s() and _m_e_m_c_p_y_s_() I’m sure), which takes one additional argument: the size of the destination buffer.
This is aimed make usages of memcpy() more secure, by only copying up to the size of the destination buffer bytes, even if that’s less than the length of the bytes you want to copy. You go from using this:
memcpy(dst, src, len);
to using this:
memcpy_s(dst, sizeof(dst), src, len);
This sounds reasonable, except most Windows programmers will just do this:
memcpy_s(dst, len, src, len);
which makes your “secure” version useless.
The problem here is not that memcpy() doesn’t check the size of the destination buffer, but rather that some programmers are using it without thinking. A 50 caliber sniper rifle is a very powerful tool in the hands of a marksman, but in a cage full of chimpanzees, the results could be disastrous.
If nothing else,
memcpy_s()makes you think about the size of the target buffer.
I suppose, unless you’re one of the mindless programmers using memcpy() unsafely before, in which case you’ll learn the new and improved mindless version memcpy_s(dst, len, src, len) and continue on your merry way.
My point here is that banning functions that are the common source of security vulnerabilities doesn’t fix the problem, because the problem isn’t with the functions. These functions are well documented and we know exactly how they work and what their dangers are. The problem is with the programmers.
You’ve got to teach your programmers how to use these functions securely, or at least evaluate when they should ask for someone to review their code. If training isn’t an option, there’s a better option than banning these functions.
Ban programmers who use them wrong. Yes, banish them to the land of C# and other fluffy dynamic languages with garbage collectors and infinite buffers. They’ll do far less harm there.
The key to doing memory management correctly (which includes using memcpy(), strcpy(), etc. in safe ways) is to completely engage your brain when you’re doing it. You cannot zone out when writing memory managing code. Although given the quality of code coming out of Redmond, I would not be surprised if most of the programmers have their brains permanently switched off.
As classic-Microsoft as this blog post was, the best line was last one.
I wonder when Larry, Steve and Linus will start banning
strcpy()in their products?
Words cannot express the hilarity that ensued when I read this line. Maybe, just maybe, the reason they haven’t found the need to ban them is because they’re using them correctly. Perhaps if Microsoft tried that every once in a while, they would churn out more secure products themselves without having to resort to Franken-C.
Excellent words. I’m slow to this memcpy() ban debate, but I agree with you 100%.
-kto
It’s great to read something that’s both enjoyable and prioveds pragmatisdc solutions.
Pingback: Microsoft banned function list | >kloctalk
> My point here is that banning functions that are the common source of security vulnerabilities doesn’t fix the problem, because the problem isn’t with the functions
You’re simplifying your point too much, and thus making it wrong. memcpy() can indeed be used safely (make sure len is smaller than the destination buffer!), so memcpy_s() is mostly redundant. However, something like gets() is just broken and *cannot* be used properly and therefore should be deprecated. strcpy() falls somewhere in the middle.
I wonder if it says something about MS’s corporate culture, particularly putting process over people.
Um, actually strcpy and strcat have been largely replaced by strlcpy and strlcat or equivalents both in all major BSDs and the Linux kernel. Pretty much the only person who thinks strlcpy and strlcat are a bad idea is Ulrich Drepper.
#define memcpy(dst, src, len) memcpy_s(dst, len, src, len)
Even if 5% of programmers that wrote software on windows saw the banned APIs and fixed their code it would be better than 0. I guess your solution is – hire better programmers. Yeah.. um.. thanks for that insight.
Microsoft: “Hello I’m from Microsoft and um we’d like you to replace this amateur programmer Ted from your company for messing up parameters to memcpy.”
Software Vendors: “Fuck off”
I agree, it is pretty useless, but the worst would be that Microsoft forced to used them
@Joe
Seems like ‘len’ could still be too large. Wouldn’t
#define memcpy(dst,src,len) memcpy_s(dst, sizeof(dst), src, len);
be better? Or even something like
#define MEMCPY_ERR do_something_like_compile_error_or_fail_loudly
#define memcpy(dst, src, len) (sizeof( dst )>len ? memcpy(dst, src, len) : MEMCPY_ERR)
Maybe that doesn’t make sense; I’m not a programmer, so…