02-11-2016, 11:55 PM
(02-10-2016, 12:21 AM)xoft Wrote: Tell me, Linux enthisiasts, how does this reflect the "Linux is safer" mantra that I hear oh so often? How could Linux be so safe if the default configuration allows programs to execute data, and thus is very prone to buffer over-/underflow attack vectors?
OK, I will answer you =) But before reading my explanation, try to answer by yourself: is there really any harm in executing read-only data?
Look at code. "main" is defined as const. That this means? Lets dig into C2011 standart, paragraph 6.7.3:
Quote:If an attempt is made to modify an object defined with a const-qualified type through use of an lvalue with non-const-qualified type, the behavior is undefined.So, basically, object with const modifier can't be directly modified through C code and that's all; anything beyond is up to compiler/OS. So, let's see how different toolchain handles this.
The implementation may place a const object that is not volatile in a read-only region of
storage. Moreover, the implementation need not allocate storage for such an object if its address is
never used.
Simple code example:
Code:
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
const char * const msg = "Hello, world!";
int main(int argc, char *argv[])
{
memset(msg, 'T',strlen(msg));
puts(msg);
return 0;
}
Windows 7 64-bit, MSVC 14.0 (from Visual Studio 13, if I remember correctly) compiles code fine, but gives a warning about mismatch of types because memset isn't expect to take const memory location. If we a trying to run code, this is what we will get:
Code:
TTTTTTTTTTTTT
Now, Linux. Kernel 4.5.0 x86-64, GCC 4.9.3. Compiler emits the same warning about const qualifier, but code compiles. Let's run it:
Code:
Segmentation fault
Now, I can answer your second question:
(02-10-2016, 12:21 AM)xoft Wrote: On Windows, the original code doesn't work simply because the "code" for main is stored within the data segment, which is non-executable by default, thus making it safe. Why doesn't this happen on Linux, too?Because on Linux .data section is modifiable. By the way, on Windows too, as you can see. Windows loads read-only data into DATA x86 segment, thus not restricting it to change. So, that is better - allow read-only data to be changed (Windows way) or to be executed (Linux-way)? I think Linux way is better, because answer to my question ("Is there any harm in executing read-only data?") is no. This data isn't going to change as program executes. It just can't. No stack or buffer overflows can do any harm to read-only segment. And there is no way in mistakingly run variable, don't you think? But this is very simple to modify read-only data by mistake. Linux will not allow you to do that. Windows will. Refer to my example with RSA key. It's bad practice, but it will work on Linux. On Windows someone can modify your key with buffer over/underflow. So, is Linux safer or not? =)