app: remove split implementation
All checks were successful
Test / Create distribution (push) Successful in 32s
Test / Sandbox (push) Successful in 1m56s
Test / Hakurei (push) Successful in 2m42s
Test / Sandbox (race detector) (push) Successful in 3m5s
Test / Planterette (push) Successful in 3m37s
Test / Hakurei (race detector) (push) Successful in 4m19s
Test / Flake checks (push) Successful in 1m7s
All checks were successful
Test / Create distribution (push) Successful in 32s
Test / Sandbox (push) Successful in 1m56s
Test / Hakurei (push) Successful in 2m42s
Test / Sandbox (race detector) (push) Successful in 3m5s
Test / Planterette (push) Successful in 3m37s
Test / Hakurei (race detector) (push) Successful in 4m19s
Test / Flake checks (push) Successful in 1m7s
It is completely nonsensical and highly error-prone to have multiple implementations of this in the same build. This should be switched at compile time instead therefore the split packages are pointless. Signed-off-by: Ophestra <cat@gensokyo.uk>
This commit is contained in:
parent
e6967b8bbb
commit
087959e81b
@ -13,12 +13,11 @@ import (
|
|||||||
"syscall"
|
"syscall"
|
||||||
"time"
|
"time"
|
||||||
|
|
||||||
"hakurei.app/cmd/hakurei/internal/app"
|
|
||||||
"hakurei.app/cmd/hakurei/internal/app/instance"
|
|
||||||
"hakurei.app/cmd/hakurei/internal/state"
|
|
||||||
"hakurei.app/command"
|
"hakurei.app/command"
|
||||||
"hakurei.app/hst"
|
"hakurei.app/hst"
|
||||||
"hakurei.app/internal"
|
"hakurei.app/internal"
|
||||||
|
"hakurei.app/internal/app"
|
||||||
|
"hakurei.app/internal/app/state"
|
||||||
"hakurei.app/internal/hlog"
|
"hakurei.app/internal/hlog"
|
||||||
"hakurei.app/system"
|
"hakurei.app/system"
|
||||||
"hakurei.app/system/dbus"
|
"hakurei.app/system/dbus"
|
||||||
@ -33,7 +32,7 @@ func buildCommand(out io.Writer) command.Command {
|
|||||||
Flag(&flagVerbose, "v", command.BoolFlag(false), "Increase log verbosity").
|
Flag(&flagVerbose, "v", command.BoolFlag(false), "Increase log verbosity").
|
||||||
Flag(&flagJSON, "json", command.BoolFlag(false), "Serialise output in JSON when applicable")
|
Flag(&flagJSON, "json", command.BoolFlag(false), "Serialise output in JSON when applicable")
|
||||||
|
|
||||||
c.Command("shim", command.UsageInternal, func([]string) error { instance.ShimMain(); return errSuccess })
|
c.Command("shim", command.UsageInternal, func([]string) error { app.ShimMain(); return errSuccess })
|
||||||
|
|
||||||
c.Command("app", "Load app from configuration file", func(args []string) error {
|
c.Command("app", "Load app from configuration file", func(args []string) error {
|
||||||
if len(args) < 1 {
|
if len(args) < 1 {
|
||||||
@ -244,14 +243,14 @@ func runApp(config *hst.Config) {
|
|||||||
ctx, stop := signal.NotifyContext(context.Background(),
|
ctx, stop := signal.NotifyContext(context.Background(),
|
||||||
syscall.SIGINT, syscall.SIGTERM)
|
syscall.SIGINT, syscall.SIGTERM)
|
||||||
defer stop() // unreachable
|
defer stop() // unreachable
|
||||||
a := instance.MustNew(instance.ISetuid, ctx, std)
|
a := app.MustNew(ctx, std)
|
||||||
|
|
||||||
rs := new(app.RunState)
|
rs := new(app.RunState)
|
||||||
if sa, err := a.Seal(config); err != nil {
|
if sa, err := a.Seal(config); err != nil {
|
||||||
hlog.PrintBaseError(err, "cannot seal app:")
|
hlog.PrintBaseError(err, "cannot seal app:")
|
||||||
internal.Exit(1)
|
internal.Exit(1)
|
||||||
} else {
|
} else {
|
||||||
internal.Exit(instance.PrintRunStateErr(instance.ISetuid, rs, sa.Run(rs)))
|
internal.Exit(app.PrintRunStateErr(rs, sa.Run(rs)))
|
||||||
}
|
}
|
||||||
|
|
||||||
*(*int)(nil) = 0 // not reached
|
*(*int)(nil) = 0 // not reached
|
||||||
|
@ -1,17 +0,0 @@
|
|||||||
package instance
|
|
||||||
|
|
||||||
import (
|
|
||||||
"syscall"
|
|
||||||
|
|
||||||
"hakurei.app/cmd/hakurei/internal/app"
|
|
||||||
"hakurei.app/cmd/hakurei/internal/app/internal/setuid"
|
|
||||||
)
|
|
||||||
|
|
||||||
func PrintRunStateErr(whence int, rs *app.RunState, runErr error) (code int) {
|
|
||||||
switch whence {
|
|
||||||
case ISetuid:
|
|
||||||
return setuid.PrintRunStateErr(rs, runErr)
|
|
||||||
default:
|
|
||||||
panic(syscall.EINVAL)
|
|
||||||
}
|
|
||||||
}
|
|
@ -1,33 +0,0 @@
|
|||||||
// Package instance exposes cross-package implementation details and provides constructors for builtin implementations.
|
|
||||||
package instance
|
|
||||||
|
|
||||||
import (
|
|
||||||
"context"
|
|
||||||
"log"
|
|
||||||
"syscall"
|
|
||||||
|
|
||||||
"hakurei.app/cmd/hakurei/internal/app"
|
|
||||||
"hakurei.app/cmd/hakurei/internal/app/internal/setuid"
|
|
||||||
"hakurei.app/internal/sys"
|
|
||||||
)
|
|
||||||
|
|
||||||
const (
|
|
||||||
ISetuid = iota
|
|
||||||
)
|
|
||||||
|
|
||||||
func New(whence int, ctx context.Context, os sys.State) (app.App, error) {
|
|
||||||
switch whence {
|
|
||||||
case ISetuid:
|
|
||||||
return setuid.New(ctx, os)
|
|
||||||
default:
|
|
||||||
return nil, syscall.EINVAL
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
func MustNew(whence int, ctx context.Context, os sys.State) app.App {
|
|
||||||
a, err := New(whence, ctx, os)
|
|
||||||
if err != nil {
|
|
||||||
log.Fatalf("cannot create app: %v", err)
|
|
||||||
}
|
|
||||||
return a
|
|
||||||
}
|
|
@ -1,6 +0,0 @@
|
|||||||
package instance
|
|
||||||
|
|
||||||
import "hakurei.app/cmd/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() }
|
|
@ -10,8 +10,8 @@ import (
|
|||||||
"strings"
|
"strings"
|
||||||
"syscall"
|
"syscall"
|
||||||
|
|
||||||
"hakurei.app/cmd/hakurei/internal/state"
|
|
||||||
"hakurei.app/hst"
|
"hakurei.app/hst"
|
||||||
|
"hakurei.app/internal/app/state"
|
||||||
"hakurei.app/internal/hlog"
|
"hakurei.app/internal/hlog"
|
||||||
)
|
)
|
||||||
|
|
||||||
|
@ -12,8 +12,8 @@ import (
|
|||||||
"text/tabwriter"
|
"text/tabwriter"
|
||||||
"time"
|
"time"
|
||||||
|
|
||||||
"hakurei.app/cmd/hakurei/internal/state"
|
|
||||||
"hakurei.app/hst"
|
"hakurei.app/hst"
|
||||||
|
"hakurei.app/internal/app/state"
|
||||||
"hakurei.app/internal/hlog"
|
"hakurei.app/internal/hlog"
|
||||||
"hakurei.app/system/dbus"
|
"hakurei.app/system/dbus"
|
||||||
)
|
)
|
||||||
|
@ -5,14 +5,13 @@ import (
|
|||||||
"testing"
|
"testing"
|
||||||
"time"
|
"time"
|
||||||
|
|
||||||
"hakurei.app/cmd/hakurei/internal/app"
|
|
||||||
"hakurei.app/cmd/hakurei/internal/state"
|
|
||||||
"hakurei.app/hst"
|
"hakurei.app/hst"
|
||||||
|
"hakurei.app/internal/app/state"
|
||||||
"hakurei.app/system/dbus"
|
"hakurei.app/system/dbus"
|
||||||
)
|
)
|
||||||
|
|
||||||
var (
|
var (
|
||||||
testID = app.ID{
|
testID = state.ID{
|
||||||
0x8e, 0x2c, 0x76, 0xb0,
|
0x8e, 0x2c, 0x76, 0xb0,
|
||||||
0x66, 0xda, 0xbe, 0x57,
|
0x66, 0xda, 0xbe, 0x57,
|
||||||
0x4c, 0xf0, 0x73, 0xbd,
|
0x4c, 0xf0, 0x73, 0xbd,
|
||||||
@ -460,7 +459,7 @@ func Test_printPs(t *testing.T) {
|
|||||||
{"no entries", make(state.Entries), false, false, " Instance PID Application Uptime\n"},
|
{"no entries", make(state.Entries), false, false, " Instance PID Application Uptime\n"},
|
||||||
{"no entries short", make(state.Entries), true, false, ""},
|
{"no entries short", make(state.Entries), true, false, ""},
|
||||||
{"nil instance", state.Entries{testID: nil}, false, false, " Instance PID Application Uptime\n"},
|
{"nil instance", state.Entries{testID: nil}, false, false, " Instance PID Application Uptime\n"},
|
||||||
{"state corruption", state.Entries{app.ID{}: testState}, false, false, " Instance PID Application Uptime\n"},
|
{"state corruption", state.Entries{state.ID{}: testState}, false, false, " Instance PID Application Uptime\n"},
|
||||||
|
|
||||||
{"valid pd", state.Entries{testID: &state.State{ID: testID, PID: 1 << 8, Config: new(hst.Config), Time: testAppTime}}, false, false, ` Instance PID Application Uptime
|
{"valid pd", state.Entries{testID: &state.State{ID: testID, PID: 1 << 8, Config: new(hst.Config), Time: testAppTime}}, false, false, ` Instance PID Application Uptime
|
||||||
8e2c76b0 256 0 (app.hakurei.8e2c76b0) 1h2m32s
|
8e2c76b0 256 0 (app.hakurei.8e2c76b0) 1h2m32s
|
||||||
|
@ -2,15 +2,19 @@
|
|||||||
package app
|
package app
|
||||||
|
|
||||||
import (
|
import (
|
||||||
|
"context"
|
||||||
|
"log"
|
||||||
"syscall"
|
"syscall"
|
||||||
"time"
|
"time"
|
||||||
|
|
||||||
"hakurei.app/hst"
|
"hakurei.app/hst"
|
||||||
|
"hakurei.app/internal/app/state"
|
||||||
|
"hakurei.app/internal/sys"
|
||||||
)
|
)
|
||||||
|
|
||||||
type App interface {
|
type App interface {
|
||||||
// ID returns a copy of [ID] held by App.
|
// ID returns a copy of [ID] held by App.
|
||||||
ID() ID
|
ID() state.ID
|
||||||
|
|
||||||
// Seal determines the outcome of config as a [SealedApp].
|
// Seal determines the outcome of config as a [SealedApp].
|
||||||
// The value of config might be overwritten and must not be used again.
|
// The value of config might be overwritten and must not be used again.
|
||||||
@ -47,3 +51,11 @@ func (rs *RunState) SetStart() {
|
|||||||
now := time.Now().UTC()
|
now := time.Now().UTC()
|
||||||
rs.Time = &now
|
rs.Time = &now
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func MustNew(ctx context.Context, os sys.State) App {
|
||||||
|
a, err := New(ctx, os)
|
||||||
|
if err != nil {
|
||||||
|
log.Fatalf("cannot create app: %v", err)
|
||||||
|
}
|
||||||
|
return a
|
||||||
|
}
|
@ -1,12 +1,12 @@
|
|||||||
package setuid
|
package app
|
||||||
|
|
||||||
import (
|
import (
|
||||||
"context"
|
"context"
|
||||||
"fmt"
|
"fmt"
|
||||||
"sync"
|
"sync"
|
||||||
|
|
||||||
. "hakurei.app/cmd/hakurei/internal/app"
|
|
||||||
"hakurei.app/hst"
|
"hakurei.app/hst"
|
||||||
|
"hakurei.app/internal/app/state"
|
||||||
"hakurei.app/internal/hlog"
|
"hakurei.app/internal/hlog"
|
||||||
"hakurei.app/internal/sys"
|
"hakurei.app/internal/sys"
|
||||||
)
|
)
|
||||||
@ -16,15 +16,15 @@ func New(ctx context.Context, os sys.State) (App, error) {
|
|||||||
a.sys = os
|
a.sys = os
|
||||||
a.ctx = ctx
|
a.ctx = ctx
|
||||||
|
|
||||||
id := new(ID)
|
id := new(state.ID)
|
||||||
err := NewAppID(id)
|
err := state.NewAppID(id)
|
||||||
a.id = newID(id)
|
a.id = newID(id)
|
||||||
|
|
||||||
return a, err
|
return a, err
|
||||||
}
|
}
|
||||||
|
|
||||||
type app struct {
|
type app struct {
|
||||||
id *stringPair[ID]
|
id *stringPair[state.ID]
|
||||||
sys sys.State
|
sys sys.State
|
||||||
ctx context.Context
|
ctx context.Context
|
||||||
|
|
||||||
@ -32,7 +32,7 @@ type app struct {
|
|||||||
mu sync.RWMutex
|
mu sync.RWMutex
|
||||||
}
|
}
|
||||||
|
|
||||||
func (a *app) ID() ID { a.mu.RLock(); defer a.mu.RUnlock(); return a.id.unwrap() }
|
func (a *app) ID() state.ID { a.mu.RLock(); defer a.mu.RUnlock(); return a.id.unwrap() }
|
||||||
|
|
||||||
func (a *app) String() string {
|
func (a *app) String() string {
|
||||||
if a == nil {
|
if a == nil {
|
@ -1,4 +1,4 @@
|
|||||||
package setuid_test
|
package app_test
|
||||||
|
|
||||||
import (
|
import (
|
||||||
"encoding/json"
|
"encoding/json"
|
||||||
@ -7,10 +7,10 @@ import (
|
|||||||
"testing"
|
"testing"
|
||||||
"time"
|
"time"
|
||||||
|
|
||||||
"hakurei.app/cmd/hakurei/internal/app"
|
|
||||||
"hakurei.app/cmd/hakurei/internal/app/internal/setuid"
|
|
||||||
"hakurei.app/container"
|
"hakurei.app/container"
|
||||||
"hakurei.app/hst"
|
"hakurei.app/hst"
|
||||||
|
"hakurei.app/internal/app"
|
||||||
|
"hakurei.app/internal/app/state"
|
||||||
"hakurei.app/internal/sys"
|
"hakurei.app/internal/sys"
|
||||||
"hakurei.app/system"
|
"hakurei.app/system"
|
||||||
)
|
)
|
||||||
@ -19,7 +19,7 @@ type sealTestCase struct {
|
|||||||
name string
|
name string
|
||||||
os sys.State
|
os sys.State
|
||||||
config *hst.Config
|
config *hst.Config
|
||||||
id app.ID
|
id state.ID
|
||||||
wantSys *system.I
|
wantSys *system.I
|
||||||
wantContainer *container.Params
|
wantContainer *container.Params
|
||||||
}
|
}
|
||||||
@ -29,7 +29,7 @@ func TestApp(t *testing.T) {
|
|||||||
|
|
||||||
for _, tc := range testCases {
|
for _, tc := range testCases {
|
||||||
t.Run(tc.name, func(t *testing.T) {
|
t.Run(tc.name, func(t *testing.T) {
|
||||||
a := setuid.NewWithID(tc.id, tc.os)
|
a := app.NewWithID(tc.id, tc.os)
|
||||||
var (
|
var (
|
||||||
gotSys *system.I
|
gotSys *system.I
|
||||||
gotContainer *container.Params
|
gotContainer *container.Params
|
||||||
@ -39,7 +39,7 @@ func TestApp(t *testing.T) {
|
|||||||
t.Errorf("Seal: error = %v", err)
|
t.Errorf("Seal: error = %v", err)
|
||||||
return
|
return
|
||||||
} else {
|
} else {
|
||||||
gotSys, gotContainer = setuid.AppIParams(a, sa)
|
gotSys, gotContainer = app.AppIParams(a, sa)
|
||||||
}
|
}
|
||||||
}) {
|
}) {
|
||||||
return
|
return
|
@ -1,10 +1,10 @@
|
|||||||
package setuid_test
|
package app_test
|
||||||
|
|
||||||
import (
|
import (
|
||||||
"hakurei.app/cmd/hakurei/internal/app"
|
|
||||||
"hakurei.app/container"
|
"hakurei.app/container"
|
||||||
"hakurei.app/container/seccomp"
|
"hakurei.app/container/seccomp"
|
||||||
"hakurei.app/hst"
|
"hakurei.app/hst"
|
||||||
|
"hakurei.app/internal/app/state"
|
||||||
"hakurei.app/system"
|
"hakurei.app/system"
|
||||||
"hakurei.app/system/acl"
|
"hakurei.app/system/acl"
|
||||||
"hakurei.app/system/dbus"
|
"hakurei.app/system/dbus"
|
||||||
@ -52,7 +52,7 @@ var testCasesNixos = []sealTestCase{
|
|||||||
Data: "/var/lib/persist/module/hakurei/0/1",
|
Data: "/var/lib/persist/module/hakurei/0/1",
|
||||||
Identity: 1, Groups: []string{},
|
Identity: 1, Groups: []string{},
|
||||||
},
|
},
|
||||||
app.ID{
|
state.ID{
|
||||||
0x8e, 0x2c, 0x76, 0xb0,
|
0x8e, 0x2c, 0x76, 0xb0,
|
||||||
0x66, 0xda, 0xbe, 0x57,
|
0x66, 0xda, 0xbe, 0x57,
|
||||||
0x4c, 0xf0, 0x73, 0xbd,
|
0x4c, 0xf0, 0x73, 0xbd,
|
@ -1,12 +1,12 @@
|
|||||||
package setuid_test
|
package app_test
|
||||||
|
|
||||||
import (
|
import (
|
||||||
"os"
|
"os"
|
||||||
|
|
||||||
"hakurei.app/cmd/hakurei/internal/app"
|
|
||||||
"hakurei.app/container"
|
"hakurei.app/container"
|
||||||
"hakurei.app/container/seccomp"
|
"hakurei.app/container/seccomp"
|
||||||
"hakurei.app/hst"
|
"hakurei.app/hst"
|
||||||
|
"hakurei.app/internal/app/state"
|
||||||
"hakurei.app/system"
|
"hakurei.app/system"
|
||||||
"hakurei.app/system/acl"
|
"hakurei.app/system/acl"
|
||||||
"hakurei.app/system/dbus"
|
"hakurei.app/system/dbus"
|
||||||
@ -16,7 +16,7 @@ var testCasesPd = []sealTestCase{
|
|||||||
{
|
{
|
||||||
"nixos permissive defaults no enablements", new(stubNixOS),
|
"nixos permissive defaults no enablements", new(stubNixOS),
|
||||||
&hst.Config{Username: "chronos", Data: "/home/chronos"},
|
&hst.Config{Username: "chronos", Data: "/home/chronos"},
|
||||||
app.ID{
|
state.ID{
|
||||||
0x4a, 0x45, 0x0b, 0x65,
|
0x4a, 0x45, 0x0b, 0x65,
|
||||||
0x96, 0xd7, 0xbc, 0x15,
|
0x96, 0xd7, 0xbc, 0x15,
|
||||||
0xbd, 0x01, 0x78, 0x0e,
|
0xbd, 0x01, 0x78, 0x0e,
|
||||||
@ -115,7 +115,7 @@ var testCasesPd = []sealTestCase{
|
|||||||
},
|
},
|
||||||
Enablements: system.EWayland | system.EDBus | system.EPulse,
|
Enablements: system.EWayland | system.EDBus | system.EPulse,
|
||||||
},
|
},
|
||||||
app.ID{
|
state.ID{
|
||||||
0xeb, 0xf0, 0x83, 0xd1,
|
0xeb, 0xf0, 0x83, 0xd1,
|
||||||
0xb1, 0x75, 0x91, 0x17,
|
0xb1, 0x75, 0x91, 0x17,
|
||||||
0x82, 0xd4, 0x13, 0x36,
|
0x82, 0xd4, 0x13, 0x36,
|
@ -1,4 +1,4 @@
|
|||||||
package setuid_test
|
package app_test
|
||||||
|
|
||||||
import (
|
import (
|
||||||
"fmt"
|
"fmt"
|
@ -1,4 +1,4 @@
|
|||||||
package common
|
package app
|
||||||
|
|
||||||
import (
|
import (
|
||||||
"errors"
|
"errors"
|
||||||
@ -19,9 +19,9 @@ import (
|
|||||||
// allocating slightly more as a margin for future expansion
|
// allocating slightly more as a margin for future expansion
|
||||||
const preallocateOpsCount = 1 << 5
|
const preallocateOpsCount = 1 << 5
|
||||||
|
|
||||||
// NewContainer initialises [sandbox.Params] via [hst.ContainerConfig].
|
// newContainer initialises [container.Params] via [hst.ContainerConfig].
|
||||||
// Note that remaining container setup must be queued by the caller.
|
// Note that remaining container setup must be queued by the caller.
|
||||||
func NewContainer(s *hst.ContainerConfig, os sys.State, uid, gid *int) (*container.Params, map[string]string, error) {
|
func newContainer(s *hst.ContainerConfig, os sys.State, uid, gid *int) (*container.Params, map[string]string, error) {
|
||||||
if s == nil {
|
if s == nil {
|
||||||
return nil, nil, syscall.EBADE
|
return nil, nil, syscall.EBADE
|
||||||
}
|
}
|
@ -1,10 +1,9 @@
|
|||||||
package setuid
|
package app
|
||||||
|
|
||||||
import (
|
import (
|
||||||
"errors"
|
"errors"
|
||||||
"log"
|
"log"
|
||||||
|
|
||||||
. "hakurei.app/cmd/hakurei/internal/app"
|
|
||||||
"hakurei.app/internal/hlog"
|
"hakurei.app/internal/hlog"
|
||||||
)
|
)
|
||||||
|
|
@ -1,13 +1,13 @@
|
|||||||
package setuid
|
package app
|
||||||
|
|
||||||
import (
|
import (
|
||||||
. "hakurei.app/cmd/hakurei/internal/app"
|
|
||||||
"hakurei.app/container"
|
"hakurei.app/container"
|
||||||
|
"hakurei.app/internal/app/state"
|
||||||
"hakurei.app/internal/sys"
|
"hakurei.app/internal/sys"
|
||||||
"hakurei.app/system"
|
"hakurei.app/system"
|
||||||
)
|
)
|
||||||
|
|
||||||
func NewWithID(id ID, os sys.State) App {
|
func NewWithID(id state.ID, os sys.State) App {
|
||||||
a := new(app)
|
a := new(app)
|
||||||
a.id = newID(&id)
|
a.id = newID(&id)
|
||||||
a.sys = os
|
a.sys = os
|
@ -1,4 +1,4 @@
|
|||||||
package common
|
package app
|
||||||
|
|
||||||
import (
|
import (
|
||||||
"path/filepath"
|
"path/filepath"
|
@ -1,4 +1,4 @@
|
|||||||
package common
|
package app
|
||||||
|
|
||||||
import (
|
import (
|
||||||
"testing"
|
"testing"
|
@ -1,4 +1,4 @@
|
|||||||
package setuid
|
package app
|
||||||
|
|
||||||
import (
|
import (
|
||||||
"context"
|
"context"
|
||||||
@ -12,10 +12,9 @@ import (
|
|||||||
"syscall"
|
"syscall"
|
||||||
"time"
|
"time"
|
||||||
|
|
||||||
. "hakurei.app/cmd/hakurei/internal/app"
|
|
||||||
"hakurei.app/cmd/hakurei/internal/state"
|
|
||||||
"hakurei.app/container"
|
"hakurei.app/container"
|
||||||
"hakurei.app/internal"
|
"hakurei.app/internal"
|
||||||
|
"hakurei.app/internal/app/state"
|
||||||
"hakurei.app/internal/hlog"
|
"hakurei.app/internal/hlog"
|
||||||
"hakurei.app/system"
|
"hakurei.app/system"
|
||||||
)
|
)
|
@ -1,4 +1,4 @@
|
|||||||
package setuid
|
package app
|
||||||
|
|
||||||
import (
|
import (
|
||||||
"bytes"
|
"bytes"
|
||||||
@ -16,11 +16,10 @@ import (
|
|||||||
"sync/atomic"
|
"sync/atomic"
|
||||||
"syscall"
|
"syscall"
|
||||||
|
|
||||||
. "hakurei.app/cmd/hakurei/internal/app"
|
|
||||||
"hakurei.app/cmd/hakurei/internal/app/instance/common"
|
|
||||||
"hakurei.app/container"
|
"hakurei.app/container"
|
||||||
"hakurei.app/hst"
|
"hakurei.app/hst"
|
||||||
"hakurei.app/internal"
|
"hakurei.app/internal"
|
||||||
|
"hakurei.app/internal/app/state"
|
||||||
"hakurei.app/internal/hlog"
|
"hakurei.app/internal/hlog"
|
||||||
"hakurei.app/internal/sys"
|
"hakurei.app/internal/sys"
|
||||||
"hakurei.app/system"
|
"hakurei.app/system"
|
||||||
@ -66,7 +65,7 @@ var posixUsername = regexp.MustCompilePOSIX("^[a-z_]([A-Za-z0-9_-]{0,31}|[A-Za-z
|
|||||||
// outcome stores copies of various parts of [hst.Config]
|
// outcome stores copies of various parts of [hst.Config]
|
||||||
type outcome struct {
|
type outcome struct {
|
||||||
// copied from initialising [app]
|
// copied from initialising [app]
|
||||||
id *stringPair[ID]
|
id *stringPair[state.ID]
|
||||||
// copied from [sys.State] response
|
// copied from [sys.State] response
|
||||||
runDirPath string
|
runDirPath string
|
||||||
|
|
||||||
@ -281,7 +280,7 @@ func (seal *outcome) finalise(ctx context.Context, sys sys.State, config *hst.Co
|
|||||||
{
|
{
|
||||||
var uid, gid int
|
var uid, gid int
|
||||||
var err error
|
var err error
|
||||||
seal.container, seal.env, err = common.NewContainer(config.Container, sys, &uid, &gid)
|
seal.container, seal.env, err = newContainer(config.Container, sys, &uid, &gid)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return hlog.WrapErrSuffix(err,
|
return hlog.WrapErrSuffix(err,
|
||||||
"cannot initialise container configuration:")
|
"cannot initialise container configuration:")
|
@ -1,4 +1,4 @@
|
|||||||
package setuid
|
package app
|
||||||
|
|
||||||
import (
|
import (
|
||||||
"context"
|
"context"
|
@ -1,4 +1,4 @@
|
|||||||
package app
|
package state
|
||||||
|
|
||||||
import (
|
import (
|
||||||
"crypto/rand"
|
"crypto/rand"
|
@ -1,22 +1,22 @@
|
|||||||
package app_test
|
package state_test
|
||||||
|
|
||||||
import (
|
import (
|
||||||
"errors"
|
"errors"
|
||||||
"testing"
|
"testing"
|
||||||
|
|
||||||
. "hakurei.app/cmd/hakurei/internal/app"
|
"hakurei.app/internal/app/state"
|
||||||
)
|
)
|
||||||
|
|
||||||
func TestParseAppID(t *testing.T) {
|
func TestParseAppID(t *testing.T) {
|
||||||
t.Run("bad length", func(t *testing.T) {
|
t.Run("bad length", func(t *testing.T) {
|
||||||
if err := ParseAppID(new(ID), "meow"); !errors.Is(err, ErrInvalidLength) {
|
if err := state.ParseAppID(new(state.ID), "meow"); !errors.Is(err, state.ErrInvalidLength) {
|
||||||
t.Errorf("ParseAppID: error = %v, wantErr = %v", err, ErrInvalidLength)
|
t.Errorf("ParseAppID: error = %v, wantErr = %v", err, state.ErrInvalidLength)
|
||||||
}
|
}
|
||||||
})
|
})
|
||||||
|
|
||||||
t.Run("bad byte", func(t *testing.T) {
|
t.Run("bad byte", func(t *testing.T) {
|
||||||
wantErr := "invalid char '\\n' at byte 15"
|
wantErr := "invalid char '\\n' at byte 15"
|
||||||
if err := ParseAppID(new(ID), "02bc7f8936b2af6\n\ne2535cd71ef0bb7"); err == nil || err.Error() != wantErr {
|
if err := state.ParseAppID(new(state.ID), "02bc7f8936b2af6\n\ne2535cd71ef0bb7"); err == nil || err.Error() != wantErr {
|
||||||
t.Errorf("ParseAppID: error = %v, wantErr = %v", err, wantErr)
|
t.Errorf("ParseAppID: error = %v, wantErr = %v", err, wantErr)
|
||||||
}
|
}
|
||||||
})
|
})
|
||||||
@ -30,30 +30,30 @@ func TestParseAppID(t *testing.T) {
|
|||||||
|
|
||||||
func FuzzParseAppID(f *testing.F) {
|
func FuzzParseAppID(f *testing.F) {
|
||||||
for i := 0; i < 16; i++ {
|
for i := 0; i < 16; i++ {
|
||||||
id := new(ID)
|
id := new(state.ID)
|
||||||
if err := NewAppID(id); err != nil {
|
if err := state.NewAppID(id); err != nil {
|
||||||
panic(err.Error())
|
panic(err.Error())
|
||||||
}
|
}
|
||||||
f.Add(id[0], id[1], id[2], id[3], id[4], id[5], id[6], id[7], id[8], id[9], id[10], id[11], id[12], id[13], id[14], id[15])
|
f.Add(id[0], id[1], id[2], id[3], id[4], id[5], id[6], id[7], id[8], id[9], id[10], id[11], id[12], id[13], id[14], id[15])
|
||||||
}
|
}
|
||||||
|
|
||||||
f.Fuzz(func(t *testing.T, b0, b1, b2, b3, b4, b5, b6, b7, b8, b9, b10, b11, b12, b13, b14, b15 byte) {
|
f.Fuzz(func(t *testing.T, b0, b1, b2, b3, b4, b5, b6, b7, b8, b9, b10, b11, b12, b13, b14, b15 byte) {
|
||||||
testParseAppID(t, &ID{b0, b1, b2, b3, b4, b5, b6, b7, b8, b9, b10, b11, b12, b13, b14, b15})
|
testParseAppID(t, &state.ID{b0, b1, b2, b3, b4, b5, b6, b7, b8, b9, b10, b11, b12, b13, b14, b15})
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
|
||||||
func testParseAppIDWithRandom(t *testing.T) {
|
func testParseAppIDWithRandom(t *testing.T) {
|
||||||
id := new(ID)
|
id := new(state.ID)
|
||||||
if err := NewAppID(id); err != nil {
|
if err := state.NewAppID(id); err != nil {
|
||||||
t.Fatalf("cannot generate app ID: %v", err)
|
t.Fatalf("cannot generate app ID: %v", err)
|
||||||
}
|
}
|
||||||
testParseAppID(t, id)
|
testParseAppID(t, id)
|
||||||
}
|
}
|
||||||
|
|
||||||
func testParseAppID(t *testing.T, id *ID) {
|
func testParseAppID(t *testing.T, id *state.ID) {
|
||||||
s := id.String()
|
s := id.String()
|
||||||
got := new(ID)
|
got := new(state.ID)
|
||||||
if err := ParseAppID(got, s); err != nil {
|
if err := state.ParseAppID(got, s); err != nil {
|
||||||
t.Fatalf("cannot parse app ID: %v", err)
|
t.Fatalf("cannot parse app ID: %v", err)
|
||||||
}
|
}
|
||||||
|
|
@ -13,7 +13,6 @@ import (
|
|||||||
"sync"
|
"sync"
|
||||||
"syscall"
|
"syscall"
|
||||||
|
|
||||||
"hakurei.app/cmd/hakurei/internal/app"
|
|
||||||
"hakurei.app/hst"
|
"hakurei.app/hst"
|
||||||
"hakurei.app/internal/hlog"
|
"hakurei.app/internal/hlog"
|
||||||
)
|
)
|
||||||
@ -130,7 +129,7 @@ type multiBackend struct {
|
|||||||
lock sync.RWMutex
|
lock sync.RWMutex
|
||||||
}
|
}
|
||||||
|
|
||||||
func (b *multiBackend) filename(id *app.ID) string {
|
func (b *multiBackend) filename(id *ID) string {
|
||||||
return path.Join(b.path, id.String())
|
return path.Join(b.path, id.String())
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -190,8 +189,8 @@ func (b *multiBackend) load(decode bool) (Entries, error) {
|
|||||||
return nil, fmt.Errorf("unexpected directory %q in store", e.Name())
|
return nil, fmt.Errorf("unexpected directory %q in store", e.Name())
|
||||||
}
|
}
|
||||||
|
|
||||||
id := new(app.ID)
|
id := new(ID)
|
||||||
if err := app.ParseAppID(id, e.Name()); err != nil {
|
if err := ParseAppID(id, e.Name()); err != nil {
|
||||||
return nil, err
|
return nil, err
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -336,7 +335,7 @@ func (b *multiBackend) encodeState(w io.WriteSeeker, state *State, configWriter
|
|||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
|
|
||||||
func (b *multiBackend) Destroy(id app.ID) error {
|
func (b *multiBackend) Destroy(id ID) error {
|
||||||
b.lock.Lock()
|
b.lock.Lock()
|
||||||
defer b.lock.Unlock()
|
defer b.lock.Unlock()
|
||||||
|
|
@ -3,7 +3,7 @@ package state_test
|
|||||||
import (
|
import (
|
||||||
"testing"
|
"testing"
|
||||||
|
|
||||||
"hakurei.app/cmd/hakurei/internal/state"
|
"hakurei.app/internal/app/state"
|
||||||
)
|
)
|
||||||
|
|
||||||
func TestMulti(t *testing.T) { testStore(t, state.NewMulti(t.TempDir())) }
|
func TestMulti(t *testing.T) { testStore(t, state.NewMulti(t.TempDir())) }
|
@ -1,3 +1,4 @@
|
|||||||
|
// Package state provides cross-process state tracking for hakurei container instances.
|
||||||
package state
|
package state
|
||||||
|
|
||||||
import (
|
import (
|
||||||
@ -5,13 +6,12 @@ import (
|
|||||||
"io"
|
"io"
|
||||||
"time"
|
"time"
|
||||||
|
|
||||||
"hakurei.app/cmd/hakurei/internal/app"
|
|
||||||
"hakurei.app/hst"
|
"hakurei.app/hst"
|
||||||
)
|
)
|
||||||
|
|
||||||
var ErrNoConfig = errors.New("state does not contain config")
|
var ErrNoConfig = errors.New("state does not contain config")
|
||||||
|
|
||||||
type Entries map[app.ID]*State
|
type Entries map[ID]*State
|
||||||
|
|
||||||
type Store interface {
|
type Store interface {
|
||||||
// Do calls f exactly once and ensures store exclusivity until f returns.
|
// Do calls f exactly once and ensures store exclusivity until f returns.
|
||||||
@ -30,7 +30,7 @@ type Store interface {
|
|||||||
// Cursor provides access to the store
|
// Cursor provides access to the store
|
||||||
type Cursor interface {
|
type Cursor interface {
|
||||||
Save(state *State, configWriter io.WriterTo) error
|
Save(state *State, configWriter io.WriterTo) error
|
||||||
Destroy(id app.ID) error
|
Destroy(id ID) error
|
||||||
Load() (Entries, error)
|
Load() (Entries, error)
|
||||||
Len() (int, error)
|
Len() (int, error)
|
||||||
}
|
}
|
||||||
@ -38,7 +38,7 @@ type Cursor interface {
|
|||||||
// State is an instance state
|
// State is an instance state
|
||||||
type State struct {
|
type State struct {
|
||||||
// hakurei instance id
|
// hakurei instance id
|
||||||
ID app.ID `json:"instance"`
|
ID ID `json:"instance"`
|
||||||
// child process PID value
|
// child process PID value
|
||||||
PID int `json:"pid"`
|
PID int `json:"pid"`
|
||||||
// sealed app configuration
|
// sealed app configuration
|
@ -10,9 +10,8 @@ import (
|
|||||||
"testing"
|
"testing"
|
||||||
"time"
|
"time"
|
||||||
|
|
||||||
"hakurei.app/cmd/hakurei/internal/app"
|
|
||||||
"hakurei.app/cmd/hakurei/internal/state"
|
|
||||||
"hakurei.app/hst"
|
"hakurei.app/hst"
|
||||||
|
"hakurei.app/internal/app/state"
|
||||||
)
|
)
|
||||||
|
|
||||||
func testStore(t *testing.T, s state.Store) {
|
func testStore(t *testing.T, s state.Store) {
|
||||||
@ -134,7 +133,7 @@ func testStore(t *testing.T, s state.Store) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
func makeState(t *testing.T, s *state.State, ct io.Writer) {
|
func makeState(t *testing.T, s *state.State, ct io.Writer) {
|
||||||
if err := app.NewAppID(&s.ID); err != nil {
|
if err := state.NewAppID(&s.ID); err != nil {
|
||||||
t.Fatalf("cannot create dummy state: %v", err)
|
t.Fatalf("cannot create dummy state: %v", err)
|
||||||
}
|
}
|
||||||
if err := gob.NewEncoder(ct).Encode(hst.Template()); err != nil {
|
if err := gob.NewEncoder(ct).Encode(hst.Template()); err != nil {
|
@ -1,13 +1,13 @@
|
|||||||
package setuid
|
package app
|
||||||
|
|
||||||
import (
|
import (
|
||||||
"strconv"
|
"strconv"
|
||||||
|
|
||||||
. "hakurei.app/cmd/hakurei/internal/app"
|
"hakurei.app/internal/app/state"
|
||||||
)
|
)
|
||||||
|
|
||||||
func newInt(v int) *stringPair[int] { return &stringPair[int]{v, strconv.Itoa(v)} }
|
func newInt(v int) *stringPair[int] { return &stringPair[int]{v, strconv.Itoa(v)} }
|
||||||
func newID(id *ID) *stringPair[ID] { return &stringPair[ID]{*id, id.String()} }
|
func newID(id *state.ID) *stringPair[state.ID] { return &stringPair[state.ID]{*id, id.String()} }
|
||||||
|
|
||||||
// stringPair stores a value and its string representation.
|
// stringPair stores a value and its string representation.
|
||||||
type stringPair[T comparable] struct {
|
type stringPair[T comparable] struct {
|
Loading…
x
Reference in New Issue
Block a user