I could check that, but don't you have a security team there at Red Hat whose job it is to investigate things like these? Or shouldn't the people who introduced the feature into the kernel be responsible for it working as they claim? I have no interest in installing rawhide. When it's released officially, then I'll likely upgrade to it.
You mentioned various measures, could you link me to the ones I haven't found? All I've been able to find so far is the copy_from_user changes which use __builtin_object_size (and fix up cases where gcc couldn't determine the size for copies into stack objects (where that stack object didn't exist in another file)). But there are caveats for this, some of which are mentioned and others that are not.
You can tell by the name how impressed I was with the amount of coverage.
It was so ineffective, in fact, that I haven't included it in grsecurity. I went through and analyzed the disassembly of my own code (all the code in the grsecurity directory) and some other kernel code to see how it was being protected by the extra __builtin_object_size checks for memory/string operations, as well as copy_to/from_user. What I found was that it was basically only "proving"/protecting trivial/unexploitable cases. I even added in attributes for the kernel allocators so that the size of the objects they returned could be determined (in some cases). I think the addition of those attributes added 10% coverage (from 20% initially).
I also noticed __builtin_object_size couldn't figure out the size of "blah" in the simple example below:
typedef struct {
int test;
char blah[10];
int test2;
} teststruct;
int blah(char *buf, int len)
{
teststruct wee;
memcpy(&wee.blah, buf, len);
}
Basically, any array within a structure (and there are tons of examples of this within the kernel) gcc couldn't determine the size of. Nobody apparently had investigated this the entire time __builtin_object_size had been around, or nobody cared. I reported the problem and received no credit for it (further proof for you that I don't find bugs in Linux), but the fix for it should be in some new version of gcc (I don't know if it's made it into a version anyone's using yet).
I found 2 or 3 unexploitable overflows detected at compile-time with the above patch (or perhaps only after I added some enhancements of my own that would have mimicked the gcc fix) and reported those as well (more bugs I don't report/fix).
So now here you have implemented a feature that implements "provable" security, yet what it actually protects is wildly dependent upon the version of gcc the person is using. I noticed a warning was added (by configure option) to show the cases where gcc can't figure out the size. Judging from my own experience above, this will most likely be useless given that gcc can't determine the size in 70% of the cases, and so cases that the developer could fix easily would be thrown in with 100 other cases that he/she couldn't fix easily or at all.
It's an improvement, but a very minor one. A better improvement would be to make -fstack-protector-all actually do what it claims to do.
And just as a demonstration of the limitations of __builtin_object_size, you show how it would have prevented the perf_counter exploit (which is more a statement of how utterly trivial the vulnerability was). It would indeed have prevented it (even with an older 4.X compiler I believe). However, making one small change of having perf_copy_attr() become a global function, and __builtin_object_size suddenly becomes useless. There's tons of real kernel code like that to be found.
-Brad
Kernel release status
Posted Oct 1, 2009 14:38 UTC (Thu) by spender (subscriber, #23067)
[Link]