Landlock-Sharp

Quick Start

A five-minute tour of Landlock-Sharp: check kernel support, build a ruleset, allow one directory, enforce the sandbox, and watch unauthorised accesses fail.

If you haven't already, install the NuGet package:

dotnet add package Landlock

Landlock's full kernel-side semantics are documented on the landlock.io site and the landlock(7) man page. This guide focuses on the C# binding — refer back to those for the authoritative behaviour.


1. Check kernel support

Landlock is Linux-only and needs kernel 5.13+. Always branch on IsSupported() so your code stays portable.

using Sandbox;

if (!Landlock.IsSupported())
{
    Console.WriteLine("Landlock unavailable — running without sandbox.");
    return;
}

IsSupported() returns true only on Linux x86-64 with a kernel that exposes Landlock. See ABI versions if you also need to detect which features are available.


2. Create a ruleset

A ruleset declares which access rights the sandbox will handle. Anything you don't list is left untouched by Landlock; anything you do list is denied by default and must be re-granted by a rule.

var sandbox = Landlock.CreateRuleset(Landlock.FileSystem.CORE);

FileSystem.CORE is a convenience that expands to every filesystem right available on the current kernel. To restrict only specific operations, pass them individually:

var sandbox = Landlock.CreateRuleset(
    Landlock.FileSystem.READ_FILE,
    Landlock.FileSystem.WRITE_FILE,
    Landlock.FileSystem.EXECUTE);

For the meaning of each right, see the "Filesystem flags" section of landlock(7).


3. Allow a directory

Use AddPathBeneathRule to grant specific rights to a directory tree. The path must be a directory; rules cascade to everything beneath it.

sandbox.AddPathBeneathRule(
    "/var/lib/myapp/data",
    Landlock.FileSystem.READ_FILE,
    Landlock.FileSystem.READ_DIR);

The rights you grant per rule must be a subset of the rights you declared when creating the ruleset — you cannot grant WRITE_FILE here unless WRITE_FILE (or CORE) appeared in CreateRuleset.

Filesystem rules guide


4. Enforce the sandbox

Enforce() is the point of no return. Once it returns, the calling thread (and every child thread and process) is permanently bound to the ruleset.

sandbox.Enforce();

Internally the call:

  1. Sets PR_SET_NO_NEW_PRIVS so the process cannot gain privileges via setuid binaries.
  2. Invokes landlock_restrict_self to bind the ruleset to the current thread.
  3. Closes the ruleset file descriptor.

The restriction is irrevocable — there is no way to widen the sandbox afterwards. The only way to "escape" is to fork an entirely new process from a less-restricted parent.

One-way door

You cannot re-call CreateRuleset and "replace" the sandbox. New rulesets only ever layer further restrictions on top of the existing one. See the Enforcing guide for thread vs. process semantics.


5. See it in action

With the sandbox in place, anything outside the allowed path fails with EACCES.

// OK — inside the allowed tree
string contents = File.ReadAllText("/var/lib/myapp/data/hello.txt");

// Denied — outside the allowed tree
try
{
    File.ReadAllText("/etc/passwd");
}
catch (UnauthorizedAccessException)
{
    Console.WriteLine("Blocked by Landlock");
}

// Denied — write was never allowed, even inside the tree
try
{
    File.WriteAllText("/var/lib/myapp/data/new.txt", "nope");
}
catch (UnauthorizedAccessException)
{
    Console.WriteLine("Blocked: write was never granted");
}

6. Put it all together

app/Program.cs
using Sandbox;

if (!Landlock.IsSupported())
{
    Console.WriteLine("Landlock unavailable.");
    return;
}

var sandbox = Landlock.CreateRuleset(Landlock.FileSystem.CORE);

sandbox.AddPathBeneathRule(
    "/var/lib/myapp/data",
    Landlock.FileSystem.READ_FILE,
    Landlock.FileSystem.READ_DIR);

sandbox.Enforce();

Console.WriteLine(File.ReadAllText("/var/lib/myapp/data/hello.txt"));

try { File.ReadAllText("/etc/passwd"); }
catch (UnauthorizedAccessException) { Console.WriteLine("blocked /etc/passwd"); }
Expected output
hello world
blocked /etc/passwd

Going further

Landlock can do more than filesystem rules:

  • TCP ports — bind/connect allow-lists via AddPortRule (kernel 6.7+). See Network rules.
  • IPC scopes — block abstract Unix sockets and inbound signals (kernel 6.12+). See Scopes.
  • Deny logging — opt into audit logs of blocked accesses (kernel 6.13+). See Logging.

Where next?

Core Concepts

What Landlock actually does, how the ABI versioning works, and the shape of the C# API.

Guides

Filesystem rules, TCP port rules, IPC scopes, enforcement, and deny logging.

Advanced

Error handling, testing on hosts where Landlock isn't available, and multi-threaded apps.

Upstream docs

The official Landlock project site — kernel semantics, tutorials, and the full LSM design.

© 2026 Landlock-Sharp. All rights reserved.