github.com/SagerNet/gvisor@v0.0.0-20210707092255-7731c139d75c/runsc/cmd/verity_prepare.go (about) 1 // Copyright 2021 The gVisor Authors. 2 // 3 // Licensed under the Apache License, Version 2.0 (the "License"); 4 // you may not use this file except in compliance with the License. 5 // You may obtain a copy of the License at 6 // 7 // http://www.apache.org/licenses/LICENSE-2.0 8 // 9 // Unless required by applicable law or agreed to in writing, software 10 // distributed under the License is distributed on an "AS IS" BASIS, 11 // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 12 // See the License for the specific language governing permissions and 13 // limitations under the License. 14 15 package cmd 16 17 import ( 18 "context" 19 "fmt" 20 "math/rand" 21 "os" 22 23 "github.com/google/subcommands" 24 specs "github.com/opencontainers/runtime-spec/specs-go" 25 "golang.org/x/sys/unix" 26 "github.com/SagerNet/gvisor/runsc/config" 27 "github.com/SagerNet/gvisor/runsc/flag" 28 "github.com/SagerNet/gvisor/runsc/specutils" 29 ) 30 31 // VerityPrepare implements subcommands.Commands for the "verity-prepare" 32 // command. It sets up a sandbox with a writable verity mount mapped to "--dir", 33 // and executes the verity measure tool specified by "--tool" in the sandbox. It 34 // is intended to prepare --dir to be mounted as a verity filesystem. 35 type VerityPrepare struct { 36 root string 37 tool string 38 dir string 39 } 40 41 // Name implements subcommands.Command.Name. 42 func (*VerityPrepare) Name() string { 43 return "verity-prepare" 44 } 45 46 // Synopsis implements subcommands.Command.Synopsis. 47 func (*VerityPrepare) Synopsis() string { 48 return "Generates the data structures necessary to enable verityfs on a filesystem." 49 } 50 51 // Usage implements subcommands.Command.Usage. 52 func (*VerityPrepare) Usage() string { 53 return "verity-prepare --tool=<measure_tool> --dir=<path>" 54 } 55 56 // SetFlags implements subcommands.Command.SetFlags. 57 func (c *VerityPrepare) SetFlags(f *flag.FlagSet) { 58 f.StringVar(&c.root, "root", "/", `path to the root directory, defaults to "/"`) 59 f.StringVar(&c.tool, "tool", "", "path to the verity measure_tool") 60 f.StringVar(&c.dir, "dir", "", "path to the directory to be hashed") 61 } 62 63 // Execute implements subcommands.Command.Execute. 64 func (c *VerityPrepare) Execute(_ context.Context, f *flag.FlagSet, args ...interface{}) subcommands.ExitStatus { 65 conf := args[0].(*config.Config) 66 waitStatus := args[1].(*unix.WaitStatus) 67 68 hostname, err := os.Hostname() 69 if err != nil { 70 return Errorf("Error to retrieve hostname: %v", err) 71 } 72 73 // Map the entire host file system. 74 absRoot, err := resolvePath(c.root) 75 if err != nil { 76 return Errorf("Error resolving root: %v", err) 77 } 78 79 spec := &specs.Spec{ 80 Root: &specs.Root{ 81 Path: absRoot, 82 }, 83 Process: &specs.Process{ 84 Cwd: absRoot, 85 Args: []string{c.tool, "--path", "/verityroot"}, 86 Env: os.Environ(), 87 Capabilities: specutils.AllCapabilities(), 88 }, 89 Hostname: hostname, 90 Mounts: []specs.Mount{ 91 specs.Mount{ 92 Source: c.dir, 93 Destination: "/verityroot", 94 Type: "bind", 95 Options: []string{"verity.roothash="}, 96 }, 97 }, 98 } 99 100 cid := fmt.Sprintf("runsc-%06d", rand.Int31n(1000000)) 101 102 // Force no networking, it is not necessary to run the verity measure tool. 103 conf.Network = config.NetworkNone 104 105 conf.Verity = true 106 107 return startContainerAndWait(spec, conf, cid, waitStatus) 108 }