Chapter 50. Virtual Memory Operations

This chapter looks at various system calls that perform operations on a process’s virtual address space:

Some of these system calls find particular use in conjunction with shared memory regions (Chapter 48, Chapter 49, and Chapter 54), but they can be applied to any region of a process’s virtual memory.

Note

The techniques described in this chapter are not in fact about IPC at all, but we include them in this part of the book because they are sometimes used with shared memory.

The mprotect() system call changes the protection on the virtual memory pages in the range starting at addr and continuing for length bytes.

#include <sys/mman.h>

int mprotect(void *addr, size_t length, int prot);

Note

Returns 0 on success, or -1 on error

The value given in addr must be a multiple of the system page size (as returned by sysconf(_SC_PAGESIZE)). (SUSv3 specified that addr must be page-aligned. SUSv4 says that an implementation may require this argument to be page-aligned.) Because protections are set on whole pages, length is, in effect, rounded up to the next multiple of the system page size.

The prot argument is a bit mask specifying the new protection for this region of memory. It must be specified as either PROT_NONE or a combination created by ORing together one or more of PROT_READ, PROT_WRITE, and PROT_EXEC. All of these values have the same meaning as for mmap() (Table 49-2, in Creating a Mapping: mmap()).

If a process attempts to access a region of memory in a manner that violates the memory protection, the kernel generates a SIGSEGV signal for the process.

One use of mprotect() is to change the protection of a region of mapped memory originally set in a call to mmap(), as shown in Example 50-1. This program creates an anonymous mapping that initially has all access denied (PROT_NONE). The program then changes the protection on the region to read plus write. Before and after making the change, the program uses the system() function to execute a shell command that displays the line from the /proc/PID/maps file corresponding to the mapped region, so that we can see the change in memory protection. (We could have obtained the mapping information by directly parsing /proc/self/maps, but we used the call to system() because it results in a shorter program.) When we run this program, we see the following:

$ ./t_mprotect
Before mprotect()
b7cde000-b7dde000 ---s 00000000 00:04 18258    /dev/zero (deleted)
After mprotect()
b7cde000-b7dde000 rw-s 00000000 00:04 18258    /dev/zero (deleted)

From the last line of output, we can see that mprotect() has changed the permissions of the memory region to PROT_READ | PROT_WRITE. (For an explanation of the (deleted) string that appears after /dev/zero in the shell output, refer to Section 48.5.)