MLOCKALL(2)

πŸ’– MLOCKALL(2) β€” the system calls manual, bestie edition πŸ’–

okay so bestie, we're in section 2 of the manual (that's the system calls section, iykyk) and today's topic is mlockall and munlockall. yes, both. they're a package deal. slay.


✨ NAME ✨

mlockall, munlockall β€” lock (unlock) the address space of a process

like… the whole vibe of a process's memory? locked. or unlocked. depending on which one you call. periodt.


πŸ“š LIBRARY πŸ“š

Standard C Library (libc, -lc)

so you gotta link the C library, and yeah the flag for that is literally -lc. classic.


🌸 SYNOPSIS 🌸

#include <sys/mman.h>

int
mlockall(int flags);

int
munlockall(void);

there they are 🫢. one takes flags, one takes nothing because it has nothing to prove. munlockall said "no arguments, no problems."


πŸ’… DESCRIPTION πŸ’…

The mlockall() system call locks into memory the physical pages associated with the address space of a process until the address space is unlocked, the process exits, or execs another program image.

read that again bestie: those pages stay pinned down until one of three things happens β€” somebody unlocks them, the process dips out (exits), or it execs into a whole different program image. three exits, no exceptions. πŸšͺ✨

The following flags affect the behavior of mlockall():

  • MCL_CURRENT β€” Lock all pages currently mapped into the process's address space. like, everything you've already got mapped right now? locked. immediately. no cap.
  • MCL_FUTURE β€” Lock all pages mapped into the process's address space in the future, at the time the mapping is established. this is the forward-looking one, main character energy fr fr. Note that this may cause future mappings to fail if those mappings cause resource limits to be exceeded. 😭 so yeah, it can absolutely bite you later.

Since physical memory is a potentially scarce resource, processes are limited in how much they can lock down. A single process can lock the minimum of a system-wide β€œwired pages” limit vm.max_user_wired and the per-process RLIMIT_MEMLOCK resource limit.

translation: you don't get unlimited locked memory, babe. one process gets the minimum of two things β€” the system-wide "wired pages" limit vm.max_user_wired, and the per-process RLIMIT_MEMLOCK limit. whichever is smaller wins. the smaller one is the vibe check. πŸ“‰

If security.bsd.unprivileged_mlock is set to 0 these calls are only available to the super-user. so if that's zeroed out? unprivileged besties can't touch these calls at all, only the super-user can. πŸ’€

If vm.old_mlock is set to 1 the per-process RLIMIT_MEMLOCK resource limit will not be applied for mlockall() calls. yup β€” old behavior mode, and in that mode RLIMIT_MEMLOCK just… doesn't apply to mlockall(). iconic of it honestly.

The munlockall() call unlocks any locked memory regions in the process address space. Any regions mapped after an munlockall() call will not be locked.

so munlockall() frees everything that's locked right now. and anything you map after the call? not locked. sorry. it doesn't retroactively care. 🧚


πŸŽ€ RETURN VALUES πŸŽ€

A return value of 0 indicates that the call succeeded and all pages in the range have either been locked or unlocked.

zero = slay, everything worked, every page in the range is locked or unlocked as requested. βœ…

A return value of -1 indicates an error occurred and the locked status of all pages in the range remains unchanged. In this case, the global location errno is set to indicate the error.

minus one = nope, error, and here's the important part: the locked status of all pages in the range stays exactly the way it was. no partial vibes. and the global location errno gets set so you can find out what went wrong. πŸ”


πŸ”₯ ERRORS πŸ”₯

mlockall() will fail if:

  • [EINVAL] β€” The flags argument is zero, or includes unimplemented flags. so either you passed literally nothing, or you passed something nobody implemented. either way, invalid. πŸ™ˆ
  • [ENOMEM] β€” Locking the indicated range would exceed either the system or per-process limit for locked memory. you asked for more locked memory than you're allowed, system-wide or per-process. nope.
  • [EAGAIN] β€” Some or all of the memory mapped into the process's address space could not be locked when the call was made. some or all of it just wouldn't lock at that moment. 😭
  • [EPERM] β€” The calling process does not have the appropriate privilege to perform the requested operation. you don't have the privilege, bestie. no permission slip, no entry. 🚫

πŸ‘€ SEE ALSO πŸ‘€

mincore(2), mlock(2), mmap(2), munmap(2), setrlimit(2)

go read these next, they're the friend group:


⭐ STANDARDS ⭐

The mlockall() and munlockall() functions are believed to conform to IEEE Std 1003.1-2001 (β€œPOSIX.1”).

"believed to conform" β€” okay so it's not a flex, it's a vibe. but yes, IEEE Std 1003.1-2001, aka β€œPOSIX.1”. πŸ’œ


🌈 HISTORY 🌈

The mlockall() and munlockall() functions first appeared in FreeBSD 5.1.

og debut: FreeBSD 5.1. we love a legacy moment. πŸ‘‘


πŸ’€ BUGS πŸ’€

The per-process and system-wide resource limits of locked memory apply to the amount of virtual memory locked, not the amount of locked physical pages. Hence two distinct locked mappings of the same physical page counts as 2 pages aginst the system limit, and also against the per-process limit if both mappings belong to the same physical map.

okay this is the one that gets people, so listen up πŸ“’. the limits count virtual memory locked, NOT physical pages locked. so if you map the same physical page twice and lock both? that's counted as 2 pages against the system limit β€” and it also counts against the per-process limit if both mappings belong to the same physical map. yes, really. double counting. it's giving scam, but it's documented, so. πŸ™ƒ


and that's the whole page, bestie!! you now know more about locking process address space than 99% of the group chat. go forth and mlockall responsibly (or don't, but like, know the limits). πŸ¦‹

this lil gem came from the Debian crew, dated May 13, 2019, and it lives in section MLOCKALL(2) β€” mwah, take care of her πŸ’–βœ¨

πŸ“¦ where this page comes from