0

Hi I was reading an textbook,it says that programs are not allowed to access addresses greater than 0xc0000000 (as is the case for 32-bit versions of Linux), so below assembly code is invalid:

1. irmovl $1,%eax
2. xorl %esp,%esp // Set stack pointer to 0 and CC to 100
3. pushl %eax    // Attempt to write to 0xfffffffc, will fail

I'm confused. and I have two questions:

  1. why programs are not allowed to access addresses greater than 0xc0000000, isn't that address like 0xc0000008 a valid address?

  2. if programs are really not allowed to access addresses greater than 0xc0000000, 0xfffffffc is lower(less) than 0xc0000000, so why it will fail?

Jonathon Reinhart
  • 132,704
  • 33
  • 254
  • 328
  • 5
    There's nothing about the CPU that makes addresses greater than 0xc0000000 invalid. That is an operating system decision. – Raymond Chen Oct 11 '18 at 06:54
  • 1
    The default configuration for Linux is to put the kernel in the upper 1gb (>= 0xC0000000) of memory. This 1gb of krnel memory is mapped into the address space of all user mode programs so is by default off limits to user mode code. – Michael Petch Oct 11 '18 at 07:11
  • 1
    0xFFFFFFFC is greater than 0xC0000000. – prl Oct 11 '18 at 08:10
  • Linux doesn't run on y86, AFAIK. Are you really asking about x86 Linux? – Peter Cordes Oct 13 '18 at 03:18

1 Answers1

4
  1. why programs are not allowed to access addresses greater than 0xc0000000, isn't that address like 0xc0000008 a valid address?

Modern operating systems leverage features of the hardware to prevent running applications from interfering with each other. The primary components of this isolation are privilege separation and virtual memory.

Virtual memory (as opposed to physical memory) means that the addresses accessed by code (e.g. a mov instruction) aren't actual addresses of RAM. Instead, the memory management unit (MMU) leverages the page tables to translate virtual addresses (VA) to physical addresses (PA) before sending them out to RAM.

Privilege separation is enforced by the CPU (and MMU), and is what allows for a single operating system kernel to have total control of the hardware, while safely running multiple user applications.

Putting these two concepts together, typically the kernel runs in one region of virtual memory (inaccessible to userspace), and userspace processes run in another part.

In the x86 32-bit arch port of the Linux kernel, a 1-3 split is often used, to provide 1 GB of VA space to the kernel, leaving 3 GB of VA space for each user application. Thus:

  • 0x00000000 - 0xBFFFFFFF : Userspace
  • 0xC0000000 - 0xFFFFFFFF : Kernel
  1. if programs are really not allowed to access addresses greater than 0xc0000000, 0xfffffffc is lower(less) than 0xc0000000, so why it will fail?

There's a big difference between how data is represented (e.g. in a hardware register or in memory) and how it is interpreted (e.g. signed/unsigned integer, floating point number, text string, image, etc.)

Note that if you interpret 0xFFFFFFFF as a 32-bit two's-compliment (signed) integer, you get -1. If you interpret it as an unsigned integer, you get (2^32 - 1) = 4294967295.

Addresses are always unsigned; very generally speaking, there are no negative numbers when it gets down to the hardware.

0xFFFFFFFC is greater than 0xC0000000. Thus, here it is a kernel address, and any userspace application that tries to access it will fault and be delivered a SIGSEGV signal.

Jonathon Reinhart
  • 132,704
  • 33
  • 254
  • 328
  • 2
    Note for anyone experimenting with this on a real modern x86 Linux system: a 32-bit process under a 64-bit kernel can use all 4 GiB of virtual address space, except for the low 64k (reserved by default so NULL pointer deref faults instead of silently succeeding: https://wiki.debian.org/mmap_min_addr), and the high 2 pages. [Why can't I mmap(MAP\_FIXED) the highest virtual page in a 32-bit Linux process on a 64-bit kernel?](https://stackoverflow.com/q/47712502).) The 1:3 or 2:2 split is only when you're running a 32-bit kernel as well as 32-bit userspace, or 64-bit process + kernel. – Peter Cordes Oct 13 '18 at 03:23