summaryrefslogtreecommitdiffhomepage
diff options
context:
space:
mode:
authorChong Cai <chongc@google.com>2021-03-11 17:52:43 -0800
committergVisor bot <gvisor-bot@google.com>2021-03-11 17:54:29 -0800
commita7197c9c688fdfc2d37005063d3f6dbf9cef2341 (patch)
tree19e75cd2e05f3a5d3c42281f90a66e30618f8926
parentcda7d5d44a9c923118f5e791a487b7f5996988b9 (diff)
Implement Merkle tree generate tool binary
This binary is used to recursively enable and generate Merkle tree files for all files and directories in a file system from inside a gVisor sandbox. PiperOrigin-RevId: 362418770
-rw-r--r--tools/verity/BUILD15
-rw-r--r--tools/verity/measure_tool.go87
-rw-r--r--tools/verity/measure_tool_unsafe.go39
3 files changed, 141 insertions, 0 deletions
diff --git a/tools/verity/BUILD b/tools/verity/BUILD
new file mode 100644
index 000000000..77d16359c
--- /dev/null
+++ b/tools/verity/BUILD
@@ -0,0 +1,15 @@
+load("//tools:defs.bzl", "go_binary")
+
+licenses(["notice"])
+
+go_binary(
+ name = "measure_tool",
+ srcs = [
+ "measure_tool.go",
+ "measure_tool_unsafe.go",
+ ],
+ pure = True,
+ deps = [
+ "//pkg/abi/linux",
+ ],
+)
diff --git a/tools/verity/measure_tool.go b/tools/verity/measure_tool.go
new file mode 100644
index 000000000..0d314ae70
--- /dev/null
+++ b/tools/verity/measure_tool.go
@@ -0,0 +1,87 @@
+// Copyright 2021 The gVisor Authors.
+//
+// Licensed under the Apache License, Version 2.0 (the "License");
+// you may not use this file except in compliance with the License.
+// You may obtain a copy of the License at
+//
+// http://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing, software
+// distributed under the License is distributed on an "AS IS" BASIS,
+// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+// See the License for the specific language governing permissions and
+// limitations under the License.
+
+// This binary can be used to run a measurement of the verity file system,
+// generate the corresponding Merkle tree files, and return the root hash.
+package main
+
+import (
+ "flag"
+ "io/ioutil"
+ "log"
+ "os"
+ "syscall"
+
+ "gvisor.dev/gvisor/pkg/abi/linux"
+)
+
+var path = flag.String("path", "", "path to the verity file system.")
+
+const maxDigestSize = 64
+
+type digest struct {
+ metadata linux.DigestMetadata
+ digest [maxDigestSize]byte
+}
+
+func main() {
+ flag.Parse()
+ if *path == "" {
+ log.Fatalf("no path provided")
+ }
+ if err := enableDir(*path); err != nil {
+ log.Fatalf("Failed to enable file system %s: %v", *path, err)
+ }
+ // Print the root hash of the file system to stdout.
+ if err := measure(*path); err != nil {
+ log.Fatalf("Failed to measure file system %s: %v", *path, err)
+ }
+}
+
+// enableDir enables verity features on all the files and sub-directories within
+// path.
+func enableDir(path string) error {
+ files, err := ioutil.ReadDir(path)
+ if err != nil {
+ return err
+ }
+ for _, file := range files {
+ if file.IsDir() {
+ // For directories, first enable its children.
+ if err := enableDir(path + "/" + file.Name()); err != nil {
+ return err
+ }
+ } else if file.Mode().IsRegular() {
+ // For regular files, open and enable verity feature.
+ f, err := os.Open(path + "/" + file.Name())
+ if err != nil {
+ return err
+ }
+ var p uintptr
+ if _, _, err := syscall.Syscall(syscall.SYS_IOCTL, uintptr(f.Fd()), uintptr(linux.FS_IOC_ENABLE_VERITY), p); err != 0 {
+ return err
+ }
+ }
+ }
+ // Once all children are enabled, enable the parent directory.
+ f, err := os.Open(path)
+ if err != nil {
+ return err
+ }
+ var p uintptr
+ if _, _, err := syscall.Syscall(syscall.SYS_IOCTL, uintptr(f.Fd()), uintptr(linux.FS_IOC_ENABLE_VERITY), p); err != 0 {
+ return err
+ }
+ return nil
+}
diff --git a/tools/verity/measure_tool_unsafe.go b/tools/verity/measure_tool_unsafe.go
new file mode 100644
index 000000000..d4079be9e
--- /dev/null
+++ b/tools/verity/measure_tool_unsafe.go
@@ -0,0 +1,39 @@
+// Copyright 2021 The gVisor Authors.
+//
+// Licensed under the Apache License, Version 2.0 (the "License");
+// you may not use this file except in compliance with the License.
+// You may obtain a copy of the License at
+//
+// http://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing, software
+// distributed under the License is distributed on an "AS IS" BASIS,
+// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+// See the License for the specific language governing permissions and
+// limitations under the License.
+package main
+
+import (
+ "encoding/hex"
+ "fmt"
+ "os"
+ "syscall"
+ "unsafe"
+
+ "gvisor.dev/gvisor/pkg/abi/linux"
+)
+
+// measure prints the hash of path to stdout.
+func measure(path string) error {
+ f, err := os.Open(path)
+ if err != nil {
+ return err
+ }
+ var digest digest
+ digest.metadata.DigestSize = maxDigestSize
+ if _, _, err := syscall.Syscall(syscall.SYS_IOCTL, uintptr(f.Fd()), uintptr(linux.FS_IOC_MEASURE_VERITY), uintptr(unsafe.Pointer(&digest))); err != 0 {
+ return err
+ }
+ fmt.Fprintf(os.Stdout, "%s\n", hex.EncodeToString(digest.digest[:digest.metadata.DigestSize]))
+ return err
+}