From 6df0d37c5a73732417ce0eb2be824b02fce0c54f Mon Sep 17 00:00:00 2001 From: Ophestra Date: Thu, 19 Feb 2026 15:09:40 +0900 Subject: [PATCH] cmd/mbf: Rosa OS container helper This sets up a Rosa OS container with its shell as the initial process. Signed-off-by: Ophestra --- cmd/mbf/main.go | 148 +++++++++++++++++++++++++++++++++++++++++++++--- 1 file changed, 141 insertions(+), 7 deletions(-) diff --git a/cmd/mbf/main.go b/cmd/mbf/main.go index dccc1b0..ee00465 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",