state: store config in separate gob stream
All checks were successful
Build / Create distribution (push) Successful in 1m37s
Test / Run NixOS test (push) Successful in 3m38s

This enables early serialisation of config.

Signed-off-by: Ophestra <cat@gensokyo.uk>
This commit is contained in:
2025-01-21 12:10:58 +09:00
parent fa0616b274
commit dfcdc5ce20
7 changed files with 135 additions and 55 deletions

View File

@@ -3,7 +3,6 @@ package app
import (
"context"
"sync"
"sync/atomic"
"git.gensokyo.uk/security/fortify/fst"
"git.gensokyo.uk/security/fortify/internal/linux"
@@ -30,9 +29,6 @@ type RunState struct {
}
type app struct {
// single-use config reference
ct *appCt
// application unique identifier
id *fst.ID
// operating system interface
@@ -74,24 +70,3 @@ func New(os linux.System) (App, error) {
a.os = os
return a, fst.NewAppID(a.id)
}
// appCt ensures its wrapped val is only accessed once
type appCt struct {
val *fst.Config
done *atomic.Bool
}
func (a *appCt) Unwrap() *fst.Config {
if !a.done.Load() {
defer a.done.Store(true)
return a.val
}
panic("attempted to access config reference twice")
}
func newAppCt(config *fst.Config) (ct *appCt) {
ct = new(appCt)
ct.done = new(atomic.Bool)
ct.val = config
return ct
}

View File

@@ -1,8 +1,11 @@
package app
import (
"bytes"
"encoding/gob"
"errors"
"fmt"
"io"
"io/fs"
"path"
"regexp"
@@ -47,6 +50,8 @@ type appSeal struct {
// pass-through enablement tracking from config
et system.Enablements
// initial config gob encoding buffer
ct io.WriterTo
// pass-through seccomp config from config
scmp *fst.SyscallConfig
// wayland socket direct access
@@ -87,6 +92,14 @@ func (a *app) Seal(config *fst.Config) error {
// create seal
seal := new(appSeal)
// encode initial configuration for state tracking
ct := new(bytes.Buffer)
if err := gob.NewEncoder(ct).Encode(config); err != nil {
return fmsg.WrapErrorSuffix(err,
"cannot encode initial config:")
}
seal.ct = ct
// fetch system constants
seal.Paths = a.os.Paths()
@@ -261,6 +274,5 @@ func (a *app) Seal(config *fst.Config) error {
// seal app and release lock
a.seal = seal
a.ct = newAppCt(config)
return nil
}

View File

@@ -89,16 +89,15 @@ func (a *app) Run(ctx context.Context, rs *RunState) error {
// shim accepted setup payload, create process state
sd := state.State{
ID: *a.id,
PID: a.shim.Unwrap().Process.Pid,
Config: a.ct.Unwrap(),
Time: *startTime,
ID: *a.id,
PID: a.shim.Unwrap().Process.Pid,
Time: *startTime,
}
// register process state
var err0 = new(StateStoreError)
err0.Inner, err0.DoErr = a.seal.store.Do(a.seal.sys.user.aid, func(c state.Cursor) {
err0.InnerErr = c.Save(&sd)
err0.InnerErr = c.Save(&sd, a.seal.ct)
})
a.seal.sys.saveState = true
if err = err0.equiv("cannot save process state:"); err != nil {