aboutsummaryrefslogtreecommitdiffhomepage
path: root/internal/pkg
diff options
context:
space:
mode:
authorOphestra <cat@gensokyo.uk>2026-05-12 15:10:43 +0900
committerOphestra <cat@gensokyo.uk>2026-05-12 15:11:17 +0900
commit6643cfbeee181ee1bd543e2b3783bb5a8c01ad13 (patch)
tree04b1b3b1d3fa044a1f8d5097355fa2779fe95af9 /internal/pkg
parentdcde38f2e967ebf14a3c8a7f933b7dd1bf465566 (diff)
internal/pkg: optionally measure exec artifact
Useful for verifying deterministic output without enabling network access. Signed-off-by: Ophestra <cat@gensokyo.uk>
Diffstat (limited to 'internal/pkg')
-rw-r--r--internal/pkg/exec.go48
-rw-r--r--internal/pkg/exec_test.go20
-rw-r--r--internal/pkg/internal/testtool/expected/sum_amd64.go2
-rw-r--r--internal/pkg/internal/testtool/expected/sum_arm64.go2
-rw-r--r--internal/pkg/internal/testtool/expected/sum_riscv64.go2
-rw-r--r--internal/pkg/ir_test.go26
6 files changed, 66 insertions, 34 deletions
diff --git a/internal/pkg/exec.go b/internal/pkg/exec.go
index b91299dd..c0ea7485 100644
--- a/internal/pkg/exec.go
+++ b/internal/pkg/exec.go
@@ -167,6 +167,9 @@ var _ fmt.Stringer = new(execArtifact)
type execNetArtifact struct {
checksum Checksum
+ // Whether to keep host net namespace.
+ hostNet bool
+
execArtifact
}
@@ -175,15 +178,24 @@ var _ KnownChecksum = new(execNetArtifact)
// Checksum returns the caller-supplied checksum.
func (a *execNetArtifact) Checksum() Checksum { return a.checksum }
-// Kind returns the hardcoded [Kind] constant.
-func (*execNetArtifact) Kind() Kind { return KindExecNet }
+// Kind returns [KindExecNet], or [KindExec] if hostNet is false.
+func (a *execNetArtifact) Kind() Kind {
+ if a == nil || a.hostNet {
+ return KindExecNet
+ }
+ return KindExec
+}
// Cure cures the [Artifact] in the container described by the caller. The
// container retains host networking.
func (a *execNetArtifact) Cure(f *FContext) error {
- return a.cure(f, true)
+ return a.cure(f, a.hostNet)
}
+// ErrNetChecksum is panicked by [NewExec] if host net namespace is requested
+// with a nil checksum.
+var ErrNetChecksum = errors.New("attempting to keep net namespace without checksum")
+
// NewExec returns a new [Artifact] that executes the program path in a
// container with specified paths bind mounted read-only in order. A private
// instance of /proc and /dev is made available to the container.
@@ -197,7 +209,7 @@ func (a *execNetArtifact) Cure(f *FContext) error {
// regular or symlink.
//
// If checksum is non-nil, the resulting [Artifact] implements [KnownChecksum]
-// and its container runs in the host net namespace.
+// and its container optionally runs in the host net namespace.
//
// The container is allowed to run for the specified duration before the initial
// process and all processes originating from it is terminated. A zero or
@@ -211,7 +223,7 @@ func NewExec(
name, arch string,
checksum *Checksum,
timeout time.Duration,
- exclusive bool,
+ hostNet, exclusive bool,
dir *check.Absolute,
env []string,
@@ -234,9 +246,12 @@ func NewExec(
}
a := execArtifact{name, arch, paths, dir, env, pathname, args, timeout, exclusive}
if checksum == nil {
+ if hostNet {
+ panic(ErrNetChecksum)
+ }
return &a
}
- return &execNetArtifact{*checksum, a}
+ return &execNetArtifact{*checksum, hostNet, a}
}
// Kind returns the hardcoded [Kind] constant.
@@ -361,22 +376,17 @@ func readExecArtifact(r *IRReader, net bool) Artifact {
exclusive := r.ReadUint32() != 0
checksum, ok := r.Finalise()
-
var checksumP *Checksum
- if net {
- if !ok {
- panic(ErrExpectedChecksum)
- }
- checksumVal := checksum.Value()
- checksumP = &checksumVal
- } else {
- if ok {
- panic(ErrUnexpectedChecksum)
- }
+ if ok {
+ checksumP = new(checksum.Value())
+ }
+
+ if net && !ok {
+ panic(ErrExpectedChecksum)
}
return NewExec(
- name, arch, checksumP, timeout, exclusive, dir, env, pathname, args, paths...,
+ name, arch, checksumP, timeout, net, exclusive, dir, env, pathname, args, paths...,
)
}
@@ -590,7 +600,7 @@ func (c *Cache) EnterExec(
case *execNetArtifact:
e = &f.execArtifact
- hostNet = true
+ hostNet = f.hostNet
default:
return ErrNotExec
diff --git a/internal/pkg/exec_test.go b/internal/pkg/exec_test.go
index 6e436cae..f9d4158e 100644
--- a/internal/pkg/exec_test.go
+++ b/internal/pkg/exec_test.go
@@ -57,7 +57,7 @@ func TestExec(t *testing.T) {
cureMany(t, c, []cureStep{
{"container", pkg.NewExec(
- "exec-offline", "", nil, 0, false,
+ "exec-offline", "", new(wantOffline.hash()), 0, false, false,
pkg.AbsWork,
[]string{"HAKUREI_TEST=1"},
check.MustAbs("/opt/bin/testtool"),
@@ -80,7 +80,7 @@ func TestExec(t *testing.T) {
), ignorePathname, wantOffline, nil},
{"error passthrough", pkg.NewExec(
- "", "", nil, 0, true,
+ "", "", nil, 0, false, true,
pkg.AbsWork,
[]string{"HAKUREI_TEST=1"},
check.MustAbs("/opt/bin/testtool"),
@@ -103,7 +103,7 @@ func TestExec(t *testing.T) {
}},
{"invalid paths", pkg.NewExec(
- "", "", nil, 0, false,
+ "", "", nil, 0, false, false,
pkg.AbsWork,
[]string{"HAKUREI_TEST=1"},
check.MustAbs("/opt/bin/testtool"),
@@ -116,7 +116,7 @@ func TestExec(t *testing.T) {
// check init failure passthrough
var exitError *exec.ExitError
if _, _, err := c.Cure(pkg.NewExec(
- "", "", nil, 0, false,
+ "", "", nil, 0, false, false,
pkg.AbsWork,
nil,
check.MustAbs("/opt/bin/testtool"),
@@ -157,7 +157,7 @@ func TestExec(t *testing.T) {
}
cureMany(t, c, []cureStep{
{"container", pkg.NewExec(
- "exec-net", "", new(wantNet.hash()), 0, false,
+ "exec-net", "", new(wantNet.hash()), 0, true, false,
pkg.AbsWork,
[]string{"HAKUREI_TEST=1"},
check.MustAbs("/opt/bin/testtool"),
@@ -206,7 +206,7 @@ func TestExec(t *testing.T) {
cureMany(t, c, []cureStep{
{"container", pkg.NewExec(
- "exec-overlay-root", "", nil, 0, false,
+ "exec-overlay-root", "", nil, 0, false, false,
pkg.AbsWork,
[]string{"HAKUREI_TEST=1", "HAKUREI_ROOT=1"},
check.MustAbs("/opt/bin/testtool"),
@@ -247,7 +247,7 @@ func TestExec(t *testing.T) {
cureMany(t, c, []cureStep{
{"container", pkg.NewExec(
- "exec-overlay-work", "", nil, 0, false,
+ "exec-overlay-work", "", nil, 0, false, false,
pkg.AbsWork,
[]string{"HAKUREI_TEST=1", "HAKUREI_ROOT=1"},
check.MustAbs("/work/bin/testtool"),
@@ -293,7 +293,7 @@ func TestExec(t *testing.T) {
cureMany(t, c, []cureStep{
{"container", pkg.NewExec(
- "exec-multiple-layers", "", nil, 0, false,
+ "exec-multiple-layers", "", nil, 0, false, false,
pkg.AbsWork,
[]string{"HAKUREI_TEST=1", "HAKUREI_ROOT=1"},
check.MustAbs("/opt/bin/testtool"),
@@ -366,7 +366,7 @@ func TestExec(t *testing.T) {
cureMany(t, c, []cureStep{
{"container", pkg.NewExec(
- "exec-layer-promotion", "", nil, 0, true,
+ "exec-layer-promotion", "", nil, 0, false, true,
pkg.AbsWork,
[]string{"HAKUREI_TEST=1", "HAKUREI_ROOT=1"},
check.MustAbs("/opt/bin/testtool"),
@@ -416,7 +416,7 @@ func TestExec(t *testing.T) {
cureMany(t, c, []cureStep{
{"container", pkg.NewExec(
- "exec-binfmt", "cafe", nil, 0, true,
+ "exec-binfmt", "cafe", nil, 0, false, true,
pkg.AbsWork,
[]string{"HAKUREI_TEST=1", "HAKUREI_BINFMT=1"},
check.MustAbs("/opt/bin/sample"),
diff --git a/internal/pkg/internal/testtool/expected/sum_amd64.go b/internal/pkg/internal/testtool/expected/sum_amd64.go
index 7ac5d2d5..b062f601 100644
--- a/internal/pkg/internal/testtool/expected/sum_amd64.go
+++ b/internal/pkg/internal/testtool/expected/sum_amd64.go
@@ -1,7 +1,7 @@
package expected
const (
- Offline = "oe7Uv1u5BwxcuX3HLQzZRg1Q5oetJo6jWiKGMOeqLiqBkaVgyKzvx82N81_IzUAz"
+ Offline = "q5ktDTq0miP-VvB2blxqXQeaRXCUWgP_KbC18KNtUDtyoaI_h5mHmGuPMArVEBDs"
OvlRoot = "NacZGXwuRkTvcHaG08a22ujJ8qCWN0RSoFlRSR5FSt0ZcBbJ28FRvkYsHEtX7G8i"
Layers = "WBJDrATtX6rIE5yAu8ePX3WmDF0Tt9kFiue0m3cRnyRoVx1my8a67fh3CAW486oP"
Net = "CmYtj2sNB3LHtqiDuck_Lz3MjLLIiwyP8N4NDitQ1Icvv__LVP9p8tm-sHeQaKKp"
diff --git a/internal/pkg/internal/testtool/expected/sum_arm64.go b/internal/pkg/internal/testtool/expected/sum_arm64.go
index 4f6216ea..ad02f493 100644
--- a/internal/pkg/internal/testtool/expected/sum_arm64.go
+++ b/internal/pkg/internal/testtool/expected/sum_arm64.go
@@ -1,7 +1,7 @@
package expected
const (
- Offline = "K88Nrt1Mt6NZTdAjdq8_Zq2_Jv2mZYyNOfJzkjhTdxiV9G8FY1NtKNh21Kj-H3CO"
+ Offline = "WapqyoPxbWSnq07dWHt71mHaJXq99pAjJfFlELlJljSiZMhTFqqlzU1_mN86shSj"
OvlRoot = "V9anFOiRvjGfAeBhLl14AL8TKdWZyD0WTPYe4fS9mOBw8iW5Lmarvt6TG6MV8uWm"
Layers = "tKx7JNRoSBdK_7MdzI-nwTNV2wmiPzwYdcd17oLmXKL_iLmUzUiA79qTqdrTasrv"
Net = "aXyDLzBCJ9XltXZIfetEVsEkrqHfcXuD5XE_FcUnYbN3emwL55N6P8LlHzNfGnM5"
diff --git a/internal/pkg/internal/testtool/expected/sum_riscv64.go b/internal/pkg/internal/testtool/expected/sum_riscv64.go
index 9fd8102a..adc843c0 100644
--- a/internal/pkg/internal/testtool/expected/sum_riscv64.go
+++ b/internal/pkg/internal/testtool/expected/sum_riscv64.go
@@ -1,7 +1,7 @@
package expected
const (
- Offline = "9pGgev_rDp5fUxMjgM-Z67p_IZYYAVv-cwhgS8XUtJeMWhsaf_YycQPfYLQFSfWk"
+ Offline = "Z6yXE5gOJScL3srmnVMWgCXccDiUNZ5snSrf6RkXuU1_U0rX_kGVwsfHUgNG_awd"
OvlRoot = "zYXJHFRLuxvUhuisZEXgGgVvdQd6piMfp5jmtT6jdVjvC2gICXquOq-UTwlrSD5I"
Layers = "_F8EDazHbcLeT0sVSQXRN_kn9IjduqJcDYgzXpsT-hpKU4EBcZ0PISN2zchpqMbm"
Net = "CA_FAaSIYJgapBEHV40doxpH23PdUEy_6s1TZc7wfSPN0XYqwGpMceXXDSabGveO"
diff --git a/internal/pkg/ir_test.go b/internal/pkg/ir_test.go
index ad895471..9a465e55 100644
--- a/internal/pkg/ir_test.go
+++ b/internal/pkg/ir_test.go
@@ -39,7 +39,7 @@ func TestIRRoundtrip(t *testing.T) {
)},
{"exec offline", pkg.NewExec(
- "exec-offline", "", nil, 0, false,
+ "exec-offline", "", nil, 0, false, false,
pkg.AbsWork,
[]string{"HAKUREI_TEST=1"},
check.MustAbs("/opt/bin/testtool"),
@@ -61,7 +61,7 @@ func TestIRRoundtrip(t *testing.T) {
{"exec net", pkg.NewExec(
"exec-net", "",
(*pkg.Checksum)(bytes.Repeat([]byte{0xfc}, len(pkg.Checksum{}))),
- 0, false,
+ 0, false, false,
pkg.AbsWork,
[]string{"HAKUREI_TEST=1"},
check.MustAbs("/opt/bin/testtool"),
@@ -80,6 +80,28 @@ func TestIRRoundtrip(t *testing.T) {
)),
)},
+ {"exec measured", pkg.NewExec(
+ "exec-measured", "",
+ (*pkg.Checksum)(bytes.Repeat([]byte{0xfd}, len(pkg.Checksum{}))),
+ 0, false, false,
+ pkg.AbsWork,
+ []string{"HAKUREI_TEST=1"},
+ check.MustAbs("/opt/bin/testtool"),
+ []string{"testtool", "measured"},
+
+ pkg.MustPath("/file", false, pkg.NewFile("file", []byte(
+ "stub file",
+ ))), pkg.MustPath("/.hakurei", false, pkg.NewHTTPGetTar(
+ nil, "file:///hakurei.tar",
+ pkg.Checksum(bytes.Repeat([]byte{0xfd}, len(pkg.Checksum{}))),
+ pkg.TarUncompressed,
+ )), pkg.MustPath("/opt", false, pkg.NewHTTPGetTar(
+ nil, "file:///testtool.tar.gz",
+ pkg.Checksum(bytes.Repeat([]byte{0xfd}, len(pkg.Checksum{}))),
+ pkg.TarGzip,
+ )),
+ )},
+
{"file anonymous", pkg.NewFile("", []byte{0})},
{"file", pkg.NewFile("stub", []byte("stub"))},
}