diff --git a/cmd/hakurei/command.go b/cmd/hakurei/command.go index 0c3e5e7..d284e07 100644 --- a/cmd/hakurei/command.go +++ b/cmd/hakurei/command.go @@ -45,7 +45,7 @@ func buildCommand(ctx context.Context, msg container.Msg, early *earlyHardeningE 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 and start container from configuration file", func(args []string) error { if len(args) < 1 { log.Fatal("app requires at least 1 argument") } @@ -74,14 +74,14 @@ func buildCommand(ctx context.Context, msg container.Msg, early *earlyHardeningE flagWayland, flagX11, flagDBus, flagPulse bool ) - c.NewCommand("run", "Configure and start a permissive default sandbox", func(args []string) error { + c.NewCommand("run", "Configure and start a permissive container", func(args []string) error { // initialise config from flags config := &hst.Config{ ID: flagID, Args: args, } - if flagIdentity < 0 || flagIdentity > 9999 { + if flagIdentity < hst.IdentityMin || flagIdentity > hst.IdentityMax { log.Fatalf("identity %d out of range", flagIdentity) } diff --git a/cmd/hakurei/command_test.go b/cmd/hakurei/command_test.go index dd16b25..d22249f 100644 --- a/cmd/hakurei/command_test.go +++ b/cmd/hakurei/command_test.go @@ -21,8 +21,8 @@ func TestHelp(t *testing.T) { Usage: hakurei [-h | --help] [-v] [--json] COMMAND [OPTIONS] Commands: - app Load app from configuration file - run Configure and start a permissive default sandbox + app Load and start container from configuration file + run Configure and start a permissive container show Show live or local app configuration ps List active instances version Display version information diff --git a/cmd/hsu/main.go b/cmd/hsu/main.go index cb82c20..1f6ca7b 100644 --- a/cmd/hsu/main.go +++ b/cmd/hsu/main.go @@ -1,5 +1,7 @@ package main +// minimise imports to avoid inadvertently calling init or global variable functions + import ( "bytes" "fmt" @@ -19,6 +21,9 @@ const ( envGroups = "HAKUREI_GROUPS" PR_SET_NO_NEW_PRIVS = 0x26 + + identityMin = 0 + identityMax = 9999 ) func main() { @@ -91,7 +96,7 @@ func main() { // allowed identity range 0 to 9999 if as, ok := os.LookupEnv(envIdentity); !ok { log.Fatal("HAKUREI_IDENTITY not set") - } else if identity, err := parseUint32Fast(as); err != nil || identity < 0 || identity > 9999 { + } else if identity, err := parseUint32Fast(as); err != nil || identity < identityMin || identity > identityMax { log.Fatal("invalid identity") } else { uid += identity diff --git a/dist/comp/_hakurei b/dist/comp/_hakurei index a855426..7f3974b 100644 --- a/dist/comp/_hakurei +++ b/dist/comp/_hakurei @@ -54,8 +54,8 @@ __hakurei_instances() { { local -a _hakurei_cmds _hakurei_cmds=( - "app:Load app from configuration file" - "run:Configure and start a permissive default sandbox" + "app:Load and start container from configuration file" + "run:Configure and start a permissive container" "show:Show live or local app configuration" "ps:List active instances" "version:Display version information" diff --git a/hst/config.go b/hst/config.go index 4fd3fa9..7f6b079 100644 --- a/hst/config.go +++ b/hst/config.go @@ -12,10 +12,20 @@ const Tmp = "/.hakurei" var AbsTmp = container.MustAbs(Tmp) const ( - // DefaultWaitDelay is used when WaitDelay has its zero value. - DefaultWaitDelay = 5 * time.Second - // MaxWaitDelay is used if WaitDelay exceeds its value. - MaxWaitDelay = 30 * time.Second + // WaitDelayDefault is used when WaitDelay has its zero value. + WaitDelayDefault = 5 * time.Second + // WaitDelayMax is used if WaitDelay exceeds its value. + WaitDelayMax = 30 * time.Second + + // IdentityMin is the minimum value of [Config.Identity]. This is enforced by cmd/hsu. + IdentityMin = 0 + // IdentityMax is the maximum value of [Config.Identity]. This is enforced by cmd/hsu. + IdentityMax = 9999 + + // ShimExitRequest is returned when the priv side process requests shim exit. + ShimExitRequest = 254 + // ShimExitOrphan is returned when the shim is orphaned before priv side delivers a signal. + ShimExitOrphan = 3 ) type ( @@ -69,8 +79,8 @@ type ( Hostname string `json:"hostname,omitempty"` // Duration in nanoseconds to wait for after interrupting the initial process. - // Defaults to [DefaultWaitDelay] if less than or equals to zero, - // or [MaxWaitDelay] if greater than [MaxWaitDelay]. + // Defaults to [WaitDelayDefault] if less than or equals to zero, + // or [WaitDelayMax] if greater than [WaitDelayMax]. WaitDelay time.Duration `json:"wait_delay,omitempty"` // Emit Flatpak-compatible seccomp filter programs. diff --git a/internal/app/finalise.go b/internal/app/finalise.go index ec2d0a9..3d6ec38 100644 --- a/internal/app/finalise.go +++ b/internal/app/finalise.go @@ -83,8 +83,8 @@ func (k *outcome) finalise(ctx context.Context, msg container.Msg, id *state.ID, k.ct = ct } - // allowed identity range 0 to 9999, this is checked again in hsu - if config.Identity < 0 || config.Identity > 9999 { + // this is checked again in hsu + if config.Identity < hst.IdentityMin || config.Identity > hst.IdentityMax { return newWithMessage(fmt.Sprintf("identity %d out of range", config.Identity)) } @@ -187,9 +187,9 @@ func (k *outcome) finalise(ctx context.Context, msg container.Msg, id *state.ID, // enforce bounds and default early if s.Container.WaitDelay <= 0 { - kp.waitDelay = hst.DefaultWaitDelay - } else if s.Container.WaitDelay > hst.MaxWaitDelay { - kp.waitDelay = hst.MaxWaitDelay + kp.waitDelay = hst.WaitDelayDefault + } else if s.Container.WaitDelay > hst.WaitDelayMax { + kp.waitDelay = hst.WaitDelayMax } else { kp.waitDelay = s.Container.WaitDelay } diff --git a/internal/app/shim.go b/internal/app/shim.go index de53b97..4927f5c 100644 --- a/internal/app/shim.go +++ b/internal/app/shim.go @@ -15,6 +15,7 @@ import ( "hakurei.app/container" "hakurei.app/container/seccomp" + "hakurei.app/hst" ) //#include "shim-signal.h" @@ -23,27 +24,21 @@ import "C" const shimEnv = "HAKUREI_SHIM" type shimParams struct { - // monitor pid, checked against ppid in signal handler + // Priv side pid, checked against ppid in signal handler for the syscall.SIGCONT hack. Monitor int - // duration to wait for after interrupting a container's initial process before the container is killed; - // zero value defaults to [DefaultShimWaitDelay], values exceeding [MaxShimWaitDelay] becomes [MaxShimWaitDelay] + // Duration to wait for after interrupting a container's initial process before the container is killed. + // Limits are enforced on the priv side. WaitDelay time.Duration - // finalised container params + // Finalised container params. + // TODO(ophestra): transmit outcomeState instead (params to shim) Container *container.Params - // verbosity pass through + // Verbosity pass through. Verbose bool } -const ( - // ShimExitRequest is returned when the monitor process requests shim exit. - ShimExitRequest = 254 - // ShimExitOrphan is returned when the shim is orphaned before monitor delivers a signal. - ShimExitOrphan = 3 -) - // ShimMain is the main function of the shim process and runs as the unconstrained target user. func ShimMain() { log.SetPrefix("shim: ") @@ -107,12 +102,12 @@ func ShimMain() { // setup has not completed, terminate immediately msg.Resume() - os.Exit(ShimExitRequest) + os.Exit(hst.ShimExitRequest) return case 1: // got SIGCONT after adoption: monitor died before delivering signal msg.BeforeExit() - os.Exit(ShimExitOrphan) + os.Exit(hst.ShimExitOrphan) return case 2: // unreachable