views:

190

answers:

5

When using copy-on-write semantics to share memory among processes, how can you test if a memory page is writable or if it is marked as read-only? Can this be done by calling a specific assembler code, or reading a certain spot in memory, or through the OS's API?

+1  A: 

If you're using Win32, there are the calls IsBadReadPtr and IsBadWritePtr. However, their use is discouraged:

"The general consensus is that the IsBad family of functions (IsBadReadPtr, IsBadWritePtr, and so forth) is broken and should not be used to validate pointers."

The title of Raymond Chen's take on this says it all: "IsBadXxxPtr should really be called CrashProgramRandomly"

Chen has some helpful advice about how to deal with this issue here.

The upshot is, you shouldn't be testing this kind of thing at run-time. Code so that you know what you're being handed, and if it's not what's expected, treat it as a bug. If you really have no choice, look into SEH for handling the exception.

Jim Nelson
+3  A: 

On Linux you can examine /proc/pid/maps:

$ cat /proc/self/maps

002b3000-002cc000 r-xp 00000000 68:01 143009   /lib/ld-2.5.so
002cc000-002cd000 r-xp 00018000 68:01 143009   /lib/ld-2.5.so
002cd000-002ce000 rwxp 00019000 68:01 143009   /lib/ld-2.5.so
002d0000-00407000 r-xp 00000000 68:01 143010   /lib/libc-2.5.so
00407000-00409000 r-xp 00137000 68:01 143010   /lib/libc-2.5.so
00409000-0040a000 rwxp 00139000 68:01 143010   /lib/libc-2.5.so
0040a000-0040d000 rwxp 0040a000 00:00 0
00c6f000-00c70000 r-xp 00c6f000 00:00 0        [vdso]
08048000-0804d000 r-xp 00000000 68:01 379298   /bin/cat
0804d000-0804e000 rw-p 00004000 68:01 379298   /bin/cat
08326000-08347000 rw-p 08326000 00:00 0
b7d1b000-b7f1b000 r--p 00000000 68:01 226705   /usr/lib/locale/locale-archive
b7f1b000-b7f1c000 rw-p b7f1b000 00:00 0
b7f28000-b7f29000 rw-p b7f28000 00:00 0
bfe37000-bfe4d000 rw-p bfe37000 00:00 0        [stack]

The first column is the virtual memory address range, the second column contains the permissions (read, write, execute, and private), columns 3-6 contain the offset, major and minor device numbers, the inode, and the name of memory mapped files.

Robert Gamble
+1  A: 

Are you talking abou the variety of shared memory allocated via shmget (on Unix)? I.e.

int shmget(key_t, size_t, int);

If so, you can query that memory using

int shmctl(int, int, struct shmid_ds *);

For example:

key_t key = /* your choice of memory api */
int flag = /* set of flags for your app */
int shmid = shmget(key, 4096, flag);

struct shmid_ds buf;
int result = shmctl(shmid, IPC_STAT, &buf);
/* buf.ipc_perm.mode contains the permissions for the memory segment */
Don Wakefield
+3  A: 

On Win32, the best way is to use VirtualQuery. It returns a MEMORY_BASIC_INFORMATION for the page an address falls in. One of the members is Protect, which is some combination of these flags, which contain the possible protection modes. The function also tells you if the memory is free, committed, reserved, and whether it is private, part of an image or shared memory section.

The OS's API is the best way to detirmine the a page's protection. The CPU reads the protection mode from a page descriptor, which is only accessible from kernel mode.

Chris Smith
Chris' comment is correct for Windows. Be sure to see Jim Nelson comment and Raymond Chen's blogs below.
Foredecker
A: 

You can try writing to it and see if you get some kind of fault as a result.

Claudiu