[HN Gopher] Landrun: Sandbox any Linux process using Landlock, n...
___________________________________________________________________
Landrun: Sandbox any Linux process using Landlock, no root or
containers
Author : Zoup
Score : 211 points
Date : 2025-03-22 13:56 UTC (9 hours ago)
(HTM) web link (github.com)
(TXT) w3m dump (github.com)
| Zoup wrote:
| Linux Landlock is a kernel-native security module that lets
| unprivileged processes sandbox themselves - but nobody uses it
| because the API is ... hard!
|
| I built `landrun`, a small CLI tool in Go, to make it practical
| to sandbox any command with fine-grained filesystem and network
| access controls. No root. No containers. No SELinux/AppArmor
| configs.
|
| It's lightweight, auditable, and wraps Landlock v5 features (file
| access + TCP restrictions).
|
| Demo + usage examples in the README.
|
| Would love feedback from the HN crowd!
| Filligree wrote:
| I'll try it, but just off the bat, how does this compare to
| bubblewrap?
| camkego wrote:
| I also would like to understand the differences relative to
| bubblewrap
| bitbang wrote:
| If I understand it correctly, landlock is an API used by an
| app to sandbox itself. The app itself controls the
| sandboxing. Bubble wrap is user space tooling external to the
| app, so the app had no direct awareness or control of its
| sandboxing. The scenarios each is intended for are orthogonal
| to one another.
| amarshall wrote:
| Landlock can be used to sandbox a launched sub process, as
| it is here, just as the Kernel APIs used by Bubblewrap
| could (and sometimes are!) used by programs to sandbox
| themselves.
| 1oooqooq wrote:
| not exactly correct. bubblewrap, firejail, and i not sure,
| but maybe even apparmour, all remove capabilities and
| create+join restricted fs/net namespaces, and then fork the
| actual thing you want to execute. so it's exactly the same
| concept, but those use the cap and cgroups.
| codedokode wrote:
| Bubblewrap is very limited, for example it doesn't allow to
| grant access to /proc/self/exe without giving access to whole
| /proc subsystem. So I had to write an emulation of /proc in
| Python and mount it with FUSE to work around this. I wonder
| if this issue is fixed in landlock, firejail and others.
|
| Also bubblewrap cannot ask for a decision in runtime: you
| must set up the rules beforehand.
| bastiao wrote:
| This seems pretty nice, as it using directly landlock API from
| the Linux Kernel (like pledge from OpenBSD). One feature I
| would like to have is like yaml description for some set of
| configuration rather that use all this arguments. So we could
| have preconfigured commands and just execute them. But I think
| it is just a matter of taste. I will try the tool. Thanks for
| it.
| yjftsjthsd-h wrote:
| That could be a separate wrapper, like bubblejail is for
| bubblewrap. Landjail?
| mdaniel wrote:
| If you want a file format, I'd lobby for one of the existing
| ones rather than some random yaml one
|
| - sandbox-exec's scheme one https://github.com/BrianSwift/mac
| OSSandboxBuild/blob/main/co...
|
| - AppArmor https://wiki.apparmor.net/ (although I'm cognizant
| that tries to address way more than just filesystem access)
|
| - Java's permission one https://docs.oracle.com/javase/8/docs
| /technotes/guides/secur...
|
| Likely tens more
| bastiao wrote:
| I agree that re-use file format could a good option. BTW
| the used landlock go library has sort of example
| https://github.com/landlock-lsm/go-
| landlock/blob/main/exampl...
| Foxboron wrote:
| Still early but Mickael Salaun, the author of landlock, is
| working on this.
|
| https://github.com/landlock-lsm/landlockconfig
|
| I'm going to write up some Go bindings for this when it
| becomes relevant.
| gnoack wrote:
| (Author of go-Landlock here)
|
| Awesome! I'm happy to hear that you and others are
| interested in the configuration language. We should
| probably coordinate that on the Landlock mailing list when
| the time comes, so that we don't duplicate that work. We
| are open to outside contributions :)
| ARob109 wrote:
| Would be cool to see integration of landlock with
| configuration file in a way that a service launched by
| systemd can apply the configuration to the executable.
|
| Akin to systemd SystemCallFilter directive for no-code
| application of seccomp filters to the sandboxed process h
| ttps://www.freedesktop.org/software/systemd/man/latest/sy
| st...
| l0kod wrote:
| We are working on a JSON/TOML format for Landlock, with the
| related library, and bindings for several languages:
| https://github.com/landlock-lsm/landlockconfig
|
| We are working to make it part of the OCI runtime
| specification too.
|
| Using existing configuration format would not work because
| Landlock has its own unique properties: unprivileged, nested
| sandboxes, dedicated Linux syscalls, and a good compatibility
| story with opt-in and incremental features.
| linsomniac wrote:
| I didn't have much luck with one of the readme examples:
| # rm -f /tmp/foo; ./landrun-linux-amd64 --log-level debug --ro
| /usr/bin --ro /lib --ro /lib64 --rw /tmp touch /tmp/foo
| [landrun] 2025/03/22 10:28:02 Sandbox config:
| {ReadOnlyPaths:[/usr/bin /lib /lib64] ReadWritePaths:[/tmp]
| AllowExec:false BindTCPPorts:[] ConnectTCPPorts:[]
| BestEffort:true} [landrun:debug] 2025/03/22 10:28:02
| Adding read-only path: /usr/bin [landrun:debug]
| 2025/03/22 10:28:02 Adding read-only path: /lib
| [landrun:debug] 2025/03/22 10:28:02 Adding read-only path:
| /lib64 [landrun:debug] 2025/03/22 10:28:02 Adding read-
| write path: /tmp [landrun:debug] 2025/03/22 10:28:02
| Applying Landlock restrictions [landrun] 2025/03/22
| 10:28:02 Landlock restrictions applied successfully
| [landrun] 2025/03/22 10:28:02 Executing: [touch /tmp/foo]
| touch: cannot touch '/tmp/foo': Permission denied
|
| Looks very interesting. I'm achieving something somewhat
| similar by running soeme processes under docker and mounting
| volumes ro, but could definitely see a usecase for adding
| landlock to more server processes.
| ranger_danger wrote:
| This is the minimum options I needed to get it to work:
|
| landrun --log-level debug --exec --ro /usr/bin --ro /usr/lib
| --rw /tmp touch /tmp/foo
|
| Personally I don't like that --exec would allow binaries in
| /tmp to be executed as well...
| nine_k wrote:
| As a workaround you could create a tmpfs device like
| /tmp_noexec with noexec flag, and mount it instead of the
| normal /tmp. But landrun does not (yet?) allow changing the
| name in directory options :(
|
| For added security, I'd create an ephemeral tmpfs disk for
| each landlocked invocation: obviously the program we're
| running has no business seeing what _other_ processes may
| have put to /tmp.
| ranger_danger wrote:
| > I'd create an ephemeral tmpfs disk for each landlocked
| invocation
|
| And now you've just invented firejail.
| nine_k wrote:
| UX-wise, yes. Internally firejail and landrun use
| different isolation APIs.
| ranger_danger wrote:
| Firejail supports Landlock though:
| https://github.com/netblue30/firejail/pull/6078
| qwertox wrote:
| But
|
| `landrun --ro /usr/bin --ro /lib --ro /lib64 --rw
| /path/to/dir touch /path/to/dir/newfile`
|
| vs
|
| `landrun --ro /usr/bin --ro /lib --ro /lib64 --exec
| /usr/bin/bash`
|
| seems to indicate that `--exec` is only required if the
| command you're executing then uses an `exec`-call
| internally, which `bash` would need to be able to fork.
|
| So `touch` should not need `--exec`, while `bash` should be
| able to run anything it can read (including that
| whitelisted `/tmp`).
| ranger_danger wrote:
| The former does not work for me, I have to add --exec. I
| can only assume it's because touch is in /usr/bin and so
| it needs permission to execute it from there.
|
| It seems that using --ro or --rw at all makes --exec also
| mandatory.
| bastiao wrote:
| Would be possible/make sense to use landlock on
| OCI/containers land?
| codethief wrote:
| Syd[0] uses landlock (among many other mechanisms) to
| containerize applications and provides an OCI-compatible
| interface.
|
| [0]: https://gitlab.exherbo.org/sydbox/sydbox
| ranger_danger wrote:
| that looks really cool, but unfortunately without any
| obvious examples or even a link to documentation, I'm
| closing the tab and likely forgetting it exists... I
| would assume many others would feel the same way.
| bastiao wrote:
| True! I had the same feeling.
| rainworld wrote:
| // If we have no rules, just return if len(rules) == 0 {
| log.Info("No sandbox rules to apply") return nil
| }
|
| Really cool and well-written project, but I disagree with this
| choice: No rules should mean no rules (everything denied).
|
| I would have suggested support for more fine-grained
| file/directory permissions--good to see that's already planned.
| __turbobrew__ wrote:
| > but nobody uses it because the API is ... hard!
|
| OpenBSD really got it right with pledge and unveil.
| gnoack wrote:
| OpenBSD did get it right, but they also have a more relaxed
| scheme for backwards compatibility across releases. Linux's
| strict ABI compatibility guarantees complicate matters
| slightly, but with the right supporting library it becomes
| tolerable.
|
| See the example at the top of the Readme at
| https://github.com/landlock-lsm/go-landlock
|
| (Full disclosure, I am the author of that library)
|
| FWIW, I do hope that we can motivate people to use Landlock
| in the same way as people use pledge on OpenBSD, as a
| lightweight self-sandboxing mechanism that requires fewer
| architectural changes to your program and results in more
| constrained sandboxes than Linux namespaces and other
| mechanisms do.
| __turbobrew__ wrote:
| As far as I know the ABI for pledge and unveil really
| haven't changed since release? What is stopping linux from
| creating NEW security primitives which are easy to use? We
| have wireguard in the linux kernel as a recent addition.
| Wireguard shows that new simple primitives can be added to
| the kernel, it requires someone with "good taste" to do the
| implementation without sacrificing usability.
| l0kod wrote:
| BSD systems ship a kernel and user space, which
| simplifies a lot of things. Linux is more flexible but it
| comes at a cost. Adding new security features can also be
| challenging for other reasons. Anyway, Landlock is one of
| these new security primitives, and it is gaining new
| features over time.
|
| The Landlock interface must not change the underlying
| semantic of what is allowed or denied, otherwise it could
| break apps build for an older or a newer kernel. However,
| these apps should still use all the available security
| features. This is challenging.
|
| Landlock provides a way to define fine-grained security
| policies. I would not say the kernel interface is complex
| (rather flexible), but what really matter are the user
| space library interfaces and how they can safely abstract
| complexity.
| __turbobrew__ wrote:
| I know how linux and bsd work. I still have yet to find a
| satisfactory answer to why linux cannot create security
| primitives which are useful -- like wireguard. I
| understand that landlock tries to abstract complexity,
| but why do we need to design complex user interfaces?
| Pledge and unveil are just simple syscalls, there is no
| magic secret sauce on BSDs which enable these syscalls.
| It is true that bsd userspace has been compiled to bake
| in plege and unviel syscalls, but that is totally
| separate from the usability of the interfaces.
| mulle_nat wrote:
| I have been using https://github.com/marty1885/landlock-
| unveil on Linux for about two years now on my stock Ubuntu
| kernel. I am not sure, why this hasn't become more popular.
| It's also rootless sandboxing (and it does `unveil` like
| OpenBSD I guess). I use it to confine builds of third party
| software with success.
| BlimpSpike wrote:
| Similarly to the bubblewrap comment, I'd also like to know how
| it compares to nsjail.
|
| I think nsjail uses mount namespaces (CLONE_NEWNS) instead of
| landlock for filesystem sandboxing, but what would the
| practical differences be?
| trikko wrote:
| Are (abstract) unix sockets supported?
|
| I'm trying to run a self-contained webserver executable without
| any external dependency. It starts but daemon <-> workers
| communication doesn't seem working (it is done via unix socket)
|
| It works fine with bubblewrap or inside a scratch docker
| container.
| ximm wrote:
| This looks nice, but I fail to see any use cases that cannot be
| handled with bwrap and mount namespaces.
| amarshall wrote:
| Some systems or admins may not trust unprivileged namespacing
| (thus disabling and its use requiring root), while Landlock may
| be enabled (and is specifically designed to be used by
| unprivileged processes).
| 1oooqooq wrote:
| namespace, specially user and net, are terrible to setup and
| use.
|
| I'm not sure this is better, but assuming it is by the author
| into.
| aw4y wrote:
| nice! it would be cool (since it's in Go) how to use it like a
| library, sandboxing some exec directly from your code.
| NewJazz wrote:
| https://pkg.go.dev/github.com/landlock-lsm/go-landlock/landl...
| gnoack wrote:
| (Author of that library here)
|
| It is a library, as already linked in the other comment:
| https://github.com/landlock-lsm/go-landlock
|
| The landrun tool is built on the same library. We also provide
| an official library for Rust, and obviously you can do it from
| C as well.
|
| I also collected some libraries for other languages at
| https://wiki.gnoack.org/SoftwareUsingLandlock (but I can not
| vouch for their quality in detail)
| teabee89 wrote:
| Nice work! Too bad it's GPL v2 :(
| yjftsjthsd-h wrote:
| When would that matter?
| allset_ wrote:
| The underlying library that does most of the work is MIT.
|
| https://github.com/landlock-lsm/go-landlock
| jbverschoor wrote:
| Imo, (almost) every directory should be treated as a new sandbox
| IshKebab wrote:
| Pretty much how Plan 9 works IIRC. I think Fuchsia might have a
| similar idea.
| zekrioca wrote:
| How does one do resource control with Landrun, e.g., CPU, memory,
| I/O..?
| IshKebab wrote:
| You can't. It's only for filesystem and TCP sandboxing.
| gnoack wrote:
| Exactly, for resource limits you can use setrlimit(2) or
| cgroups if needed.
| turrini wrote:
| Not directly, but I think you can run it with systemd:
|
| systemd-run --user --scope -p
| MemoryMax=1G,IOReadIOPSMax=8000,CPUQuota=20%,<...> landrun ...
| thiht wrote:
| How does the Landlock API compare to mount/network namespaces, as
| used in Docker containers? As I understand it, namespaces are for
| isolation, and Landlock would be more like access permissions, is
| that correct?
|
| Could it be possible for the system to use the Landlock api to
| catch unauthorized net/fs access by an app and display a popup to
| ask for authorization, like macOS does?
| gnoack wrote:
| (Landlock reviewer here)
|
| Namespaces can also be used for sandboxing, but they have a
| series of problems. Most importantly, they require more
| substantial changes to your program that wants to sandbox
| itself, and the program has to jump through a series of hoops
| to get everything into the right state. It is possible, but the
| resulting program environment is in the end more unusual and
| the mechanisms for enabling unprivileged namespaces are making
| it difficult to use it for smaller use cases. (It involves re-
| execution of the program that wants to sandbox itself, whereas
| with Landlock, a small program can just install a Landlock
| policy during an early startup phase and continue with that.)
|
| Controlling the rules through a separate process is not
| currently possible, but it was proposed earlier this month on
| the kernel mailing lists:
|
| https://lore.kernel.org/all/cover.1741047969.git.m@maowtm.or...
| thiht wrote:
| Great answer, thanks!
| l0kod wrote:
| Namespaces (used by containers) are very powerful but they are
| also a door to a large attack surface:
| https://lwn.net/Articles/673597/
|
| Landlock is (only) an access control system, but it's designed
| to let any process use it, including potentially untrusted
| ones, which makes it suitable for any apps. It's close and
| complementary to seccomp.
| dpc_01234 wrote:
| Seems like a Nix could take a good advantage of Landlock, as it
| already (kind of) knows all the paths processes need access to.
| qwertox wrote:
| My biggest problem with Linux is that there are no per-process
| firewall settings. I think one can get around this by using
| AppArmor or using an user per app and assigning rules to a user.
|
| I've used Linux for over a decade now, but there are still many
| things I haven't learned, so maybe I'm missing something in this
| regard.
|
| The GitHub page says
|
| - TCP network access control (binding and connecting)
|
| and
|
| - Support for UDP and other network protocol restrictions (when
| supported by Linux kernel)
|
| so maybe this can be used to firewall processes in an easy way
| (assuming that it is easy to set up landrun)?
| tobias2014 wrote:
| You can use firejail for network isolation, it can run
| applications in a new network namespace [1]. I'm using this to
| run applications over tor to make sure that nothing leaks.
|
| [1] https://firejail.wordpress.com/documentation-2/basic-
| usage/#... "A network namespace is a new, independent TCP/IP
| stack attached to the sandbox. The stack has its own routing
| table, firewall and set of interfaces."
| throwfaraway398 wrote:
| I saw there's an option to match on a cgroup among nft meta
| expressions (but I've never tried it). It could be enough if
| you just want to add per-process firewall rules, but not
| configure an additional namespace with it's associated
| interfaces, routing/nating.
| kanbankaren wrote:
| Yes. You could match packets based on username or even
| SELinux labels.
|
| You could also set a special mark on a packet for each
| container and then filter based on that. The Internet is
| surprsingly very thin on nft resources. I spent a few weeks
| learning how to write them. Definitely, not for the average
| consumer.
| nolist_policy wrote:
| > My biggest problem with Linux is that there are no per-
| process firewall settings.
|
| There is, with cgroups:
| https://www.kernel.org/doc/Documentation/cgroup-v1/net_cls.t...
| its-kostya wrote:
| Why not use linux network namespaces to run your processes in
| different network stack? nftables rules are per network
| namespaces so you can get all sorts of sophisticated and
| achieve essentially per process firewalling. The pattern is to
| create a network namespace, create a veth pair and move one end
| of the pair into the namespace. Then you could set up rules to
| route traffic from default namespace to the process namespace
| via veth device.
|
| Systemd has `NetworkNamespacePath` directive which can spin up
| services in new namespaces as well. See `man 5 systemd.exec`
| nickandbro wrote:
| This is great, I run a hobby project, vimgolf.ai, to get my
| friends to learn vim and had to do a lot with firejail to sandbox
| the neovim instances correctly. This looks be a lot easier to
| setup
| riobard wrote:
| Is it just me or Linux seems to have too many non-orthogonal ways
| to restrict processes? Like why Landlock does TCP filtering based
| on port only? What about non-TCP traffic and maybe IP based
| restrictions is more useful? How does it interact with Netfilter?
| Puzzling.
| l0kod wrote:
| It takes time to develop theses features, but Landlock is
| gaining new network filtering features. We are working in a way
| to control socket creation according to their protocols, and
| also a way to filter UDP (which makes sense to developers and
| users).
|
| From the point of view of an app developer, it might not make
| sense to filters peers but services (ports) instead, and
| filtering peers without their names would not be ideal (the
| kernel doesn't know about DNS, only IPs). Anyway, this feature
| might come one day if someone want to work on it, but we follow
| well-tested incremental development.
|
| Netfiler is a privileged network feature that allows to do
| almost anything with the network, which makes it unsuitable for
| (app/unprivileged) sandboxing.
| gnoack wrote:
| +1
|
| A rough description of upcoming network restriction features
| in Landlock and how they map to the BSD socket API is in the
| talk at https://youtu.be/K2onopkMhuM?start=2025 starting
| around 33:45
|
| I really hope we can get back to these features soon :) I
| think these would be very useful.
| btdmaster wrote:
| Very cool project! I was curious if this was possible with util-
| linux (provider of the unshare command that provides namespace
| management, the underlying feature behind containers), and it is
| indeed possible:
|
| setpriv --landlock-access 'fs:remove-file,remove-dir,write-
| file,make-reg' touch /tmp/foo # Permission denied
|
| setpriv --landlock-access 'fs:remove-file,remove-dir,write-
| file,make-reg' --landlock-rule "path-beneath:make-reg:/tmp" touch
| /tmp/foo # Allowed
|
| Very verbose unlike unshare and really deals with internal
| details, so I'd find it hard to use setpriv in practice.
___________________________________________________________________
(page generated 2025-03-22 23:00 UTC)