hst: optionally reject insecure options
All checks were successful
Test / Create distribution (push) Successful in 1m31s
Test / Sandbox (push) Successful in 3m35s
Test / Hakurei (push) Successful in 4m43s
Test / ShareFS (push) Successful in 4m49s
Test / Sandbox (race detector) (push) Successful in 5m59s
Test / Hakurei (race detector) (push) Successful in 7m13s
Test / Flake checks (push) Successful in 1m30s
All checks were successful
Test / Create distribution (push) Successful in 1m31s
Test / Sandbox (push) Successful in 3m35s
Test / Hakurei (push) Successful in 4m43s
Test / ShareFS (push) Successful in 4m49s
Test / Sandbox (race detector) (push) Successful in 5m59s
Test / Hakurei (race detector) (push) Successful in 7m13s
Test / Flake checks (push) Successful in 1m30s
This prevents inadvertent use of insecure compatibility features. Closes #30. Signed-off-by: Ophestra <cat@gensokyo.uk>
This commit is contained in:
@@ -38,8 +38,9 @@ var errSuccess = errors.New("success")
|
|||||||
|
|
||||||
func buildCommand(ctx context.Context, msg message.Msg, early *earlyHardeningErrs, out io.Writer) command.Command {
|
func buildCommand(ctx context.Context, msg message.Msg, early *earlyHardeningErrs, out io.Writer) command.Command {
|
||||||
var (
|
var (
|
||||||
flagVerbose bool
|
flagVerbose bool
|
||||||
flagJSON bool
|
flagInsecure bool
|
||||||
|
flagJSON bool
|
||||||
)
|
)
|
||||||
c := command.New(out, log.Printf, "hakurei", func([]string) error {
|
c := command.New(out, log.Printf, "hakurei", func([]string) error {
|
||||||
msg.SwapVerbose(flagVerbose)
|
msg.SwapVerbose(flagVerbose)
|
||||||
@@ -57,6 +58,7 @@ func buildCommand(ctx context.Context, msg message.Msg, early *earlyHardeningErr
|
|||||||
return nil
|
return nil
|
||||||
}).
|
}).
|
||||||
Flag(&flagVerbose, "v", command.BoolFlag(false), "Increase log verbosity").
|
Flag(&flagVerbose, "v", command.BoolFlag(false), "Increase log verbosity").
|
||||||
|
Flag(&flagInsecure, "insecure", command.BoolFlag(false), "Allow use of insecure compatibility options").
|
||||||
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 { outcome.Shim(msg); return errSuccess })
|
c.Command("shim", command.UsageInternal, func([]string) error { outcome.Shim(msg); return errSuccess })
|
||||||
@@ -75,7 +77,12 @@ func buildCommand(ctx context.Context, msg message.Msg, early *earlyHardeningErr
|
|||||||
config.Container.Args = append(config.Container.Args, args[1:]...)
|
config.Container.Args = append(config.Container.Args, args[1:]...)
|
||||||
}
|
}
|
||||||
|
|
||||||
outcome.Main(ctx, msg, config, flagIdentifierFile)
|
var flags int
|
||||||
|
if flagInsecure {
|
||||||
|
flags |= hst.VAllowInsecure
|
||||||
|
}
|
||||||
|
|
||||||
|
outcome.Main(ctx, msg, config, flags, flagIdentifierFile)
|
||||||
panic("unreachable")
|
panic("unreachable")
|
||||||
}).
|
}).
|
||||||
Flag(&flagIdentifierFile, "identifier-fd", command.IntFlag(-1),
|
Flag(&flagIdentifierFile, "identifier-fd", command.IntFlag(-1),
|
||||||
@@ -282,7 +289,7 @@ func buildCommand(ctx context.Context, msg message.Msg, early *earlyHardeningErr
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
outcome.Main(ctx, msg, &config, -1)
|
outcome.Main(ctx, msg, &config, 0, -1)
|
||||||
panic("unreachable")
|
panic("unreachable")
|
||||||
}).
|
}).
|
||||||
Flag(&flagDBusConfigSession, "dbus-config", command.StringFlag("builtin"),
|
Flag(&flagDBusConfigSession, "dbus-config", command.StringFlag("builtin"),
|
||||||
|
|||||||
@@ -20,7 +20,7 @@ func TestHelp(t *testing.T) {
|
|||||||
}{
|
}{
|
||||||
{
|
{
|
||||||
"main", []string{}, `
|
"main", []string{}, `
|
||||||
Usage: hakurei [-h | --help] [-v] [--json] COMMAND [OPTIONS]
|
Usage: hakurei [-h | --help] [-v] [--insecure] [--json] COMMAND [OPTIONS]
|
||||||
|
|
||||||
Commands:
|
Commands:
|
||||||
run Load and start container from configuration file
|
run Load and start container from configuration file
|
||||||
|
|||||||
@@ -56,7 +56,7 @@ func printShowInstance(
|
|||||||
t := newPrinter(output)
|
t := newPrinter(output)
|
||||||
defer t.MustFlush()
|
defer t.MustFlush()
|
||||||
|
|
||||||
if err := config.Validate(); err != nil {
|
if err := config.Validate(hst.VAllowInsecure); err != nil {
|
||||||
valid = false
|
valid = false
|
||||||
if m, ok := message.GetMessage(err); ok {
|
if m, ok := message.GetMessage(err); ok {
|
||||||
mustPrint(output, "Error: "+m+"!\n\n")
|
mustPrint(output, "Error: "+m+"!\n\n")
|
||||||
|
|||||||
@@ -140,21 +140,29 @@ var (
|
|||||||
ErrInsecure = errors.New("configuration is insecure")
|
ErrInsecure = errors.New("configuration is insecure")
|
||||||
)
|
)
|
||||||
|
|
||||||
|
const (
|
||||||
|
// VAllowInsecure allows use of compatibility options considered insecure
|
||||||
|
// under any configuration, to work around ecosystem-wide flaws.
|
||||||
|
VAllowInsecure = 1 << iota
|
||||||
|
)
|
||||||
|
|
||||||
// Validate checks [Config] and returns [AppError] if an invalid value is encountered.
|
// Validate checks [Config] and returns [AppError] if an invalid value is encountered.
|
||||||
func (config *Config) Validate() error {
|
func (config *Config) Validate(flags int) error {
|
||||||
|
const step = "validate configuration"
|
||||||
|
|
||||||
if config == nil {
|
if config == nil {
|
||||||
return &AppError{Step: "validate configuration", Err: ErrConfigNull,
|
return &AppError{Step: step, Err: ErrConfigNull,
|
||||||
Msg: "invalid configuration"}
|
Msg: "invalid configuration"}
|
||||||
}
|
}
|
||||||
|
|
||||||
// this is checked again in hsu
|
// this is checked again in hsu
|
||||||
if config.Identity < IdentityStart || config.Identity > IdentityEnd {
|
if config.Identity < IdentityStart || config.Identity > IdentityEnd {
|
||||||
return &AppError{Step: "validate configuration", Err: ErrIdentityBounds,
|
return &AppError{Step: step, Err: ErrIdentityBounds,
|
||||||
Msg: "identity " + strconv.Itoa(config.Identity) + " out of range"}
|
Msg: "identity " + strconv.Itoa(config.Identity) + " out of range"}
|
||||||
}
|
}
|
||||||
|
|
||||||
if config.SchedPolicy < 0 || config.SchedPolicy > ext.SCHED_LAST {
|
if config.SchedPolicy < 0 || config.SchedPolicy > ext.SCHED_LAST {
|
||||||
return &AppError{Step: "validate configuration", Err: ErrSchedPolicyBounds,
|
return &AppError{Step: step, Err: ErrSchedPolicyBounds,
|
||||||
Msg: "scheduling policy " +
|
Msg: "scheduling policy " +
|
||||||
strconv.Itoa(int(config.SchedPolicy)) +
|
strconv.Itoa(int(config.SchedPolicy)) +
|
||||||
" out of range"}
|
" out of range"}
|
||||||
@@ -168,34 +176,51 @@ func (config *Config) Validate() error {
|
|||||||
}
|
}
|
||||||
|
|
||||||
if config.Container == nil {
|
if config.Container == nil {
|
||||||
return &AppError{Step: "validate configuration", Err: ErrConfigNull,
|
return &AppError{Step: step, Err: ErrConfigNull,
|
||||||
Msg: "configuration missing container state"}
|
Msg: "configuration missing container state"}
|
||||||
}
|
}
|
||||||
if config.Container.Home == nil {
|
if config.Container.Home == nil {
|
||||||
return &AppError{Step: "validate configuration", Err: ErrConfigNull,
|
return &AppError{Step: step, Err: ErrConfigNull,
|
||||||
Msg: "container configuration missing path to home directory"}
|
Msg: "container configuration missing path to home directory"}
|
||||||
}
|
}
|
||||||
if config.Container.Shell == nil {
|
if config.Container.Shell == nil {
|
||||||
return &AppError{Step: "validate configuration", Err: ErrConfigNull,
|
return &AppError{Step: step, Err: ErrConfigNull,
|
||||||
Msg: "container configuration missing path to shell"}
|
Msg: "container configuration missing path to shell"}
|
||||||
}
|
}
|
||||||
if config.Container.Path == nil {
|
if config.Container.Path == nil {
|
||||||
return &AppError{Step: "validate configuration", Err: ErrConfigNull,
|
return &AppError{Step: step, Err: ErrConfigNull,
|
||||||
Msg: "container configuration missing path to initial program"}
|
Msg: "container configuration missing path to initial program"}
|
||||||
}
|
}
|
||||||
|
|
||||||
for key := range config.Container.Env {
|
for key := range config.Container.Env {
|
||||||
if strings.IndexByte(key, '=') != -1 || strings.IndexByte(key, 0) != -1 {
|
if strings.IndexByte(key, '=') != -1 || strings.IndexByte(key, 0) != -1 {
|
||||||
return &AppError{Step: "validate configuration", Err: ErrEnviron,
|
return &AppError{Step: step, Err: ErrEnviron,
|
||||||
Msg: "invalid environment variable " + strconv.Quote(key)}
|
Msg: "invalid environment variable " + strconv.Quote(key)}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
if et := config.Enablements.Unwrap(); !config.DirectPulse && et&EPulse != 0 {
|
et := config.Enablements.Unwrap()
|
||||||
return &AppError{Step: "validate configuration", Err: ErrInsecure,
|
if !config.DirectPulse && et&EPulse != 0 {
|
||||||
|
return &AppError{Step: step, Err: ErrInsecure,
|
||||||
Msg: "enablement PulseAudio is insecure and no longer supported"}
|
Msg: "enablement PulseAudio is insecure and no longer supported"}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if flags&VAllowInsecure == 0 {
|
||||||
|
switch {
|
||||||
|
case et&EWayland != 0 && config.DirectWayland:
|
||||||
|
return &AppError{Step: step, Err: ErrInsecure,
|
||||||
|
Msg: "direct_wayland is insecure and no longer supported"}
|
||||||
|
|
||||||
|
case et&EPipeWire != 0 && config.DirectPipeWire:
|
||||||
|
return &AppError{Step: step, Err: ErrInsecure,
|
||||||
|
Msg: "direct_pipewire is insecure and no longer supported"}
|
||||||
|
|
||||||
|
case et&EPulse != 0 && config.DirectPulse:
|
||||||
|
return &AppError{Step: step, Err: ErrInsecure,
|
||||||
|
Msg: "direct_pulse is insecure and no longer supported"}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -14,65 +14,109 @@ func TestConfigValidate(t *testing.T) {
|
|||||||
testCases := []struct {
|
testCases := []struct {
|
||||||
name string
|
name string
|
||||||
config *hst.Config
|
config *hst.Config
|
||||||
|
flags int
|
||||||
wantErr error
|
wantErr error
|
||||||
}{
|
}{
|
||||||
{"nil", nil, &hst.AppError{Step: "validate configuration", Err: hst.ErrConfigNull,
|
{"nil", nil, 0, &hst.AppError{Step: "validate configuration", Err: hst.ErrConfigNull,
|
||||||
Msg: "invalid configuration"}},
|
Msg: "invalid configuration"}},
|
||||||
{"identity lower", &hst.Config{Identity: -1}, &hst.AppError{Step: "validate configuration", Err: hst.ErrIdentityBounds,
|
|
||||||
|
{"identity lower", &hst.Config{Identity: -1}, 0, &hst.AppError{Step: "validate configuration", Err: hst.ErrIdentityBounds,
|
||||||
Msg: "identity -1 out of range"}},
|
Msg: "identity -1 out of range"}},
|
||||||
{"identity upper", &hst.Config{Identity: 10000}, &hst.AppError{Step: "validate configuration", Err: hst.ErrIdentityBounds,
|
{"identity upper", &hst.Config{Identity: 10000}, 0, &hst.AppError{Step: "validate configuration", Err: hst.ErrIdentityBounds,
|
||||||
Msg: "identity 10000 out of range"}},
|
Msg: "identity 10000 out of range"}},
|
||||||
{"sched lower", &hst.Config{SchedPolicy: -1}, &hst.AppError{Step: "validate configuration", Err: hst.ErrSchedPolicyBounds,
|
|
||||||
|
{"sched lower", &hst.Config{SchedPolicy: -1}, 0, &hst.AppError{Step: "validate configuration", Err: hst.ErrSchedPolicyBounds,
|
||||||
Msg: "scheduling policy -1 out of range"}},
|
Msg: "scheduling policy -1 out of range"}},
|
||||||
{"sched upper", &hst.Config{SchedPolicy: 0xcafe}, &hst.AppError{Step: "validate configuration", Err: hst.ErrSchedPolicyBounds,
|
{"sched upper", &hst.Config{SchedPolicy: 0xcafe}, 0, &hst.AppError{Step: "validate configuration", Err: hst.ErrSchedPolicyBounds,
|
||||||
Msg: "scheduling policy 51966 out of range"}},
|
Msg: "scheduling policy 51966 out of range"}},
|
||||||
{"dbus session", &hst.Config{SessionBus: &hst.BusConfig{See: []string{""}}},
|
|
||||||
|
{"dbus session", &hst.Config{SessionBus: &hst.BusConfig{See: []string{""}}}, 0,
|
||||||
&hst.BadInterfaceError{Interface: "", Segment: "session"}},
|
&hst.BadInterfaceError{Interface: "", Segment: "session"}},
|
||||||
{"dbus system", &hst.Config{SystemBus: &hst.BusConfig{See: []string{""}}},
|
{"dbus system", &hst.Config{SystemBus: &hst.BusConfig{See: []string{""}}}, 0,
|
||||||
&hst.BadInterfaceError{Interface: "", Segment: "system"}},
|
&hst.BadInterfaceError{Interface: "", Segment: "system"}},
|
||||||
{"container", &hst.Config{}, &hst.AppError{Step: "validate configuration", Err: hst.ErrConfigNull,
|
|
||||||
|
{"container", &hst.Config{}, 0, &hst.AppError{Step: "validate configuration", Err: hst.ErrConfigNull,
|
||||||
Msg: "configuration missing container state"}},
|
Msg: "configuration missing container state"}},
|
||||||
{"home", &hst.Config{Container: &hst.ContainerConfig{}}, &hst.AppError{Step: "validate configuration", Err: hst.ErrConfigNull,
|
{"home", &hst.Config{Container: &hst.ContainerConfig{}}, 0, &hst.AppError{Step: "validate configuration", Err: hst.ErrConfigNull,
|
||||||
Msg: "container configuration missing path to home directory"}},
|
Msg: "container configuration missing path to home directory"}},
|
||||||
{"shell", &hst.Config{Container: &hst.ContainerConfig{
|
{"shell", &hst.Config{Container: &hst.ContainerConfig{
|
||||||
Home: fhs.AbsTmp,
|
Home: fhs.AbsTmp,
|
||||||
}}, &hst.AppError{Step: "validate configuration", Err: hst.ErrConfigNull,
|
}}, 0, &hst.AppError{Step: "validate configuration", Err: hst.ErrConfigNull,
|
||||||
Msg: "container configuration missing path to shell"}},
|
Msg: "container configuration missing path to shell"}},
|
||||||
{"path", &hst.Config{Container: &hst.ContainerConfig{
|
{"path", &hst.Config{Container: &hst.ContainerConfig{
|
||||||
Home: fhs.AbsTmp,
|
Home: fhs.AbsTmp,
|
||||||
Shell: fhs.AbsTmp,
|
Shell: fhs.AbsTmp,
|
||||||
}}, &hst.AppError{Step: "validate configuration", Err: hst.ErrConfigNull,
|
}}, 0, &hst.AppError{Step: "validate configuration", Err: hst.ErrConfigNull,
|
||||||
Msg: "container configuration missing path to initial program"}},
|
Msg: "container configuration missing path to initial program"}},
|
||||||
|
|
||||||
{"env equals", &hst.Config{Container: &hst.ContainerConfig{
|
{"env equals", &hst.Config{Container: &hst.ContainerConfig{
|
||||||
Home: fhs.AbsTmp,
|
Home: fhs.AbsTmp,
|
||||||
Shell: fhs.AbsTmp,
|
Shell: fhs.AbsTmp,
|
||||||
Path: fhs.AbsTmp,
|
Path: fhs.AbsTmp,
|
||||||
Env: map[string]string{"TERM=": ""},
|
Env: map[string]string{"TERM=": ""},
|
||||||
}}, &hst.AppError{Step: "validate configuration", Err: hst.ErrEnviron,
|
}}, 0, &hst.AppError{Step: "validate configuration", Err: hst.ErrEnviron,
|
||||||
Msg: `invalid environment variable "TERM="`}},
|
Msg: `invalid environment variable "TERM="`}},
|
||||||
{"env NUL", &hst.Config{Container: &hst.ContainerConfig{
|
{"env NUL", &hst.Config{Container: &hst.ContainerConfig{
|
||||||
Home: fhs.AbsTmp,
|
Home: fhs.AbsTmp,
|
||||||
Shell: fhs.AbsTmp,
|
Shell: fhs.AbsTmp,
|
||||||
Path: fhs.AbsTmp,
|
Path: fhs.AbsTmp,
|
||||||
Env: map[string]string{"TERM\x00": ""},
|
Env: map[string]string{"TERM\x00": ""},
|
||||||
}}, &hst.AppError{Step: "validate configuration", Err: hst.ErrEnviron,
|
}}, 0, &hst.AppError{Step: "validate configuration", Err: hst.ErrEnviron,
|
||||||
Msg: `invalid environment variable "TERM\x00"`}},
|
Msg: `invalid environment variable "TERM\x00"`}},
|
||||||
|
|
||||||
{"insecure pulse", &hst.Config{Enablements: hst.NewEnablements(hst.EPulse), Container: &hst.ContainerConfig{
|
{"insecure pulse", &hst.Config{Enablements: hst.NewEnablements(hst.EPulse), Container: &hst.ContainerConfig{
|
||||||
Home: fhs.AbsTmp,
|
Home: fhs.AbsTmp,
|
||||||
Shell: fhs.AbsTmp,
|
Shell: fhs.AbsTmp,
|
||||||
Path: fhs.AbsTmp,
|
Path: fhs.AbsTmp,
|
||||||
}}, &hst.AppError{Step: "validate configuration", Err: hst.ErrInsecure,
|
}}, 0, &hst.AppError{Step: "validate configuration", Err: hst.ErrInsecure,
|
||||||
Msg: "enablement PulseAudio is insecure and no longer supported"}},
|
Msg: "enablement PulseAudio is insecure and no longer supported"}},
|
||||||
|
|
||||||
|
{"direct wayland", &hst.Config{Enablements: hst.NewEnablements(hst.EWayland), DirectWayland: true, Container: &hst.ContainerConfig{
|
||||||
|
Home: fhs.AbsTmp,
|
||||||
|
Shell: fhs.AbsTmp,
|
||||||
|
Path: fhs.AbsTmp,
|
||||||
|
}}, 0, &hst.AppError{Step: "validate configuration", Err: hst.ErrInsecure,
|
||||||
|
Msg: "direct_wayland is insecure and no longer supported"}},
|
||||||
|
{"direct wayland allow", &hst.Config{Enablements: hst.NewEnablements(hst.EWayland), DirectWayland: true, Container: &hst.ContainerConfig{
|
||||||
|
Home: fhs.AbsTmp,
|
||||||
|
Shell: fhs.AbsTmp,
|
||||||
|
Path: fhs.AbsTmp,
|
||||||
|
}}, hst.VAllowInsecure, nil},
|
||||||
|
|
||||||
|
{"direct pipewire", &hst.Config{Enablements: hst.NewEnablements(hst.EPipeWire), DirectPipeWire: true, Container: &hst.ContainerConfig{
|
||||||
|
Home: fhs.AbsTmp,
|
||||||
|
Shell: fhs.AbsTmp,
|
||||||
|
Path: fhs.AbsTmp,
|
||||||
|
}}, 0, &hst.AppError{Step: "validate configuration", Err: hst.ErrInsecure,
|
||||||
|
Msg: "direct_pipewire is insecure and no longer supported"}},
|
||||||
|
{"direct pipewire allow", &hst.Config{Enablements: hst.NewEnablements(hst.EPipeWire), DirectPipeWire: true, Container: &hst.ContainerConfig{
|
||||||
|
Home: fhs.AbsTmp,
|
||||||
|
Shell: fhs.AbsTmp,
|
||||||
|
Path: fhs.AbsTmp,
|
||||||
|
}}, hst.VAllowInsecure, nil},
|
||||||
|
|
||||||
|
{"direct pulse", &hst.Config{Enablements: hst.NewEnablements(hst.EPulse), DirectPulse: true, Container: &hst.ContainerConfig{
|
||||||
|
Home: fhs.AbsTmp,
|
||||||
|
Shell: fhs.AbsTmp,
|
||||||
|
Path: fhs.AbsTmp,
|
||||||
|
}}, 0, &hst.AppError{Step: "validate configuration", Err: hst.ErrInsecure,
|
||||||
|
Msg: "direct_pulse is insecure and no longer supported"}},
|
||||||
|
{"direct pulse allow", &hst.Config{Enablements: hst.NewEnablements(hst.EPulse), DirectPulse: true, Container: &hst.ContainerConfig{
|
||||||
|
Home: fhs.AbsTmp,
|
||||||
|
Shell: fhs.AbsTmp,
|
||||||
|
Path: fhs.AbsTmp,
|
||||||
|
}}, hst.VAllowInsecure, nil},
|
||||||
|
|
||||||
{"valid", &hst.Config{Container: &hst.ContainerConfig{
|
{"valid", &hst.Config{Container: &hst.ContainerConfig{
|
||||||
Home: fhs.AbsTmp,
|
Home: fhs.AbsTmp,
|
||||||
Shell: fhs.AbsTmp,
|
Shell: fhs.AbsTmp,
|
||||||
Path: fhs.AbsTmp,
|
Path: fhs.AbsTmp,
|
||||||
}}, nil},
|
}}, 0, nil},
|
||||||
}
|
}
|
||||||
for _, tc := range testCases {
|
for _, tc := range testCases {
|
||||||
t.Run(tc.name, func(t *testing.T) {
|
t.Run(tc.name, func(t *testing.T) {
|
||||||
t.Parallel()
|
t.Parallel()
|
||||||
if err := tc.config.Validate(); !reflect.DeepEqual(err, tc.wantErr) {
|
if err := tc.config.Validate(tc.flags); !reflect.DeepEqual(err, tc.wantErr) {
|
||||||
t.Errorf("Validate: error = %#v, want %#v", err, tc.wantErr)
|
t.Errorf("Validate: error = %#v, want %#v", err, tc.wantErr)
|
||||||
}
|
}
|
||||||
})
|
})
|
||||||
|
|||||||
@@ -32,7 +32,14 @@ type outcome struct {
|
|||||||
syscallDispatcher
|
syscallDispatcher
|
||||||
}
|
}
|
||||||
|
|
||||||
func (k *outcome) finalise(ctx context.Context, msg message.Msg, id *hst.ID, config *hst.Config) error {
|
// finalise prepares an outcome for main.
|
||||||
|
func (k *outcome) finalise(
|
||||||
|
ctx context.Context,
|
||||||
|
msg message.Msg,
|
||||||
|
id *hst.ID,
|
||||||
|
config *hst.Config,
|
||||||
|
flags int,
|
||||||
|
) error {
|
||||||
if ctx == nil || id == nil {
|
if ctx == nil || id == nil {
|
||||||
// unreachable
|
// unreachable
|
||||||
panic("invalid call to finalise")
|
panic("invalid call to finalise")
|
||||||
@@ -43,7 +50,7 @@ func (k *outcome) finalise(ctx context.Context, msg message.Msg, id *hst.ID, con
|
|||||||
}
|
}
|
||||||
k.ctx = ctx
|
k.ctx = ctx
|
||||||
|
|
||||||
if err := config.Validate(); err != nil {
|
if err := config.Validate(flags); err != nil {
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -18,7 +18,13 @@ import (
|
|||||||
func IsPollDescriptor(fd uintptr) bool
|
func IsPollDescriptor(fd uintptr) bool
|
||||||
|
|
||||||
// Main runs an app according to [hst.Config] and terminates. Main does not return.
|
// Main runs an app according to [hst.Config] and terminates. Main does not return.
|
||||||
func Main(ctx context.Context, msg message.Msg, config *hst.Config, fd int) {
|
func Main(
|
||||||
|
ctx context.Context,
|
||||||
|
msg message.Msg,
|
||||||
|
config *hst.Config,
|
||||||
|
flags int,
|
||||||
|
fd int,
|
||||||
|
) {
|
||||||
// avoids runtime internals or standard streams
|
// avoids runtime internals or standard streams
|
||||||
if fd >= 0 {
|
if fd >= 0 {
|
||||||
if IsPollDescriptor(uintptr(fd)) || fd < 3 {
|
if IsPollDescriptor(uintptr(fd)) || fd < 3 {
|
||||||
@@ -34,7 +40,7 @@ func Main(ctx context.Context, msg message.Msg, config *hst.Config, fd int) {
|
|||||||
k := outcome{syscallDispatcher: direct{msg}}
|
k := outcome{syscallDispatcher: direct{msg}}
|
||||||
|
|
||||||
finaliseTime := time.Now()
|
finaliseTime := time.Now()
|
||||||
if err := k.finalise(ctx, msg, &id, config); err != nil {
|
if err := k.finalise(ctx, msg, &id, config, flags); err != nil {
|
||||||
printMessageError(msg.GetLogger().Fatalln, "cannot seal app:", err)
|
printMessageError(msg.GetLogger().Fatalln, "cannot seal app:", err)
|
||||||
panic("unreachable")
|
panic("unreachable")
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -41,7 +41,7 @@ func entryDecode(r io.Reader, p *hst.State) (hst.Enablement, error) {
|
|||||||
return et, err
|
return et, err
|
||||||
} else if err = gob.NewDecoder(r).Decode(&p); err != nil {
|
} else if err = gob.NewDecoder(r).Decode(&p); err != nil {
|
||||||
return et, &hst.AppError{Step: "decode state body", Err: err}
|
return et, &hst.AppError{Step: "decode state body", Err: err}
|
||||||
} else if err = p.Config.Validate(); err != nil {
|
} else if err = p.Config.Validate(hst.VAllowInsecure); err != nil {
|
||||||
return et, err
|
return et, err
|
||||||
} else if p.Enablements.Unwrap() != et {
|
} else if p.Enablements.Unwrap() != et {
|
||||||
return et, &hst.AppError{Step: "validate state enablement", Err: os.ErrInvalid,
|
return et, &hst.AppError{Step: "validate state enablement", Err: os.ErrInvalid,
|
||||||
|
|||||||
@@ -265,7 +265,7 @@ in
|
|||||||
'';
|
'';
|
||||||
in
|
in
|
||||||
pkgs.writeShellScriptBin app.name ''
|
pkgs.writeShellScriptBin app.name ''
|
||||||
exec hakurei${if app.verbose then " -v" else ""} run ${checkedConfig "hakurei-app-${app.name}.json" conf} $@
|
exec hakurei${if app.verbose then " -v" else ""}${if app.insecureWayland then " --insecure" else ""} run ${checkedConfig "hakurei-app-${app.name}.json" conf} $@
|
||||||
''
|
''
|
||||||
)
|
)
|
||||||
]
|
]
|
||||||
|
|||||||
Reference in New Issue
Block a user