Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

simplify zeroDevice to just zero first block #1672

Merged
merged 3 commits into from
Feb 28, 2023
Merged
Show file tree
Hide file tree
Changes from 1 commit
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
13 changes: 8 additions & 5 deletions internal/guest/storage/crypt/crypt.go
Original file line number Diff line number Diff line change
Expand Up @@ -23,8 +23,8 @@ var (
_getBlockDeviceSize = getBlockDeviceSize
_osMkdirTemp = os.MkdirTemp
_mkfsXfs = mkfsXfs
_zeroDevice = zeroDevice
_osRemoveAll = os.RemoveAll
_zeroFirstBlock = zeroFirstBlock
)

// cryptsetupCommand runs cryptsetup with the provided arguments
Expand Down Expand Up @@ -172,13 +172,16 @@ func EncryptDevice(ctx context.Context, source string, dmCryptName string) (path
return "", fmt.Errorf("error getting size of: %s: %w", deviceNamePath, err)
}

if deviceSize == 0 {
if deviceSize < 4096 {
anmaxvl marked this conversation as resolved.
Show resolved Hide resolved
return "", fmt.Errorf("invalid size obtained for: %s", deviceNamePath)
}

// 4.1. Zero the first block. It appears that mkfs.xfs reads this before formatting.
if err = _zeroDevice(deviceNamePath, 4096, 1); err != nil {
return "", fmt.Errorf("failed zero'ing start of device %s: %w", deviceNamePath, err)
// 4.1. Zero the first block.
// In the xfs mkfs case it appears to attempt to read the first block of the device.
// This results in an integrity error. This function zeros out the start of the device,
// so we are sure that when it is read it has already been hashed so matches.
if err := _zeroFirstBlock(deviceNamePath, 4096); err != nil {
return "", fmt.Errorf("failed to zero first block: %w", err)
}

// 4.2. Format it as xfs
Expand Down
12 changes: 6 additions & 6 deletions internal/guest/storage/crypt/crypt_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -26,6 +26,7 @@ func clearCryptTestDependencies() {
_getBlockDeviceSize = nil
_osMkdirTemp = osMkdirTempTest
_osRemoveAll = nil
_zeroFirstBlock = nil
}

func Test_Encrypt_Generate_Key_Error(t *testing.T) {
Expand Down Expand Up @@ -203,10 +204,7 @@ func Test_Encrypt_Mkfs_Error(t *testing.T) {
// Return a non-zero size
return blockDeviceSize, nil
}
_mkfsXfs = func(string) error {
return nil
}
_zeroDevice = func(string, int64, int64) error {
_zeroFirstBlock = func(_ string, _ int) error {
return nil
}

Expand All @@ -221,8 +219,7 @@ func Test_Encrypt_Mkfs_Error(t *testing.T) {
return expectedErr
}

_, err := EncryptDevice(context.Background(), source, "dm-crypt-name")
if errors.Unwrap(err) != expectedErr {
if _, err := EncryptDevice(context.Background(), source, "dm-crypt-name"); errors.Unwrap(err) != expectedErr {
t.Fatalf("expected err: '%v' got: '%v'", expectedErr, err)
}
}
Expand Down Expand Up @@ -250,6 +247,9 @@ func Test_Encrypt_Success(t *testing.T) {
// Return a non-zero size
return blockDeviceSize, nil
}
_zeroFirstBlock = func(_ string, _ int) error {
return nil
}
_mkfsXfs = func(arg string) error {
return nil
}
Expand Down
43 changes: 7 additions & 36 deletions internal/guest/storage/crypt/utilities.go
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,7 @@
package crypt

import (
"bytes"
"context"
"crypto/rand"
"fmt"
Expand Down Expand Up @@ -33,46 +34,16 @@ func getBlockDeviceSize(ctx context.Context, path string) (int64, error) {
return pos, nil
}

// In the xfs mkfs case it appears to attempt to read the first block of the device.
// This results in an integrity error. This function zeros out the start of the device
// so we are sure that when it is read it has already been hashed so matches.
func zeroDevice(devicePath string, blockSize int64, numberOfBlocks int64) error {
fout, err := os.OpenFile(devicePath, os.O_WRONLY, 0)
func zeroFirstBlock(path string, blockSize int) error {
fout, err := os.OpenFile(path, os.O_WRONLY, 0)
if err != nil {
return fmt.Errorf("failed to open device file %s: %w", devicePath, err)
return fmt.Errorf("failed to open file for zero'ing: %w", err)
}
defer fout.Close()

zeros := make([]byte, blockSize)
for i := range zeros {
zeros[i] = 0
}

// get the size so we don't overrun the end of the device
foutSize, err := fout.Seek(0, io.SeekEnd)
if err != nil {
return fmt.Errorf("zeroDevice: failed to seek to end, device file %s: %w", devicePath, err)
}

// move back to the front.
_, err = fout.Seek(0, io.SeekStart)
if err != nil {
return fmt.Errorf("zeroDevice: failed to seek to start, device file %s: %w", devicePath, err)
}

var offset int64 = 0
var which int64
for which = 0; which < numberOfBlocks; which++ {
// Exit when the end of the file is reached
if offset >= foutSize {
break
}
// Write data to destination file
written, err := fout.Write(zeros)
if err != nil {
return fmt.Errorf("failed to write destination file %s offset %d: %w", devicePath, offset, err)
}
offset += int64(written)
zeros := bytes.Repeat([]byte{0}, blockSize)
if _, err := fout.Write(zeros); err != nil {
return fmt.Errorf("failed writing zero bytes: %w", err)
anmaxvl marked this conversation as resolved.
Show resolved Hide resolved
}
return nil
}
Expand Down