[HN Gopher] Landrun: Sandbox any Linux process using Landlock, n...
       ___________________________________________________________________
        
       Landrun: Sandbox any Linux process using Landlock, no root or
       containers
        
       Author : Zoup
       Score  : 440 points
       Date   : 2025-03-22 13:56 UTC (1 days 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.
        
             | mid-kid wrote:
             | Emulating /proc isn't super interesting when you can simply
             | enter a new process namespace.
        
           | BoingBoomTschak wrote:
           | Same question. One thing I really dislike in Bubblewrap is
           | that I must share the whole net user namespace even if all I
           | want to do is use UNIX domain sockets.
           | 
           | Since I only see net options specifying ports, does this
           | handle this use case?
        
         | 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.
        
               | Zoup wrote:
               | well yeah you'll need --exec when you want to run
               | binaries (unlike... cat?) I hope landlock adds support to
               | bind --exec to actual directories, that'll be fun!
        
               | ranger_danger wrote:
               | > you'll need --exec when you want to run binaries
               | 
               | well when _wouldn 't_ it do that? in what scenario could
               | you even use this tool without needing to execute a
               | binary?
        
               | Zoup wrote:
               | running cat isn't a --exec for one :)
        
               | ranger_danger wrote:
               | how so?
               | 
               | $ landrun --ro /usr/bin cat a
               | 
               | [landrun:error] 2025/03/22 23:50:16 permission denied
        
               | Zoup wrote:
               | in this case doesn't have access to "a" wherever it is...
               | 
               | $ landrun --ro /usr cat /usr/bin/ls | wc -l
               | 
               | 400
               | 
               | executing ls (as in actual binary execution) will require
               | --exec
               | 
               | $ landrun --ro /usr ls /usr/bin/
               | 
               | ls: cannot open directory '/usr/bin/': Permission denied
               | 
               | $ landrun --ro /usr --exec ls /usr/bin/
               | 
               | list of billions of files
               | 
               | note that I don't really love the --exec thingy, if it's
               | not "on" by default it's just for sake of being explicit.
               | 
               | Update: there's a bug to limit "file access", which I'll
               | fix asap.
               | 
               | Update2: Adding a --exec-path instead to limit
               | executable, it wasn't the best idea to have a global
               | --exec anyway
               | 
               | Update3: Have a look at V0.1.4, I think it's far cleaner
               | now.
        
               | ranger_danger wrote:
               | --ro /usr does not apply to /usr/bin. change it to --ro
               | /usr/bin and then cat will refuse to run.
        
               | Zoup wrote:
               | it's recursive by default
        
               | ranger_danger wrote:
               | well it's not working. please try it
        
               | Zoup wrote:
               | give it a try with v0.10: landrun --rox /usr/ --ro
               | /usr/lib ls /usr/bin/
        
           | 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.
        
               | codethief wrote:
               | From the README:
               | 
               | > Read the fine manuals of syd, libsyd, gosyd, plsyd,
               | pysyd, rbsyd, syd.el and watch the asciicasts Memory
               | Sandboxing, PID Sandboxing, Network Sandboxing, and
               | Sandboxing Emacs with syd.
               | 
               | I do agree, though, that the docs could be improved.
        
               | ammmir wrote:
               | thanks for the link, Sydbox seems like a super cool
               | project, but there's something weird about it: too many
               | links in the README. not on GitHub, and the project
               | that's on GitHub with a similar name hasn't had a commit
               | in 16 years, is it by the same person?
               | 
               | if they can polish up the public facing side of the
               | project, it would instill more confidence.
        
               | sudahtigabulan wrote:
               | > too many links in the README
               | 
               | In other documents too. And _very_ repetitive.
               | 
               | I don't need a link to Wikipedia _every time_ "PoC" is
               | used. Or to an online man page _every time_ strace(1) is
               | mentioned.
               | 
               | I get it that a documentation can have more than one
               | "entry point", and hyperlinking all occurrences solves
               | that.
               | 
               | But I think assuming certain audience leads to a document
               | that is more effective. You don't explain addition in
               | university-level textbooks, to make it easier to children
               | from primary school.
               | 
               | This product is simply not for people who hear of strace
               | for the first time.
        
               | yellowapple wrote:
               | Eh. Personally I find it refreshing to see a page err on
               | the side of too many links instead of too few. No need to
               | explain addition in any book if you can just link to the
               | best explanation available.
               | 
               | The bigger issue IMO is that the links seem to be
               | automatically-generated, and the generation is a bit
               | sloppy; for example, the "Syd" links should probably link
               | to the sandboxing technology instead of Pink Floyd's
               | original frontman.
        
               | sudahtigabulan wrote:
               | > the links seem to be automatically-generated, and the
               | generation is a bit sloppy; for example, the "Syd" links
               | 
               | I dare you, check the git history! (if you care anyway)
               | 
               | It's all manually crafted, with love. From the Shine On
               | You Crazy Diamond badge at the top down to the very last
               | link.
        
               | yellowapple wrote:
               | Fair enough lol
        
               | chuckadams wrote:
               | Some Wikipedia articles themselves do this, linking every
               | common word in the article, which makes trying to simply
               | highlight a section of text a fun adventure. I ended up
               | at one point making a userscript to strip all internally-
               | pointing links just to make an article more readable (as
               | an addition to an existing script that stripped all the
               | "[citation needed]" and other noise).
               | 
               | Wikipedia needs some notion of "suggested links" that
               | don't become links unless the text is selected or they're
               | toggled globally or some other explicit action. With
               | those, authors could go and link every last word if they
               | like.
        
               | tczMUFlmoNk wrote:
               | > which makes trying to simply highlight a section of
               | text a fun adventure
               | 
               | Tip: in Firefox, you can hold Alt to drag and select text
               | without triggering links.
        
               | chuckadams wrote:
               | TIL. I wish I knew years ago, I've never been happier to
               | have switched.
               | 
               | Still using Chrome for work stuff, since profile
               | management in FF is still pure hate.
        
               | seego wrote:
               | what's wrong with `firefox -ProfileManager` and the like
               | or alternatively containers?
        
               | chuckadams wrote:
               | I always seem to end up with duplicate profiles, or
               | `about:profiles` refuses to open ("Another copy of
               | Firefox has made changes to profiles.") and on and on
               | with various hiccups and speedbumps. Small annoyances,
               | but profiles on Chrome always Just Work, and the half-
               | dozen times I tried it on FF was always death by a
               | thousand cuts.
               | 
               | It's been a few years, so I'll give profiles another try
               | I guess. Containers likely won't do it since multiple
               | profiles all use the same domain (console.aws.amazon.com
               | being the obvious one).
        
               | codethief wrote:
               | I agree regarding polishing the public-facing side of the
               | project, though I don't find it particularly problematic
               | that it's not on Github.
        
           | Zoup wrote:
           | yeah you are missing --exec there, which feels a bit useless
           | that you have to mention it, but I prefer things explicit and
           | use all LSM can provide, I can imagine cases where --exec
           | isn't really required. like `cat`.
           | 
           | either case have a look at latest release, it's a bit
           | cleaner.
        
             | mikedelfino wrote:
             | Could you please help me understand why exec is required
             | for this touch example? Is it necessary to actually launch
             | the touch binary? Or touch itself exec()s something else?
        
               | extraduder_ire wrote:
               | This might be related to needing execute permissions
               | (filesystem x bit) on the directory to modify files
               | within.
        
               | mikedelfino wrote:
               | Got it. I thought it had to do with execve() syscall.
        
         | 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.
        
           | Zoup wrote:
           | Yeah I agree with that, just release a new version that does
           | that.
        
             | rainworld wrote:
             | Does Linux 6.8 in fact ship ABI v5? At least it's not
             | guaranteed (Ubuntu 24.04, 6.8.0-55-generic). This post
             | suggests 6.10: https://lore.kernel.org/landlock/20240716.yu
             | i4Iezai8ae@digik...
        
               | Zoup wrote:
               | good catch, fixed.
        
         | __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.
        
               | l0kod wrote:
               | For instance, with Pledge, the "dns" promise is
               | implemented with hardcoded path in the kernel. Linux is
               | complex because it is versatile and flexible. Controlling
               | access to such features requires some complexity and the
               | kernel might not be enough.
               | 
               | About interfaces, another example is that Unveil is
               | configured with path names but Landlock uses file
               | descriptors instead (more flexible).
               | 
               | Also, these OpenBSD primitives only apply to the current
               | executed binary, there is no nested sandboxes because the
               | goal is not to create this kind of secure environment but
               | mainly to secure a _trusted_ binary.
        
               | mkj wrote:
               | For a given linux libc function (what a program calls),
               | the underlying kernel syscall might change over time or
               | vary for other reasons. Since the landlock/seccomp
               | filters are at the kernel level, that breaks programs
               | which only interact with libc calls and don't expect
               | different behaviour.
        
               | yellowapple wrote:
               | The underlying kernel syscall should never change,
               | though, right? Pretty sure that's the sort of userspace-
               | backwards-compatibility-breaking change that would result
               | in one of Linus' famous angry emails.
        
               | mkj wrote:
               | Things like clock_gettime64() to handle dates past 2038.
               | 
               | Calling clock_gettime() in libc will call the newer
               | syscall (assuming __TIME_BITS=64 is set). But Linux has
               | kept backwards compat, old programs can still call the
               | old syscall.
               | 
               | If you wrote your seccomp rule for your program before
               | clock_gettime64 existed, it'd break when glibc switched.
               | I guess that implies each language stdlib should have
               | their own seccomp etc wrappers.
               | 
               | For landlock, the equivalent is that glibc reads various
               | files in /etc varying per libc version or system
               | settings, so landlock rules need to account for that.
        
               | __turbobrew__ wrote:
               | > Since the landlock/seccomp filters are at the kernel
               | level
               | 
               | That arguably shows that seccomp is operating at the
               | wrong abstraction level, or the kernel needs another
               | higher level api. With pledge, you operate on
               | capabilities and as new functionality is added to the
               | kernel it is categorized under existing capabilities (for
               | example, if your program pledges not to use networking
               | you can assume that it should not be able to use new
               | networking syscalls added to the kernel in the future).
        
           | 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.
        
           | bjconlan wrote:
           | This is where I need to shout out to everyone's favorite
           | developer Justine for keeping Linux cool:
           | 
           | https://justine.lol/pledge/
           | 
           | Which also points to landlock-make[0] or vice-versa (the
           | original project that made me aware of the kernel
           | functionality (although didn't realize it also isolated
           | network which is great).
           | 
           | [0]https://justine.lol/make/
        
           | charcircuit wrote:
           | I disagree. Android's model of starting with a strong sandbox
           | and having apps request permission to acces things outside of
           | it has been much more successful in getting apps to be
           | sandboxed.
           | 
           | Defaults are important.
        
             | zzo38computer wrote:
             | I think that isn't good enough either (but at least they
             | tried).
             | 
             | My operating system design is: programs start with nothing
             | other than the ability to perform deterministic computation
             | and to send/receive messages with the capabilities it
             | receives in the initial message. It is not allowed to know
             | what these capabilities refer to; they may be proxies set
             | up by the user, network resources, or something else, and
             | is not necessarily what it asked for. All I/O including the
             | ability to determine the current date/time or how much time
             | has passed, requires the use of capabilities. (Due to this,
             | a program with no capabilities left can be terminated
             | automatically by the operating system (unless a debugger is
             | attached; it is also necessary that the program cannot
             | notice the debugger attached to it), since it is no longer
             | capable of any I/O.)
        
               | charcircuit wrote:
               | Is argue it is good enough, but yes it could have gone
               | farther. But ultimately permissions for things like audio
               | would be automatically granted so in the end you end up
               | around the same place.
        
         | 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.
        
           | dsp_person wrote:
           | aren't abstract sockets un-jailable unless using network
           | namespaces?
           | 
           | or in the other direction, to truly prevent e.g. xorg socket
           | from being accessed by a bubblejailed application, it should
           | exclude --share-net, regardless if you bind the actual path
           | to the socket (since abstract permeates beyond that)
        
             | trikko wrote:
             | Well, so should it work?
             | 
             | You're telling me there's another reason, then... Can't
             | guess which one.
             | 
             | Hmmm...
        
               | Zoup wrote:
               | they can be jailed by landlock, we don't have support in
               | go-landlock tho afaik, @Gnoack
        
               | gnoack wrote:
               | It's tracked in https://github.com/landlock-lsm/go-
               | landlock/issues/35 - signals and abstract Unix sockets do
               | unfortunately not interact well with the inherently
               | multithreaded Go runtime. We are working on a fix in
               | https://github.com/landlock-lsm/go-landlock/issues/36 but
               | this needs to be on the kernel side and this is delaying
               | this feature in Go, unfortunately. It is usable from
               | (single threaded) C programs though.
        
               | Zoup wrote:
               | Thanks!
        
         | Zoup wrote:
         | V0.1.3 is out now!
        
         | JohnTheSealion wrote:
         | How does Landrun compare to Firejail?
        
         | rmccue wrote:
         | I'd recommend adding your first (and maybe second) paragraphs
         | directly to your readme - this is a much clearer description if
         | you don't know what landlock is already!
        
       | 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)
        
           | Zoup wrote:
           | Great job on the lib, thank you!
        
       | 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
        
         | Zoup wrote:
         | haha, why!
        
       | 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.
        
           | anthk wrote:
           | Not directory but maybe processes with namespaces. rfork
           | controls that, and then you have bind.
        
           | jbverschoor wrote:
           | I made shell-container for myself which works fine for me
           | (link below). I just run shell and I'm in a new/stateful
           | container with only that for mounted. Works pretty well, but
           | has some quirks here and there
           | 
           | https://github.com/jrz/container-shell
        
       | 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!
        
           | bjackman wrote:
           | I think in the upstream kernel LSMs are also still the only
           | way to prevent a process from creating child namespaces where
           | it has privileges?
           | 
           | E.g. if you can cat CAP_NET_ADMIN even within a restricted
           | namespace, you have access to huge amounts of horrbly broken
           | kernel code. It's easy (for people who know how to exploit
           | kernel bugs) to escalate privileges from there.
           | 
           | Distros have their own fixes for this issue so namespaces
           | definitely aren't useless in practice for sandboxing. But the
           | basic mechanism just doesn't that well suited to it.
        
             | anybody8824 wrote:
             | The user.max_user_namespaces sysctl itself is namespace
             | aware and is used by bubblewrap's --disable-userns option.
             | 
             | But a prctl like NO_NEW_PRIVS would be better, since it
             | could avoid an intermediary namespace that is needed for
             | the namespace-aware sysctl.
        
               | bjackman wrote:
               | Ah I didn't know about that. So you can block the child
               | from creating a userns completely... That seems like an
               | unnecessarily big hammer, but also probably 95% of cases
               | works fine?
               | 
               | I think probably we want an inherited mask of what
               | capabilities you can get in child namespaces. I think I
               | heard someone proposed that upstream but I haven't seen
               | the patches.
        
               | o11c wrote:
               | NO_NEW_PRIVS is quite irritating in a lot of contexts,
               | since it breaks distant dependencies. For example, you
               | can't run `ping`, so good luck debugging your networking!
        
         | 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...
        
           | NewJazz wrote:
           | Is there an example of this that uses cgroup2?
        
             | zokier wrote:
             | https://www.freedesktop.org/software/systemd/man/latest/sys
             | 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`
        
           | mikedelfino wrote:
           | I'm not sure about the other commenter's intentions, but on
           | desktop, I wish every program started in a restricted network
           | namespace. Instead of blocking all incoming and outgoing
           | connections by default, it would request user permission
           | interactively and adjust access accordingly.
        
             | ranger_danger wrote:
             | opensnitch does this
        
               | y7 wrote:
               | Are you sure? Because last I checked OpenSnitch used
               | different techniques from namespaces, that seemed more
               | brittle to me.
        
               | ranger_danger wrote:
               | I was referring to "request user permission interactively
               | and adjust access accordingly"... it can do that. It uses
               | eBPF though
        
           | ranger_danger wrote:
           | My biggest issue with using namespaces is that it bypasses
           | the main host firewall entirely.
        
             | its-kostya wrote:
             | That depends on how you set it up, it doesn't have to
             | bypass the "main host" firewall. Consider the following
             | example:
             | 
             | 0. If you set up no additional network namespaces, there is
             | still one present, this is called the "default" or "root"
             | network namespace. It is what you refered to as "main
             | host".
             | 
             | 1. Say the default net ns has device eth0 that your server
             | receives traffic on.
             | 
             | 2. You create a veth pair in the default net ns, veth0 and
             | veth1.
             | 
             | 3. You create a new net ns and move veth1 into new net ns.
             | Only veth0 and eth0 remain in default net ns.
             | 
             | 4. You set up routes and nftable rules in default net ns as
             | you would normally. Certain traffic you want to route to
             | your new net is so you have a next hop veth0 (note, you ha
             | e to route through to the IP of veth1, using veth0 as next
             | hop)
             | 
             | 5. You set up additional nftable rules and whatever you
             | want in the new net ns and this is isolated from default
             | net ns.
             | 
             | End-to-end flow: packet arrives on eth0, traverses
             | netfilter (nftables/iptables) and route lookup to route to
             | "new network" via veth0. Packet is sent "out" the default
             | net stack via veth0 and arrives on veth1 (since they are a
             | pair) in new net ns network stack. There, the packet
             | traverses an isolated netfilter and routing table and a
             | socket can be listening for your service or whatever.
             | Replies would follow the same in reverse. Sent out veth1 in
             | new net ns, arrive on veth0 in default net ns, and exit
             | that stack via eth0
        
               | ranger_danger wrote:
               | I was speaking from a defensive security point of view
               | and not a server trying to route traffic.
               | 
               | The fact that local users can simply create namespaces
               | that bypass the host's firewall is extremely dangerous in
               | my opinion.
        
         | fulafel wrote:
         | Attaching a separate firewall rules to every process would be a
         | bit heavyweight. What we do have is network namespaces that let
         | you have networking rules (incl firewall) per a group of
         | processes.
        
           | 1oooqooq wrote:
           | that's what all firewall apps on Android (bastardized Linux)
           | does.
           | 
           | well, they already have a user namespace per app which they
           | can match on the firewall rule, but a per "main" program pid
           | net namespace would be pretty much the same. i guess this can
           | be a cool patch to this plus a one weekend qt+rust gui to
           | manage the firewall (or a patch to firewalld gui)... only if
           | i ever had a weekend.
        
       | 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.
        
       | khrbtxyz wrote:
       | I don't quite understand what --exec does. If I leave out --exec
       | from example 3, is it supposed to prevent bash from executing
       | other programs?                 $ landrun --log-level debug --ro
       | /usr/bin,/lib,/lib64 /usr/bin/bash --norc       [landrun]
       | 2025/03/22 17:16:29 Sandbox config: {ReadOnlyPaths:[/usr/bin /lib
       | /lib64] ReadWritePaths:[] AllowExec:false BindTCPPorts:[]
       | ConnectTCPPorts:[] BestEffort:true}       [landrun:debug]
       | 2025/03/22 17:16:29 Adding read-only path: /usr/bin
       | [landrun:debug] 2025/03/22 17:16:29 Adding read-only path: /lib
       | [landrun:debug] 2025/03/22 17:16:29 Adding read-only path: /lib64
       | [landrun:debug] 2025/03/22 17:16:29 Applying Landlock
       | restrictions       [landrun] 2025/03/22 17:16:29 Landlock
       | restrictions applied successfully       [landrun] 2025/03/22
       | 17:16:29 Executing: [/usr/bin/bash --norc]       bash-5.2$
       | bash-5.2$ /usr/bin/uname -r       6.13.7-200.fc41.aarch64
        
         | Zoup wrote:
         | yeah it wasn't the best call, have a look at v0.1.4, I think
         | it's better now!
        
       | Zoup wrote:
       | Thank you all for your support, I really didn't expect this to
       | take off like this! given that project is roughly two days old
       | (:D) it's still fair to expect some issues all around, please
       | report them on GH if you found one.
        
       | johnisgood wrote:
       | I will just leave this here:
       | https://man.archlinux.org/man/firejail.1
       | 
       | And someone also said, but Firejail supports Landlock, too:
       | https://github.com/netblue30/firejail/pull/6078.
        
       | aucisson_masque wrote:
       | Would that make feasible (in the long term) to have macOS
       | permission manager like << do you want terminal to access
       | documents folder ? >> on Linux ?
       | 
       | As a very average user, that's the kind of thing I miss on
       | windows and Linux.
       | 
       | Because I installed Google chrome, it doesn't mean I want it to
       | be able to scan every single file I have on my computer yet there
       | is no way to prevent it and I feel it's a big security and
       | privacy issue that no one speak about !
        
         | mikedelfino wrote:
         | You might find Flatpak interesting if you're not already
         | familiar with it. Properly packaged applications start with
         | limited file system access--for example, when you browse
         | file:/// in Firefox, it can't see all your files. However,
         | using the "Open File" menu acts as a file system portal,
         | granting access to selected files on demand. While this isn't
         | exactly how macOS handles permissions, it does prevent the
         | unrestricted system access you're concerned about.
        
         | marcthe12 wrote:
         | Thats is xdg-portals and it works. It needs apps to support it
         | though which slows adoption
        
       | borplk wrote:
       | Weird question, but would this work inside docker as "extra
       | protection"?
        
         | Zoup wrote:
         | well yeah maybe, if you like.
        
       | zahlman wrote:
       | I get that the "o" in "--ro" is supposed to stand for "only", but
       | this feels clunky to me (especially if there's also a "--rox",
       | which is self-contradictory). I like my long options to be, well,
       | long (complete English words), and backed up by short options. In
       | this case, I'd propose having "-r, --read, -w, --write, -x,
       | --exec", and allowing the short options to be combined as flags
       | (i.e. -rwx).
        
         | Zoup wrote:
         | ROX isn't self-contradictory, Allowing read() and execve(), but
         | denying write() and truncate() are totally valid and common in
         | secure execution contexts, although things gets worse with
         | directory traverse.
         | 
         | So yeah, --rox is fine semantically, just ugly. :D
        
       | simjnd wrote:
       | Super cool project. Justine Tunney released the `pledge` cli [1]
       | a couple years ago that does the same thing, wrapping Landlock.
       | 
       | [1]: https://justine.lol/pledge/
        
       | Zoup wrote:
       | V0.1.11 out, with env support and bunch of other fixes, update!
        
       | teleforce wrote:
       | There's very nice presentation on Landlock in the last year Open
       | Source Europe Summit Europe [1].
       | 
       | [1] Linux Sandboxing with Landlock - Mickael Salaun, Microsoft
       | [video]:
       | 
       | https://youtu.be/d85TDpv8L9U
        
       ___________________________________________________________________
       (page generated 2025-03-23 23:01 UTC)