Skip to content

Build1 publisher2 min readPublished

An unprivileged process can confine itself to a directory list without root

Landlock has been in mainline since kernel 5.13 and needs no policy file and no administrator to confine a process to named paths. The dev.to walkthrough explaining it leaves the enforcing syscall inside a comment.

The Engineer · Build desk

Illustration accompanying An unprivileged process can confine itself to a directory list without root

What happened

  • Landlock, available from Linux kernel 5.13, lets any user define a sandbox and confine a running program in it with no policy language, no root password and no deep system changes.
  • The dev.to post frames the gap: a user without root cannot restrict or adapt AppArmor or SELinux policy, so a compromised process with their rights reaches their home directory, SSH keys, passwords and documents.
  • The walkthrough's C example is labelled a heavily simplified illustration, and its landlock_restrict_self call appears only inside a comment marked as a simulation of a call.
  • For real use the post points at firejail or modern browser versions that use Landlock internally instead of driving raw kernel headers.

Compiled by The EngineerSomething wrong?How this is made

Why it matters

  • decision Confinement can be written into the program's own startup path, so the rule is authored by whoever knows which directories the binary opens.
  • constraint The restriction only narrows, so every path the process will ever need must be released before the call. Leave out a log directory and it surfaces as a runtime failure after deploy, not at build time.
  • exposure A self-confined process still depends on root-configured policy for anything that is not a filesystem path, so the sysadmin stays in the loop for the rest of the threat surface.
  • cost Blog walkthroughs are how most teams meet this facility, and a reader who lifts this one's sample ships a binary that prints a confinement claim it never applies. Verification then sits with the reader.

Read the sample in the dev.to post as a spec and you can see what the call does. A struct declares which access types the process wants the kernel to handle. The printed version sets `.handled_access_fs` to `LANDLOCK_FS_ACCESS_READ | LANDLOCK_FS_ACCESS_WRITE`, with `.parent_handle = NULL` and `.num_rules = 2` [7]. Handles for the two permitted paths, `.` and `./data`, would normally be produced with liblandlock, the post says [10]. Then the process calls `landlock_restrict_self(ruleset_fd, 0)`, and from that point the kernel blocks every path that was not explicitly released, whatever UID the process holds [5]. A comment in the sample makes the effect concrete: after the call, access to /home/user/Documents would be locked immediately [9].

That call does not run. It sits inside a comment, next to a second comment marked "Simulation eines Aufrufs", and the post labels the struct itself "ein stark vereinfachtes Schema zur Veranschaulichung" [8]. What is left executable is two printf lines, one of them telling the user "Dieser Prozess darf nur '.' und './data' lesen/schreiben", then `sleep(10)` and a return [11]. Compile it and you get a program that announces its confinement and applies none of it [13].

The property that matters for an application author is the timing. The restriction only ever narrows: once it is active, the only paths the process can reach are the ones it explicitly released, and the kernel refuses the rest [5]. So the path list has to be complete before the call, and it has to cover what the process will want at shutdown as well as at startup [5].

Landlock changes nothing about discretionary access control; it adds a mandatory layer above it [6]. A script running as bob still inherits all of bob's rights, which is why a hole in that script hands an attacker bob's full rights in the first place [3]. Landlock's own scope, per the post, is primarily the filesystem [5]. Everything that is not a path stays with SELinux or AppArmor, and those are extremely powerful, extremely complex, and require root to configure [4].

What to watch

  • Whether the post replaces its simulated call with a sequence that compiles and enforces, since the struct is labelled an illustration.
  • Which shipping programs confine themselves directly, as against going through firejail or a browser build that already uses Landlock.
  • Whether coverage beyond filesystem paths appears, because the post scopes the facility primarily to the filesystem.
Loading claim ledger
Loading source directory links
Loading share composer
Loading topic controls
Loading related stories