go.mod: Bump hcsshim to v0.10.0-rc.1

This contains quite a bit (also bumps google/uuid to 1.3.0). Some HostProcess
container improvements to get ready for whenever it goes to stable in
Kubernetes, Hyper-V (windows) container support for CRI, and a plethora of
other small additions and fixes.

Signed-off-by: Daniel Canter <dcanter@microsoft.com>
This commit is contained in:
Daniel Canter
2022-08-12 23:43:27 -07:00
parent a04268132e
commit 1f8db2467b
168 changed files with 3532 additions and 1131 deletions

View File

@@ -1,6 +1,7 @@
package dmverity
import (
"bufio"
"bytes"
"crypto/rand"
"crypto/sha256"
@@ -12,19 +13,29 @@ import (
"github.com/pkg/errors"
"github.com/Microsoft/hcsshim/ext4/internal/compactext4"
"github.com/Microsoft/hcsshim/internal/memory"
)
const (
blockSize = compactext4.BlockSize
// RecommendedVHDSizeGB is the recommended size in GB for VHDs, which is not a hard limit.
RecommendedVHDSizeGB = 128 * 1024 * 1024 * 1024
// MerkleTreeBufioSize is a default buffer size to use with bufio.Reader
MerkleTreeBufioSize = memory.MiB // 1MB
// RecommendedVHDSizeGB is the recommended size in GB for VHDs, which is not a hard limit.
RecommendedVHDSizeGB = 128 * memory.GiB
// VeritySignature is a value written to dm-verity super-block.
VeritySignature = "verity"
)
var (
salt = bytes.Repeat([]byte{0}, 32)
sbSize = binary.Size(dmveritySuperblock{})
)
var salt = bytes.Repeat([]byte{0}, 32)
var (
ErrSuperBlockReadFailure = errors.New("failed to read dm-verity super block")
ErrSuperBlockParseFailure = errors.New("failed to parse dm-verity super block")
ErrRootHashReadFailure = errors.New("failed to read dm-verity root hash")
ErrNotVeritySuperBlock = errors.New("invalid dm-verity super-block signature")
)
type dmveritySuperblock struct {
@@ -69,20 +80,19 @@ type VerityInfo struct {
Version uint32
}
// MerkleTree constructs dm-verity hash-tree for a given byte array with a fixed salt (0-byte) and algorithm (sha256).
func MerkleTree(data []byte) ([]byte, error) {
// MerkleTree constructs dm-verity hash-tree for a given io.Reader with a fixed salt (0-byte) and algorithm (sha256).
func MerkleTree(r io.Reader) ([]byte, error) {
layers := make([][]byte, 0)
currentLevel := r
currentLevel := bytes.NewBuffer(data)
for currentLevel.Len() != blockSize {
blocks := currentLevel.Len() / blockSize
for {
nextLevel := bytes.NewBuffer(make([]byte, 0))
for i := 0; i < blocks; i++ {
for {
block := make([]byte, blockSize)
_, err := currentLevel.Read(block)
if err != nil {
if _, err := io.ReadFull(currentLevel, block); err != nil {
if err == io.EOF {
break
}
return nil, errors.Wrap(err, "failed to read data block")
}
h := hash2(salt, block)
@@ -92,14 +102,18 @@ func MerkleTree(data []byte) ([]byte, error) {
padding := bytes.Repeat([]byte{0}, blockSize-(nextLevel.Len()%blockSize))
nextLevel.Write(padding)
currentLevel = nextLevel
layers = append(layers, currentLevel.Bytes())
layers = append(layers, nextLevel.Bytes())
currentLevel = bufio.NewReaderSize(nextLevel, MerkleTreeBufioSize)
// This means that only root hash remains and our job is done
if nextLevel.Len() == blockSize {
break
}
}
var tree = bytes.NewBuffer(make([]byte, 0))
tree := bytes.NewBuffer(make([]byte, 0))
for i := len(layers) - 1; i >= 0; i-- {
_, err := tree.Write(layers[i])
if err != nil {
if _, err := tree.Write(layers[i]); err != nil {
return nil, errors.Wrap(err, "failed to write merkle tree")
}
}
@@ -125,7 +139,7 @@ func NewDMVeritySuperblock(size uint64) *dmveritySuperblock {
SaltSize: uint16(len(salt)),
}
copy(superblock.Signature[:], "verity")
copy(superblock.Signature[:], VeritySignature)
copy(superblock.Algorithm[:], "sha256")
copy(superblock.Salt[:], salt)
@@ -165,7 +179,7 @@ func ReadDMVerityInfo(vhdPath string, offsetInBytes int64) (*VerityInfo, error)
block := make([]byte, blockSize)
if s, err := vhd.Read(block); err != nil || s != blockSize {
if err != nil {
return nil, errors.Wrapf(ErrSuperBlockReadFailure, "%s", err)
return nil, errors.Wrapf(err, "%s", ErrSuperBlockReadFailure)
}
return nil, errors.Wrapf(ErrSuperBlockReadFailure, "unexpected bytes read: expected=%d, actual=%d", blockSize, s)
}
@@ -173,13 +187,15 @@ func ReadDMVerityInfo(vhdPath string, offsetInBytes int64) (*VerityInfo, error)
dmvSB := &dmveritySuperblock{}
b := bytes.NewBuffer(block)
if err := binary.Read(b, binary.LittleEndian, dmvSB); err != nil {
return nil, errors.Wrapf(ErrSuperBlockParseFailure, "%s", err)
return nil, errors.Wrapf(err, "%s", ErrSuperBlockParseFailure)
}
if string(bytes.Trim(dmvSB.Signature[:], "\x00")[:]) != VeritySignature {
return nil, ErrNotVeritySuperBlock
}
// read the merkle tree root
if s, err := vhd.Read(block); err != nil || s != blockSize {
if err != nil {
return nil, errors.Wrapf(ErrRootHashReadFailure, "%s", err)
return nil, errors.Wrapf(err, "%s", ErrRootHashReadFailure)
}
return nil, errors.Wrapf(ErrRootHashReadFailure, "unexpected bytes read: expected=%d, actual=%d", blockSize, s)
}
@@ -196,3 +212,37 @@ func ReadDMVerityInfo(vhdPath string, offsetInBytes int64) (*VerityInfo, error)
Version: dmvSB.Version,
}, nil
}
// ComputeAndWriteHashDevice builds merkle tree from a given io.ReadSeeker and writes the result
// hash device (dm-verity super-block combined with merkle tree) to io.WriteSeeker.
func ComputeAndWriteHashDevice(r io.ReadSeeker, w io.WriteSeeker) error {
if _, err := r.Seek(0, io.SeekStart); err != nil {
return err
}
tree, err := MerkleTree(r)
if err != nil {
return errors.Wrap(err, "failed to build merkle tree")
}
devSize, err := r.Seek(0, io.SeekEnd)
if err != nil {
return err
}
dmVeritySB := NewDMVeritySuperblock(uint64(devSize))
if _, err := w.Seek(0, io.SeekEnd); err != nil {
return err
}
if err := binary.Write(w, binary.LittleEndian, dmVeritySB); err != nil {
return errors.Wrap(err, "failed to write dm-verity super-block")
}
// write super-block padding
padding := bytes.Repeat([]byte{0}, blockSize-(sbSize%blockSize))
if _, err = w.Write(padding); err != nil {
return err
}
// write tree
if _, err := w.Write(tree); err != nil {
return errors.Wrap(err, "failed to write merkle tree")
}
return nil
}