Skip to content

Commit 035362c

Browse files
committed
🚨WIP: Populate new base layers with real but empty hives
Somewhere between Windows RS5 (Server LTSC 2019) and Windows 20H2, the HCS started trying to load one of the hives in the base layer when importing a layer that depends on it. The observed symptom is: > hcsshim::ImportLayer - failed failed in Win32: The configuration registry database is corrupt. (0x3f1) WIP because at some point since I had this working in 2021, the behaviour of `go mod vendor` changed and no longer includes the testdata/minimal file, so that probably needs to be replaced. Possibly, just with a HTTP pull from GitHub; the relevant file hasn't changed in 3 years. Signed-off-by: Paul "TBBle" Hampson <[email protected]>
1 parent d376404 commit 035362c

66 files changed

Lines changed: 13660 additions & 8 deletions

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.

‎go.mod‎

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -12,6 +12,7 @@ require (
1212
github.com/containerd/go-runc v1.0.0
1313
github.com/containerd/ttrpc v1.1.0
1414
github.com/containerd/typeurl v1.0.2
15+
github.com/gabriel-samfira/go-hivex v0.0.0-20190725123041-b40bc95a7ced
1516
github.com/gogo/protobuf v1.3.2
1617
github.com/golang/mock v1.6.0
1718
github.com/google/go-cmp v0.5.6
@@ -30,6 +31,7 @@ require (
3031
go.opencensus.io v0.22.3
3132
golang.org/x/sync v0.0.0-20210220032951-036812b2e83c
3233
golang.org/x/sys v0.0.0-20220412211240-33da011f77ad
34+
golang.org/x/tools v0.1.5
3335
google.golang.org/grpc v1.40.0
3436
)
3537

@@ -50,8 +52,10 @@ require (
5052
github.com/opencontainers/image-spec v1.0.2 // indirect
5153
github.com/russross/blackfriday/v2 v2.0.1 // indirect
5254
github.com/shurcooL/sanitized_anchor_name v1.0.0 // indirect
55+
golang.org/x/mod v0.4.2 // indirect
5356
golang.org/x/net v0.0.0-20210825183410-e898025ed96a // indirect
5457
golang.org/x/text v0.3.6 // indirect
58+
golang.org/x/xerrors v0.0.0-20200804184101-5ec99f83aff1 // indirect
5559
google.golang.org/genproto v0.0.0-20201110150050-8816d57aaa9a // indirect
5660
google.golang.org/protobuf v1.27.1 // indirect
5761
)

‎go.sum‎

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -266,6 +266,8 @@ github.com/frankban/quicktest v1.11.3/go.mod h1:wRf/ReqHper53s+kmmSZizM8NamnL3IM
266266
github.com/fsnotify/fsnotify v1.4.7/go.mod h1:jwhsz4b93w/PPRr/qN1Yymfu8t87LnFCMoQvtojpjFo=
267267
github.com/fsnotify/fsnotify v1.4.9/go.mod h1:znqG4EE+3YCdAaPaxE2ZRY/06pZUdp0tY4IgpuI1SZQ=
268268
github.com/fullsailor/pkcs7 v0.0.0-20190404230743-d7302db945fa/go.mod h1:KnogPXtdwXqoenmZCw6S+25EAm2MkxbG0deNDu4cbSA=
269+
github.com/gabriel-samfira/go-hivex v0.0.0-20190725123041-b40bc95a7ced h1:QGy2AdPMyJWF1pI/GaAxpEY0qIFn/ekrimYrucQeNNk=
270+
github.com/gabriel-samfira/go-hivex v0.0.0-20190725123041-b40bc95a7ced/go.mod h1:2uhxVfr/8oFRFnCQbpoSzKG+qCvKH3yVt8FPASfJO28=
269271
github.com/garyburd/redigo v0.0.0-20150301180006-535138d7bcd7/go.mod h1:NR3MbYisc3/PwhQ00EMzDiPmrwpPxAn5GI05/YaO1SY=
270272
github.com/ghodss/yaml v0.0.0-20150909031657-73d445a93680/go.mod h1:4dBDuWmgqj2HViK6kFavaiC9ZROes6MMH2rRYeMEF04=
271273
github.com/ghodss/yaml v1.0.0/go.mod h1:4dBDuWmgqj2HViK6kFavaiC9ZROes6MMH2rRYeMEF04=
@@ -698,6 +700,7 @@ golang.org/x/mod v0.1.1-0.20191105210325-c90efee705ee/go.mod h1:QqPTAvyqsEbceGzB
698700
golang.org/x/mod v0.1.1-0.20191107180719-034126e5016b/go.mod h1:QqPTAvyqsEbceGzBzNggFXnrqF1CaUcvgkdR5Ot7KZg=
699701
golang.org/x/mod v0.2.0/go.mod h1:s0Qsj1ACt9ePp/hMypM3fl4fZqREWJwdYDEqhRiZZUA=
700702
golang.org/x/mod v0.3.0/go.mod h1:s0Qsj1ACt9ePp/hMypM3fl4fZqREWJwdYDEqhRiZZUA=
703+
golang.org/x/mod v0.4.2 h1:Gz96sIWK3OalVv/I/qNygP42zyoKp3xptRVCWRFEBvo=
701704
golang.org/x/mod v0.4.2/go.mod h1:s0Qsj1ACt9ePp/hMypM3fl4fZqREWJwdYDEqhRiZZUA=
702705
golang.org/x/net v0.0.0-20180724234803-3673e40ba225/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4=
703706
golang.org/x/net v0.0.0-20180906233101-161cd47e91fd/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4=
@@ -878,6 +881,7 @@ golang.org/x/tools v0.0.0-20200619180055-7c47624df98f/go.mod h1:EkVYQZoAsY45+roY
878881
golang.org/x/tools v0.0.0-20200916195026-c9a70fc28ce3/go.mod h1:z6u4i615ZeAfBE4XtMziQW1fSVJXACjjbWkB/mvPzlU=
879882
golang.org/x/tools v0.0.0-20210106214847-113979e3529a/go.mod h1:emZCQorbCU4vsT4fOWvOPXz4eW1wZW4PmDk9uLelYpA=
880883
golang.org/x/tools v0.1.1/go.mod h1:o0xws9oXOQQZyjljx8fwUC0k7L1pTE6eaCbjGeHmOkk=
884+
golang.org/x/tools v0.1.5 h1:ouewzE6p+/VEB31YYnTbEJdi8pFqKp4P4n85vwo3DHA=
881885
golang.org/x/tools v0.1.5/go.mod h1:o0xws9oXOQQZyjljx8fwUC0k7L1pTE6eaCbjGeHmOkk=
882886
golang.org/x/xerrors v0.0.0-20190717185122-a985d3407aa7/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0=
883887
golang.org/x/xerrors v0.0.0-20191011141410-1b5146add898/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0=

‎internal/wclayer/converttobaselayer.go‎

Lines changed: 18 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -16,14 +16,28 @@ import (
1616

1717
var hiveNames = []string{"DEFAULT", "SAM", "SECURITY", "SOFTWARE", "SYSTEM"}
1818

19-
// Ensure the given file exists as an ordinary file, and create a zero-length file if not.
20-
func ensureFile(path string, root *os.File) error {
19+
//go:generate go run mkminimalhive_windows.go -output zminimalhive_windows.go
20+
21+
// Ensure the given file exists as an ordinary file, and create a minimal hive file if not.
22+
func ensureHive(path string, root *os.File) error {
2123
stat, err := safefile.LstatRelative(path, root)
2224
if err != nil && os.IsNotExist(err) {
23-
newFile, err := safefile.OpenRelative(path, root, 0, syscall.FILE_SHARE_WRITE, winapi.FILE_CREATE, 0)
25+
minimalHiveBytes, err := minimalHiveContents()
26+
if err != nil {
27+
return err
28+
}
29+
30+
newFile, err := safefile.OpenRelative(path, root, syscall.GENERIC_WRITE, syscall.FILE_SHARE_WRITE, winapi.FILE_CREATE, 0)
2431
if err != nil {
2532
return err
2633
}
34+
35+
_, err = newFile.Write(minimalHiveBytes)
36+
if err != nil {
37+
newFile.Close()
38+
return err
39+
}
40+
2741
return newFile.Close()
2842
}
2943

@@ -48,7 +62,7 @@ func ensureBaseLayer(root *os.File) (hasUtilityVM bool, err error) {
4862

4963
for _, hiveName := range hiveNames {
5064
hivePath := filepath.Join(hiveSourcePath, hiveName)
51-
if err = ensureFile(hivePath, root); err != nil {
65+
if err = ensureHive(hivePath, root); err != nil {
5266
return
5367
}
5468
}
Lines changed: 17 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,17 @@
1+
//go:build generate_but_never_actually_compile
2+
3+
// This exists to force the inclusion of the below package in
4+
// go.mod and hence the vendor directory, so that
5+
// golang.org/x/tools/go/packages.Load can read files from it.
6+
7+
// However, if this import statement gets pulled into an actual
8+
// compile (i.e. by appearing in mkminimalhive_windows.go) then
9+
// it forces both CGO and installation of the libhive library
10+
// this package wraps.
11+
12+
// Per https://github.com/golang/go/wiki/Modules#how-can-i-track-tool-dependencies-for-a-module
13+
// this is the best option.
14+
15+
package main
16+
17+
import _ "github.com/gabriel-samfira/go-hivex"
Lines changed: 90 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,90 @@
1+
//go:build generate
2+
3+
/*
4+
mkminimalhive_windows generates a minimal hive blob function
5+
so that we do not carry a runtime dependency on the hive source.
6+
7+
The generated source contains a single function, minimalHiveContents,
8+
which returns a []byte of the desired data.
9+
10+
Largely based on how mksyscall_windows works.
11+
*/
12+
13+
package main
14+
15+
import (
16+
"encoding/base64"
17+
"errors"
18+
"flag"
19+
"fmt"
20+
"log"
21+
"os"
22+
"path/filepath"
23+
24+
"golang.org/x/tools/go/packages"
25+
)
26+
27+
var (
28+
filename = flag.String("output", "", "output file name (standard output if omitted)")
29+
)
30+
31+
//readMinimalHiveContents finds the `minimal` hive binary from the package as there's no way to create this file
32+
// Originally from https://github.com/buildpacks/imgutil/blob/main/tools/bcdhive_generator/bcdhive_hivex.go
33+
func readMinimalHiveContents() ([]byte, error) {
34+
pkgs, err := packages.Load(&packages.Config{}, "github.com/gabriel-samfira/go-hivex")
35+
if err != nil {
36+
return nil, err
37+
}
38+
if len(pkgs) != 1 || len(pkgs[0].GoFiles) != 1 {
39+
return nil, errors.New("hivex module root not found")
40+
}
41+
hivexRootPath := filepath.Dir(pkgs[0].GoFiles[0])
42+
minimalHivePath := filepath.Join(hivexRootPath, "testdata", "minimal")
43+
return os.ReadFile(minimalHivePath)
44+
}
45+
46+
func usage() {
47+
fmt.Fprintf(os.Stderr, "usage: mkminimalhive_windows [flags] [path ...]\n")
48+
flag.PrintDefaults()
49+
os.Exit(1)
50+
}
51+
52+
func main() {
53+
flag.Usage = usage
54+
flag.Parse()
55+
if len(flag.Args()) != 0 {
56+
fmt.Fprintf(os.Stderr, "unexpected filename arguments\n")
57+
usage()
58+
}
59+
60+
hiveData, err := readMinimalHiveContents()
61+
if err != nil {
62+
log.Fatal(err)
63+
}
64+
65+
hiveBase64 := base64.StdEncoding.EncodeToString(hiveData)
66+
67+
source := []byte(`// Code generated by mkminimalhive_windows DO NOT EDIT.
68+
69+
package wclayer
70+
71+
import (
72+
"encoding/base64"
73+
)
74+
75+
const hiveBase64 = "` + hiveBase64 + `"
76+
77+
func minimalHiveContents() ([]byte, error) {
78+
return base64.StdEncoding.DecodeString(hiveBase64)
79+
}
80+
`)
81+
82+
if *filename == "" {
83+
_, err = os.Stdout.Write(source)
84+
} else {
85+
err = os.WriteFile(*filename, source, 0644)
86+
}
87+
if err != nil {
88+
log.Fatal(err)
89+
}
90+
}

‎internal/wclayer/zminimalhive_windows.go‎

Lines changed: 13 additions & 0 deletions
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

‎test/go.mod‎

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -36,6 +36,7 @@ require (
3636
github.com/docker/docker v1.4.2-0.20190924003213-a8608b5b67c7 // indirect
3737
github.com/docker/docker-credential-helpers v0.6.3 // indirect
3838
github.com/docker/go-events v0.0.0-20190806004212-e31b211e4f1c // indirect
39+
github.com/gabriel-samfira/go-hivex v0.0.0-20190725123041-b40bc95a7ced // indirect
3940
github.com/gogo/googleapis v1.4.0 // indirect
4041
github.com/golang/groupcache v0.0.0-20200121045136-8c9f03a8e57e // indirect
4142
github.com/golang/protobuf v1.5.0 // indirect
@@ -53,8 +54,11 @@ require (
5354
github.com/xeipuuv/gojsonreference v0.0.0-20180127040603-bd5ef7bd5415 // indirect
5455
github.com/xeipuuv/gojsonschema v0.0.0-20180618132009-1d523034197f // indirect
5556
go.opencensus.io v0.22.3 // indirect
57+
golang.org/x/mod v0.4.2 // indirect
5658
golang.org/x/net v0.0.0-20220127200216-cd36cc0744dd // indirect
5759
golang.org/x/text v0.3.7 // indirect
60+
golang.org/x/tools v0.1.5 // indirect
61+
golang.org/x/xerrors v0.0.0-20200804184101-5ec99f83aff1 // indirect
5862
google.golang.org/genproto v0.0.0-20220107163113-42d7afdf6368 // indirect
5963
google.golang.org/protobuf v1.27.1 // indirect
6064
)

0 commit comments

Comments
 (0)