Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
3 changes: 3 additions & 0 deletions internal/winapi/cimfs.go
Original file line number Diff line number Diff line change
Expand Up @@ -56,3 +56,6 @@ type CimFsImagePath struct {
//sys CimMergeMountImage(numCimPaths uint32, backingImagePaths *CimFsImagePath, flags uint32, volumeID *g) (hr error) = cimfs.CimMergeMountImage?
//sys CimTombstoneFile(cimFSHandle FsHandle, path string) (hr error) = cimfs.CimTombstoneFile?
//sys CimCreateMergeLink(cimFSHandle FsHandle, newPath string, oldPath string) (hr error) = cimfs.CimCreateMergeLink?
//sys CimSealImage(blockCimPath string, hashSize *uint64, fixedHeaderSize *uint64, hash *byte) (hr error) = cimfs.CimSealImage?
//sys CimGetVerificationInformation(blockCimPath string, isSealed *uint32, hashSize *uint64, signatureSize *uint64, fixedHeaderSize *uint64, hash *byte, signature *byte) (hr error) = cimfs.CimGetVerificationInformation?
//sys CimMountVerifiedImage(imagePath string, fsName string, flags uint32, volumeID *g, hashSize uint16, hash *byte) (hr error) = cimfs.CimMountVerifiedImage?
80 changes: 80 additions & 0 deletions internal/winapi/zsyscall_windows.go

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

128 changes: 128 additions & 0 deletions pkg/cimfs/cim_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -5,9 +5,11 @@ package cimfs

import (
"bytes"
"context"
"errors"
"fmt"
"io"
"strings"
"syscall"

"os"
Expand Down Expand Up @@ -53,6 +55,14 @@ func (t *testBlockCIM) cimPath() string {
return filepath.Join(t.BlockPath, t.CimName)
}

type testVerifiedBlockCIM struct {
BlockCIM
}

func (t *testVerifiedBlockCIM) cimPath() string {
return filepath.Join(t.BlockPath, t.CimName)
}

// A utility function to create a file/directory and write data to it in the given cim.
func createCimFileUtil(c *CimFsWriter, fileTuple tuple) error {
// create files inside the cim
Expand Down Expand Up @@ -99,6 +109,8 @@ func openNewCIM(t *testing.T, newCIM testCIM) *CimFsWriter {
writer, err = Create(val.imageDir, val.parentName, val.imageName)
case *testBlockCIM:
writer, err = CreateBlockCIM(val.BlockPath, val.CimName, val.Type)
case *testVerifiedBlockCIM:
writer, err = CreateBlockCIMWithOptions(context.Background(), &val.BlockCIM, WithDataIntegrity())
}
if err != nil {
t.Fatalf("failed while creating a cim: %s", err)
Expand Down Expand Up @@ -666,3 +678,119 @@ func TestMergedLinksInMergedBlockCIMs(rootT *testing.T) {
rootT.Logf("file contents don't match!")
}
}

func TestVerifiedSingleFileBlockCIM(t *testing.T) {
if !IsVerifiedCimSupported() {
t.Skipf("verified CIMs are not supported")
}

// contents to write to the CIM
testContents := []tuple{
{"foo.txt", []byte("foo1"), false},
{"bar.txt", []byte("bar"), false},
}

root := t.TempDir()
blockPath := filepath.Join(root, "layer.bcim")
tc := &testVerifiedBlockCIM{
BlockCIM: BlockCIM{
Type: BlockCIMTypeSingleFile,
BlockPath: blockPath,
CimName: "layer.cim",
}}
writer := openNewCIM(t, tc)
writeCIM(t, writer, testContents)

mountvol := mountCIM(t, tc, CimMountVerifiedCim|CimMountSingleFileCim)

compareContent(t, mountvol, testContents)
}

func TestVerifiedSingleFileBlockCIMMount(t *testing.T) {
if !IsVerifiedCimSupported() {
t.Skipf("verified CIMs are not supported")
}

// contents to write to the CIM
testContents := []tuple{
{"foo.txt", []byte("foo1"), false},
{"bar.txt", []byte("bar"), false},
}

root := t.TempDir()
blockPath := filepath.Join(root, "layer.bcim")
tc := &testVerifiedBlockCIM{
BlockCIM: BlockCIM{
Type: BlockCIMTypeSingleFile,
BlockPath: blockPath,
CimName: "layer.cim",
}}
writer := openNewCIM(t, tc)
writeCIM(t, writer, testContents)

rootHash, err := GetVerificationInfo(blockPath)
if err != nil {
t.Fatalf("failed to get verification info: %s", err)
}

// mount and read the contents of the cim
volumeGUID, err := guid.NewV4()
if err != nil {
t.Fatalf("generate cim mount GUID: %s", err)
}

mountvol, err := MountVerifiedBlockCIM(&tc.BlockCIM, CimMountSingleFileCim, volumeGUID, rootHash)
if err != nil {
t.Fatalf("mount verified cim : %s", err)
}
t.Cleanup(func() {
if err := Unmount(mountvol); err != nil {
t.Logf("CIM unmount failed: %s", err)
}
})
compareContent(t, mountvol, testContents)
}

func TestVerifiedSingleFileBlockCIMMountReadFailure(t *testing.T) {
if !IsVerifiedCimSupported() {
t.Skipf("verified CIMs are not supported")
}

// contents to write to the CIM
testContents := []tuple{
{"foo.txt", []byte("foo1"), false},
{"bar.txt", []byte("bar"), false},
}

root := t.TempDir()
blockPath := filepath.Join(root, "layer.bcim")
tc := &testVerifiedBlockCIM{
BlockCIM: BlockCIM{
Type: BlockCIMTypeSingleFile,
BlockPath: blockPath,
CimName: "layer.cim",
}}
writer := openNewCIM(t, tc)
writeCIM(t, writer, testContents)

rootHash, err := GetVerificationInfo(blockPath)
if err != nil {
t.Fatalf("failed to get verification info: %s", err)
}

// mount and read the contents of the cim
volumeGUID, err := guid.NewV4()
if err != nil {
t.Fatalf("generate cim mount GUID: %s", err)
}

// change the rootHash slightly, this may cause the mount to fail due to integrity check.
rootHash[0] = rootHash[0] + 1

_, err = MountVerifiedBlockCIM(&tc.BlockCIM, CimMountSingleFileCim, volumeGUID, rootHash)
if err == nil {
t.Fatalf("mount verified cim should fail with integrity error")
} else if !strings.Contains(err.Error(), "integrity violation") {
t.Fatalf("expected integrity violation error")
}
}
Loading