GithubHelp home page GithubHelp logo

go-landlock's People

Contributors

gnoack avatar tklauser avatar yaronf avatar

Stargazers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar

Watchers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar

go-landlock's Issues

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.

RestrictPaths needs to apply to all OS threads and Goroutines at once

The mapping of Goroutines to system threads is managed by the Go runtime and even at the start of main() you don't get the guarantee that there is only one OS thread active. (In fact, even the GC uses Goroutines, so it's clear to see this is difficult to guarantee.)

The same problem has already been discussed in the context of seccomp(2), which has the same semantics: golang/go#3405 @AndrewGMorgan is pointing to syscall.AllThreadsSyscall() as a way to apply a syscall to all Go-managed OS threads at once.

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

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)

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 opencontainers/runtime-spec#1111 (review)
Landlock access rules in spec file go in string format that is needed to be converted in AccessFSSet one:
image

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.

Do some exhaustive testing

I should do some exhaustive testing before tagging v1, to make sure golandlock works as expected.

  • It needs to work in the presence of multiple Goroutines (issue #5)
  • The shell script tests should ideally be ported to Go tests. (but how...?!?)

Missing license

Could you please pick (a) license(s) to make it open-source? As free as possible would be great. 😉

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

Minimal landlock not working with ffmpeg/ffprobe

Trying to sandbox a Go wrapper that calls ffprobe, code looks something like this:

package main

import (
	"fmt"
	"github.com/landlock-lsm/go-landlock/landlock"
	"os"
	"os/exec"
)

func main() {
	ffprobe, _ := exec.LookPath("ffprobe")
	file := "/path/to/file"

	err := landlock.V3.BestEffort().RestrictPaths(
		landlock.ROFiles("/dev/null"),
		landlock.ROFiles(ffprobe),
		landlock.ROFiles(file),
	)

	cmd := exec.Command(ffprobe,"-print_format", "json","-show_streams", file)
	out, err := cmd.Output()
	if err != nil {
		fmt.Fprintf(os.Stderr, "ffprobe encountered an error.\nError JSON:\n%s\nError: %s", string(out), err.Error())
	}
}

This always returns

/usr/bin/ffprobe
ffprobe encountered an error.
Error JSON:

Error: fork/exec /usr/bin/ffprobe: permission denied

Using strace, I see it fails with epoll_ctl(4, EPOLL_CTL_ADD, 3, {events=EPOLLIN|EPOLLOUT|EPOLLRDHUP|EPOLLET, data={u32=1363365560, u64=139699469635256}}) = -1 EPERM (Operation not permitted)

Is this a limitation from Landlock? Or is this something from the Go implementation?

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.

Make it possible to create composable libraries of Landlock rules

Users should be able to group their own libraries of commonly used rules that are used together

idea:

package llopts

import ...

var SharedLibraries = landlock.GroupRules(
    landlock.RODirs("/usr/lib", "/lib"),
    landlock.RWDirs(os.Getenv("TMPDIR")),
)

// Looking a bit into the future here with Network rules...
var DNSClient = landlock.GroupRules(
    landlock.ROFiles("/etc/hosts"),
    landlock.DialTCP(53),
    landlock.DialUDP(53),
)

(This is just an example -- the details of these rules are not really fleshed out)

Recommend Projects

  • React photo React

    A declarative, efficient, and flexible JavaScript library for building user interfaces.

  • Vue.js photo Vue.js

    🖖 Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.

  • Typescript photo Typescript

    TypeScript is a superset of JavaScript that compiles to clean JavaScript output.

  • TensorFlow photo TensorFlow

    An Open Source Machine Learning Framework for Everyone

  • Django photo Django

    The Web framework for perfectionists with deadlines.

  • D3 photo D3

    Bring data to life with SVG, Canvas and HTML. 📊📈🎉

Recommend Topics

  • javascript

    JavaScript (JS) is a lightweight interpreted programming language with first-class functions.

  • web

    Some thing interesting about web. New door for the world.

  • server

    A server is a program made to process requests and deliver data to clients.

  • Machine learning

    Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.

  • Game

    Some thing interesting about game, make everyone happy.

Recommend Org

  • Facebook photo Facebook

    We are working to build community through open source technology. NB: members must have two-factor auth.

  • Microsoft photo Microsoft

    Open source projects and samples from Microsoft.

  • Google photo Google

    Google ❤️ Open Source for everyone.

  • D3 photo D3

    Data-Driven Documents codes.