container: optionally isolate host abstract UNIX domain sockets via landlock
Some checks failed
Test / Create distribution (push) Failing after 52s
Test / Sandbox (push) Successful in 2m22s
Test / Sandbox (race detector) (push) Successful in 4m4s
Test / Planterette (push) Successful in 4m3s
Test / Create distribution (pull_request) Failing after 29s
Test / Sandbox (pull_request) Successful in 40s
Test / Sandbox (race detector) (pull_request) Successful in 41s
Test / Planterette (pull_request) Successful in 41s
Test / Hakurei (push) Failing after 20m46s
Test / Hakurei (race detector) (push) Failing after 22m7s
Test / Flake checks (push) Has been skipped
Test / Hakurei (pull_request) Failing after 34m54s
Test / Hakurei (race detector) (pull_request) Failing after 36m37s
Test / Flake checks (pull_request) Has been skipped
Some checks failed
Test / Create distribution (push) Failing after 52s
Test / Sandbox (push) Successful in 2m22s
Test / Sandbox (race detector) (push) Successful in 4m4s
Test / Planterette (push) Successful in 4m3s
Test / Create distribution (pull_request) Failing after 29s
Test / Sandbox (pull_request) Successful in 40s
Test / Sandbox (race detector) (pull_request) Successful in 41s
Test / Planterette (pull_request) Successful in 41s
Test / Hakurei (push) Failing after 20m46s
Test / Hakurei (race detector) (push) Failing after 22m7s
Test / Flake checks (push) Has been skipped
Test / Hakurei (pull_request) Failing after 34m54s
Test / Hakurei (race detector) (pull_request) Failing after 36m37s
Test / Flake checks (pull_request) Has been skipped
This commit is contained in:
parent
6ba19a7ba5
commit
7add29b79c
@ -29,6 +29,8 @@ type appInfo struct {
|
|||||||
// passed through to [hst.Config]
|
// passed through to [hst.Config]
|
||||||
Net bool `json:"net,omitempty"`
|
Net bool `json:"net,omitempty"`
|
||||||
// passed through to [hst.Config]
|
// passed through to [hst.Config]
|
||||||
|
ScopeAbstract bool `json:"scope_abstract,omitempty"`
|
||||||
|
// passed through to [hst.Config]
|
||||||
Device bool `json:"dev,omitempty"`
|
Device bool `json:"dev,omitempty"`
|
||||||
// passed through to [hst.Config]
|
// passed through to [hst.Config]
|
||||||
Tty bool `json:"tty,omitempty"`
|
Tty bool `json:"tty,omitempty"`
|
||||||
|
@ -83,6 +83,8 @@ type (
|
|||||||
RetainSession bool
|
RetainSession bool
|
||||||
// Do not [syscall.CLONE_NEWNET].
|
// Do not [syscall.CLONE_NEWNET].
|
||||||
HostNet bool
|
HostNet bool
|
||||||
|
// Scope abstract UNIX domain sockets using LANDLOCK_SCOPE_ABSTRACT_UNIX_SOCKET.
|
||||||
|
ScopeAbstract bool
|
||||||
// Retain CAP_SYS_ADMIN.
|
// Retain CAP_SYS_ADMIN.
|
||||||
Privileged bool
|
Privileged bool
|
||||||
}
|
}
|
||||||
|
@ -13,6 +13,7 @@ import (
|
|||||||
. "syscall"
|
. "syscall"
|
||||||
"time"
|
"time"
|
||||||
|
|
||||||
|
"hakurei.app/container/landlock"
|
||||||
"hakurei.app/container/seccomp"
|
"hakurei.app/container/seccomp"
|
||||||
)
|
)
|
||||||
|
|
||||||
@ -256,6 +257,12 @@ func Init(prepare func(prefix string), setVerbose func(verbose bool)) {
|
|||||||
msg.Verbose("syscall filter not configured")
|
msg.Verbose("syscall filter not configured")
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if params.ScopeAbstract {
|
||||||
|
if err := landlock.ScopeAbstract(); err != nil {
|
||||||
|
log.Fatalf("could not scope abstract unix sockets: %v", err)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
extraFiles := make([]*os.File, params.Count)
|
extraFiles := make([]*os.File, params.Count)
|
||||||
for i := range extraFiles {
|
for i := range extraFiles {
|
||||||
// setup fd is placed before all extra files
|
// setup fd is placed before all extra files
|
||||||
|
14
container/landlock/landlock-helper.c
Normal file
14
container/landlock/landlock-helper.c
Normal file
@ -0,0 +1,14 @@
|
|||||||
|
#include <errno.h>
|
||||||
|
#include <linux/landlock.h>
|
||||||
|
#include <sys/psx_syscall.h>
|
||||||
|
#include <sys/syscall.h>
|
||||||
|
|
||||||
|
#include "landlock-helper.h"
|
||||||
|
|
||||||
|
int hakurei_scope_abstract_unix_sockets(int* p_errno, int fd) {
|
||||||
|
int res = psx_syscall3(SYS_landlock_restrict_self, fd, 0, 0);
|
||||||
|
|
||||||
|
*p_errno = errno;
|
||||||
|
|
||||||
|
return res;
|
||||||
|
}
|
3
container/landlock/landlock-helper.h
Normal file
3
container/landlock/landlock-helper.h
Normal file
@ -0,0 +1,3 @@
|
|||||||
|
#pragma once
|
||||||
|
|
||||||
|
int hakurei_scope_abstract_unix_sockets(int* p_errno, int fd);
|
57
container/landlock/landlock.go
Normal file
57
container/landlock/landlock.go
Normal file
@ -0,0 +1,57 @@
|
|||||||
|
package landlock
|
||||||
|
|
||||||
|
/*
|
||||||
|
#cgo linux pkg-config: --static libpsx
|
||||||
|
|
||||||
|
#include <linux/landlock.h>
|
||||||
|
#include <sys/syscall.h>
|
||||||
|
|
||||||
|
#include "landlock-helper.h"
|
||||||
|
*/
|
||||||
|
import "C"
|
||||||
|
|
||||||
|
import (
|
||||||
|
"fmt"
|
||||||
|
"syscall"
|
||||||
|
"unsafe"
|
||||||
|
)
|
||||||
|
|
||||||
|
const (
|
||||||
|
LANDLOCK_CREATE_RULESET_VERSION = C.LANDLOCK_CREATE_RULESET_VERSION
|
||||||
|
LANDLOCK_SCOPE_ABSTRACT_UNIX_SOCKET = C.LANDLOCK_SCOPE_ABSTRACT_UNIX_SOCKET
|
||||||
|
|
||||||
|
SYS_LANDLOCK_CREATE_RULESET = C.SYS_landlock_create_ruleset
|
||||||
|
)
|
||||||
|
|
||||||
|
type LandlockRulesetAttr = C.struct_landlock_ruleset_attr
|
||||||
|
|
||||||
|
func ScopeAbstract() error {
|
||||||
|
abi, _, err := syscall.Syscall(SYS_LANDLOCK_CREATE_RULESET, 0, 0, LANDLOCK_CREATE_RULESET_VERSION)
|
||||||
|
|
||||||
|
if err != 0 {
|
||||||
|
return fmt.Errorf("could not fetch landlock ABI: errno %v", err)
|
||||||
|
}
|
||||||
|
|
||||||
|
if abi < 6 {
|
||||||
|
return fmt.Errorf("landlock ABI must be >= 6, got %d", abi)
|
||||||
|
}
|
||||||
|
|
||||||
|
attrs := LandlockRulesetAttr{
|
||||||
|
scoped: LANDLOCK_SCOPE_ABSTRACT_UNIX_SOCKET,
|
||||||
|
}
|
||||||
|
|
||||||
|
fd, _, err := syscall.Syscall(SYS_LANDLOCK_CREATE_RULESET, uintptr(unsafe.Pointer(&attrs)), unsafe.Sizeof(attrs), 0)
|
||||||
|
|
||||||
|
if err != 0 {
|
||||||
|
return fmt.Errorf("could not create landlock ruleset: errno %v", err)
|
||||||
|
}
|
||||||
|
|
||||||
|
defer syscall.Close(int(fd))
|
||||||
|
|
||||||
|
var errno C.int
|
||||||
|
if rv := C.hakurei_scope_abstract_unix_sockets(&errno, C.int(fd)); rv != 0 {
|
||||||
|
return fmt.Errorf("could not restrict self via landlock: errno %v", errno)
|
||||||
|
}
|
||||||
|
|
||||||
|
return nil
|
||||||
|
}
|
@ -22,6 +22,8 @@ type (
|
|||||||
Userns bool `json:"userns,omitempty"`
|
Userns bool `json:"userns,omitempty"`
|
||||||
// share host net namespace
|
// share host net namespace
|
||||||
Net bool `json:"net,omitempty"`
|
Net bool `json:"net,omitempty"`
|
||||||
|
// disallow accessing abstract UNIX domain sockets created outside the container
|
||||||
|
ScopeAbstract bool `json:"scope_abstract,omitempty"`
|
||||||
// allow dangerous terminal I/O
|
// allow dangerous terminal I/O
|
||||||
Tty bool `json:"tty,omitempty"`
|
Tty bool `json:"tty,omitempty"`
|
||||||
// allow multiarch
|
// allow multiarch
|
||||||
|
@ -32,6 +32,7 @@ func newContainer(s *hst.ContainerConfig, os sys.State, uid, gid *int) (*contain
|
|||||||
SeccompPresets: s.SeccompPresets,
|
SeccompPresets: s.SeccompPresets,
|
||||||
RetainSession: s.Tty,
|
RetainSession: s.Tty,
|
||||||
HostNet: s.Net,
|
HostNet: s.Net,
|
||||||
|
ScopeAbstract: s.ScopeAbstract,
|
||||||
}
|
}
|
||||||
|
|
||||||
{
|
{
|
||||||
|
@ -135,6 +135,7 @@ in
|
|||||||
multiarch
|
multiarch
|
||||||
env
|
env
|
||||||
;
|
;
|
||||||
|
scope_abstract = app.scopeAbstract;
|
||||||
map_real_uid = app.mapRealUid;
|
map_real_uid = app.mapRealUid;
|
||||||
|
|
||||||
filesystem =
|
filesystem =
|
||||||
|
22
options.md
22
options.md
@ -572,6 +572,28 @@ boolean
|
|||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
*Example:*
|
||||||
|
` true `
|
||||||
|
|
||||||
|
|
||||||
|
## environment\.hakurei\.apps\.\<name>\.scopeAbstract
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
Whether to restrict abstract UNIX domain socket access\.
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
*Type:*
|
||||||
|
boolean
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
*Default:*
|
||||||
|
` true `
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
*Example:*
|
*Example:*
|
||||||
` true `
|
` true `
|
||||||
|
|
||||||
|
@ -203,6 +203,9 @@ in
|
|||||||
net = mkEnableOption "network access" // {
|
net = mkEnableOption "network access" // {
|
||||||
default = true;
|
default = true;
|
||||||
};
|
};
|
||||||
|
scopeAbstract = mkEnableOption "abstract unix domain socket access" // {
|
||||||
|
default = true;
|
||||||
|
};
|
||||||
|
|
||||||
nix = mkEnableOption "nix daemon access";
|
nix = mkEnableOption "nix daemon access";
|
||||||
mapRealUid = mkEnableOption "mapping to priv-user uid";
|
mapRealUid = mkEnableOption "mapping to priv-user uid";
|
||||||
|
11
package.nix
11
package.nix
@ -5,6 +5,7 @@
|
|||||||
makeBinaryWrapper,
|
makeBinaryWrapper,
|
||||||
xdg-dbus-proxy,
|
xdg-dbus-proxy,
|
||||||
pkg-config,
|
pkg-config,
|
||||||
|
libcap,
|
||||||
libffi,
|
libffi,
|
||||||
libseccomp,
|
libseccomp,
|
||||||
acl,
|
acl,
|
||||||
@ -80,11 +81,17 @@ buildGoModule rec {
|
|||||||
hsu = "/run/wrappers/bin/hsu";
|
hsu = "/run/wrappers/bin/hsu";
|
||||||
};
|
};
|
||||||
|
|
||||||
# nix build environment does not allow acls
|
env = {
|
||||||
env.GO_TEST_SKIP_ACL = 1;
|
# required by libpsx
|
||||||
|
CGO_LDFLAGS_ALLOW = "-Wl,(--no-whole-archive|--whole-archive)";
|
||||||
|
|
||||||
|
# nix build environment does not allow acls
|
||||||
|
GO_TEST_SKIP_ACL = 1;
|
||||||
|
};
|
||||||
|
|
||||||
buildInputs =
|
buildInputs =
|
||||||
[
|
[
|
||||||
|
libcap
|
||||||
libffi
|
libffi
|
||||||
libseccomp
|
libseccomp
|
||||||
acl
|
acl
|
||||||
|
@ -68,6 +68,10 @@ func (p *Proxy) Start() error {
|
|||||||
argF, func(z *container.Container) {
|
argF, func(z *container.Container) {
|
||||||
z.SeccompFlags |= seccomp.AllowMultiarch
|
z.SeccompFlags |= seccomp.AllowMultiarch
|
||||||
z.SeccompPresets |= seccomp.PresetStrict
|
z.SeccompPresets |= seccomp.PresetStrict
|
||||||
|
|
||||||
|
// xdg-dbus-proxy requires host abstract UNIX domain socket access
|
||||||
|
z.ScopeAbstract = false
|
||||||
|
|
||||||
z.Hostname = "hakurei-dbus"
|
z.Hostname = "hakurei-dbus"
|
||||||
z.CommandContext = p.CommandContext
|
z.CommandContext = p.CommandContext
|
||||||
if p.output != nil {
|
if p.output != nil {
|
||||||
|
Loading…
x
Reference in New Issue
Block a user