4

A raw computer basically just has memory with physical addresses starting at 0, right? Then someone could write assembly code (such as a BIOS) and actually put a value at 0.

Now if there is a BIOS that starts the computer, then someone could write a loader for an operating system. Can that person decide to move actual values to position 0 in the memory in assembly language?

What if they use C or C++? Can they have a pointer with value 0 and use it to access the first memory location? Does that need a specially adapted compiler?

And then the operating system enters the scene. It has a memory manager which is called by malloc to get more memory. Could an operating system be written which can simply use null pointers as normal pointers, but otherwise behaves exactly like Linux, and then if someone compiles a C program with a normal, unmodified GCC for it, a null pointer wouldn't lead to a segmentation fault?

Felix Dombek
  • 13,664
  • 17
  • 79
  • 131
  • Is your hope to somehow design the scourge of null pointer exceptions out of existence at the system level? – harpo Mar 12 '11 at 14:35
  • That's a funny idea, but I think it's generally good to have one value reserved for "this points nowhere". I just want to better understand how this is actually defined. I actually thought that it is defined by the operating system -- in a way that the memory manager really returns 0 to a calling `malloc` if it doesn't want to give it memory, and if someone then writes a value into it, the operating system forcably terminates the application. On the level of the operating system kernel, however, this definition does not yet exist -- still the kernel can be written in C. – Felix Dombek Mar 12 '11 at 14:49
  • I was looking for a good article about Segmentation, Paging, LDT, GDT and (perhaps) NX and its effects on paging (all on x86) for the OP. I studied them in CS (except the NX part).. But I wasn't able to find anything... Does anyone have a link? (I know, I shouldn't use comments to ask questions, but I don't want to post a full blown question) – xanatos Mar 12 '11 at 15:34
  • Who says that the physical memory on a system is addressed by a pointer? Who says that 0 is a meaningful physical address? – David Heffernan Mar 12 '11 at 19:15

4 Answers4

2

While the NULL pointer is represented in C source code as a 0, there is no requirement that the underlying bit pattern actually has to be 0. It just has to be distinguishable from non-NULL pointers. There are examples of architectures where it isn't zero under the covers.

It's the C implementation itself that decides what a NULL is.

You should also realise that modern operating systems (well, those that do virtual memory) have a disconnect between a process virtual address space and the underlying physical memory.

paxdiablo
  • 854,327
  • 234
  • 1,573
  • 1,953
2

Read this Why does Linux program that derefrences (char*)0 not always segfault? it's at least half of your response :-) And this http://wiki.debian.org/mmap_min_addr The first part, about the vulnerabilities that where possible before the "fixing" of mmap_min_addr. And this http://eparis.livejournal.com/606.html, with a story of the vulnerability.

So yes, it's possible to map a page to address 0 and put code there. Your system will be weaker to errors in programs, but "perfect" programs will work in the same way as before. As for the question "what would happen if a program access the segment 0"... Well... Whatever you want...

But I think you don't exactly comprehend how the protected memory of "modern" processors work. Each process can see a different block of memory mapped to an address, and some processes can "write" to this page, and some can only "read" (and some can execute).

Community
  • 1
  • 1
xanatos
  • 109,618
  • 12
  • 197
  • 280
2

The null pointer in C and similar languages is just a convention, to allow an easy to check for indication that a pointer doesn't point to anything valid. There is nothing in the computer that physically stops anything from storing data at memory location 0. In fact, the C standard doesn't even state that the null pointer must have all bits zero or correspond to memory location 0, just that it must be what you get from (void *)0.

malloc and similar functions cannot return a null pointer as a valid memory location, because a return of a null pointer is specifically defined to indicate failure.

Now, to support this extremely common usage of the null pointer in C, some operating systems will specifically not map or otherwise set a trap for the memory location corresponding to the null pointer so any accidental accesses will immediately raise a segmentation violation or the like. Operating systems do exist that do not do this, of course.

Anomie
  • 92,546
  • 13
  • 126
  • 145
1

Linux (or any "normal" processes and virtual-memory OS) leaves the lowest addresses unmapped, specifically to gain detection of null-pointer bugs. consider the following example:

#include <unistd.h>
#include <sys/mman.h>
int main() {
    char *p = mmap(0,4096,PROT_READ|PROT_WRITE,MAP_ANONYMOUS|MAP_SHARED|MAP_FIXED,-1,0);
    if (p == MAP_FAILED) return 1;
    p[0] = 'x';
    p[1] = '\n';
    write(1,0,2);
    return 0;
}

this works on pre-selinux systems (prints "x"), though on my desktop with selinux disabled, it only works as root, not a normal user. but the point is that you generally have control of everything in your virtual address space. if you really want to put something at 0, you can, though you might run into, for instance, code that refuses to deal with a string at 0.

markhahn
  • 565
  • 4
  • 6