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

feat(cmd/rofl): Use qcow2 images, enable stage 2 persistence flag #354

Merged
merged 3 commits into from
Feb 7, 2025
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
4 changes: 2 additions & 2 deletions .github/workflows/ci-lint.yml
Original file line number Diff line number Diff line change
Expand Up @@ -41,7 +41,7 @@ jobs:
- name: Set up Go
uses: actions/setup-go@v5
with:
go-version: "1.22.x"
go-version: "1.23.x"
cache: false
- name: Install gitlint
run: |
Expand All @@ -63,7 +63,7 @@ jobs:
# 'make lint-go'.
uses: golangci/[email protected]
with:
version: v1.56
version: v1.61
# Always run this step so that all linting errors can be seen at once.
if: always()
- name: Ensure a clean code checkout
Expand Down
2 changes: 1 addition & 1 deletion .github/workflows/ci-tests.yml
Original file line number Diff line number Diff line change
Expand Up @@ -29,7 +29,7 @@ jobs:
- name: Set up Go
uses: actions/setup-go@v5
with:
go-version: "1.22.x"
go-version: "1.23.x"
- name: Cache Go dependencies
uses: actions/cache@v4
with:
Expand Down
2 changes: 1 addition & 1 deletion .github/workflows/release.yml
Original file line number Diff line number Diff line change
Expand Up @@ -22,7 +22,7 @@ jobs:
- name: Set up Go
uses: actions/setup-go@v5
with:
go-version: "1.22.x"
go-version: "1.23.x"
- name: Install GoReleaser
uses: goreleaser/goreleaser-action@v5
with:
Expand Down
4 changes: 2 additions & 2 deletions build/measurement/acpi/acpi.go
Original file line number Diff line number Diff line change
Expand Up @@ -57,7 +57,7 @@ func GenerateTablesQemu(resources *bundle.TDXResources) ([]byte, []byte, []byte,
binary.LittleEndian.PutUint32(tpl[od.Memory.RangeMinimumOffset:], 0x80000000)
binary.LittleEndian.PutUint32(tpl[od.Memory.LengthOffset:], 0x60000000)
} else {
memSizeBytes := uint32(resources.Memory * 1024 * 1024)
memSizeBytes := uint32(resources.Memory * 1024 * 1024) //nolint: gosec
binary.LittleEndian.PutUint32(tpl[od.Memory.RangeMinimumOffset:], memSizeBytes)
binary.LittleEndian.PutUint32(tpl[od.Memory.LengthOffset:], 0xe0000000-memSizeBytes)
}
Expand Down Expand Up @@ -140,7 +140,7 @@ func findAcpiTable(tables []byte, signature string) (uint32, uint32, uint32, err
tblSig := string(tables[offset : offset+4])
tblLen := int(binary.LittleEndian.Uint32(tables[offset+4 : offset+8]))
if tblSig == signature {
return uint32(offset), uint32(offset + 9), uint32(tblLen), nil
return uint32(offset), uint32(offset + 9), uint32(tblLen), nil //nolint: gosec
}

// Skip other tables.
Expand Down
12 changes: 6 additions & 6 deletions build/measurement/tdx_qemu.go
Original file line number Diff line number Diff line change
Expand Up @@ -268,11 +268,11 @@ func (m *tdvfMetadata) computeMrtd(fw []byte, variant int) []byte {
// All the other bytes contain 0.
var buf [128]byte
copy(buf[:9], []byte("MR.EXTEND"))
binary.LittleEndian.PutUint64(buf[16:24], s.memoryAddress+page*pageSize+uint64(i*mrExtendGranularity))
binary.LittleEndian.PutUint64(buf[16:24], s.memoryAddress+page*pageSize+uint64(i*mrExtendGranularity)) //nolint: gosec
_, _ = h.Write(buf[:])

// The other two extension buffers contain the chunk’s content.
chunkOffset := int(s.dataOffset) + int(page*pageSize) + i*mrExtendGranularity
chunkOffset := int(s.dataOffset) + int(page*pageSize) + i*mrExtendGranularity //nolint: gosec
_, _ = h.Write(fw[chunkOffset : chunkOffset+mrExtendGranularity])
}
}
Expand Down Expand Up @@ -427,7 +427,7 @@ func computeEnclaveIdentity(
rtmr1 []byte,
rtmr2 []byte,
rtmr3 []byte,
) *sgx.EnclaveIdentity {
) sgx.EnclaveIdentity {
var (
zeroMrSigner sgx.MrSigner
mrEnclave sgx.MrEnclave
Expand All @@ -441,7 +441,7 @@ func computeEnclaveIdentity(
rawMrEnclave := h.Sum(nil)
copy(mrEnclave[:], rawMrEnclave)

return &sgx.EnclaveIdentity{
return sgx.EnclaveIdentity{
MrEnclave: mrEnclave,
MrSigner: zeroMrSigner, // All-zero MRSIGNER (invalid in SGX).
}
Expand All @@ -453,7 +453,7 @@ func computeEnclaveIdentity(
//
// It may return multiple identities because there may be differences between QEMU versions that can
// cause differences in measurements (e.g. with MRTD).
func MeasureTdxQemu(bnd *bundle.Bundle, comp *bundle.Component) ([]*sgx.EnclaveIdentity, error) {
func MeasureTdxQemu(bnd *bundle.Bundle, comp *bundle.Component) ([]sgx.EnclaveIdentity, error) {
if comp.TDX == nil {
return nil, fmt.Errorf("component does not support TDX")
}
Expand Down Expand Up @@ -526,7 +526,7 @@ func MeasureTdxQemu(bnd *bundle.Bundle, comp *bundle.Component) ([]*sgx.EnclaveI

// Compute MRTD for all known QEMU variants as there are unfortunately different
// implementations.
eids := make([]*sgx.EnclaveIdentity, 0, 2)
eids := make([]sgx.EnclaveIdentity, 0, 2)
for _, variant := range []int{
mrtdVariantTwoPass,
mrtdVariantSinglePass,
Expand Down
2 changes: 1 addition & 1 deletion cmd/network/add_local.go
Original file line number Diff line number Diff line change
Expand Up @@ -110,7 +110,7 @@ func AddLocalNetwork(name string, rpc string) {
}

if numDecimals != 0 {
net.Denomination.Decimals = uint8(numDecimals)
net.Denomination.Decimals = uint8(numDecimals) //nolint: gosec
}

if description != "" {
Expand Down
36 changes: 33 additions & 3 deletions cmd/rofl/build/artifacts.go
Original file line number Diff line number Diff line change
Expand Up @@ -372,7 +372,7 @@ func padWithEmptySpace(fn string, size uint64) error {
return err
}

currentSize := uint64(fi.Size())
currentSize := uint64(fi.Size()) //nolint: gosec
if currentSize >= size {
return nil
}
Expand All @@ -397,17 +397,47 @@ func appendEmptySpace(fn string, size uint64, align uint64) (uint64, error) {
if err != nil {
return 0, err
}
offset := uint64(fi.Size())
offset := uint64(fi.Size()) //nolint: gosec

// Ensure proper alignment.
if size%align != 0 {
return 0, fmt.Errorf("size is not properly aligned")
}
offset += (align - (offset % align)) % align

if err = f.Truncate(int64(offset + size)); err != nil {
if err = f.Truncate(int64(offset + size)); err != nil { //nolint: gosec
return 0, err
}

return offset, nil
}

// convertToQcow2 converts a raw image to qcow2 format.
func convertToQcow2(fn string) error {
const qemuImgBin = "qemu-img"
if err := ensureBinaryExists(qemuImgBin, "qemu-utils"); err != nil {
return err
}

tmpOutFn := fn + ".qcow2"

// Execute qemu-img.
cmd := exec.Command(
qemuImgBin,
"convert",
"-O", "qcow2",
fn,
tmpOutFn,
)
var out strings.Builder
cmd.Stderr = &out
cmd.Stdout = &out
if err := cmd.Run(); err != nil {
return fmt.Errorf("%w\n%s", err, out.String())
}

if err := os.Rename(tmpOutFn, fn); err != nil {
return fmt.Errorf("failed to rename temporary file: %w", err)
}
return nil
}
4 changes: 2 additions & 2 deletions cmd/rofl/build/artifacts_unix.go
Original file line number Diff line number Diff line change
Expand Up @@ -10,7 +10,7 @@ import (
)

func extractHandleSpecialNode(path string, header *tar.Header) error {
mode := uint32(header.Mode & 0o7777)
mode := uint32(header.Mode & 0o7777) //nolint: gosec
switch header.Typeflag {
case tar.TypeBlock:
mode |= unix.S_IFBLK
Expand All @@ -20,7 +20,7 @@ func extractHandleSpecialNode(path string, header *tar.Header) error {
mode |= unix.S_IFIFO
}

return unix.Mknod(path, mode, int(unix.Mkdev(uint32(header.Devmajor), uint32(header.Devminor))))
return unix.Mknod(path, mode, int(unix.Mkdev(uint32(header.Devmajor), uint32(header.Devminor)))) //nolint: gosec
}

func extractChtimes(path string, atime, mtime time.Time) error {
Expand Down
13 changes: 5 additions & 8 deletions cmd/rofl/build/build.go
Original file line number Diff line number Diff line change
Expand Up @@ -157,7 +157,7 @@ var (

buildEnclaves := make(map[sgx.EnclaveIdentity]struct{})
for _, eid := range eids {
buildEnclaves[*eid] = struct{}{}
buildEnclaves[eid] = struct{}{}
}

manifestEnclaves := make(map[sgx.EnclaveIdentity]struct{})
Expand Down Expand Up @@ -246,10 +246,7 @@ var (
fmt.Println("Next time you can also use the --update-manifest flag to apply changes.")
case true:
// Update the manifest with the given enclave identities, overwriting existing ones.
deployment.Policy.Enclaves = make([]sgx.EnclaveIdentity, 0, len(eids))
for _, eid := range eids {
deployment.Policy.Enclaves = append(deployment.Policy.Enclaves, *eid)
}
deployment.Policy.Enclaves = eids

if err = manifest.Save(); err != nil {
cobra.CheckErr(fmt.Errorf("failed to update manifest: %w", err))
Expand Down Expand Up @@ -301,7 +298,7 @@ func fetchTrustRoot(npa *common.NPASelection, cfg *buildRofl.TrustRootConfig) (s
}
default:
// Use configured height.
height = int64(cfg.Height)
height = int64(cfg.Height) //nolint: gosec
}

blk, err := conn.Consensus().GetBlock(ctx, height)
Expand All @@ -311,7 +308,7 @@ func fetchTrustRoot(npa *common.NPASelection, cfg *buildRofl.TrustRootConfig) (s
hash = blk.Hash.Hex()
default:
// Hash is known, just use it.
height = int64(cfg.Height)
height = int64(cfg.Height) //nolint: gosec
hash = cfg.Hash
}

Expand All @@ -323,7 +320,7 @@ func fetchTrustRoot(npa *common.NPASelection, cfg *buildRofl.TrustRootConfig) (s
ChainContext string `json:"chain_context"`
}
root := trustRoot{
Height: uint64(height),
Height: uint64(height), //nolint: gosec
Hash: hash,
RuntimeID: npa.ParaTime.Namespace(),
ChainContext: npa.Network.ChainContext,
Expand Down
10 changes: 7 additions & 3 deletions cmd/rofl/build/tdx.go
Original file line number Diff line number Diff line change
Expand Up @@ -231,11 +231,11 @@ func tdxBundleComponent(

// Add some sparse padding to allow for growth of the root partition during upgrades.
// Note that this will not actually take any space so it could be arbitrarily large.
if err := padWithEmptySpace(stage2.fn, 256*1024*1024); err != nil {
if err := padWithEmptySpace(stage2.fn, 2*1024*1024*1024); err != nil {
return err
}

// TODO: (Oasis Core 25.0+) Set comp.TDX.Stage2Persist = true
comp.TDX.Stage2Persist = true
case buildRofl.StorageKindDiskEphemeral:
// Ephemeral storage can be set up by stage 1 directly.
storageMode = "disk"
Expand All @@ -258,7 +258,11 @@ func tdxBundleComponent(
return fmt.Errorf("unsupported storage mode: %s", storageKind)
}

// TODO: (Oasis Core 25.0+) Use qcow2 image format to support sparse files.
// Use qcow2 image format to support sparse files.
if err := convertToQcow2(stage2.fn); err != nil {
return fmt.Errorf("failed to convert to qcow2 image: %w", err)
}
comp.TDX.Stage2Format = "qcow2"

// Add extra kernel options.
comp.TDX.ExtraKernelOptions = append(comp.TDX.ExtraKernelOptions, extraKernelOpts...)
Expand Down
9 changes: 2 additions & 7 deletions cmd/rofl/common/identity.go
Original file line number Diff line number Diff line change
Expand Up @@ -12,7 +12,7 @@ import (

// ComputeEnclaveIdentity computes the enclave identity of the given ROFL components. If no specific
// component ID is passed, it uses the first ROFL component.
func ComputeEnclaveIdentity(bnd *bundle.Bundle, compID string) ([]*sgx.EnclaveIdentity, error) {
func ComputeEnclaveIdentity(bnd *bundle.Bundle, compID string) ([]sgx.EnclaveIdentity, error) {
var cid component.ID
if compID != "" {
if err := cid.UnmarshalText([]byte(compID)); err != nil {
Expand All @@ -35,12 +35,7 @@ func ComputeEnclaveIdentity(bnd *bundle.Bundle, compID string) ([]*sgx.EnclaveId

switch teeKind := comp.TEEKind(); teeKind {
case component.TEEKindSGX:
var enclaveID *sgx.EnclaveIdentity
enclaveID, err := bnd.EnclaveIdentity(comp.ID())
if err != nil {
return nil, err
}
return []*sgx.EnclaveIdentity{enclaveID}, nil
return bnd.EnclaveIdentities(comp.ID())
case component.TEEKindTDX:
return measurement.MeasureTdxQemu(bnd, comp)
default:
Expand Down
Loading
Loading