Why does Software Crash #2 – The Access Violation (continued)

In our last post (here), we took a look at an Access Violation of a user mode application attempting to access memory in kernel mode address space.

It's interesting to note that we can't just go reading and writing memory in the kernel- if we try to blindly access another application's memory, we'll get the same AV error (on an NT OS, anyhow). Let's take a look:

   int foo;

   int * ip = (int*)16777216; //Address 0x01000000, in another process' address space

   foo = *ip; //Crash!

This will crash with the following error:

Unhandled exception at 0x004173c8 in cpractice.exe: 0xC0000005: Access violation reading location 0x01000000.

A few notes:

  • On most machines, you'll see a Watson dialog instead of this unfriendly crash dialog. I've used the `unfriendly' crash dialog here for demonstration purposes.
  • AT posted some interesting comments in the other post here. The win32 API has tools for sharing memory between processes, and the above code was legal on DOS, which was without a protected memory space.

Comments

  • Anonymous
    January 18, 2005
    Every process has its own virtual private address space. The pointers you are using are not physical locations, they are virtual addresses that (without your knowing) map to a real physical address (that you do not know).

    Therefore, it's not meaningful to use phrases like "in another process' address space". Every address (pointer) that you have applies to your own address space, by definition. You can never directly address another processes address space simply because any pointer value you have is only meaningful to your process.

    There are special API's to setup shared memory or you can use special linker directives to establish shared memory blocks, but again this goes through virtual private mappings. The important point is that a pointer is only valid for THAT process... it is meaningless to any other process.


  • Anonymous
    January 18, 2005
    Um, a few points. BTW, when I say 'Windows' I mean Windows NT/2000/XP/2003, not 9x or CE.

    1) address 0 (in the last post) is in your process's address space, not in the kernel's. Windows never maps the first 64KB of space - partly to catch null and near-null pointer bugs and partly - my guess, anyway - because of the existence of integer resource IDs.

    2) Address 0x01000000 is also in your address space. You cannot directly access another process's address space in Windows. You can access memory that's also mapped in another process - e.g. memory-mapped files - but it won't necessarily be mapped at the same address in both processes.

    Typically, however, this address won't be mapped at program startup as your thread's stack and default heap are below this address. Your program's code will be located much lower; system DLLs will be located much higher, near to the 2GB boundary.
  • Anonymous
    January 18, 2005
    Interesting. I had always interpreted "you cannot access another process's address space" as meaning you technically can, but you'd suffer an immediate AV as a result for doing so.

    Thanks for the comments!