SYD-LOCK(1)

πŸ“¦
version 3.59.0 Β· 3 versions
, in arch rolling

πŸŽ€ SYD-LOCK(1) πŸŽ€

okay bestie, this is the SYD-LOCK(1) page from the General Commands Manual. We’re talking syd-lock, we’re talking landlock(7), and we’re keeping every flag, path, port, default, and warning exactly as written. No cap. πŸ’–

🌸 NAME 🌸

syd-lock β€” run a program under landlock(7).

🌸 SYNOPSIS 🌸

bestie, the shape is literally this:

syd-lock [-bchrvwASUV] [-C level] [-E errata] [-F flag]... [-l
       category[,category...]{+|-}path|port[-port][,port[-port]...]]...
       {command [args...]}

πŸ¦‹ DESCRIPTION πŸ¦‹

okay so syd-lock runs a program under landlock(7). The program gets confined by the landlock(7) categories you hand it. The supported categories are read, write, exec, ioctl, create, delete, rename, symlink, truncate, readdir, mkdir, rmdir, mkbdev, mkcdev, mkfifo, bind, and connect.

Categories other than bind and connect must specify paths to be confined. Both absolute and relative paths are permitted. Path must not contain magic symbolic links or parent (..) components. Path is permitted to contain regular symbolic links. These regular symbolic symlinks are permitted to resolve to targets with parent (..) components in them.

bind and connect are the network categories: they must specify a network port, a closed port range separated by dash, or a comma-separated list of ports and ranges. Zero is a valid port number to confine binds and connects to ephemeral ports. The bind category also supports absolute UNIX domain socket paths to confine their creation via mknod(2).

For full details and the specific behavior of each landlock(7) category, refer to the Sandboxing and Lock Sandboxing sections of the syd(7) manual page. πŸ’…

πŸ’… OPTIONS πŸ’…

full flag buffet, no skipping, no merging, no invented options. ✨

  • -h β€” Display help.
  • -v β€” Be verbose. Print landlock(7) status to stderr(3) before running the program.
  • -V β€” Print landlock(7) ABI version on stdout(3).
  • -A β€” Print landlock(7) ABI version on stdout(3) and exit with it as exit code. Use for scripting.
  • -l cat[,cat...]{+|-}path|port[-port] β€” Add or remove a landlock(7) rule with categories and an associated resource (path or port), may be repeated. Join categories and resource by either a + (plus) for add or a - (minus) for remove. Resource must be a path for all categories except bind and connect. Resource must be a port, a dash-delimited closed port range, or a comma-separated list of ports and ranges for bind and connect. Resource may also be a UNIX domain socket path for bind to confine mknod(2) with S_IFSOCK. Resource may also be a UNIX domain socket path for connect to confine connect(2) and sendmsg(2) to sockets created outside the domain. Both absolute and relative paths are permitted for all categories except bind and connect which require an absolute path. Paths are stored as hash sets and ports as fixed bit sets to make stacking options simple and predictable.
  • -C level β€” Set landlock(7) compatibility level. Must be one of hard-requirement, soft-requirement, and best-effort. Default is hard-requirement to adhere to the principle of secure defaults. Level can be given shortly as hard (or h), soft (or s) and best (or b).
  • -E errata β€” Query supported landlock(7) errata fixes. Use -E list to print list of known erratas. The argument may be a name or number. Use a number to query undefined erratas. Multiple erratas may be specified split by commas.
  • -F flags β€” Set landlock_restrict_self(2) flags. Use -F list to print a list of flags. See the FLAGS section for information on flags and their functionality.
  • -S β€” Enable scoped signals introduced with landlock(7) ABI 6.
  • -U β€” Enable scoped UNIX abstract sockets introduced with landlock(7) ABI 6.
  • -r path β€” Specify a read-only path, may be repeated. Equivalent to -l read,readdir,exec,ioctl+path.
  • -w path β€” Specify a read-write path, may be repeated. Equivalent to -l all+path.
  • -b port[-port][,port[-port]...] β€” Specify port(s) for bind(2), may be repeated. Equivalent to -l bind+port.
  • -c port[-port][,port[-port]...] β€” Specify port(s) for connect(2), may be repeated. Equivalent to -l connect+port.

🌸 CONFIGURATION 🌸

okay so this is the part where you actually tell syd-lock what to lock down, and honestly it's giving main character energy πŸ’…

landlock(7) categories and their associated resources (paths or ports) are given with the -l option. That option takes a comma separated list of categories, followed by either a + (plus) or a - (minus) symbol that tells it whether you're adding or removing the given rule. Rulesets store paths as hash sets and ports as fixed bit sets, which is what lets multiple -l options stack in a simple and predictable way πŸŽ€

Use the -V option to check for landlock(7) support in the Linux kernel. The specific support level can be figured out from the exit code. And use the -A option to check for the landlock(7) ABI version ✨

πŸ¦‹ ABI

landlock(7) ABI versioning is literally what makes it possible to adjust the security policy according to kernel capabilities. syd-lock has support for landlock(7) ABI 10, which is new in Linux-7.2 πŸ‘‘

See the HISTORY section for the tea on when each landlock(7) ABI was introduced to the Linux kernel.

πŸ“ SETS

As of version 3.38.0, multiple categories may be specified split by commas, and these sets are defined to simplify sandbox profile composition. The names are intentionally chosen to be consistent with OpenBSD's pledge(2) β€” iykyk πŸ’œ

  • all β€” All filesystem access rights
  • all-x β€” All filesystem access rights except exec
  • rpath β€” read, readdir
  • wpath β€” write, truncate
  • cpath β€” create, delete, rename
  • dpath β€” mkbdev, mkcdev
  • spath β€” mkfifo, symlink
  • tpath β€” mkdir, rmdir
  • inet β€” bind, connect

🧚 COMPATIBILITY LEVELS

As of version 3.35.0, the landlock(7) compatibility level may be set using the -C option to one of these levels: hard-requirement, or just hard or h, soft-requirement, or just short or s, and best-effort, or just best or b. Default is hard-requirement, to adhere to the principle of secure defaults πŸ”₯

So here's the vibe check on each one:

In hard-requirement level, the requested landlock(7) restrictions are taken into account only if they're supported by the running system. If any requested feature isn't supported, the operation returns a compatibility error and the sandbox is not entered, periodt. File open(2) errors during sandbox setup β€” including the ENOENT ("No such file or directory") errno(3) β€” return a fatal error in this level 😀

In soft-requirement level, the requested restrictions are taken into account if they're supported by the running system, or the entire sandboxing request is silently ignored otherwise; no compatibility error is returned πŸ™ˆ

In best-effort level, the requested restrictions are taken into account if they're supported by the running system, and any unsupported restrictions are silently ignored; no compatibility error is returned 🫢

Also: in soft-requirement and best-effort levels, file open(2) errors with the ENOENT ("No such file or directory") errno(3) are silently ignored. Other file open(2) errors are fatal ⚠️

πŸ’… FLAGS

As of version 3.38.0, landlock(7) flags may be set using the -F option. Flags may be specified using their names or numerical values. Multiple flags may be set at once by specifying them as a comma-separated list πŸŽ€

Flags are supported beginning with landlock(7) ABI 7, which is new in Linux-6.15. The list of supported flags is given below. Setting a flag on an unsupported ABI is a NO-OP unless otherwise noted πŸ‘€

  • log_same_exec_off (1) β€” Disables logging of denied accesses originating from the thread creating the landlock(7) domain, as well as its children, as long as they continue running the same executable code (i.e., without an intervening execve(2) call). This is intended for programs that execute unknown code without invoking execve(2), such as script interpreters. Programs that only sandbox themselves should not set this flag, so users can be notified of unauthorized access attempts via system logs. This flag requires landlock(7) ABI 7 support which is new in Linux-6.15 πŸ¦‹
  • log_new_exec_on (2) β€” Enables logging of denied accesses after an execve(2) call, providing visibility into unauthorized access attempts by newly executed programs within the created landlock(7) domain. This flag is recommended only when all potential executables in the domain are expected to comply with the access restrictions, as excessive audit log entries could make it more difficult to identify critical events. This flag requires landlock(7) ABI 7 support which is new in Linux-6.15 πŸ”₯
  • log_subdomains_off (4) β€” Disables logging of denied accesses originating from nested landlock(7) domains created by the caller or its descendants. This flag should be set according to runtime configuration, not hardcoded, to avoid suppressing important security events. It is useful for container runtimes or sandboxing tools that may launch programs which themselves create landlock(7) domains and could otherwise generate excessive logs. Unlike log_same_exec_off, this flag only affects future nested domains, not the one being created. This flag requires landlock(7) ABI 7 support which is new in Linux-6.15 πŸ’€

πŸ”’ SECURITY πŸ”’

bestie this section is important, lean in 🫢

As of version 3.35.0, the default landlock(7) compatibility level has been changed from best-effort to hard-requirement, and ENOENT (No such file or directory) errors are made fatal unless level is set to best-effort. This adheres to the principle of secure defaults and above all avoids the silent and dangerous trap where a non-existing file or directory which had been denied access (and skipped) at startup is created after, and landlock(7) ends up allowing access to the newly created file or directory 😭

For more information, see: https://landlock.io/rust-landlock/landlock/trait.Compatible.html

As of version 3.46.0, path must not contain magic symbolic links or parent (..) components. Path is permitted to contain regular symbolic links. These regular symbolic symlinks are permitted to resolve to targets with parent (..) components in them. bind category requires absolute UNIX socket paths. Path may be relative for other categories, in which case it is resolved relative to the directory where syd-lock(1) was executed ✨

Consider combining syd-lock(1) use with syd-mdwe(1) to get W^X memory protections. See syd-mdwe(1) manual page for more information πŸ‘‘


πŸ“œ HISTORY πŸ“œ

the landlock(7) ABI lore, chronological:

Refer to following links for more information:


πŸšͺ EXIT STATUS πŸšͺ

syd-lock exits with the same code as the child process on clean exit. On unclean termination, exit code is set to 128 plus signal number. In case executing the child process fails, syd-lock(1) exits with the errno(3) number. syd-lock -A exits with the landlock(7) ABI version as exit code πŸ’…

syd-lock -E exits with one of the following exit codes:

  1. 0 β€” All erratas are available.
  2. 1 β€” Some erratas are not available.
  3. 2 β€” No erratas are available.

syd-lock -V exits with one of the following exit codes based on support for the latest landlock(7) ABI:

  • 0 β€” Fully enforced
  • 1 β€” Partially enforced
  • 2 β€” Not enforced
  • 127 β€” Not supported

And syd-lock exits with 22 (EINVAL) for invalid CLI arguments πŸ™ˆ

✨ EXAMPLES ✨

Okay bestie, this is the part where it all clicks, I promise. 🫢 We're gonna watch wget slowly earn its privileges like it's leveling up in a video game, and honestly? It's giving character development. πŸ”₯


πŸŽ€ Example the First: vibes only, no permissions

$ syd-lock wget -O/dev/null chesswob.org

That's it, that's the whole first one. Nothing to show you yet β€” keep reading, the drama escalates. πŸ’…


πŸŽ€ Example the Second: the /dev/null jumpscare

So you've got read and execute on / β€” that's read,exec+/ β€” and you think you're fine. You are not fine. 😭

$ syd-lock -l read,exec+/ wget -O/dev/null chesswob.org
/dev/null: Permission denied

Permission denied. On /dev/null. Of all things. The void said no. πŸ’€


πŸŽ€ Example the Third: give it the write, watch it still flop

Bestie said "fine, have /dev/null," and look what happened. 🫠

$ syd-lock -l read,exec+/ -l write+/dev/null wget -O/dev/null chesswob.org
Prepended http:// to 'chesswob.org'
--2025-04-30 16:24:35--  http://chesswob.org/
Resolving chesswob.org (chesswob.org)... 95.216.39.164, fe80::468a:5bff:fe88:2141
Connecting to chesswob.org (chesswob.org)|95.216.39.164|:80... failed: Permission denied.
Connecting to chesswob.org (chesswob.org)|fe80::468a:5bff:fe88:2141|:80... failed: Permission denied.
Retrying.

^C
$

Look at that. 🌸 It wrote to /dev/null just fine, it resolved the name just fine, and then it tried to connect on port 80 and boom β€” Permission denied, not once but twice (v4 and v6, because it's thorough like that). Then it says Retrying. and you're sitting there like 😭 and you hit Ctrl+C.

The lesson? Every. Little. Thing. Needs its own -l rule. No cap. πŸ’…


πŸŽ€ Example the Fourth: the glow-up, the main character moment

Now we hand it connect on 80 and 443, and bestie β€” it ate. πŸ‘‘

$ syd-lock -l read,exec+/ -l write+/dev/null -l connect+80 -l connect+443 wget -O/dev/null chesswob.org
Prepended http:// to 'chesswob.org'
--2025-04-30 16:25:59--  http://chesswob.org/
Resolving chesswob.org (chesswob.org)... 95.216.39.164, fe80::468a:5bff:fe88:2141
Connecting to chesswob.org (chesswob.org)|95.216.39.164|:80... connected.
HTTP request sent, awaiting response... 302 Moved Temporarily
Location: https://www.chesswob.org/ [following]
--2025-04-30 16:25:59--  https://www.chesswob.org/
Loaded CA certificate '/etc/ssl/certs/ca-certificates.crt'
Resolving www.chesswob.org (www.chesswob.org)... 95.216.39.164, fe80::468a:5bff:fe88:2141
Connecting to www.chesswob.org (www.chesswob.org)|95.216.39.164|:443... connected.
HTTP request sent, awaiting response... 200 OK
Length: 148827 (145K) [text/html]
Saving to: β€˜/dev/null’

/dev/null                         100%[=============================================================>] 145.34K  --.-KB/s    in 0.01s

2025-04-30 16:25:59 (11.9 MB/s) - β€˜/dev/null’ saved [148827/148827]
$

Iconic. 🌈 Watch the whole plot: it does plain http on port 80, gets a 302 Moved Temporarily redirect over to https, follows it like the good little user-agent it is, loads the CA cert, connects on 443, gets 200 OK, and yeets 148827 bytes straight into the void. πŸ•³οΈβœ¨ And it only worked because we told it about both 80 and 443 up front. Foresight is everything, iykyk.

🧚 Small but important vibe check: the numbers and outputs above are exactly the ones the original page shows β€” don't come at me if your IP or your bandwidth looks different, bestie. 😌

🌸 SEE ALSO 🌸

Everything adjacent that you're gonna want to read next, alphabetized because we're classy:

And the links, because knowledge is free and slaying is mandatory: πŸ’–


πŸ‘‘ AUTHORS πŸ‘‘

Maintained by Ali Polatel. πŸ’œ

Up-to-date sources live at https://gitlab.exherbo.org/sydbox/sydbox.git and on Radicle at rad:z38HCnbmcDegA2BMxuPaPRPMdp6wF.

Got bugs? Got patches? Both go to https://gitlab.exherbo.org/groups/sydbox/-/issues. πŸ›

Wanna actually talk to humans about it? Come hang out in #sydbox on Libera Chat, or #sydbox:mailstation.de on Matrix. We don't bite. 🫢


okay that's the whole page bestie, you made it, I'm so proud of you πŸ₯ΉπŸ’…βœ¨ This was SYD-LOCK(1), dated 2026-09-01, and that date is straight from the source β€” literally. Now go lock down something cute. πŸŽ€πŸ¦‹

πŸ“¦ where this page comes from