A Go library for the Linux Landlock sandboxing feature

Overview

Go Landlock library

The Go Landlock library restricts the current processes' ability to use files, using Linux 5.13's Landlock feature. (Package documentation)

For a more low-level interface, please see the landlock/syscall package.

This package used to be located at github.com/gnoack/golandlock. Please update your import paths to point to github.com/landlock-lsm/go-landlock/landlock.

Comments
  • Move golandlock under landlock-lsm

    Move golandlock under landlock-lsm

    Let's move golandlock into github.com/landlock-lsm, as offered by @l0kod.

    Constraints:

    • The imported Go package name (last part of path) should only contain letters
      • underscores not recommended, dashes don't work
      • Only applies to last path component. It can also be nested in an additional subdirectory and that wouldn't look completely wrong.
      • Prior art: the popular package github.com/go-cmp/cmp and others (I grepped my own Go imports and found a few)
    • There is already github.com/landlock-lsm/rust-landlock, and naming it similarly would be logical.
    • Let's move it sooner rather than later before the old location is used too much

    Proposal

    Let's move it to: github.com/landlock-lsm/go-landlock/landlock The name is a little bit repetitive, but:

    • last path component is just "landlock" and that would read nicely when the package is being used.
    • It's consistent with the location of the Rust package

    What we'd need to do

    Copy the repo into the desired location. Important: We should remove the git tag while doing so, so that the Go tooling doesn't interpret the new location as a stable Go module.

    (I suspect that the right way to copy this over is like this: https://docs.github.com/en/github/creating-cloning-and-archiving-repositories/creating-a-repository-on-github/duplicating-a-repository so that it's not a "fork" in the Github sense, but stays disconnected from the original location?)

    In the new git repo:

    • move the Go packages into a new "landlock" subdirectory
    • adapt the spelled-out package paths in all locations

    In the old git repo: Add a big warning pointing to the new location.

    Alternatives considered

    There is also https://docs.github.com/en/github/administering-a-repository/managing-repository-settings/transferring-a-repository If I'm reading this correctly that would make the repo accessible under both the new location and the old location (as redirect). I suspect that wouldn't play well with the Go tooling, where the modules spell out their own location in some places.

    opened by gnoack 10
  • Presence of CGO breaks the prctl call

    Presence of CGO breaks the prctl call

    Since fixing #5, the presence of the net/http package breaks the (slightly altered) prctl invocation.

    To reproduce on kernel 5.13, import

    import (
      _ "net/http"
    )
    

    and immediately call golandlock.V1.RestrictPath() in main().

    Observed results:

    2021/07/24 18:24:01 Landlock: Landlock v1: prctl(PR_SET_NO_NEW_PRIVS): operation not supported
    exit status 1
    

    Expected results: should have worked

    opened by gnoack 7
  • Make Restrict() future-proof

    Make Restrict() future-proof

    This package does not provide stability guarantees yet, and we need to fix the API so that we can provide these guarantees.

    Things I'd like to fix:

    • Arguments: When calling Restrict, it's difficult to tell apart which of the arguments is which. They all have the same type.
    • Flexibility: There is little flexibility to use different sets of permissions other than the four built-in ones. (Also see bug #3)
    • Future Landlock compatibility: The backwards compatibility story for future versions of Landlock is unclear: To make sure that calling programs don't break when golandlock starts supporting a future Landlock ABI v2, callers will need to take action to update to new versions at some point.
    • Old kernel compatibility: The backwards compatibility story for older kernels is unclear: As @l0kod pointed out, as soon as Landlock will have multiple ABI levels, there will be a use case for graceful degradation on old kernels, where the Restrict() call should lock permissions down as much as possible given the kernel that it's running on. Other users might want to still fail in that case though.

    Prior art for backwards compatibility: @l0kod's rust-landlock supports multiple backwards compatibility strategies. (See ErrorThreshold enum)

    opened by gnoack 7
  • pathOpt struct external usage

    pathOpt struct external usage

    Dear Günther! Is it possible to make pathOpt structure for external usage cause it would be convenient in runc/containerd implementation? image

    It could be easily parsed from runc spec .json and into opts array directly and then fed to RestrictPaths(opts ...pathOpt) function

    opened by BoardzMaster 6
  • Ensure that PathAccess(...).accessFS ⊆ cfg.handledAccessFS

    Ensure that PathAccess(...).accessFS ⊆ cfg.handledAccessFS

    Ensure that

    PathAccess(...).accessFS ⊆ cfg.handledAccessFS

    for all path options constructed with PathAccess().

    This is a conservative choice, but it's easier to enforce that way.

    RODirs() and friends are more "magic" - they let you give broad access permissions on entire directories, and that is supposed to work even when the user specifies a smaller AccessFSSet in their config. On the other hand, when users pass a custom AccessFSSet to PathAccess(), they should have a clear understanding of the configuration that they will use it in, and it can be expected that they ensure it is a subset.

    Examples

    This is a good example. On library upgrade, it should be enough to bump the version number, in most cases. Note that a Go-landlock library that supports V3 at some point still needs to do the exact same thing in the V2 case though:

    landlock.V2.BestEffort().RestrictPaths(
      landlock.RODirs("/bin", "/usr", "/etc"),
      landlock.RWDirs("/tmp"),
    )
    

    This is a good example as well. Making and removing directories is forbidden everywhere except in /tmp.

    landlock.MustConfig(landlock.AccessFSSet(ll.AccessFSMakeDir|ll.AccessFSRemoveDir)).BestEffort().RestrictPaths(
      landlock.RWDirs("/tmp"),
    )
    

    This is a good example as well. Making and removing directories is forbidden, except in /tmp and creating them in /home/x/tmp. It's verbose, but the author knows exactly what is being restricted and what is the scope of each exception:

    landlock.MustConfig(landlock.AccessFSSet(ll.AccessFSMakeDir|ll.AccessFSRemoveDir)).BestEffort().RestrictPaths(
      landlock.PathAccess(landlock.AccessFSSet(ll.AccessFSMakeDir|ll.AccessFSRemoveDir), "/tmp"),
      landlock.PathAccess(landlock.AccessFSSet(ll.AccessFSMakeDir), "/home/x/tmp"),
    )
    

    The following example is on the fence:

    • It's a good example as long as the author has checked that "transmogrify" is captured in Landlock ABI V99.
    • It's a bad example if the author has not checked that. If "transmogrify" is not part of Landlock ABI V99, it's very likely to be a programmer mistake, and it would be better to give an error in that case.
    landlock.V99.BestEffort().RestrictPaths(
      landlock.PathAccess(landlock.AccessFSSet(ll.AccessTransmogrifyFile), "/tmp"),
    )
    

    This last case is the one that the bug is about.

    opened by gnoack 3
  • landlock/syscall: use syscall.AllThreadsSyscall{,6} directly

    landlock/syscall: use syscall.AllThreadsSyscall{,6} directly

    Go 1.16 added the AllThreadsSyscall{,6} functions to the syscall package. The kernel.org/pub/linux/libs/security/libcap/psx package merely wraps these for Go 1.16 and newer (and implements them using cgo for older Go versions).

    This package's go.mod specifies version 1.16. Thus, AllThreadsSyscall{,6} can be used directly from package syscall.

    opened by tklauser 3
  • Make the handledAccessFS set configurable.

    Make the handledAccessFS set configurable.

    Compare https://github.com/opencontainers/runtime-spec/pull/1111#pullrequestreview-739022043

    from @kailun-qin:

    Removing the abi field from the config and will leverage the explicit access rights specified.

    In this case, I think we need direct access to ruleset.handledAccessFS in go-landlock?

    opened by gnoack 3
  • Add Landlock V2 support.

    Add Landlock V2 support.

    This adds support for the upcoming Landlock ABI V2.

    In addition to the existing file system access rights, it is now possible to move or link files across different directories with the new 'refer' access right. (For details, see Landlock documentation.)

    Changes in the library:

    • Introduce landlock.V2 config as a way to explicitly ask for this ABI level for users.
    • Introduce syscall.AccessFSRefer constant for the new "refer" right.
    • Add PathOpt.WithRefer() method so that users can ask for "refer" right.
    • The semantics of RWDirs() stay unmodified.

    The 'refer' access right for a path may only be specified handledAccessFS also contains it (i.e. by using the landlock.V2 config).

    Upgrade path:

    Callers using the landlock.V1.BestEffort().RestrictPaths(...) form can switch to use landlock.V2.BestEffort().RestrictPaths(...) with the same parameters instead. This change is compatible with before.

    If you additionally desire to link or move files between directories, make sure that both directories have the "refer" access right, by calling .WithRefer() on their landlock.PathOpt objects. For example:

    err := landlock.V2.RestrictPaths(
        landlock.RWDirs("/src", "/dest").WithRefer(),
    )
    

    NOTE: Requiring the "refer" access right is incompatible with kernels before 5.19. If you want to use Landlock with earlier kernels, do not ask for that permission.

    In particular, this means that using "best effort mode" in combination with the refer right will downgrade to "doing nothing" on kernels below 5.19, as linking and moving files would otherwise not work:

    // Downgrades to no Landlock enforcement on Linux kernels before 5.19.
    err := landlock.V2.BestEffort().RestrictPaths(
        landlock.RWDirs("/src", "/dest").WithRefer(),
    )
    

    Resolves #20.

    opened by gnoack 2
  • Auto-generated documentation

    Auto-generated documentation

    As for https://github.com/landlock-lsm/rust-landlock/pull/13, I think it would be nice to update the API documentation as soon as it get merged.

    I guess we could use https://code.rocketnine.space/tslocum/godoc-static

    opened by l0kod 1
  • Add Landlock V2 support.

    Add Landlock V2 support.

    This adds preliminary support for the upcoming Landlock ABI V2.

    In addition to the existing file system access rights, it is now possible to move or link files across different directories with the new 'refer' access right. (For details, see Landlock documentation.)

    Changes in the library:

    • Introduce landlock.V2 config as a way to explicitly ask for this ABI level for users.
    • Introduce syscall.AccessFSRefer constant for the new "refer" right.
    • Add PathOpt.WithRefer() method so that users can ask for "refer" right.
    • The semantics of RWDirs() stay unmodified.

    The 'refer' access right for a path may only be specified handledAccessFS also contains it (i.e. by using the landlock.V2 config).

    Upgrade path:

    Callers using the landlock.V1.BestEffort().RestrictPaths(...) form can switch to use landlock.V2.BestEffort().RestrictPaths(...) with the same parameters instead. This change is compatible with before.

    If you additionally desire to link or move files between directories, make sure that both directories have the "refer" access right, by calling .WithRefer() on their landlock.PathOpt objects. For example:

    err := landlock.V2.RestrictPaths( landlock.RWDirs("/src", "/dest").WithRefer(), )

    NOTE: Requiring the "refer" access right is incompatible with kernels before 5.19. If you want to use Landlock with earlier kernels, do not ask for that permission.

    In particular, using "best effort mode" in combination with the refer right will downgrade to "doing nothing" on kernels below 5.19, as linking and moving files would otherwise not work:

    err := landlock.V2.BestEffort().RestrictPaths( landlock.RWDirs("/src", "/dest").WithRefer(), )

    Resolves #20.

    opened by gnoack 1
  • Use constants from golang.org/x/sys/unix

    Use constants from golang.org/x/sys/unix

    Use the LANDLOCK_ACCESS_*, LANDLOCK_CREATE_RULESET_VERSION and LANDLOCK_RULE_PATH_BENEATH defined in the golang.org/x/sys/unix package. These are generated from the Linux kernel UAPI headers.

    opened by tklauser 1
  • Add a Github workflow for executing the tests in Qemu on actual kernels.

    Add a Github workflow for executing the tests in Qemu on actual kernels.

    @l0kod This is running the go-landlock tests as Github actions on qemu... (It's based on the example at https://github.com/florianl/bluebox/blob/main/.github/workflows/example.yml by @florianl)

    Some unsolved logistics problems:

    • It probably uses a few more CPU cycles than regular tests, but it might be worth it.
    • If we use something like this, it would also be good to host the kernel images in a better place than my personal repo. Do you already have a place for such a use case where Landlock-enabled kernels can be fetched?
    opened by gnoack 7
  • Converting allowedAccess strings into AccessFSSet uint64

    Converting allowedAccess strings into AccessFSSet uint64

    Hi Günther! Could you please add a function which converts allowedAccess strings like { "execute, "writefile....} into AccessFSSet uint64. There is already func (a AccessFSSet) String() string {....}. It would be nice to have the one that does the opposite work.

    According to the last commit in https://github.com/opencontainers/runtime-spec/pull/1111#pullrequestreview-739022043 Landlock access rules in spec file go in string format that is needed to be converted in AccessFSSet one: image

    opened by BoardzMaster 4
  • Fallback mechanism for non-existent files

    Fallback mechanism for non-existent files

    Does golandlock need a fallback mechanism for non-existent files?

    This occurred to me when landlocking some real-life programs; there are some files, such as ~/.Xauthority or various configuration directories, which probably should show up in some programs' path restrictions, but that should be permitted to be missing. (You don't have a .Xauthority on a Wayland-only system, for instance)

    Rough idea:

    golandlock.V1.RestrictPaths(
        golandlock.RODirs(".Xauthority", ".gtkrc").IfPresent(),  // may be missing
        golandlock.RODirs("/usr", "/lib"),  // always need to exist
    )
    

    Need to think about it.

    opened by gnoack 5
Owner
Landlock LSM
Unprivileged access control
Landlock LSM
MCsniperGO, a fast, efficient, and feature-packed minecraft name sniper.

MCsniperGO This project was made possible by my donators Usage This sniper is in it's beta stage, meaning bugs should be expected. Easy installation d

Kqzz 125 Dec 31, 2022
Perforator is a tool for recording performance metrics over subregions of a program using the Linux "perf" interface.

Perforator Perforator is a tool for recording performance metrics over subregions of a program (e.g., functions) using the Linux "perf" interface.

Zachary Yedidia 34 Dec 15, 2022
Package ethtool allows control of the Linux ethtool generic netlink interface.

ethtool Package ethtool allows control of the Linux ethtool generic netlink interface.

Matt Layher 47 Dec 14, 2022
Automatically set GOMAXPROCS to match Linux container CPU quota.

automaxprocs Automatically set GOMAXPROCS to match Linux container CPU quota. Installation go get -u go.uber.org/automaxprocs Quick Start import _ "go

Uber Go 2.4k Dec 29, 2022
📋 cross-platform clipboard package that supports accessing text and image in Go (macOS/Linux/Windows/Android/iOS)

clipboard Cross platform (macOS/Linux/Windows/Android/iOS) clipboard package in Go import "golang.design/x/clipboard" Features Cross platform supports

The golang.design Initiative 315 Dec 24, 2022
A fully Go userland with Linux bootloaders! u-root can create a one-binary root file system (initramfs) containing a busybox-like set of tools written in Go.

u-root Description u-root embodies four different projects. Go versions of many standard Linux tools, such as ls, cp, or shutdown. See cmds/core for m

null 2k Dec 29, 2022
Execute a binary from memory, without touching the disk. Linux only.

Memit Execute a binary from memory, without touching the disk. Linux only. Available as both a Go module and a binary. Using the Go module The Command

Liam Galvin 266 Jan 5, 2023
Govalid is a data validation library that can validate most data types supported by golang

Govalid is a data validation library that can validate most data types supported by golang. Custom validators can be used where the supplied ones are not enough.

null 61 Apr 22, 2022
Maintain a lower-bitrate copy of a music library in sync with the main copy.

msync Maintain a lower-bitrate copy of your music library, in sync with the main copy.

Chris Dzombak 18 Mar 6, 2022
Golang library to act on structure fields at runtime. Similar to Python getattr(), setattr(), hasattr() APIs.

go-attr Golang library to act on structure fields at runtime. Similar to Python getattr(), setattr(), hasattr() APIs. This package provides user frien

Shyamsunder Rathi 28 Dec 16, 2022
Go library for HTTP content type negotiation

Content-Type support library for Go This library can be used to parse the value Content-Type header (if one is present) and select an acceptable media

Elviss Strazdins 42 Jul 10, 2022
A tool and library for using structural regular expressions.

Structural Regular Expressions sregx is a package and tool for using structural regular expressions as described by Rob Pike (link).

Zachary Yedidia 41 Dec 7, 2022
A super simple Lodash like utility library with essential functions that empowers the development in Go

A simple Utility library for Go Go does not provide many essential built in functions when it comes to the data structure such as slice and map. This

Rahul Baruri 134 Jan 4, 2023
go-sysinfo is a library for collecting system information.

go-sysinfo go-sysinfo is a library for collecting system information. This includes information about the host machine and processes running on the ho

elastic 220 Dec 26, 2022
Molecule is a Go library for parsing protobufs in an efficient and zero-allocation manner

Molecule Molecule is a Go library for parsing protobufs in an efficient and zero-allocation manner. The API is loosely based on this excellent Go JSON

Richard Artoul 376 Jan 5, 2023
A Go (golang) library for parsing and verifying versions and version constraints.

go-version is a library for parsing versions and version constraints, and verifying versions against a set of constraints. go-version can sort a collection of versions properly, handles prerelease/beta versions, can increment versions, etc.

HashiCorp 1.3k Jan 9, 2023
A library for parsing ANSI encoded strings

Go ANSI Parser converts strings with ANSI escape codes into a slice of structs that represent styled text

Lea Anthony 37 Sep 20, 2022
go generate based graphql server library

gqlgen What is gqlgen? gqlgen is a Go library for building GraphQL servers without any fuss. gqlgen is based on a Schema first approach — You get to D

99designs 8.5k Dec 29, 2022
This is Go library for building GraphQL client with gqlgen

gqlgenc What is gqlgenc ? This is Go library for building GraphQL client with gqlgen Motivation Now, if you build GraphQL api client for Go, have choi

Yamashou 288 Jan 7, 2023