All checks were successful
Test / Create distribution (push) Successful in 1m14s
Test / Sandbox (push) Successful in 2m59s
Test / Hakurei (push) Successful in 4m10s
Test / ShareFS (push) Successful in 4m12s
Test / Sandbox (race detector) (push) Successful in 5m33s
Test / Hakurei (race detector) (push) Successful in 6m40s
Test / Flake checks (push) Successful in 1m25s
These are undocumented anywhere else and is required by tools invoking hakurei. Signed-off-by: Ophestra <cat@gensokyo.uk>
92 lines
3.2 KiB
Go
92 lines
3.2 KiB
Go
// Hakurei runs user-specified containers as subordinate users.
|
|
//
|
|
// This program is generally invoked by another, higher level program, which
|
|
// creates container configuration via package [hst] or an implementation of it.
|
|
//
|
|
// The parent may leave files open and specify their file descriptor for various
|
|
// uses. In these cases, standard streams and netpoll files are treated as
|
|
// invalid file descriptors and rejected. All string representations must be in
|
|
// decimal.
|
|
//
|
|
// When specifying a [hst.Config] JSON stream or file to the run subcommand, the
|
|
// argument "-" is equivalent to stdin. Otherwise, file descriptor rules
|
|
// described above applies. Invalid file descriptors are treated as file names
|
|
// in their string representation, with the exception that if a netpoll file
|
|
// descriptor is attempted, the program fails.
|
|
//
|
|
// The flag --identifier-fd can be optionally specified to the run subcommand to
|
|
// receive the identifier of the newly started instance. File descriptor rules
|
|
// described above applies, and the file must be writable. This is sent after
|
|
// its state is made available, so the client must not attempt to poll for it.
|
|
// This uses the internal binary format of [hst.ID].
|
|
//
|
|
// For the show and ps subcommands, the flag --json can be applied to the main
|
|
// hakurei command to serialise output in JSON when applicable. Additionally,
|
|
// the flag --short targeting each subcommand is used to omit some information
|
|
// in both JSON and user-facing output. Only JSON-encoded output is covered
|
|
// under the compatibility promise.
|
|
//
|
|
// A template for [hst.Config] demonstrating all available configuration fields
|
|
// is returned by [hst.Template]. The JSON-encoded equivalent of this can be
|
|
// obtained via the template subcommand. Fields left unpopulated in the template
|
|
// (the direct_* family of fields, which are insecure under any configuration if
|
|
// enabled) are unsupported.
|
|
//
|
|
// For simple (but insecure) testing scenarios, the exec subcommand can be used
|
|
// to generate a simple, permissive configuration in-memory. See its help
|
|
// message for all available options.
|
|
package main
|
|
|
|
import (
|
|
"context"
|
|
_ "embed"
|
|
"errors"
|
|
"log"
|
|
"os"
|
|
"os/signal"
|
|
"syscall"
|
|
|
|
"hakurei.app/container"
|
|
"hakurei.app/ext"
|
|
"hakurei.app/message"
|
|
)
|
|
|
|
//go:generate cp ../../LICENSE .
|
|
//go:embed LICENSE
|
|
var license string
|
|
|
|
// earlyHardeningErrs are errors collected while setting up early hardening feature.
|
|
type earlyHardeningErrs struct{ yamaLSM, dumpable error }
|
|
|
|
func main() {
|
|
// early init path, skips root check and duplicate PR_SET_DUMPABLE
|
|
container.TryArgv0(nil)
|
|
|
|
log.SetFlags(0)
|
|
log.SetPrefix("hakurei: ")
|
|
msg := message.New(log.Default())
|
|
|
|
early := earlyHardeningErrs{
|
|
yamaLSM: ext.SetPtracer(0),
|
|
dumpable: ext.SetDumpable(ext.SUID_DUMP_DISABLE),
|
|
}
|
|
|
|
if os.Geteuid() == 0 {
|
|
log.Fatal("this program must not run as root")
|
|
}
|
|
|
|
ctx, stop := signal.NotifyContext(context.Background(),
|
|
syscall.SIGINT, syscall.SIGTERM)
|
|
defer stop() // unreachable
|
|
|
|
buildCommand(ctx, msg, &early, os.Stderr).MustParse(os.Args[1:], func(err error) {
|
|
msg.Verbosef("command returned %v", err)
|
|
if errors.Is(err, errSuccess) {
|
|
msg.BeforeExit()
|
|
os.Exit(0)
|
|
}
|
|
// this catches faulty command handlers that fail to return before this point
|
|
})
|
|
log.Fatal("unreachable")
|
|
}
|