aboutsummaryrefslogtreecommitdiffhomepage
path: root/cmd
diff options
context:
space:
mode:
authorOphestra <cat@gensokyo.uk>2026-02-19 15:09:40 +0900
committerOphestra <cat@gensokyo.uk>2026-02-19 15:12:16 +0900
commit6df0d37c5a73732417ce0eb2be824b02fce0c54f (patch)
tree421801e894f35941fc093ba0a41332596761824a /cmd
parent1619b06541ac6da630529c1d80c513ae424f8078 (diff)
cmd/mbf: Rosa OS container helper
This sets up a Rosa OS container with its shell as the initial process. Signed-off-by: Ophestra <cat@gensokyo.uk>
Diffstat (limited to 'cmd')
-rw-r--r--cmd/mbf/main.go148
1 files changed, 141 insertions, 7 deletions
diff --git a/cmd/mbf/main.go b/cmd/mbf/main.go
index dccc1b02..ee00465a 100644
--- a/cmd/mbf/main.go
+++ b/cmd/mbf/main.go
@@ -10,11 +10,15 @@ import (
"path/filepath"
"runtime"
"syscall"
+ "time"
"unique"
"hakurei.app/command"
"hakurei.app/container"
"hakurei.app/container/check"
+ "hakurei.app/container/fhs"
+ "hakurei.app/container/seccomp"
+ "hakurei.app/container/std"
"hakurei.app/internal/pkg"
"hakurei.app/internal/rosa"
"hakurei.app/message"
@@ -120,9 +124,9 @@ func main() {
"stage3",
"Check for toolchain 3-stage non-determinism",
func(args []string) (err error) {
- std := rosa.Std
+ t := rosa.Std
if flagGentoo != "" {
- std -= 3 // magic number to discourage misuse
+ t -= 3 // magic number to discourage misuse
var checksum pkg.Checksum
if len(flagChecksum) != 0 {
@@ -133,9 +137,9 @@ func main() {
rosa.SetGentooStage3(flagGentoo, checksum)
}
- _, _, _, stage1 := (std - 2).NewLLVM()
- _, _, _, stage2 := (std - 1).NewLLVM()
- _, _, _, stage3 := std.NewLLVM()
+ _, _, _, stage1 := (t - 2).NewLLVM()
+ _, _, _, stage2 := (t - 1).NewLLVM()
+ _, _, _, stage3 := t.NewLLVM()
var (
pathname *check.Absolute
checksum [2]unique.Handle[pkg.Checksum]
@@ -169,7 +173,7 @@ func main() {
if flagStage0 {
if pathname, _, err = cache.Cure(
- std.Load(rosa.Stage0),
+ t.Load(rosa.Stage0),
); err != nil {
return err
}
@@ -208,7 +212,7 @@ func main() {
return errors.New("cure requires 1 argument")
}
if p, ok := rosa.ResolveName(args[0]); !ok {
- return fmt.Errorf("unsupported artifact %q", args[0])
+ return fmt.Errorf("unknown artifact %q", args[0])
} else if flagDump == "" {
pathname, _, err := cache.Cure(rosa.Std.Load(p))
if err == nil {
@@ -241,6 +245,136 @@ func main() {
)
}
+ {
+ var (
+ flagNet bool
+ flagSession bool
+
+ flagWithToolchain bool
+ )
+ c.NewCommand(
+ "shell",
+ "Interactive shell in the specified Rosa OS environment",
+ func(args []string) error {
+ root := make([]pkg.Artifact, 0, 6+len(args))
+ for _, arg := range args {
+ p, ok := rosa.ResolveName(arg)
+ if !ok {
+ return fmt.Errorf("unknown artifact %q", arg)
+ }
+ root = append(root, rosa.Std.Load(p))
+ }
+
+ musl, compilerRT, runtimes, clang := rosa.Std.NewLLVM()
+ root = append(root, musl)
+ if flagWithToolchain {
+ root = append(root, compilerRT, runtimes, clang)
+ }
+ root = append(root,
+ rosa.Std.Load(rosa.Mksh),
+ rosa.Std.Load(rosa.Toybox),
+ )
+
+ type cureRes struct {
+ pathname *check.Absolute
+ checksum unique.Handle[pkg.Checksum]
+ }
+ cured := make(map[pkg.Artifact]cureRes)
+ for _, a := range root {
+ pathname, checksum, err := cache.Cure(a)
+ if err != nil {
+ return err
+ }
+ cured[a] = cureRes{pathname, checksum}
+ }
+
+ layers := pkg.PromoteLayers(root, func(a pkg.Artifact) (
+ *check.Absolute,
+ unique.Handle[pkg.Checksum],
+ ) {
+ res := cured[a]
+ return res.pathname, res.checksum
+ }, func(i int, d pkg.Artifact) {
+ r := pkg.Encode(cache.Ident(d).Value())
+ if s, ok := d.(fmt.Stringer); ok {
+ if name := s.String(); name != "" {
+ r += "-" + name
+ }
+ }
+ msg.Verbosef("promoted layer %d as %s", i, r)
+ })
+
+ z := container.New(ctx, msg)
+ z.WaitDelay = 3 * time.Second
+ z.SeccompPresets = pkg.SeccompPresets
+ z.SeccompFlags |= seccomp.AllowMultiarch
+ z.ParentPerm = 0700
+ z.HostNet = flagNet
+ z.RetainSession = flagSession
+ z.Hostname = "localhost"
+ z.Uid, z.Gid = (1<<10)-1, (1<<10)-1
+ z.Stdin, z.Stdout, z.Stderr = os.Stdin, os.Stdout, os.Stderr
+
+ var tempdir *check.Absolute
+ if s, err := filepath.Abs(os.TempDir()); err != nil {
+ return err
+ } else if tempdir, err = check.NewAbs(s); err != nil {
+ return err
+ }
+
+ z.Dir = fhs.AbsRoot
+ z.Env = []string{
+ "SHELL=/system/bin/mksh",
+ "PATH=/system/bin",
+ "HOME=/",
+ }
+ z.Path = rosa.AbsSystem.Append("bin", "mksh")
+ z.Args = []string{"mksh"}
+ z.
+ OverlayEphemeral(fhs.AbsRoot, layers...).
+ Place(
+ fhs.AbsEtc.Append("hosts"),
+ []byte("127.0.0.1 localhost\n"),
+ ).
+ Place(
+ fhs.AbsEtc.Append("passwd"),
+ []byte("media_rw:x:1023:1023::/:/system/bin/sh\n"+
+ "nobody:x:65534:65534::/proc/nonexistent:/system/bin/false\n"),
+ ).
+ Place(
+ fhs.AbsEtc.Append("group"),
+ []byte("media_rw:x:1023:\nnobody:x:65534:\n"),
+ ).
+ Bind(tempdir, fhs.AbsTmp, std.BindWritable).
+ Proc(fhs.AbsProc).Dev(fhs.AbsDev, true)
+
+ if err := z.Start(); err != nil {
+ return err
+ }
+ if err := z.Serve(); err != nil {
+ return err
+ }
+ return z.Wait()
+ },
+ ).
+ Flag(
+ &flagNet,
+ "net", command.BoolFlag(false),
+ "Share host net namespace",
+ ).
+ Flag(
+ &flagSession,
+ "session", command.BoolFlag(false),
+ "Retain session",
+ ).
+ Flag(
+ &flagWithToolchain,
+ "with-toolchain", command.BoolFlag(false),
+ "Include the stage3 LLVM toolchain",
+ )
+
+ }
+
c.Command(
"help",
"Show this help message",