Locking memory

We understand that on a virtual memory-based OS, such as Linux, a usermode page can be swapped at any point in time; the Linux kernel memory management code makes these decisions. To the regular application process, this should not matter: any time it attempts to access (read, write, or execute) the page content, the kernel will page it back into RAM, and allow it to use it as though nothing had occurred. This handling is generally called servicing a page fault (there is a lot more to it, but for the purpose of this discussion, this is sufficient), and is completely transparent to the usermode application process.

However, there are some situations where memory pages being paged  written from RAM to swap and vice-versa  is undesirable:

  • Realtime applications
  • Cryptography (security) applications

In real-time applications, the key factor (at least within its critical code paths) is determinism  the iron-clad guarantee that the work will take a certain worst-case amount of time, and no more, no matter the load on the system.

Imagine that the real-time process is executing a critical code path and a data page has to be paged in from the swap partition at that moment  the latency (delay) introduced could ruin the application's characteristics, resulting in dismal failure (or worse). In these cases, we, the developers, need a way to guarantee that said pages of memory can guaranteed to be resident in RAM, thus avoiding any page faulting.

In some types of security applications, they would likely store some secrets in memory (a password, a key); if the memory pages containing these are written out to disk (swap), there is always the possibility that it remains on disk well after the application exits  resulting in what's called information leakage, which is a bug attackers are just waiting to pounce upon! Here, again, the need of the hour is to guarantee that those pages cannot be swapped out.

Enter the mlock(2) (and friends: mlock2 and mlockall) system calls; the express purpose of these APIs is to lock memory pages within the calling process's virtual address space. Let's figure out how to use mlock(2). Here is its signature:

int mlock(const void *addr, size_t len);

The first parameter, addr, is a pointer to the (virtual) memory region to lock; the second parameter, len, is the number of bytes to lock into RAM. As a trivial example, take look at the following code (here, to keep it easily readable, we don't show error-checking code; in a real application, please do so!):

long pgsz = sysconf(_SC_PAGESIZE);
size_t len = 3*pgsz;

void *ptr = malloc(len);

[...] // initialize the memory, etc

// Lock it!
if (mlock(ptr, len) != 0) {
// mlock failed, handle it
return ...;
}

[...] /* use the memory, confident it is resident in RAM & will stay
there until unlocked */

munlock(ptr, len); // it's now unlocked, can be swapped
..................Content has been hidden....................

You can't read the all page of ebook, please click here login for view all page.
Reset