Linux: what prevents us from reading the memory from code segment?

Viewed 270

I wrote a simple code trying to find out if we can read and print the memory in code segment:

#include <stdio.h>

void main() {
  int *code_ptr = 0x4;
  printf("code_ptr = %x\n", code_ptr);
  printf("*code_ptr = %x\n", *code_ptr);
}

My system is x86_64 + Ubuntu 19.04 (Disco Dingo). And the program failed with the following output:

code_ptr = 4
Segmentation fault (core dumped)

IIUC, in Linux, the code segment and data segment share the same base address. And if that's true, this program will read the memory in code segement, and I was expecting that there won't be any crash since 0x04 should be in the range of data segment (which starts at the beginning). And this should pass the paging check since the mapped memory for the code segment is read-only and we only read the memory here.

So did I miss anything or is there any other mechanisms that prevent us from reading from this %ds:0x4?

1 Answers

I think your key misunderstanding is that you're assuming the 8086 hardware feature called "the data segment" is the same as the executable image subdivision also called "the data segment." Xenix may have used that hardware feature that way, but no modern x86 Unix does. On a modern Unix, %ds:0 always points to linear address zero, not to the beginning of the executable's data segment. (And similarly %cs:0 points to linear address zero, not to the executable's text segment.)

All of an executable's segments will be loaded into linear address space somewhere well above linear address 0, and on current-generation OSes the load addresses will be randomized on each run.

There's no standard way to get a pointer to the beginning of the executable's code or data segment. On GNU systems you can use dl_iterate_phdr, and other OSes may have similar functionality under a different name.

Related