treewide: rename to hakurei
All checks were successful
Test / Create distribution (push) Successful in 43s
Test / Sandbox (push) Successful in 2m18s
Test / Hakurei (push) Successful in 3m10s
Test / Sandbox (race detector) (push) Successful in 3m30s
Test / Hakurei (race detector) (push) Successful in 4m43s
Test / Fpkg (push) Successful in 5m4s
Test / Flake checks (push) Successful in 1m12s
All checks were successful
Test / Create distribution (push) Successful in 43s
Test / Sandbox (push) Successful in 2m18s
Test / Hakurei (push) Successful in 3m10s
Test / Sandbox (race detector) (push) Successful in 3m30s
Test / Hakurei (race detector) (push) Successful in 4m43s
Test / Fpkg (push) Successful in 5m4s
Test / Flake checks (push) Successful in 1m12s
Fortify makes little sense for a container tool. Signed-off-by: Ophestra <cat@gensokyo.uk>
This commit is contained in:
@@ -5,7 +5,7 @@ import (
|
||||
"syscall"
|
||||
"time"
|
||||
|
||||
"git.gensokyo.uk/security/fortify/fst"
|
||||
"git.gensokyo.uk/security/hakurei/hst"
|
||||
)
|
||||
|
||||
type App interface {
|
||||
@@ -14,7 +14,7 @@ type App interface {
|
||||
|
||||
// Seal determines the outcome of config as a [SealedApp].
|
||||
// The value of config might be overwritten and must not be used again.
|
||||
Seal(config *fst.Config) (SealedApp, error)
|
||||
Seal(config *hst.Config) (SealedApp, error)
|
||||
|
||||
String() string
|
||||
}
|
||||
@@ -48,12 +48,12 @@ func (rs *RunState) SetStart() {
|
||||
rs.Time = &now
|
||||
}
|
||||
|
||||
// Paths contains environment-dependent paths used by fortify.
|
||||
// Paths contains environment-dependent paths used by hakurei.
|
||||
type Paths struct {
|
||||
// path to shared directory (usually `/tmp/fortify.%d`)
|
||||
// path to shared directory (usually `/tmp/hakurei.%d`)
|
||||
SharePath string `json:"share_path"`
|
||||
// XDG_RUNTIME_DIR value (usually `/run/user/%d`)
|
||||
RuntimePath string `json:"runtime_path"`
|
||||
// application runtime directory (usually `/run/user/%d/fortify`)
|
||||
// application runtime directory (usually `/run/user/%d/hakurei`)
|
||||
RunDirPath string `json:"run_dir_path"`
|
||||
}
|
||||
|
||||
@@ -4,7 +4,7 @@ import (
|
||||
"errors"
|
||||
"testing"
|
||||
|
||||
. "git.gensokyo.uk/security/fortify/internal/app"
|
||||
. "git.gensokyo.uk/security/hakurei/internal/app"
|
||||
)
|
||||
|
||||
func TestParseAppID(t *testing.T) {
|
||||
|
||||
@@ -8,20 +8,20 @@ import (
|
||||
"path"
|
||||
"syscall"
|
||||
|
||||
"git.gensokyo.uk/security/fortify/dbus"
|
||||
"git.gensokyo.uk/security/fortify/fst"
|
||||
"git.gensokyo.uk/security/fortify/internal/sys"
|
||||
"git.gensokyo.uk/security/fortify/sandbox"
|
||||
"git.gensokyo.uk/security/fortify/sandbox/seccomp"
|
||||
"git.gensokyo.uk/security/hakurei/dbus"
|
||||
"git.gensokyo.uk/security/hakurei/hst"
|
||||
"git.gensokyo.uk/security/hakurei/internal/sys"
|
||||
"git.gensokyo.uk/security/hakurei/sandbox"
|
||||
"git.gensokyo.uk/security/hakurei/sandbox/seccomp"
|
||||
)
|
||||
|
||||
// in practice there should be less than 30 entries added by the runtime;
|
||||
// allocating slightly more as a margin for future expansion
|
||||
const preallocateOpsCount = 1 << 5
|
||||
|
||||
// NewContainer initialises [sandbox.Params] via [fst.ContainerConfig].
|
||||
// NewContainer initialises [sandbox.Params] via [hst.ContainerConfig].
|
||||
// Note that remaining container setup must be queued by the caller.
|
||||
func NewContainer(s *fst.ContainerConfig, os sys.State, uid, gid *int) (*sandbox.Params, map[string]string, error) {
|
||||
func NewContainer(s *hst.ContainerConfig, os sys.State, uid, gid *int) (*sandbox.Params, map[string]string, error) {
|
||||
if s == nil {
|
||||
return nil, nil, syscall.EBADE
|
||||
}
|
||||
@@ -67,7 +67,7 @@ func NewContainer(s *fst.ContainerConfig, os sys.State, uid, gid *int) (*sandbox
|
||||
|
||||
container.
|
||||
Proc("/proc").
|
||||
Tmpfs(fst.Tmp, 1<<12, 0755)
|
||||
Tmpfs(hst.Tmp, 1<<12, 0755)
|
||||
|
||||
if !s.Device {
|
||||
container.Dev("/dev").Mqueue("/dev/mqueue")
|
||||
|
||||
@@ -3,8 +3,8 @@ package instance
|
||||
import (
|
||||
"syscall"
|
||||
|
||||
"git.gensokyo.uk/security/fortify/internal/app"
|
||||
"git.gensokyo.uk/security/fortify/internal/app/internal/setuid"
|
||||
"git.gensokyo.uk/security/hakurei/internal/app"
|
||||
"git.gensokyo.uk/security/hakurei/internal/app/internal/setuid"
|
||||
)
|
||||
|
||||
func PrintRunStateErr(whence int, rs *app.RunState, runErr error) (code int) {
|
||||
|
||||
@@ -6,9 +6,9 @@ import (
|
||||
"log"
|
||||
"syscall"
|
||||
|
||||
"git.gensokyo.uk/security/fortify/internal/app"
|
||||
"git.gensokyo.uk/security/fortify/internal/app/internal/setuid"
|
||||
"git.gensokyo.uk/security/fortify/internal/sys"
|
||||
"git.gensokyo.uk/security/hakurei/internal/app"
|
||||
"git.gensokyo.uk/security/hakurei/internal/app/internal/setuid"
|
||||
"git.gensokyo.uk/security/hakurei/internal/sys"
|
||||
)
|
||||
|
||||
const (
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
package instance
|
||||
|
||||
import "git.gensokyo.uk/security/fortify/internal/app/internal/setuid"
|
||||
import "git.gensokyo.uk/security/hakurei/internal/app/internal/setuid"
|
||||
|
||||
// ShimMain is the main function of the shim process and runs as the unconstrained target user.
|
||||
func ShimMain() { setuid.ShimMain() }
|
||||
|
||||
@@ -5,10 +5,10 @@ import (
|
||||
"fmt"
|
||||
"sync"
|
||||
|
||||
"git.gensokyo.uk/security/fortify/fst"
|
||||
. "git.gensokyo.uk/security/fortify/internal/app"
|
||||
"git.gensokyo.uk/security/fortify/internal/fmsg"
|
||||
"git.gensokyo.uk/security/fortify/internal/sys"
|
||||
"git.gensokyo.uk/security/hakurei/hst"
|
||||
. "git.gensokyo.uk/security/hakurei/internal/app"
|
||||
"git.gensokyo.uk/security/hakurei/internal/hlog"
|
||||
"git.gensokyo.uk/security/hakurei/internal/sys"
|
||||
)
|
||||
|
||||
func New(ctx context.Context, os sys.State) (App, error) {
|
||||
@@ -52,7 +52,7 @@ func (a *app) String() string {
|
||||
return fmt.Sprintf("(unsealed app %s)", a.id)
|
||||
}
|
||||
|
||||
func (a *app) Seal(config *fst.Config) (SealedApp, error) {
|
||||
func (a *app) Seal(config *hst.Config) (SealedApp, error) {
|
||||
a.mu.Lock()
|
||||
defer a.mu.Unlock()
|
||||
|
||||
@@ -60,7 +60,7 @@ func (a *app) Seal(config *fst.Config) (SealedApp, error) {
|
||||
panic("app sealed twice")
|
||||
}
|
||||
if config == nil {
|
||||
return nil, fmsg.WrapError(ErrConfig,
|
||||
return nil, hlog.WrapErr(ErrConfig,
|
||||
"attempted to seal app with nil config")
|
||||
}
|
||||
|
||||
|
||||
@@ -1,25 +1,25 @@
|
||||
package setuid_test
|
||||
|
||||
import (
|
||||
"git.gensokyo.uk/security/fortify/acl"
|
||||
"git.gensokyo.uk/security/fortify/dbus"
|
||||
"git.gensokyo.uk/security/fortify/fst"
|
||||
"git.gensokyo.uk/security/fortify/internal/app"
|
||||
"git.gensokyo.uk/security/fortify/sandbox"
|
||||
"git.gensokyo.uk/security/fortify/system"
|
||||
"git.gensokyo.uk/security/hakurei/acl"
|
||||
"git.gensokyo.uk/security/hakurei/dbus"
|
||||
"git.gensokyo.uk/security/hakurei/hst"
|
||||
"git.gensokyo.uk/security/hakurei/internal/app"
|
||||
"git.gensokyo.uk/security/hakurei/sandbox"
|
||||
"git.gensokyo.uk/security/hakurei/system"
|
||||
)
|
||||
|
||||
var testCasesNixos = []sealTestCase{
|
||||
{
|
||||
"nixos chromium direct wayland", new(stubNixOS),
|
||||
&fst.Config{
|
||||
&hst.Config{
|
||||
ID: "org.chromium.Chromium",
|
||||
Path: "/nix/store/yqivzpzzn7z5x0lq9hmbzygh45d8rhqd-chromium-start",
|
||||
Enablements: system.EWayland | system.EDBus | system.EPulse,
|
||||
|
||||
Container: &fst.ContainerConfig{
|
||||
Container: &hst.ContainerConfig{
|
||||
Userns: true, Net: true, MapRealUID: true, Env: nil, AutoEtc: true,
|
||||
Filesystem: []*fst.FilesystemConfig{
|
||||
Filesystem: []*hst.FilesystemConfig{
|
||||
{Src: "/bin", Must: true}, {Src: "/usr/bin", Must: true},
|
||||
{Src: "/nix/store", Must: true}, {Src: "/run/current-system", Must: true},
|
||||
{Src: "/sys/block"}, {Src: "/sys/bus"}, {Src: "/sys/class"}, {Src: "/sys/dev"}, {Src: "/sys/devices"},
|
||||
@@ -48,7 +48,7 @@ var testCasesNixos = []sealTestCase{
|
||||
DirectWayland: true,
|
||||
|
||||
Username: "u0_a1",
|
||||
Data: "/var/lib/persist/module/fortify/0/1",
|
||||
Data: "/var/lib/persist/module/hakurei/0/1",
|
||||
Identity: 1, Groups: []string{},
|
||||
},
|
||||
app.ID{
|
||||
@@ -58,19 +58,19 @@ var testCasesNixos = []sealTestCase{
|
||||
0xb4, 0x6e, 0xb5, 0xc1,
|
||||
},
|
||||
system.New(1000001).
|
||||
Ensure("/tmp/fortify.1971", 0711).
|
||||
Ensure("/tmp/fortify.1971/runtime", 0700).UpdatePermType(system.User, "/tmp/fortify.1971/runtime", acl.Execute).
|
||||
Ensure("/tmp/fortify.1971/runtime/1", 0700).UpdatePermType(system.User, "/tmp/fortify.1971/runtime/1", acl.Read, acl.Write, acl.Execute).
|
||||
Ensure("/tmp/fortify.1971/tmpdir", 0700).UpdatePermType(system.User, "/tmp/fortify.1971/tmpdir", acl.Execute).
|
||||
Ensure("/tmp/fortify.1971/tmpdir/1", 01700).UpdatePermType(system.User, "/tmp/fortify.1971/tmpdir/1", acl.Read, acl.Write, acl.Execute).
|
||||
Ensure("/run/user/1971/fortify", 0700).UpdatePermType(system.User, "/run/user/1971/fortify", acl.Execute).
|
||||
Ensure("/tmp/hakurei.1971", 0711).
|
||||
Ensure("/tmp/hakurei.1971/runtime", 0700).UpdatePermType(system.User, "/tmp/hakurei.1971/runtime", acl.Execute).
|
||||
Ensure("/tmp/hakurei.1971/runtime/1", 0700).UpdatePermType(system.User, "/tmp/hakurei.1971/runtime/1", acl.Read, acl.Write, acl.Execute).
|
||||
Ensure("/tmp/hakurei.1971/tmpdir", 0700).UpdatePermType(system.User, "/tmp/hakurei.1971/tmpdir", acl.Execute).
|
||||
Ensure("/tmp/hakurei.1971/tmpdir/1", 01700).UpdatePermType(system.User, "/tmp/hakurei.1971/tmpdir/1", acl.Read, acl.Write, acl.Execute).
|
||||
Ensure("/run/user/1971/hakurei", 0700).UpdatePermType(system.User, "/run/user/1971/hakurei", acl.Execute).
|
||||
Ensure("/run/user/1971", 0700).UpdatePermType(system.User, "/run/user/1971", acl.Execute). // this is ordered as is because the previous Ensure only calls mkdir if XDG_RUNTIME_DIR is unset
|
||||
UpdatePermType(system.EWayland, "/run/user/1971/wayland-0", acl.Read, acl.Write, acl.Execute).
|
||||
Ephemeral(system.Process, "/run/user/1971/fortify/8e2c76b066dabe574cf073bdb46eb5c1", 0700).UpdatePermType(system.Process, "/run/user/1971/fortify/8e2c76b066dabe574cf073bdb46eb5c1", acl.Execute).
|
||||
Link("/run/user/1971/pulse/native", "/run/user/1971/fortify/8e2c76b066dabe574cf073bdb46eb5c1/pulse").
|
||||
Ephemeral(system.Process, "/run/user/1971/hakurei/8e2c76b066dabe574cf073bdb46eb5c1", 0700).UpdatePermType(system.Process, "/run/user/1971/hakurei/8e2c76b066dabe574cf073bdb46eb5c1", acl.Execute).
|
||||
Link("/run/user/1971/pulse/native", "/run/user/1971/hakurei/8e2c76b066dabe574cf073bdb46eb5c1/pulse").
|
||||
CopyFile(nil, "/home/ophestra/xdg/config/pulse/cookie", 256, 256).
|
||||
Ephemeral(system.Process, "/tmp/fortify.1971/8e2c76b066dabe574cf073bdb46eb5c1", 0711).
|
||||
MustProxyDBus("/tmp/fortify.1971/8e2c76b066dabe574cf073bdb46eb5c1/bus", &dbus.Config{
|
||||
Ephemeral(system.Process, "/tmp/hakurei.1971/8e2c76b066dabe574cf073bdb46eb5c1", 0711).
|
||||
MustProxyDBus("/tmp/hakurei.1971/8e2c76b066dabe574cf073bdb46eb5c1/bus", &dbus.Config{
|
||||
Talk: []string{
|
||||
"org.freedesktop.FileManager1", "org.freedesktop.Notifications",
|
||||
"org.freedesktop.ScreenSaver", "org.freedesktop.secrets",
|
||||
@@ -83,7 +83,7 @@ var testCasesNixos = []sealTestCase{
|
||||
},
|
||||
Call: map[string]string{}, Broadcast: map[string]string{},
|
||||
Filter: true,
|
||||
}, "/tmp/fortify.1971/8e2c76b066dabe574cf073bdb46eb5c1/system_bus_socket", &dbus.Config{
|
||||
}, "/tmp/hakurei.1971/8e2c76b066dabe574cf073bdb46eb5c1/system_bus_socket", &dbus.Config{
|
||||
Talk: []string{
|
||||
"org.bluez",
|
||||
"org.freedesktop.Avahi",
|
||||
@@ -91,20 +91,20 @@ var testCasesNixos = []sealTestCase{
|
||||
},
|
||||
Filter: true,
|
||||
}).
|
||||
UpdatePerm("/tmp/fortify.1971/8e2c76b066dabe574cf073bdb46eb5c1/bus", acl.Read, acl.Write).
|
||||
UpdatePerm("/tmp/fortify.1971/8e2c76b066dabe574cf073bdb46eb5c1/system_bus_socket", acl.Read, acl.Write),
|
||||
UpdatePerm("/tmp/hakurei.1971/8e2c76b066dabe574cf073bdb46eb5c1/bus", acl.Read, acl.Write).
|
||||
UpdatePerm("/tmp/hakurei.1971/8e2c76b066dabe574cf073bdb46eb5c1/system_bus_socket", acl.Read, acl.Write),
|
||||
&sandbox.Params{
|
||||
Uid: 1971,
|
||||
Gid: 100,
|
||||
Flags: sandbox.FAllowNet | sandbox.FAllowUserns,
|
||||
Dir: "/var/lib/persist/module/fortify/0/1",
|
||||
Dir: "/var/lib/persist/module/hakurei/0/1",
|
||||
Path: "/nix/store/yqivzpzzn7z5x0lq9hmbzygh45d8rhqd-chromium-start",
|
||||
Args: []string{"/nix/store/yqivzpzzn7z5x0lq9hmbzygh45d8rhqd-chromium-start"},
|
||||
Env: []string{
|
||||
"DBUS_SESSION_BUS_ADDRESS=unix:path=/run/user/1971/bus",
|
||||
"DBUS_SYSTEM_BUS_ADDRESS=unix:path=/run/dbus/system_bus_socket",
|
||||
"HOME=/var/lib/persist/module/fortify/0/1",
|
||||
"PULSE_COOKIE=" + fst.Tmp + "/pulse-cookie",
|
||||
"HOME=/var/lib/persist/module/hakurei/0/1",
|
||||
"PULSE_COOKIE=" + hst.Tmp + "/pulse-cookie",
|
||||
"PULSE_SERVER=unix:/run/user/1971/pulse/native",
|
||||
"SHELL=/run/current-system/sw/bin/zsh",
|
||||
"TERM=xterm-256color",
|
||||
@@ -116,7 +116,7 @@ var testCasesNixos = []sealTestCase{
|
||||
},
|
||||
Ops: new(sandbox.Ops).
|
||||
Proc("/proc").
|
||||
Tmpfs(fst.Tmp, 4096, 0755).
|
||||
Tmpfs(hst.Tmp, 4096, 0755).
|
||||
Dev("/dev").Mqueue("/dev/mqueue").
|
||||
Bind("/bin", "/bin", 0).
|
||||
Bind("/usr/bin", "/usr/bin", 0).
|
||||
@@ -131,16 +131,16 @@ var testCasesNixos = []sealTestCase{
|
||||
Bind("/dev/dri", "/dev/dri", sandbox.BindDevice|sandbox.BindWritable|sandbox.BindOptional).
|
||||
Etc("/etc", "8e2c76b066dabe574cf073bdb46eb5c1").
|
||||
Tmpfs("/run/user", 4096, 0755).
|
||||
Bind("/tmp/fortify.1971/runtime/1", "/run/user/1971", sandbox.BindWritable).
|
||||
Bind("/tmp/fortify.1971/tmpdir/1", "/tmp", sandbox.BindWritable).
|
||||
Bind("/var/lib/persist/module/fortify/0/1", "/var/lib/persist/module/fortify/0/1", sandbox.BindWritable).
|
||||
Place("/etc/passwd", []byte("u0_a1:x:1971:100:Fortify:/var/lib/persist/module/fortify/0/1:/run/current-system/sw/bin/zsh\n")).
|
||||
Place("/etc/group", []byte("fortify:x:100:\n")).
|
||||
Bind("/tmp/hakurei.1971/runtime/1", "/run/user/1971", sandbox.BindWritable).
|
||||
Bind("/tmp/hakurei.1971/tmpdir/1", "/tmp", sandbox.BindWritable).
|
||||
Bind("/var/lib/persist/module/hakurei/0/1", "/var/lib/persist/module/hakurei/0/1", sandbox.BindWritable).
|
||||
Place("/etc/passwd", []byte("u0_a1:x:1971:100:Hakurei:/var/lib/persist/module/hakurei/0/1:/run/current-system/sw/bin/zsh\n")).
|
||||
Place("/etc/group", []byte("hakurei:x:100:\n")).
|
||||
Bind("/run/user/1971/wayland-0", "/run/user/1971/wayland-0", 0).
|
||||
Bind("/run/user/1971/fortify/8e2c76b066dabe574cf073bdb46eb5c1/pulse", "/run/user/1971/pulse/native", 0).
|
||||
Place(fst.Tmp+"/pulse-cookie", nil).
|
||||
Bind("/tmp/fortify.1971/8e2c76b066dabe574cf073bdb46eb5c1/bus", "/run/user/1971/bus", 0).
|
||||
Bind("/tmp/fortify.1971/8e2c76b066dabe574cf073bdb46eb5c1/system_bus_socket", "/run/dbus/system_bus_socket", 0).
|
||||
Bind("/run/user/1971/hakurei/8e2c76b066dabe574cf073bdb46eb5c1/pulse", "/run/user/1971/pulse/native", 0).
|
||||
Place(hst.Tmp+"/pulse-cookie", nil).
|
||||
Bind("/tmp/hakurei.1971/8e2c76b066dabe574cf073bdb46eb5c1/bus", "/run/user/1971/bus", 0).
|
||||
Bind("/tmp/hakurei.1971/8e2c76b066dabe574cf073bdb46eb5c1/system_bus_socket", "/run/dbus/system_bus_socket", 0).
|
||||
Tmpfs("/var/run/nscd", 8192, 0755),
|
||||
},
|
||||
},
|
||||
|
||||
@@ -3,18 +3,18 @@ package setuid_test
|
||||
import (
|
||||
"os"
|
||||
|
||||
"git.gensokyo.uk/security/fortify/acl"
|
||||
"git.gensokyo.uk/security/fortify/dbus"
|
||||
"git.gensokyo.uk/security/fortify/fst"
|
||||
"git.gensokyo.uk/security/fortify/internal/app"
|
||||
"git.gensokyo.uk/security/fortify/sandbox"
|
||||
"git.gensokyo.uk/security/fortify/system"
|
||||
"git.gensokyo.uk/security/hakurei/acl"
|
||||
"git.gensokyo.uk/security/hakurei/dbus"
|
||||
"git.gensokyo.uk/security/hakurei/hst"
|
||||
"git.gensokyo.uk/security/hakurei/internal/app"
|
||||
"git.gensokyo.uk/security/hakurei/sandbox"
|
||||
"git.gensokyo.uk/security/hakurei/system"
|
||||
)
|
||||
|
||||
var testCasesPd = []sealTestCase{
|
||||
{
|
||||
"nixos permissive defaults no enablements", new(stubNixOS),
|
||||
&fst.Config{Username: "chronos", Data: "/home/chronos"},
|
||||
&hst.Config{Username: "chronos", Data: "/home/chronos"},
|
||||
app.ID{
|
||||
0x4a, 0x45, 0x0b, 0x65,
|
||||
0x96, 0xd7, 0xbc, 0x15,
|
||||
@@ -22,11 +22,11 @@ var testCasesPd = []sealTestCase{
|
||||
0xb9, 0xa6, 0x07, 0xac,
|
||||
},
|
||||
system.New(1000000).
|
||||
Ensure("/tmp/fortify.1971", 0711).
|
||||
Ensure("/tmp/fortify.1971/runtime", 0700).UpdatePermType(system.User, "/tmp/fortify.1971/runtime", acl.Execute).
|
||||
Ensure("/tmp/fortify.1971/runtime/0", 0700).UpdatePermType(system.User, "/tmp/fortify.1971/runtime/0", acl.Read, acl.Write, acl.Execute).
|
||||
Ensure("/tmp/fortify.1971/tmpdir", 0700).UpdatePermType(system.User, "/tmp/fortify.1971/tmpdir", acl.Execute).
|
||||
Ensure("/tmp/fortify.1971/tmpdir/0", 01700).UpdatePermType(system.User, "/tmp/fortify.1971/tmpdir/0", acl.Read, acl.Write, acl.Execute),
|
||||
Ensure("/tmp/hakurei.1971", 0711).
|
||||
Ensure("/tmp/hakurei.1971/runtime", 0700).UpdatePermType(system.User, "/tmp/hakurei.1971/runtime", acl.Execute).
|
||||
Ensure("/tmp/hakurei.1971/runtime/0", 0700).UpdatePermType(system.User, "/tmp/hakurei.1971/runtime/0", acl.Read, acl.Write, acl.Execute).
|
||||
Ensure("/tmp/hakurei.1971/tmpdir", 0700).UpdatePermType(system.User, "/tmp/hakurei.1971/tmpdir", acl.Execute).
|
||||
Ensure("/tmp/hakurei.1971/tmpdir/0", 01700).UpdatePermType(system.User, "/tmp/hakurei.1971/tmpdir/0", acl.Read, acl.Write, acl.Execute),
|
||||
&sandbox.Params{
|
||||
Flags: sandbox.FAllowNet | sandbox.FAllowUserns | sandbox.FAllowTTY,
|
||||
Dir: "/home/chronos",
|
||||
@@ -43,7 +43,7 @@ var testCasesPd = []sealTestCase{
|
||||
},
|
||||
Ops: new(sandbox.Ops).
|
||||
Proc("/proc").
|
||||
Tmpfs(fst.Tmp, 4096, 0755).
|
||||
Tmpfs(hst.Tmp, 4096, 0755).
|
||||
Dev("/dev").Mqueue("/dev/mqueue").
|
||||
Bind("/bin", "/bin", sandbox.BindWritable).
|
||||
Bind("/boot", "/boot", sandbox.BindWritable).
|
||||
@@ -62,17 +62,17 @@ var testCasesPd = []sealTestCase{
|
||||
Tmpfs("/run/dbus", 8192, 0755).
|
||||
Etc("/etc", "4a450b6596d7bc15bd01780eb9a607ac").
|
||||
Tmpfs("/run/user", 4096, 0755).
|
||||
Bind("/tmp/fortify.1971/runtime/0", "/run/user/65534", sandbox.BindWritable).
|
||||
Bind("/tmp/fortify.1971/tmpdir/0", "/tmp", sandbox.BindWritable).
|
||||
Bind("/tmp/hakurei.1971/runtime/0", "/run/user/65534", sandbox.BindWritable).
|
||||
Bind("/tmp/hakurei.1971/tmpdir/0", "/tmp", sandbox.BindWritable).
|
||||
Bind("/home/chronos", "/home/chronos", sandbox.BindWritable).
|
||||
Place("/etc/passwd", []byte("chronos:x:65534:65534:Fortify:/home/chronos:/run/current-system/sw/bin/zsh\n")).
|
||||
Place("/etc/group", []byte("fortify:x:65534:\n")).
|
||||
Place("/etc/passwd", []byte("chronos:x:65534:65534:Hakurei:/home/chronos:/run/current-system/sw/bin/zsh\n")).
|
||||
Place("/etc/group", []byte("hakurei:x:65534:\n")).
|
||||
Tmpfs("/var/run/nscd", 8192, 0755),
|
||||
},
|
||||
},
|
||||
{
|
||||
"nixos permissive defaults chromium", new(stubNixOS),
|
||||
&fst.Config{
|
||||
&hst.Config{
|
||||
ID: "org.chromium.Chromium",
|
||||
Args: []string{"zsh", "-c", "exec chromium "},
|
||||
Identity: 9,
|
||||
@@ -119,19 +119,19 @@ var testCasesPd = []sealTestCase{
|
||||
0x9b, 0x64, 0xce, 0x7c,
|
||||
},
|
||||
system.New(1000009).
|
||||
Ensure("/tmp/fortify.1971", 0711).
|
||||
Ensure("/tmp/fortify.1971/runtime", 0700).UpdatePermType(system.User, "/tmp/fortify.1971/runtime", acl.Execute).
|
||||
Ensure("/tmp/fortify.1971/runtime/9", 0700).UpdatePermType(system.User, "/tmp/fortify.1971/runtime/9", acl.Read, acl.Write, acl.Execute).
|
||||
Ensure("/tmp/fortify.1971/tmpdir", 0700).UpdatePermType(system.User, "/tmp/fortify.1971/tmpdir", acl.Execute).
|
||||
Ensure("/tmp/fortify.1971/tmpdir/9", 01700).UpdatePermType(system.User, "/tmp/fortify.1971/tmpdir/9", acl.Read, acl.Write, acl.Execute).
|
||||
Ephemeral(system.Process, "/tmp/fortify.1971/ebf083d1b175911782d413369b64ce7c", 0711).
|
||||
Wayland(new(*os.File), "/tmp/fortify.1971/ebf083d1b175911782d413369b64ce7c/wayland", "/run/user/1971/wayland-0", "org.chromium.Chromium", "ebf083d1b175911782d413369b64ce7c").
|
||||
Ensure("/run/user/1971/fortify", 0700).UpdatePermType(system.User, "/run/user/1971/fortify", acl.Execute).
|
||||
Ensure("/tmp/hakurei.1971", 0711).
|
||||
Ensure("/tmp/hakurei.1971/runtime", 0700).UpdatePermType(system.User, "/tmp/hakurei.1971/runtime", acl.Execute).
|
||||
Ensure("/tmp/hakurei.1971/runtime/9", 0700).UpdatePermType(system.User, "/tmp/hakurei.1971/runtime/9", acl.Read, acl.Write, acl.Execute).
|
||||
Ensure("/tmp/hakurei.1971/tmpdir", 0700).UpdatePermType(system.User, "/tmp/hakurei.1971/tmpdir", acl.Execute).
|
||||
Ensure("/tmp/hakurei.1971/tmpdir/9", 01700).UpdatePermType(system.User, "/tmp/hakurei.1971/tmpdir/9", acl.Read, acl.Write, acl.Execute).
|
||||
Ephemeral(system.Process, "/tmp/hakurei.1971/ebf083d1b175911782d413369b64ce7c", 0711).
|
||||
Wayland(new(*os.File), "/tmp/hakurei.1971/ebf083d1b175911782d413369b64ce7c/wayland", "/run/user/1971/wayland-0", "org.chromium.Chromium", "ebf083d1b175911782d413369b64ce7c").
|
||||
Ensure("/run/user/1971/hakurei", 0700).UpdatePermType(system.User, "/run/user/1971/hakurei", acl.Execute).
|
||||
Ensure("/run/user/1971", 0700).UpdatePermType(system.User, "/run/user/1971", acl.Execute). // this is ordered as is because the previous Ensure only calls mkdir if XDG_RUNTIME_DIR is unset
|
||||
Ephemeral(system.Process, "/run/user/1971/fortify/ebf083d1b175911782d413369b64ce7c", 0700).UpdatePermType(system.Process, "/run/user/1971/fortify/ebf083d1b175911782d413369b64ce7c", acl.Execute).
|
||||
Link("/run/user/1971/pulse/native", "/run/user/1971/fortify/ebf083d1b175911782d413369b64ce7c/pulse").
|
||||
Ephemeral(system.Process, "/run/user/1971/hakurei/ebf083d1b175911782d413369b64ce7c", 0700).UpdatePermType(system.Process, "/run/user/1971/hakurei/ebf083d1b175911782d413369b64ce7c", acl.Execute).
|
||||
Link("/run/user/1971/pulse/native", "/run/user/1971/hakurei/ebf083d1b175911782d413369b64ce7c/pulse").
|
||||
CopyFile(new([]byte), "/home/ophestra/xdg/config/pulse/cookie", 256, 256).
|
||||
MustProxyDBus("/tmp/fortify.1971/ebf083d1b175911782d413369b64ce7c/bus", &dbus.Config{
|
||||
MustProxyDBus("/tmp/hakurei.1971/ebf083d1b175911782d413369b64ce7c/bus", &dbus.Config{
|
||||
Talk: []string{
|
||||
"org.freedesktop.Notifications",
|
||||
"org.freedesktop.FileManager1",
|
||||
@@ -153,7 +153,7 @@ var testCasesPd = []sealTestCase{
|
||||
"org.freedesktop.portal.*": "@/org/freedesktop/portal/*",
|
||||
},
|
||||
Filter: true,
|
||||
}, "/tmp/fortify.1971/ebf083d1b175911782d413369b64ce7c/system_bus_socket", &dbus.Config{
|
||||
}, "/tmp/hakurei.1971/ebf083d1b175911782d413369b64ce7c/system_bus_socket", &dbus.Config{
|
||||
Talk: []string{
|
||||
"org.bluez",
|
||||
"org.freedesktop.Avahi",
|
||||
@@ -161,8 +161,8 @@ var testCasesPd = []sealTestCase{
|
||||
},
|
||||
Filter: true,
|
||||
}).
|
||||
UpdatePerm("/tmp/fortify.1971/ebf083d1b175911782d413369b64ce7c/bus", acl.Read, acl.Write).
|
||||
UpdatePerm("/tmp/fortify.1971/ebf083d1b175911782d413369b64ce7c/system_bus_socket", acl.Read, acl.Write),
|
||||
UpdatePerm("/tmp/hakurei.1971/ebf083d1b175911782d413369b64ce7c/bus", acl.Read, acl.Write).
|
||||
UpdatePerm("/tmp/hakurei.1971/ebf083d1b175911782d413369b64ce7c/system_bus_socket", acl.Read, acl.Write),
|
||||
&sandbox.Params{
|
||||
Flags: sandbox.FAllowNet | sandbox.FAllowUserns | sandbox.FAllowTTY,
|
||||
Dir: "/home/chronos",
|
||||
@@ -172,7 +172,7 @@ var testCasesPd = []sealTestCase{
|
||||
"DBUS_SESSION_BUS_ADDRESS=unix:path=/run/user/65534/bus",
|
||||
"DBUS_SYSTEM_BUS_ADDRESS=unix:path=/run/dbus/system_bus_socket",
|
||||
"HOME=/home/chronos",
|
||||
"PULSE_COOKIE=" + fst.Tmp + "/pulse-cookie",
|
||||
"PULSE_COOKIE=" + hst.Tmp + "/pulse-cookie",
|
||||
"PULSE_SERVER=unix:/run/user/65534/pulse/native",
|
||||
"SHELL=/run/current-system/sw/bin/zsh",
|
||||
"TERM=xterm-256color",
|
||||
@@ -184,7 +184,7 @@ var testCasesPd = []sealTestCase{
|
||||
},
|
||||
Ops: new(sandbox.Ops).
|
||||
Proc("/proc").
|
||||
Tmpfs(fst.Tmp, 4096, 0755).
|
||||
Tmpfs(hst.Tmp, 4096, 0755).
|
||||
Dev("/dev").Mqueue("/dev/mqueue").
|
||||
Bind("/bin", "/bin", sandbox.BindWritable).
|
||||
Bind("/boot", "/boot", sandbox.BindWritable).
|
||||
@@ -204,16 +204,16 @@ var testCasesPd = []sealTestCase{
|
||||
Tmpfs("/run/dbus", 8192, 0755).
|
||||
Etc("/etc", "ebf083d1b175911782d413369b64ce7c").
|
||||
Tmpfs("/run/user", 4096, 0755).
|
||||
Bind("/tmp/fortify.1971/runtime/9", "/run/user/65534", sandbox.BindWritable).
|
||||
Bind("/tmp/fortify.1971/tmpdir/9", "/tmp", sandbox.BindWritable).
|
||||
Bind("/tmp/hakurei.1971/runtime/9", "/run/user/65534", sandbox.BindWritable).
|
||||
Bind("/tmp/hakurei.1971/tmpdir/9", "/tmp", sandbox.BindWritable).
|
||||
Bind("/home/chronos", "/home/chronos", sandbox.BindWritable).
|
||||
Place("/etc/passwd", []byte("chronos:x:65534:65534:Fortify:/home/chronos:/run/current-system/sw/bin/zsh\n")).
|
||||
Place("/etc/group", []byte("fortify:x:65534:\n")).
|
||||
Bind("/tmp/fortify.1971/ebf083d1b175911782d413369b64ce7c/wayland", "/run/user/65534/wayland-0", 0).
|
||||
Bind("/run/user/1971/fortify/ebf083d1b175911782d413369b64ce7c/pulse", "/run/user/65534/pulse/native", 0).
|
||||
Place(fst.Tmp+"/pulse-cookie", nil).
|
||||
Bind("/tmp/fortify.1971/ebf083d1b175911782d413369b64ce7c/bus", "/run/user/65534/bus", 0).
|
||||
Bind("/tmp/fortify.1971/ebf083d1b175911782d413369b64ce7c/system_bus_socket", "/run/dbus/system_bus_socket", 0).
|
||||
Place("/etc/passwd", []byte("chronos:x:65534:65534:Hakurei:/home/chronos:/run/current-system/sw/bin/zsh\n")).
|
||||
Place("/etc/group", []byte("hakurei:x:65534:\n")).
|
||||
Bind("/tmp/hakurei.1971/ebf083d1b175911782d413369b64ce7c/wayland", "/run/user/65534/wayland-0", 0).
|
||||
Bind("/run/user/1971/hakurei/ebf083d1b175911782d413369b64ce7c/pulse", "/run/user/65534/pulse/native", 0).
|
||||
Place(hst.Tmp+"/pulse-cookie", nil).
|
||||
Bind("/tmp/hakurei.1971/ebf083d1b175911782d413369b64ce7c/bus", "/run/user/65534/bus", 0).
|
||||
Bind("/tmp/hakurei.1971/ebf083d1b175911782d413369b64ce7c/system_bus_socket", "/run/dbus/system_bus_socket", 0).
|
||||
Tmpfs("/var/run/nscd", 8192, 0755),
|
||||
},
|
||||
},
|
||||
|
||||
@@ -7,7 +7,7 @@ import (
|
||||
"os/user"
|
||||
"strconv"
|
||||
|
||||
"git.gensokyo.uk/security/fortify/internal/app"
|
||||
"git.gensokyo.uk/security/hakurei/internal/app"
|
||||
)
|
||||
|
||||
// fs methods are not implemented using a real FS
|
||||
@@ -20,7 +20,7 @@ type stubNixOS struct {
|
||||
func (s *stubNixOS) Getuid() int { return 1971 }
|
||||
func (s *stubNixOS) Getgid() int { return 100 }
|
||||
func (s *stubNixOS) TempDir() string { return "/tmp" }
|
||||
func (s *stubNixOS) MustExecutable() string { return "/run/wrappers/bin/fortify" }
|
||||
func (s *stubNixOS) MustExecutable() string { return "/run/wrappers/bin/hakurei" }
|
||||
func (s *stubNixOS) Exit(code int) { panic("called exit on stub with code " + strconv.Itoa(code)) }
|
||||
func (s *stubNixOS) EvalSymlinks(path string) (string, error) { return path, nil }
|
||||
func (s *stubNixOS) Uid(aid int) (int, error) { return 1000000 + 0*10000 + aid, nil }
|
||||
@@ -127,8 +127,8 @@ func (s *stubNixOS) Open(name string) (fs.File, error) {
|
||||
|
||||
func (s *stubNixOS) Paths() app.Paths {
|
||||
return app.Paths{
|
||||
SharePath: "/tmp/fortify.1971",
|
||||
SharePath: "/tmp/hakurei.1971",
|
||||
RuntimePath: "/run/user/1971",
|
||||
RunDirPath: "/run/user/1971/fortify",
|
||||
RunDirPath: "/run/user/1971/hakurei",
|
||||
}
|
||||
}
|
||||
|
||||
@@ -7,18 +7,18 @@ import (
|
||||
"testing"
|
||||
"time"
|
||||
|
||||
"git.gensokyo.uk/security/fortify/fst"
|
||||
"git.gensokyo.uk/security/fortify/internal/app"
|
||||
"git.gensokyo.uk/security/fortify/internal/app/internal/setuid"
|
||||
"git.gensokyo.uk/security/fortify/internal/sys"
|
||||
"git.gensokyo.uk/security/fortify/sandbox"
|
||||
"git.gensokyo.uk/security/fortify/system"
|
||||
"git.gensokyo.uk/security/hakurei/hst"
|
||||
"git.gensokyo.uk/security/hakurei/internal/app"
|
||||
"git.gensokyo.uk/security/hakurei/internal/app/internal/setuid"
|
||||
"git.gensokyo.uk/security/hakurei/internal/sys"
|
||||
"git.gensokyo.uk/security/hakurei/sandbox"
|
||||
"git.gensokyo.uk/security/hakurei/system"
|
||||
)
|
||||
|
||||
type sealTestCase struct {
|
||||
name string
|
||||
os sys.State
|
||||
config *fst.Config
|
||||
config *hst.Config
|
||||
id app.ID
|
||||
wantSys *system.I
|
||||
wantContainer *sandbox.Params
|
||||
@@ -80,70 +80,25 @@ func stubDirEntries(names ...string) (e []fs.DirEntry, err error) {
|
||||
|
||||
type stubDirEntryPath string
|
||||
|
||||
func (p stubDirEntryPath) Name() string {
|
||||
return string(p)
|
||||
}
|
||||
|
||||
func (p stubDirEntryPath) IsDir() bool {
|
||||
panic("attempted to call IsDir")
|
||||
}
|
||||
|
||||
func (p stubDirEntryPath) Type() fs.FileMode {
|
||||
panic("attempted to call Type")
|
||||
}
|
||||
|
||||
func (p stubDirEntryPath) Info() (fs.FileInfo, error) {
|
||||
panic("attempted to call Info")
|
||||
}
|
||||
func (p stubDirEntryPath) Name() string { return string(p) }
|
||||
func (p stubDirEntryPath) IsDir() bool { panic("attempted to call IsDir") }
|
||||
func (p stubDirEntryPath) Type() fs.FileMode { panic("attempted to call Type") }
|
||||
func (p stubDirEntryPath) Info() (fs.FileInfo, error) { panic("attempted to call Info") }
|
||||
|
||||
type stubFileInfoMode fs.FileMode
|
||||
|
||||
func (s stubFileInfoMode) Name() string {
|
||||
panic("attempted to call Name")
|
||||
}
|
||||
|
||||
func (s stubFileInfoMode) Size() int64 {
|
||||
panic("attempted to call Size")
|
||||
}
|
||||
|
||||
func (s stubFileInfoMode) Mode() fs.FileMode {
|
||||
return fs.FileMode(s)
|
||||
}
|
||||
|
||||
func (s stubFileInfoMode) ModTime() time.Time {
|
||||
panic("attempted to call ModTime")
|
||||
}
|
||||
|
||||
func (s stubFileInfoMode) IsDir() bool {
|
||||
panic("attempted to call IsDir")
|
||||
}
|
||||
|
||||
func (s stubFileInfoMode) Sys() any {
|
||||
panic("attempted to call Sys")
|
||||
}
|
||||
func (s stubFileInfoMode) Name() string { panic("attempted to call Name") }
|
||||
func (s stubFileInfoMode) Size() int64 { panic("attempted to call Size") }
|
||||
func (s stubFileInfoMode) Mode() fs.FileMode { return fs.FileMode(s) }
|
||||
func (s stubFileInfoMode) ModTime() time.Time { panic("attempted to call ModTime") }
|
||||
func (s stubFileInfoMode) IsDir() bool { panic("attempted to call IsDir") }
|
||||
func (s stubFileInfoMode) Sys() any { panic("attempted to call Sys") }
|
||||
|
||||
type stubFileInfoIsDir bool
|
||||
|
||||
func (s stubFileInfoIsDir) Name() string {
|
||||
panic("attempted to call Name")
|
||||
}
|
||||
|
||||
func (s stubFileInfoIsDir) Size() int64 {
|
||||
panic("attempted to call Size")
|
||||
}
|
||||
|
||||
func (s stubFileInfoIsDir) Mode() fs.FileMode {
|
||||
panic("attempted to call Mode")
|
||||
}
|
||||
|
||||
func (s stubFileInfoIsDir) ModTime() time.Time {
|
||||
panic("attempted to call ModTime")
|
||||
}
|
||||
|
||||
func (s stubFileInfoIsDir) IsDir() bool {
|
||||
return bool(s)
|
||||
}
|
||||
|
||||
func (s stubFileInfoIsDir) Sys() any {
|
||||
panic("attempted to call Sys")
|
||||
}
|
||||
func (s stubFileInfoIsDir) Name() string { panic("attempted to call Name") }
|
||||
func (s stubFileInfoIsDir) Size() int64 { panic("attempted to call Size") }
|
||||
func (s stubFileInfoIsDir) Mode() fs.FileMode { panic("attempted to call Mode") }
|
||||
func (s stubFileInfoIsDir) ModTime() time.Time { panic("attempted to call ModTime") }
|
||||
func (s stubFileInfoIsDir) IsDir() bool { return bool(s) }
|
||||
func (s stubFileInfoIsDir) Sys() any { panic("attempted to call Sys") }
|
||||
|
||||
@@ -4,8 +4,8 @@ import (
|
||||
"errors"
|
||||
"log"
|
||||
|
||||
. "git.gensokyo.uk/security/fortify/internal/app"
|
||||
"git.gensokyo.uk/security/fortify/internal/fmsg"
|
||||
. "git.gensokyo.uk/security/hakurei/internal/app"
|
||||
"git.gensokyo.uk/security/hakurei/internal/hlog"
|
||||
)
|
||||
|
||||
func PrintRunStateErr(rs *RunState, runErr error) (code int) {
|
||||
@@ -13,10 +13,10 @@ func PrintRunStateErr(rs *RunState, runErr error) (code int) {
|
||||
|
||||
if runErr != nil {
|
||||
if rs.Time == nil {
|
||||
fmsg.PrintBaseError(runErr, "cannot start app:")
|
||||
hlog.PrintBaseError(runErr, "cannot start app:")
|
||||
} else {
|
||||
var e *fmsg.BaseError
|
||||
if !fmsg.AsBaseError(runErr, &e) {
|
||||
var e *hlog.BaseError
|
||||
if !hlog.AsBaseError(runErr, &e) {
|
||||
log.Println("wait failed:", runErr)
|
||||
} else {
|
||||
// Wait only returns either *app.ProcessError or *app.StateStoreError wrapped in a *app.BaseError
|
||||
@@ -37,7 +37,7 @@ func PrintRunStateErr(rs *RunState, runErr error) (code int) {
|
||||
|
||||
// every error here is wrapped in *app.BaseError
|
||||
for _, ei := range errs {
|
||||
var eb *fmsg.BaseError
|
||||
var eb *hlog.BaseError
|
||||
if !errors.As(ei, &eb) {
|
||||
// unreachable
|
||||
log.Println("invalid error type returned by revert:", ei)
|
||||
@@ -59,7 +59,7 @@ func PrintRunStateErr(rs *RunState, runErr error) (code int) {
|
||||
if rs.RevertErr != nil {
|
||||
var stateStoreError *StateStoreError
|
||||
if !errors.As(rs.RevertErr, &stateStoreError) || stateStoreError == nil {
|
||||
fmsg.PrintBaseError(rs.RevertErr, "generic fault during cleanup:")
|
||||
hlog.PrintBaseError(rs.RevertErr, "generic fault during cleanup:")
|
||||
goto out
|
||||
}
|
||||
|
||||
@@ -67,11 +67,11 @@ func PrintRunStateErr(rs *RunState, runErr error) (code int) {
|
||||
if len(stateStoreError.Err) == 2 {
|
||||
if stateStoreError.Err[0] != nil {
|
||||
if joinedErrs, ok := stateStoreError.Err[0].(interface{ Unwrap() []error }); !ok {
|
||||
fmsg.PrintBaseError(stateStoreError.Err[0], "generic fault during revert:")
|
||||
hlog.PrintBaseError(stateStoreError.Err[0], "generic fault during revert:")
|
||||
} else {
|
||||
for _, err := range joinedErrs.Unwrap() {
|
||||
if err != nil {
|
||||
fmsg.PrintBaseError(err, "fault during revert:")
|
||||
hlog.PrintBaseError(err, "fault during revert:")
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -91,11 +91,11 @@ func PrintRunStateErr(rs *RunState, runErr error) (code int) {
|
||||
}
|
||||
|
||||
if stateStoreError.DoErr != nil {
|
||||
fmsg.PrintBaseError(stateStoreError.DoErr, "state store operation unsuccessful:")
|
||||
hlog.PrintBaseError(stateStoreError.DoErr, "state store operation unsuccessful:")
|
||||
}
|
||||
|
||||
if stateStoreError.Inner && stateStoreError.InnerErr != nil {
|
||||
fmsg.PrintBaseError(stateStoreError.InnerErr, "cannot destroy state entry:")
|
||||
hlog.PrintBaseError(stateStoreError.InnerErr, "cannot destroy state entry:")
|
||||
}
|
||||
|
||||
out:
|
||||
@@ -104,7 +104,7 @@ func PrintRunStateErr(rs *RunState, runErr error) (code int) {
|
||||
}
|
||||
}
|
||||
if rs.WaitErr != nil {
|
||||
fmsg.Verbosef("wait: %v", rs.WaitErr)
|
||||
hlog.Verbosef("wait: %v", rs.WaitErr)
|
||||
}
|
||||
return
|
||||
}
|
||||
@@ -135,7 +135,7 @@ func (e *StateStoreError) equiv(a ...any) error {
|
||||
if e.Inner && e.InnerErr == nil && e.DoErr == nil && e.OpErr == nil && errors.Join(e.Err...) == nil {
|
||||
return nil
|
||||
} else {
|
||||
return fmsg.WrapErrorSuffix(e, a...)
|
||||
return hlog.WrapErrSuffix(e, a...)
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -1,10 +1,10 @@
|
||||
package setuid
|
||||
|
||||
import (
|
||||
. "git.gensokyo.uk/security/fortify/internal/app"
|
||||
"git.gensokyo.uk/security/fortify/internal/sys"
|
||||
"git.gensokyo.uk/security/fortify/sandbox"
|
||||
"git.gensokyo.uk/security/fortify/system"
|
||||
. "git.gensokyo.uk/security/hakurei/internal/app"
|
||||
"git.gensokyo.uk/security/hakurei/internal/sys"
|
||||
"git.gensokyo.uk/security/hakurei/sandbox"
|
||||
"git.gensokyo.uk/security/hakurei/system"
|
||||
)
|
||||
|
||||
func NewWithID(id ID, os sys.State) App {
|
||||
|
||||
@@ -12,12 +12,12 @@ import (
|
||||
"syscall"
|
||||
"time"
|
||||
|
||||
"git.gensokyo.uk/security/fortify/internal"
|
||||
. "git.gensokyo.uk/security/fortify/internal/app"
|
||||
"git.gensokyo.uk/security/fortify/internal/fmsg"
|
||||
"git.gensokyo.uk/security/fortify/internal/state"
|
||||
"git.gensokyo.uk/security/fortify/sandbox"
|
||||
"git.gensokyo.uk/security/fortify/system"
|
||||
"git.gensokyo.uk/security/hakurei/internal"
|
||||
. "git.gensokyo.uk/security/hakurei/internal/app"
|
||||
"git.gensokyo.uk/security/hakurei/internal/hlog"
|
||||
"git.gensokyo.uk/security/hakurei/internal/state"
|
||||
"git.gensokyo.uk/security/hakurei/sandbox"
|
||||
"git.gensokyo.uk/security/hakurei/system"
|
||||
)
|
||||
|
||||
const shimWaitTimeout = 5 * time.Second
|
||||
@@ -35,7 +35,7 @@ func (seal *outcome) Run(rs *RunState) error {
|
||||
}
|
||||
|
||||
// read comp value early to allow for early failure
|
||||
fsuPath := internal.MustFsuPath()
|
||||
hsuPath := internal.MustHsuPath()
|
||||
|
||||
if err := seal.sys.Commit(seal.ctx); err != nil {
|
||||
return err
|
||||
@@ -59,7 +59,7 @@ func (seal *outcome) Run(rs *RunState) error {
|
||||
if l := len(states); l == 0 {
|
||||
ec |= system.User
|
||||
} else {
|
||||
fmsg.Verbosef("found %d instances, cleaning up without user-scoped operations", l)
|
||||
hlog.Verbosef("found %d instances, cleaning up without user-scoped operations", l)
|
||||
}
|
||||
|
||||
// accumulate enablements of remaining launchers
|
||||
@@ -72,9 +72,9 @@ func (seal *outcome) Run(rs *RunState) error {
|
||||
}
|
||||
}
|
||||
ec |= rt ^ (system.EWayland | system.EX11 | system.EDBus | system.EPulse)
|
||||
if fmsg.Load() {
|
||||
if hlog.Load() {
|
||||
if ec > 0 {
|
||||
fmsg.Verbose("reverting operations scope", system.TypeString(ec))
|
||||
hlog.Verbose("reverting operations scope", system.TypeString(ec))
|
||||
}
|
||||
}
|
||||
|
||||
@@ -87,7 +87,7 @@ func (seal *outcome) Run(rs *RunState) error {
|
||||
|
||||
ctx, cancel := context.WithCancel(seal.ctx)
|
||||
defer cancel()
|
||||
cmd := exec.CommandContext(ctx, fsuPath)
|
||||
cmd := exec.CommandContext(ctx, hsuPath)
|
||||
cmd.Stdin, cmd.Stdout, cmd.Stderr = os.Stdin, os.Stdout, os.Stderr
|
||||
cmd.Dir = "/" // container init enters final working directory
|
||||
// shim runs in the same session as monitor; see shim.go for behaviour
|
||||
@@ -95,28 +95,28 @@ func (seal *outcome) Run(rs *RunState) error {
|
||||
|
||||
var e *gob.Encoder
|
||||
if fd, encoder, err := sandbox.Setup(&cmd.ExtraFiles); err != nil {
|
||||
return fmsg.WrapErrorSuffix(err,
|
||||
return hlog.WrapErrSuffix(err,
|
||||
"cannot create shim setup pipe:")
|
||||
} else {
|
||||
e = encoder
|
||||
cmd.Env = []string{
|
||||
// passed through to shim by fsu
|
||||
// passed through to shim by hsu
|
||||
shimEnv + "=" + strconv.Itoa(fd),
|
||||
// interpreted by fsu
|
||||
"FORTIFY_APP_ID=" + seal.user.aid.String(),
|
||||
// interpreted by hsu
|
||||
"HAKUREI_APP_ID=" + seal.user.aid.String(),
|
||||
}
|
||||
}
|
||||
|
||||
if len(seal.user.supp) > 0 {
|
||||
fmsg.Verbosef("attaching supplementary group ids %s", seal.user.supp)
|
||||
// interpreted by fsu
|
||||
cmd.Env = append(cmd.Env, "FORTIFY_GROUPS="+strings.Join(seal.user.supp, " "))
|
||||
hlog.Verbosef("attaching supplementary group ids %s", seal.user.supp)
|
||||
// interpreted by hsu
|
||||
cmd.Env = append(cmd.Env, "HAKUREI_GROUPS="+strings.Join(seal.user.supp, " "))
|
||||
}
|
||||
|
||||
fmsg.Verbosef("setuid helper at %s", fsuPath)
|
||||
fmsg.Suspend()
|
||||
hlog.Verbosef("setuid helper at %s", hsuPath)
|
||||
hlog.Suspend()
|
||||
if err := cmd.Start(); err != nil {
|
||||
return fmsg.WrapErrorSuffix(err,
|
||||
return hlog.WrapErrSuffix(err,
|
||||
"cannot start setuid wrapper:")
|
||||
}
|
||||
rs.SetStart()
|
||||
@@ -124,19 +124,19 @@ func (seal *outcome) Run(rs *RunState) error {
|
||||
// this prevents blocking forever on an early failure
|
||||
waitErr, setupErr := make(chan error, 1), make(chan error, 1)
|
||||
go func() { waitErr <- cmd.Wait(); cancel() }()
|
||||
go func() { setupErr <- e.Encode(&shimParams{os.Getpid(), seal.container, seal.user.data, fmsg.Load()}) }()
|
||||
go func() { setupErr <- e.Encode(&shimParams{os.Getpid(), seal.container, seal.user.data, hlog.Load()}) }()
|
||||
|
||||
select {
|
||||
case err := <-setupErr:
|
||||
if err != nil {
|
||||
fmsg.Resume()
|
||||
return fmsg.WrapErrorSuffix(err,
|
||||
hlog.Resume()
|
||||
return hlog.WrapErrSuffix(err,
|
||||
"cannot transmit shim config:")
|
||||
}
|
||||
|
||||
case <-ctx.Done():
|
||||
fmsg.Resume()
|
||||
return fmsg.WrapError(syscall.ECANCELED,
|
||||
hlog.Resume()
|
||||
return hlog.WrapErr(syscall.ECANCELED,
|
||||
"shim setup canceled")
|
||||
}
|
||||
|
||||
@@ -163,25 +163,25 @@ func (seal *outcome) Run(rs *RunState) error {
|
||||
select {
|
||||
case rs.WaitErr = <-waitErr:
|
||||
rs.WaitStatus = cmd.ProcessState.Sys().(syscall.WaitStatus)
|
||||
if fmsg.Load() {
|
||||
if hlog.Load() {
|
||||
switch {
|
||||
case rs.Exited():
|
||||
fmsg.Verbosef("process %d exited with code %d", cmd.Process.Pid, rs.ExitStatus())
|
||||
hlog.Verbosef("process %d exited with code %d", cmd.Process.Pid, rs.ExitStatus())
|
||||
case rs.CoreDump():
|
||||
fmsg.Verbosef("process %d dumped core", cmd.Process.Pid)
|
||||
hlog.Verbosef("process %d dumped core", cmd.Process.Pid)
|
||||
case rs.Signaled():
|
||||
fmsg.Verbosef("process %d got %s", cmd.Process.Pid, rs.Signal())
|
||||
hlog.Verbosef("process %d got %s", cmd.Process.Pid, rs.Signal())
|
||||
default:
|
||||
fmsg.Verbosef("process %d exited with status %#x", cmd.Process.Pid, rs.WaitStatus)
|
||||
hlog.Verbosef("process %d exited with status %#x", cmd.Process.Pid, rs.WaitStatus)
|
||||
}
|
||||
}
|
||||
case <-waitTimeout:
|
||||
rs.WaitErr = syscall.ETIMEDOUT
|
||||
fmsg.Resume()
|
||||
hlog.Resume()
|
||||
log.Printf("process %d did not terminate", cmd.Process.Pid)
|
||||
}
|
||||
|
||||
fmsg.Resume()
|
||||
hlog.Resume()
|
||||
if seal.sync != nil {
|
||||
if err := seal.sync.Close(); err != nil {
|
||||
log.Printf("cannot close wayland security context: %v", err)
|
||||
|
||||
@@ -16,17 +16,17 @@ import (
|
||||
"sync/atomic"
|
||||
"syscall"
|
||||
|
||||
"git.gensokyo.uk/security/fortify/acl"
|
||||
"git.gensokyo.uk/security/fortify/dbus"
|
||||
"git.gensokyo.uk/security/fortify/fst"
|
||||
"git.gensokyo.uk/security/fortify/internal"
|
||||
. "git.gensokyo.uk/security/fortify/internal/app"
|
||||
"git.gensokyo.uk/security/fortify/internal/app/instance/common"
|
||||
"git.gensokyo.uk/security/fortify/internal/fmsg"
|
||||
"git.gensokyo.uk/security/fortify/internal/sys"
|
||||
"git.gensokyo.uk/security/fortify/sandbox"
|
||||
"git.gensokyo.uk/security/fortify/sandbox/wl"
|
||||
"git.gensokyo.uk/security/fortify/system"
|
||||
"git.gensokyo.uk/security/hakurei/acl"
|
||||
"git.gensokyo.uk/security/hakurei/dbus"
|
||||
"git.gensokyo.uk/security/hakurei/hst"
|
||||
"git.gensokyo.uk/security/hakurei/internal"
|
||||
. "git.gensokyo.uk/security/hakurei/internal/app"
|
||||
"git.gensokyo.uk/security/hakurei/internal/app/instance/common"
|
||||
"git.gensokyo.uk/security/hakurei/internal/hlog"
|
||||
"git.gensokyo.uk/security/hakurei/internal/sys"
|
||||
"git.gensokyo.uk/security/hakurei/sandbox"
|
||||
"git.gensokyo.uk/security/hakurei/sandbox/wl"
|
||||
"git.gensokyo.uk/security/hakurei/system"
|
||||
)
|
||||
|
||||
const (
|
||||
@@ -63,20 +63,20 @@ var (
|
||||
|
||||
var posixUsername = regexp.MustCompilePOSIX("^[a-z_]([A-Za-z0-9_-]{0,31}|[A-Za-z0-9_-]{0,30}\\$)$")
|
||||
|
||||
// outcome stores copies of various parts of [fst.Config]
|
||||
// outcome stores copies of various parts of [hst.Config]
|
||||
type outcome struct {
|
||||
// copied from initialising [app]
|
||||
id *stringPair[ID]
|
||||
// copied from [sys.State] response
|
||||
runDirPath string
|
||||
|
||||
// initial [fst.Config] gob stream for state data;
|
||||
// initial [hst.Config] gob stream for state data;
|
||||
// this is prepared ahead of time as config is clobbered during seal creation
|
||||
ct io.WriterTo
|
||||
// dump dbus proxy message buffer
|
||||
dbusMsg func()
|
||||
|
||||
user fsuUser
|
||||
user hsuUser
|
||||
sys *system.I
|
||||
ctx context.Context
|
||||
|
||||
@@ -89,7 +89,7 @@ type outcome struct {
|
||||
|
||||
// shareHost holds optional share directory state that must not be accessed directly
|
||||
type shareHost struct {
|
||||
// whether XDG_RUNTIME_DIR is used post fsu
|
||||
// whether XDG_RUNTIME_DIR is used post hsu
|
||||
useRuntimeDir bool
|
||||
// process-specific directory in tmpdir, empty if unused
|
||||
sharePath string
|
||||
@@ -134,8 +134,8 @@ func (share *shareHost) runtime() string {
|
||||
return share.runtimeSharePath
|
||||
}
|
||||
|
||||
// fsuUser stores post-fsu credentials and metadata
|
||||
type fsuUser struct {
|
||||
// hsuUser stores post-hsu credentials and metadata
|
||||
type hsuUser struct {
|
||||
// application id
|
||||
aid *stringPair[int]
|
||||
// target uid resolved by fid:aid
|
||||
@@ -152,7 +152,7 @@ type fsuUser struct {
|
||||
username string
|
||||
}
|
||||
|
||||
func (seal *outcome) finalise(ctx context.Context, sys sys.State, config *fst.Config) error {
|
||||
func (seal *outcome) finalise(ctx context.Context, sys sys.State, config *hst.Config) error {
|
||||
if seal.ctx != nil {
|
||||
panic("finalise called twice")
|
||||
}
|
||||
@@ -162,19 +162,19 @@ func (seal *outcome) finalise(ctx context.Context, sys sys.State, config *fst.Co
|
||||
// encode initial configuration for state tracking
|
||||
ct := new(bytes.Buffer)
|
||||
if err := gob.NewEncoder(ct).Encode(config); err != nil {
|
||||
return fmsg.WrapErrorSuffix(err,
|
||||
return hlog.WrapErrSuffix(err,
|
||||
"cannot encode initial config:")
|
||||
}
|
||||
seal.ct = ct
|
||||
}
|
||||
|
||||
// allowed aid range 0 to 9999, this is checked again in fsu
|
||||
// allowed aid range 0 to 9999, this is checked again in hsu
|
||||
if config.Identity < 0 || config.Identity > 9999 {
|
||||
return fmsg.WrapError(ErrUser,
|
||||
return hlog.WrapErr(ErrUser,
|
||||
fmt.Sprintf("identity %d out of range", config.Identity))
|
||||
}
|
||||
|
||||
seal.user = fsuUser{
|
||||
seal.user = hsuUser{
|
||||
aid: newInt(config.Identity),
|
||||
data: config.Data,
|
||||
home: config.Dir,
|
||||
@@ -184,11 +184,11 @@ func (seal *outcome) finalise(ctx context.Context, sys sys.State, config *fst.Co
|
||||
seal.user.username = "chronos"
|
||||
} else if !posixUsername.MatchString(seal.user.username) ||
|
||||
len(seal.user.username) >= internal.Sysconf_SC_LOGIN_NAME_MAX() {
|
||||
return fmsg.WrapError(ErrName,
|
||||
return hlog.WrapErr(ErrName,
|
||||
fmt.Sprintf("invalid user name %q", seal.user.username))
|
||||
}
|
||||
if seal.user.data == "" || !path.IsAbs(seal.user.data) {
|
||||
return fmsg.WrapError(ErrHome,
|
||||
return hlog.WrapErr(ErrHome,
|
||||
fmt.Sprintf("invalid home directory %q", seal.user.data))
|
||||
}
|
||||
if seal.user.home == "" {
|
||||
@@ -202,7 +202,7 @@ func (seal *outcome) finalise(ctx context.Context, sys sys.State, config *fst.Co
|
||||
seal.user.supp = make([]string, len(config.Groups))
|
||||
for i, name := range config.Groups {
|
||||
if g, err := sys.LookupGroup(name); err != nil {
|
||||
return fmsg.WrapError(err,
|
||||
return hlog.WrapErr(err,
|
||||
fmt.Sprintf("unknown group %q", name))
|
||||
} else {
|
||||
seal.user.supp[i] = g.Gid
|
||||
@@ -220,13 +220,13 @@ func (seal *outcome) finalise(ctx context.Context, sys sys.State, config *fst.Co
|
||||
|
||||
// permissive defaults
|
||||
if config.Container == nil {
|
||||
fmsg.Verbose("container configuration not supplied, PROCEED WITH CAUTION")
|
||||
hlog.Verbose("container configuration not supplied, PROCEED WITH CAUTION")
|
||||
|
||||
// fsu clears the environment so resolve paths early
|
||||
// hsu clears the environment so resolve paths early
|
||||
if !path.IsAbs(config.Path) {
|
||||
if len(config.Args) > 0 {
|
||||
if p, err := sys.LookPath(config.Args[0]); err != nil {
|
||||
return fmsg.WrapError(err, err.Error())
|
||||
return hlog.WrapErr(err, err.Error())
|
||||
} else {
|
||||
config.Path = p
|
||||
}
|
||||
@@ -235,7 +235,7 @@ func (seal *outcome) finalise(ctx context.Context, sys sys.State, config *fst.Co
|
||||
}
|
||||
}
|
||||
|
||||
conf := &fst.ContainerConfig{
|
||||
conf := &hst.ContainerConfig{
|
||||
Userns: true,
|
||||
Net: true,
|
||||
Tty: true,
|
||||
@@ -245,7 +245,7 @@ func (seal *outcome) finalise(ctx context.Context, sys sys.State, config *fst.Co
|
||||
if d, err := sys.ReadDir("/"); err != nil {
|
||||
return err
|
||||
} else {
|
||||
b := make([]*fst.FilesystemConfig, 0, len(d))
|
||||
b := make([]*hst.FilesystemConfig, 0, len(d))
|
||||
for _, ent := range d {
|
||||
p := "/" + ent.Name()
|
||||
switch p {
|
||||
@@ -256,7 +256,7 @@ func (seal *outcome) finalise(ctx context.Context, sys sys.State, config *fst.Co
|
||||
case "/etc":
|
||||
|
||||
default:
|
||||
b = append(b, &fst.FilesystemConfig{Src: p, Write: true, Must: true})
|
||||
b = append(b, &hst.FilesystemConfig{Src: p, Write: true, Must: true})
|
||||
}
|
||||
}
|
||||
conf.Filesystem = append(conf.Filesystem, b...)
|
||||
@@ -269,10 +269,10 @@ func (seal *outcome) finalise(ctx context.Context, sys sys.State, config *fst.Co
|
||||
}
|
||||
// bind GPU stuff
|
||||
if config.Enablements&(system.EX11|system.EWayland) != 0 {
|
||||
conf.Filesystem = append(conf.Filesystem, &fst.FilesystemConfig{Src: "/dev/dri", Device: true})
|
||||
conf.Filesystem = append(conf.Filesystem, &hst.FilesystemConfig{Src: "/dev/dri", Device: true})
|
||||
}
|
||||
// opportunistically bind kvm
|
||||
conf.Filesystem = append(conf.Filesystem, &fst.FilesystemConfig{Src: "/dev/kvm", Device: true})
|
||||
conf.Filesystem = append(conf.Filesystem, &hst.FilesystemConfig{Src: "/dev/kvm", Device: true})
|
||||
|
||||
config.Container = conf
|
||||
}
|
||||
@@ -283,11 +283,11 @@ func (seal *outcome) finalise(ctx context.Context, sys sys.State, config *fst.Co
|
||||
var err error
|
||||
seal.container, seal.env, err = common.NewContainer(config.Container, sys, &uid, &gid)
|
||||
if err != nil {
|
||||
return fmsg.WrapErrorSuffix(err,
|
||||
return hlog.WrapErrSuffix(err,
|
||||
"cannot initialise container configuration:")
|
||||
}
|
||||
if !path.IsAbs(config.Path) {
|
||||
return fmsg.WrapError(syscall.EINVAL,
|
||||
return hlog.WrapErr(syscall.EINVAL,
|
||||
"invalid program path")
|
||||
}
|
||||
if len(config.Args) == 0 {
|
||||
@@ -364,9 +364,9 @@ func (seal *outcome) finalise(ctx context.Context, sys sys.State, config *fst.Co
|
||||
seal.env[shell] = config.Shell
|
||||
|
||||
seal.container.Place("/etc/passwd",
|
||||
[]byte(username+":x:"+mapuid.String()+":"+mapgid.String()+":Fortify:"+homeDir+":"+config.Shell+"\n"))
|
||||
[]byte(username+":x:"+mapuid.String()+":"+mapgid.String()+":Hakurei:"+homeDir+":"+config.Shell+"\n"))
|
||||
seal.container.Place("/etc/group",
|
||||
[]byte("fortify:x:"+mapgid.String()+":\n"))
|
||||
[]byte("hakurei:x:"+mapgid.String()+":\n"))
|
||||
}
|
||||
|
||||
// pass TERM for proper terminal I/O in initial process
|
||||
@@ -378,7 +378,7 @@ func (seal *outcome) finalise(ctx context.Context, sys sys.State, config *fst.Co
|
||||
// outer wayland socket (usually `/run/user/%d/wayland-%d`)
|
||||
var socketPath string
|
||||
if name, ok := sys.LookupEnv(wl.WaylandDisplay); !ok {
|
||||
fmsg.Verbose(wl.WaylandDisplay + " is not set, assuming " + wl.FallbackName)
|
||||
hlog.Verbose(wl.WaylandDisplay + " is not set, assuming " + wl.FallbackName)
|
||||
socketPath = path.Join(share.sc.RuntimePath, wl.FallbackName)
|
||||
} else if !path.IsAbs(name) {
|
||||
socketPath = path.Join(share.sc.RuntimePath, name)
|
||||
@@ -393,14 +393,14 @@ func (seal *outcome) finalise(ctx context.Context, sys sys.State, config *fst.Co
|
||||
appID := config.ID
|
||||
if appID == "" {
|
||||
// use instance ID in case app id is not set
|
||||
appID = "uk.gensokyo.fortify." + seal.id.String()
|
||||
appID = "uk.gensokyo.hakurei." + seal.id.String()
|
||||
}
|
||||
// downstream socket paths
|
||||
outerPath := path.Join(share.instance(), "wayland")
|
||||
seal.sys.Wayland(&seal.sync, outerPath, socketPath, appID, seal.id.String())
|
||||
seal.container.Bind(outerPath, innerPath, 0)
|
||||
} else { // bind mount wayland socket (insecure)
|
||||
fmsg.Verbose("direct wayland access, PROCEED WITH CAUTION")
|
||||
hlog.Verbose("direct wayland access, PROCEED WITH CAUTION")
|
||||
share.ensureRuntimeDir()
|
||||
seal.container.Bind(socketPath, innerPath, 0)
|
||||
seal.sys.UpdatePermType(system.EWayland, socketPath, acl.Read, acl.Write, acl.Execute)
|
||||
@@ -409,7 +409,7 @@ func (seal *outcome) finalise(ctx context.Context, sys sys.State, config *fst.Co
|
||||
|
||||
if config.Enablements&system.EX11 != 0 {
|
||||
if d, ok := sys.LookupEnv(display); !ok {
|
||||
return fmsg.WrapError(ErrXDisplay,
|
||||
return hlog.WrapErr(ErrXDisplay,
|
||||
"DISPLAY is not set")
|
||||
} else {
|
||||
seal.sys.ChangeHosts("#" + seal.user.uid.String())
|
||||
@@ -426,23 +426,23 @@ func (seal *outcome) finalise(ctx context.Context, sys sys.State, config *fst.Co
|
||||
|
||||
if _, err := sys.Stat(pulseRuntimeDir); err != nil {
|
||||
if !errors.Is(err, fs.ErrNotExist) {
|
||||
return fmsg.WrapErrorSuffix(err,
|
||||
return hlog.WrapErrSuffix(err,
|
||||
fmt.Sprintf("cannot access PulseAudio directory %q:", pulseRuntimeDir))
|
||||
}
|
||||
return fmsg.WrapError(ErrPulseSocket,
|
||||
return hlog.WrapErr(ErrPulseSocket,
|
||||
fmt.Sprintf("PulseAudio directory %q not found", pulseRuntimeDir))
|
||||
}
|
||||
|
||||
if s, err := sys.Stat(pulseSocket); err != nil {
|
||||
if !errors.Is(err, fs.ErrNotExist) {
|
||||
return fmsg.WrapErrorSuffix(err,
|
||||
return hlog.WrapErrSuffix(err,
|
||||
fmt.Sprintf("cannot access PulseAudio socket %q:", pulseSocket))
|
||||
}
|
||||
return fmsg.WrapError(ErrPulseSocket,
|
||||
return hlog.WrapErr(ErrPulseSocket,
|
||||
fmt.Sprintf("PulseAudio directory %q found but socket does not exist", pulseRuntimeDir))
|
||||
} else {
|
||||
if m := s.Mode(); m&0o006 != 0o006 {
|
||||
return fmsg.WrapError(ErrPulseMode,
|
||||
return hlog.WrapErr(ErrPulseMode,
|
||||
fmt.Sprintf("unexpected permissions on %q:", pulseSocket), m)
|
||||
}
|
||||
}
|
||||
@@ -457,9 +457,9 @@ func (seal *outcome) finalise(ctx context.Context, sys sys.State, config *fst.Co
|
||||
// publish current user's pulse cookie for target user
|
||||
if src, err := discoverPulseCookie(sys); err != nil {
|
||||
// not fatal
|
||||
fmsg.Verbose(strings.TrimSpace(err.(*fmsg.BaseError).Message()))
|
||||
hlog.Verbose(strings.TrimSpace(err.(*hlog.BaseError).Message()))
|
||||
} else {
|
||||
innerDst := fst.Tmp + "/pulse-cookie"
|
||||
innerDst := hst.Tmp + "/pulse-cookie"
|
||||
seal.env[pulseCookie] = innerDst
|
||||
var payload *[]byte
|
||||
seal.container.PlaceP(innerDst, &payload)
|
||||
@@ -531,15 +531,15 @@ func (seal *outcome) finalise(ctx context.Context, sys sys.State, config *fst.Co
|
||||
seal.container.Env = make([]string, 0, len(seal.env))
|
||||
for k, v := range seal.env {
|
||||
if strings.IndexByte(k, '=') != -1 {
|
||||
return fmsg.WrapError(syscall.EINVAL,
|
||||
return hlog.WrapErr(syscall.EINVAL,
|
||||
fmt.Sprintf("invalid environment variable %s", k))
|
||||
}
|
||||
seal.container.Env = append(seal.container.Env, k+"="+v)
|
||||
}
|
||||
slices.Sort(seal.container.Env)
|
||||
|
||||
if fmsg.Load() {
|
||||
fmsg.Verbosef("created application seal for uid %s (%s) groups: %v, argv: %s, ops: %d",
|
||||
if hlog.Load() {
|
||||
hlog.Verbosef("created application seal for uid %s (%s) groups: %v, argv: %s, ops: %d",
|
||||
seal.user.uid, seal.user.username, config.Groups, seal.container.Args, len(*seal.container.Ops))
|
||||
}
|
||||
|
||||
@@ -557,7 +557,7 @@ func discoverPulseCookie(sys sys.State) (string, error) {
|
||||
p = path.Join(p, ".pulse-cookie")
|
||||
if s, err := sys.Stat(p); err != nil {
|
||||
if !errors.Is(err, fs.ErrNotExist) {
|
||||
return p, fmsg.WrapErrorSuffix(err,
|
||||
return p, hlog.WrapErrSuffix(err,
|
||||
fmt.Sprintf("cannot access PulseAudio cookie %q:", p))
|
||||
}
|
||||
// not found, try next method
|
||||
@@ -571,7 +571,7 @@ func discoverPulseCookie(sys sys.State) (string, error) {
|
||||
p = path.Join(p, "pulse", "cookie")
|
||||
if s, err := sys.Stat(p); err != nil {
|
||||
if !errors.Is(err, fs.ErrNotExist) {
|
||||
return p, fmsg.WrapErrorSuffix(err,
|
||||
return p, hlog.WrapErrSuffix(err,
|
||||
fmt.Sprintf("cannot access PulseAudio cookie %q:", p))
|
||||
}
|
||||
// not found, try next method
|
||||
@@ -580,7 +580,7 @@ func discoverPulseCookie(sys sys.State) (string, error) {
|
||||
}
|
||||
}
|
||||
|
||||
return "", fmsg.WrapError(ErrPulseCookie,
|
||||
return "", hlog.WrapErr(ErrPulseCookie,
|
||||
fmt.Sprintf("cannot locate PulseAudio cookie (tried $%s, $%s/pulse/cookie, $%s/.pulse-cookie)",
|
||||
pulseCookie, xdgConfigHome, home))
|
||||
}
|
||||
|
||||
@@ -10,10 +10,10 @@ import (
|
||||
"syscall"
|
||||
"time"
|
||||
|
||||
"git.gensokyo.uk/security/fortify/internal"
|
||||
"git.gensokyo.uk/security/fortify/internal/fmsg"
|
||||
"git.gensokyo.uk/security/fortify/sandbox"
|
||||
"git.gensokyo.uk/security/fortify/sandbox/seccomp"
|
||||
"git.gensokyo.uk/security/hakurei/internal"
|
||||
"git.gensokyo.uk/security/hakurei/internal/hlog"
|
||||
"git.gensokyo.uk/security/hakurei/sandbox"
|
||||
"git.gensokyo.uk/security/hakurei/sandbox/seccomp"
|
||||
)
|
||||
|
||||
/*
|
||||
@@ -23,10 +23,10 @@ import (
|
||||
#include <errno.h>
|
||||
#include <signal.h>
|
||||
|
||||
static pid_t f_shim_param_ppid = -1;
|
||||
static pid_t hakurei_shim_param_ppid = -1;
|
||||
|
||||
// this cannot unblock fmsg since Go code is not async-signal-safe
|
||||
static void f_shim_sigaction(int sig, siginfo_t *si, void *ucontext) {
|
||||
// this cannot unblock hlog since Go code is not async-signal-safe
|
||||
static void hakurei_shim_sigaction(int sig, siginfo_t *si, void *ucontext) {
|
||||
if (sig != SIGCONT || si == NULL) {
|
||||
// unreachable
|
||||
fprintf(stderr, "sigaction: sa_sigaction got invalid siginfo\n");
|
||||
@@ -34,17 +34,17 @@ static void f_shim_sigaction(int sig, siginfo_t *si, void *ucontext) {
|
||||
}
|
||||
|
||||
// monitor requests shim exit
|
||||
if (si->si_pid == f_shim_param_ppid)
|
||||
if (si->si_pid == hakurei_shim_param_ppid)
|
||||
exit(254);
|
||||
|
||||
fprintf(stderr, "sigaction: got SIGCONT from process %d\n", si->si_pid);
|
||||
|
||||
// shim orphaned before monitor delivers a signal
|
||||
if (getppid() != f_shim_param_ppid)
|
||||
if (getppid() != hakurei_shim_param_ppid)
|
||||
exit(3);
|
||||
}
|
||||
|
||||
void f_shim_setup_cont_signal(pid_t ppid) {
|
||||
void hakurei_shim_setup_cont_signal(pid_t ppid) {
|
||||
struct sigaction new_action = {0}, old_action = {0};
|
||||
if (sigaction(SIGCONT, NULL, &old_action) != 0)
|
||||
return;
|
||||
@@ -53,7 +53,7 @@ void f_shim_setup_cont_signal(pid_t ppid) {
|
||||
return;
|
||||
}
|
||||
|
||||
new_action.sa_sigaction = f_shim_sigaction;
|
||||
new_action.sa_sigaction = hakurei_shim_sigaction;
|
||||
if (sigemptyset(&new_action.sa_mask) != 0)
|
||||
return;
|
||||
new_action.sa_flags = SA_ONSTACK | SA_SIGINFO;
|
||||
@@ -62,12 +62,12 @@ void f_shim_setup_cont_signal(pid_t ppid) {
|
||||
return;
|
||||
|
||||
errno = 0;
|
||||
f_shim_param_ppid = ppid;
|
||||
hakurei_shim_param_ppid = ppid;
|
||||
}
|
||||
*/
|
||||
import "C"
|
||||
|
||||
const shimEnv = "FORTIFY_SHIM"
|
||||
const shimEnv = "HAKUREI_SHIM"
|
||||
|
||||
type shimParams struct {
|
||||
// monitor pid, checked against ppid in signal handler
|
||||
@@ -84,7 +84,7 @@ type shimParams struct {
|
||||
|
||||
// ShimMain is the main function of the shim process and runs as the unconstrained target user.
|
||||
func ShimMain() {
|
||||
fmsg.Prepare("shim")
|
||||
hlog.Prepare("shim")
|
||||
|
||||
if err := sandbox.SetDumpable(sandbox.SUID_DUMP_DISABLE); err != nil {
|
||||
log.Fatalf("cannot set SUID_DUMP_DISABLE: %s", err)
|
||||
@@ -99,7 +99,7 @@ func ShimMain() {
|
||||
log.Fatal("invalid config descriptor")
|
||||
}
|
||||
if errors.Is(err, sandbox.ErrNotSet) {
|
||||
log.Fatal("FORTIFY_SHIM not set")
|
||||
log.Fatal("HAKUREI_SHIM not set")
|
||||
}
|
||||
|
||||
log.Fatalf("cannot receive shim setup params: %v", err)
|
||||
@@ -108,7 +108,7 @@ func ShimMain() {
|
||||
closeSetup = f
|
||||
|
||||
// the Go runtime does not expose siginfo_t so SIGCONT is handled in C to check si_pid
|
||||
if _, err = C.f_shim_setup_cont_signal(C.pid_t(params.Monitor)); err != nil {
|
||||
if _, err = C.hakurei_shim_setup_cont_signal(C.pid_t(params.Monitor)); err != nil {
|
||||
log.Fatalf("cannot install SIGCONT handler: %v", err)
|
||||
}
|
||||
|
||||
@@ -156,11 +156,11 @@ func ShimMain() {
|
||||
container.WaitDelay = 2 * time.Second
|
||||
|
||||
if err := container.Start(); err != nil {
|
||||
fmsg.PrintBaseError(err, "cannot start container:")
|
||||
hlog.PrintBaseError(err, "cannot start container:")
|
||||
os.Exit(1)
|
||||
}
|
||||
if err := container.Serve(); err != nil {
|
||||
fmsg.PrintBaseError(err, "cannot configure container:")
|
||||
hlog.PrintBaseError(err, "cannot configure container:")
|
||||
}
|
||||
|
||||
if err := seccomp.Load(seccomp.PresetCommon); err != nil {
|
||||
|
||||
@@ -3,7 +3,7 @@ package setuid
|
||||
import (
|
||||
"strconv"
|
||||
|
||||
. "git.gensokyo.uk/security/fortify/internal/app"
|
||||
. "git.gensokyo.uk/security/hakurei/internal/app"
|
||||
)
|
||||
|
||||
func newInt(v int) *stringPair[int] { return &stringPair[int]{v, strconv.Itoa(v)} }
|
||||
|
||||
Reference in New Issue
Block a user