0

(Tested on Linux 64 bits)

If you watch the content of /proc/<pid>/maps (being the process identifier of any process running in that moment in your system) you will see that the virtual space assigned to the process is between 555xxxxxxxxx and 7FFxxxxxxxxx, instead of being between 000000000000 and FFFFFFFFF000. Why is this?

I have understood that the virtual space for a process is 48 bits in a 64-bit system (read in the book Computer Architecture: A quantitative aproach. By Hennessy and Patterson. Page 118), but if it's using only the space between 55Fxxxxxxxxx and 7FFxxxxxxxxx it means that is only using, more or less, 45 bits. Why is user space smaller than what I thought?

phuclv
  • 37,963
  • 15
  • 156
  • 475
isma
  • 143
  • 1
  • 6
  • 1
    Note that `0xFFFFFFFFFFFF` is not a canonical address for a 48-bit system, so it can't be used at all. The upper variable bit must be "sign"-extended into all the higher bits. Besides, most of these "negative" addresses are used by the kernel space (except the `[vsyscall]` trampoline commonly located at `0xffffffffff600000`). Also, it's easy to create an ELF file that would be loaded at e.g. `0x1000` instead of the usual `0x555555554000`. – Ruslan Jul 05 '20 at 11:42
  • See also: [How is the address of the text section of a PIE executable determined in Linux?](https://stackoverflow.com/q/51343596/673852) – Ruslan Jul 05 '20 at 11:47
  • @Ruslan Let's see if I understand: "By default" the virtual addresses of a process go from 0x555555554000 to 0x7FFFFFFFF000. Because the virtual space of the process with the higher weight bit setted to '1' (that is, from 0x800..00) is reserved to the system. But it would be possible to modify this so that the virtual addresses of the process belonging to the user were from 0x00..01000 (for example) to 0x7FF..F000. Right? And one little question: why modify it so that the first address is 0x1000 instead of 0x0? Is it the 0x0 virtual page address a reserved one? – isma Jul 05 '20 at 12:21
  • The 0th page is reserved for detection of null pointer dereference. Attempt to put the load address there will lead to `SIGSEGV` on `execve()`. The fact that the binary is loaded at `0x555555554000` doesn't make the lower addresses invalid. They can still get e.g. `mmap`ped and accessed after that. I'm not sure how this "default" address is chosen. Also I suspect it's only such for PIE binaries. Since I don't know the complete answer, I only comment here. – Ruslan Jul 05 '20 at 12:33
  • @Ruslan And the afirmation that I wrote since the begining of my previous comment to the word "Right?" is correct? If it is, you have helped me a lot understanding this. Thanks in advance. – isma Jul 05 '20 at 12:40
  • No, that's not right. The range doesn't belong to the user. Only the addresses that were actively allocated do. In particular, attempt to access most of the addresses between the end of the binary and the stack, as well as below the binary, will result in `SIGSEGV` (unless another binary happens to be mapped there — like a shared library). – Ruslan Jul 05 '20 at 12:48
  • @Ruslan Sorry! I expressed myself wrong!! what I meant is that those addresses up to 0x7FFFFFFFF000 **MAY belong to the user**, but the virtual page addresses of the process from 0x800000000000 **CANNOT belong** to the user, only to the system. Is this already correct? – isma Jul 05 '20 at 12:52
  • Almost correct. Just not that there's no such address as `0x800000000000` on a 48-bit system (it's not a canonical address). The lowest valid of such addresses is `0xffff800000000000`. – Ruslan Jul 05 '20 at 13:04
  • But 0xFFFF80..0 is a 64 bits address, not a 48-bit one. And in 64 bits system the virtual address space is made up of 48 bits, doesn't it? – isma Jul 05 '20 at 13:06
  • 1
    See "[x86-64 canonical address?](https://stackoverflow.com/q/25852367/673852)" – Ruslan Jul 05 '20 at 13:07

0 Answers0