If this is your first visit, be sure to
check out the FAQ by clicking the
link above. You may have to register
before you can post: click the register link above to proceed. To start viewing messages,
select the forum that you want to visit from the selection below.
Announcement
Collapse
No announcement yet.
Systemd 241 Being Prepared With "System Down" Security Fixes
As Guest already pointed out, there's no way to store that information in a C array, without completely breaking compatibility with almost all existing C code. We could imagine to invent a optional compiler switch that automatically adds code to:
store the array size somewhere else, maybe a portion of the heap memory, but not into the array itself, when the array is created or the pointer is referenced. That alone would hit performance to a level that would render C useless.
enable automatic checks on every array access (square brackets) and pointer dereference, by looking up bounds stored in point 1. That would render any C code execution slower than ancient Scheme on a 80286 machine.
garbage collect all the sheer amount of array and pointer sizes information stored in 1.
If you really want that all, then I have good news for you: that compiler switch already exists. You can switch to javac...
Technically you can easily store it before the array, unless it's part of a struct whose layout must be exact. In this case probably needs a new syntax to declare such arrays, just to avoid this ambiguity.
The main reason why C does allow out of bounds access is that storing the array length was horribly expensive when computers had only 1 to 32 kB of RAM. Now they have 32 GB, but C programmers will still argue that billion dollar bugs every now and then are way better than wasting 4 bytes worth of space for every array.
Yeah though afaik on amd64 it will use up 8 (not 4) bytes as noted here [1]. OTOH when I have an array in C++ I still usually store its length somewhere so it kinda evens out except that in Rust it's part of the language and enforced which is awesome.
But I'm not saying everything in Rust is good.
The main reason why C does allow out of bounds access is that storing the array length was horribly expensive when computers had only 1 to 32 kB of RAM. Now they have 32 GB, but C programmers will still argue that billion dollar bugs every now and then are way better than wasting 4 bytes worth of space for every array.
I am a hobby C programmer and I don't think you fully understand this do you? First of all 4 bytes is not by any means a suitable size to store any random array length so this is far off already (this has nothing to do with 32bits vs 64bits by the way).
Second in C code you can easily access stuff in an array without using the brackets at all - imagine a pointer to an array for example.
Third. If you check for out of bounds access every single time you access an array it will be a performance hit no matter if you are running on a gazillion terrahertz or 1Mhz. Have you ever considered how much more complex the code will get if you need to check out of bounds on every array access!? do that in assembly code first and see the difference. If you have a tight loop then using extra registers for storing array length can be a significant performance hit as you may need to push and pop on the stack to be able to do all the thing you need to do in that loop.
Hypothetically speaking, how would one store a length property in a C array anyway? An extra 4 bytes at the end for the size at the end of the bytes sequence?
Perhaps, throw the length and the array pointer into a struct, and pass the struct pointer around? Another argument they have used against bounds checking is that it takes an arithmatic operation to do, adding a little more overhead. Ignore this, better to be safe adn a little slower.
Also, avoid alloca. Send all of your variable length data to functions as an array pointer you malloc'd. The use of alloca in systemd is egregious.
Can't think of any reasons of having such anal security measures on my desktop PC. And on a sever it also doesn't make a lot of sense given that nowadays it's trendy to put each daemon into a container. In this case if an attacker gets access to a root user via journald this hardening is pretty much worthless.
Automatic bounds checks are garbage because they apply everywhere, even in places where they are not needed, which is disgusting (not just the bytes, lol, also execution, wasting an entry in the branch predictor, and cache pollution).
You don't need to perform checks every time you access the array elements. Instead, only once per operation, which means O(1) overhead per any array operation. This is already way better than the current behavior. Computing the length would be O(1) instead of O(n). A boxed representation only requires few bytes. If you care about the caches so much, use a custom allocator.
Useless bounds checks also make you more vulnerable to Spectre. The irony.
There are ways to avoid that.
Originally posted by lucrus
As hussam already pointed out, there's no way to store that information in a C array, without completely breaking compatibility with almost all existing C code.
Of course you can add a new array type with its own operations and functions. I didn't ask you to use C. Look how other languages (not C++) did it.
If you really want that all, then I have good news for you: that compiler switch already exists. You can switch to javac...
Java is one possibility. It's not dramatically slower. Enterprises use it. The runtime will be a it bloated for generating simple logs though.
Originally posted by waxhead
First of all 4 bytes is not by any means a suitable size to store any random array length so this is far off already (this has nothing to do with 32bits vs 64bits by the way).
Well obviously the size needs to be stored using size_t.
Second in C code you can easily access stuff in an array without using the brackets at all - imagine a pointer to an array for example.
You can also kill yourself in 10000 different ways. It doesn't imply you should.
If you check for out of bounds access every single time you access an array it will be a performance hit no matter if you are running on a gazillion terrahertz or 1Mhz. Have you ever considered how much more complex the code will get if you need to check out of bounds on every array access!?
Bollocks. You keep around references to a boxed representation, check once, and use optimized safe operations that validate with the size field.
Originally posted by jpg44
Another argument they have used against bounds checking is that it takes an arithmatic operation to do, adding a little more overhead. Ignore this, better to be safe adn a little slower.
Java does this and I can tell you it's not really that slow.
Yeah, nothing beats the beauty of a plain pointer that will let you read whatever memory location you can think of (and quite often locations you don't think about).
Sure my idea was bad but no, definitely not a bait. I'm actually interested on how this can be accomplished in C. I know it is easy with an Array class in object oriented languages.
@jpg44 That's a good idea. I think GLib achieves something similar with structs.
Maybe it's my own bias here, but it seems to me that people take a certain amount of delight in bugs in systemd. That seemed evident to me when I read about these vulnerabilities on Reddit.
To me it's simply a case of 'bug found in systemd...systemd devs patch it and release a new version'. This is pretty much the case with every software project ever. People talk about systemd like it's the only program to ever have an exploit found in it.
Comment