Skip to content

Commit

Permalink
pr feedback: internal/guest/linux package, Makefile, refactor
Browse files Browse the repository at this point in the history
Add new internal/guest/linux package, which for now includes linux specific
ioctl definitions and Ioctl call.

Refactor devicemapper to use the new package.

Update makefile to conditionally include snp-report binary in initrd

Signed-off-by: Maksim An <[email protected]>
  • Loading branch information
anmaxvl committed Apr 4, 2022
1 parent efa12ce commit 47a2fcf
Show file tree
Hide file tree
Showing 12 changed files with 102 additions and 96 deletions.
5 changes: 4 additions & 1 deletion Makefile
Original file line number Diff line number Diff line change
@@ -1,4 +1,5 @@
BASE:=base.tar.gz
INCLUDE_UTILITIES:=0

GO:=go
GO_FLAGS:=-ldflags "-s -w" # strip Go binaries
Expand Down Expand Up @@ -49,7 +50,9 @@ out/delta.tar.gz: bin/init bin/vsockexec bin/cmd/gcs bin/cmd/gcstools bin/cmd/ho
cp bin/cmd/gcs rootfs/bin/
cp bin/cmd/gcstools rootfs/bin/
cp bin/cmd/hooks/wait-paths rootfs/bin/
cp bin/internal/tools/snp-report rootfs/bin/
if [ $(INCLUDE_UTILITIES) -eq 1 ]; then \
cp bin/internal/tools/snp-report rootfs/bin/; \
fi
for tool in $(GCS_TOOLS); do ln -s gcstools rootfs/bin/$$tool; done
git -C $(SRCROOT) rev-parse HEAD > rootfs/gcs.commit && \
git -C $(SRCROOT) rev-parse --abbrev-ref HEAD > rootfs/gcs.branch
Expand Down
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
//go:build linux
// +build linux

package snp
package amdsev

import (
"bytes"
Expand Down
71 changes: 8 additions & 63 deletions internal/guest/snp/report.go → internal/guest/amdsev/report.go
Original file line number Diff line number Diff line change
@@ -1,9 +1,9 @@
//go:build linux
// +build linux

// package snp contains minimal functionality required to fetch
// Package amdsev contains minimal functionality required to fetch
// attestation reports inside an enlightened guest.
package snp
package amdsev

import (
"bytes"
Expand All @@ -13,7 +13,7 @@ import (
"os"
"unsafe"

"golang.org/x/sys/unix"
"github.com/Microsoft/hcsshim/internal/guest/linux"
)

const (
Expand Down Expand Up @@ -46,42 +46,18 @@ type SevSNPGuestRequest struct {
Error uint32
}

// Below is ported from Linux kernel code:
// https://github.com/torvalds/linux/blob/5bfc75d92efd494db37f5c4c173d3639d4772966/include/uapi/asm-generic/ioctl.h
// AMD SEV ioctl definitions
const (
iocNone = 0
iocWrite = 1
iocRead = 2
iocNRBits = 8
iocTypeBits = 8
iocSizeBits = 14
iocDirBits = 2

// bit shifts
iocNRShift = 0
iocTypeShift = iocNRBits
iocSizeShift = iocTypeShift + iocTypeBits
iocDirShift = iocSizeShift + iocSizeBits

// SEV-SNP IOCTL type
sevGuestType = 'S'
// SEV-SNP IOCTL size, same as unsafe.Sizeof(SevSNPGuestRequest{})
sevGuestSize = 40
sevGuestSize = 40
SevSnpIoctlBase = linux.IocWRBase | sevGuestType<<linux.IocTypeShift | sevGuestSize<<linux.IocSizeShift

// SEV-SNP requests
sevSNPReportCode = 0x1
)

// _IOC macros equivalent
func ioc(dir, t, nr, size int) int {
return dir<<iocDirShift | t<<iocTypeShift | nr<<iocNRShift | size<<iocSizeShift
}

// _IOCWR macros equivalent
func iocWR(t, nr, size int) int {
return ioc(iocRead|iocWrite, t, nr, size)
}

// msgReportRequest used to issue SEV-SNP request
// https://www.amd.com/system/files/TechDocs/56860.pdf
// MSG_REPORT_REQ Table 20.
Expand Down Expand Up @@ -166,15 +142,6 @@ type msgReportResponse struct {
reserved2 [64]byte // padding to the size of SEV_SNP_REPORT_RSP_BUF_SZ (i.e., 1280 bytes)
}

func snpIoctl(f *os.File, code int, payload *SevSNPGuestRequest) error {
sevSNPIOCBase := iocWR(sevGuestType, 0x0, sevGuestSize)
_, _, errno := unix.Syscall(unix.SYS_IOCTL, f.Fd(), uintptr(code|sevSNPIOCBase), uintptr(unsafe.Pointer(payload)))
if errno != 0 {
return fmt.Errorf("failed to make snp IOCTL: %s", errno)
}
return nil
}

// FetchRawSNPReport returns attestation report bytes.
func FetchRawSNPReport(reportData string) ([]byte, error) {
f, err := os.OpenFile("/dev/sev", os.O_RDWR, 0)
Expand All @@ -199,7 +166,7 @@ func FetchRawSNPReport(reportData string) ([]byte, error) {
copy(msgReportIn.ReportData[:], rd[:])
}

payload := SevSNPGuestRequest{
payload := &SevSNPGuestRequest{
RequestMsgType: MsgReportRequest,
ResponseMsgType: MsgReportResponse,
MsgVersion: 1,
Expand All @@ -210,7 +177,7 @@ func FetchRawSNPReport(reportData string) ([]byte, error) {
Error: 0,
}

if err := snpIoctl(f, sevSNPReportCode, &payload); err != nil {
if err := linux.Ioctl(f, sevSNPReportCode|SevSnpIoctlBase, uintptr(unsafe.Pointer(payload))); err != nil {
return nil, err
}
return msgReportOut.Report[:], nil
Expand Down Expand Up @@ -297,25 +264,3 @@ func FetchParsedSNPReport(reportData string) (Report, error) {
}
return report.report(), nil
}

// ValidateHostData fetches SNP report (if applicable) and validates `hostData` against
// HostData set at UVM launch.
func ValidateHostData(hostData, reportData string) error {
report, err := FetchParsedSNPReport(reportData)
if err != nil {
// For non-SNP hardware /dev/sev will not exist
if os.IsNotExist(err) {
return nil
}
return err
}

if report.HostData != hostData {
return fmt.Errorf(
"security policy digest %q doesn't match HostData provided at launch %q",
hostData,
report.HostData,
)
}
return nil
}
36 changes: 36 additions & 0 deletions internal/guest/linux/ioctl.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,36 @@
//go:build linux
// +build linux

package linux

import (
"os"

"golang.org/x/sys/unix"
)

const (
IocWrite = 1
IocRead = 2
IocNRBits = 8
IocTypeBits = 8
IocSizeBits = 14
IocDirBits = 2

IocNRMask = (1 << IocNRBits) - 1
IocTypeMask = (1 << IocTypeBits) - 1
IocSizeMask = (1 << IocSizeBits) - 1
IocDirMask = (1 << IocDirBits) - 1
IocTypeShift = IocNRBits
IocSizeShift = IocTypeShift + IocTypeBits
IocDirShift = IocSizeShift + IocSizeBits
IocWRBase = (IocRead | IocWrite) << IocDirShift
)

func Ioctl(f *os.File, code int, payloadPtr uintptr) error {
_, _, errno := unix.Syscall(unix.SYS_IOCTL, f.Fd(), uintptr(code), payloadPtr)
if errno != 0 {
return errno
}
return nil
}
33 changes: 33 additions & 0 deletions internal/guest/runtime/hcsv2/hostdata.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,33 @@
//go:build linux
// +build linux

package hcsv2

import (
"fmt"
"os"

"github.com/Microsoft/hcsshim/internal/guest/amdsev"
)

// ValidateHostData fetches SNP report (if applicable) and validates `hostData` against
// HostData set at UVM launch.
func ValidateHostData(hostData, reportData string) error {
report, err := amdsev.FetchParsedSNPReport(reportData)
if err != nil {
// For non-SNP hardware /dev/sev will not exist
if os.IsNotExist(err) {
return nil
}
return err
}

if report.HostData != hostData {
return fmt.Errorf(
"security policy digest %q doesn't match HostData provided at launch %q",
hostData,
report.HostData,
)
}
return nil
}
3 changes: 1 addition & 2 deletions internal/guest/runtime/hcsv2/uvm.go
Original file line number Diff line number Diff line change
Expand Up @@ -16,7 +16,6 @@ import (
"syscall"
"time"

"github.com/Microsoft/hcsshim/internal/guest/snp"
"github.com/mattn/go-shellwords"
"github.com/pkg/errors"

Expand Down Expand Up @@ -101,7 +100,7 @@ func (h *Host) SetSecurityPolicy(base64Policy string) error {
return err
}

if err := snp.ValidateHostData(hostData, ""); err != nil {
if err := ValidateHostData(hostData, ""); err != nil {
return err
}

Expand Down
23 changes: 4 additions & 19 deletions internal/guest/storage/devicemapper/devicemapper.go
Original file line number Diff line number Diff line change
Expand Up @@ -11,6 +11,7 @@ import (
"time"
"unsafe"

"github.com/Microsoft/hcsshim/internal/guest/linux"
"golang.org/x/sys/unix"
)

Expand All @@ -28,24 +29,9 @@ var (
)

const (
_IOC_WRITE = 1
_IOC_READ = 2
_IOC_NRBITS = 8
_IOC_TYPEBITS = 8
_IOC_SIZEBITS = 14
_IOC_DIRBITS = 2

_IOC_NRMASK = ((1 << _IOC_NRBITS) - 1)
_IOC_TYPEMASK = ((1 << _IOC_TYPEBITS) - 1)
_IOC_SIZEMASK = ((1 << _IOC_SIZEBITS) - 1)
_IOC_DIRMASK = ((1 << _IOC_DIRBITS) - 1)
_IOC_TYPESHIFT = (_IOC_NRBITS)
_IOC_SIZESHIFT = (_IOC_TYPESHIFT + _IOC_TYPEBITS)
_IOC_DIRSHIFT = (_IOC_SIZESHIFT + _IOC_SIZEBITS)

_DM_IOCTL = 0xfd
_DM_IOCTL_SIZE = 312
_DM_IOCTL_BASE = (_IOC_READ|_IOC_WRITE)<<_IOC_DIRSHIFT | _DM_IOCTL<<_IOC_TYPESHIFT | _DM_IOCTL_SIZE<<_IOC_SIZESHIFT
_DM_IOCTL_BASE = linux.IocWRBase | _DM_IOCTL<<linux.IocTypeShift | _DM_IOCTL_SIZE<<linux.IocSizeShift

_DM_READONLY_FLAG = 1 << 0
_DM_SUSPEND_FLAG = 1 << 1
Expand Down Expand Up @@ -134,9 +120,8 @@ func (err *dmError) Error() string {

// ioctl issues the specified device-mapper ioctl
func ioctl(f *os.File, code int, data *dmIoctl) error {
_, _, errno := unix.Syscall(unix.SYS_IOCTL, f.Fd(), uintptr(code|_DM_IOCTL_BASE), uintptr(unsafe.Pointer(data)))
if errno != 0 {
return &dmError{Op: code, Err: errno}
if err := linux.Ioctl(f, code|_DM_IOCTL_BASE, uintptr(unsafe.Pointer(data))); err != nil {
return &dmError{Op: code, Err: err}
}
return nil
}
Expand Down
10 changes: 5 additions & 5 deletions internal/tools/snp-report/main.go
Original file line number Diff line number Diff line change
Expand Up @@ -8,7 +8,7 @@ import (
"fmt"
"os"

"github.com/Microsoft/hcsshim/internal/guest/snp"
"github.com/Microsoft/hcsshim/internal/guest/amdsev"
)

func main() {
Expand Down Expand Up @@ -41,7 +41,7 @@ func main() {
flag.Parse()

if *binaryFmtFlag {
binaryReport, err := snp.FetchRawSNPReport(*reportDataFlag)
binaryReport, err := amdsev.FetchRawSNPReport(*reportDataFlag)
if err != nil {
fmt.Println(err)
os.Exit(1)
Expand All @@ -50,12 +50,12 @@ func main() {
os.Exit(0)
}

var report snp.Report
var report amdsev.Report
var err error
if *fakeReportFlag {
report, err = snp.FetchFakeSNPReport(*hostDataFlag)
report, err = amdsev.FetchFakeSNPReport(*hostDataFlag)
} else {
report, err = snp.FetchParsedSNPReport(*reportDataFlag)
report, err = amdsev.FetchParsedSNPReport(*reportDataFlag)
}
if err != nil {
fmt.Printf("failed to fetch SNP report: %s", err)
Expand Down
Binary file added internal/tools/snp-report/snp-report
Binary file not shown.
5 changes: 3 additions & 2 deletions pkg/securitypolicy/securitypolicy.go
Original file line number Diff line number Diff line change
Expand Up @@ -88,8 +88,9 @@ func NewOpenDoorPolicy() *SecurityPolicy {
}
}

// NewSecurityPolicyDigest converts base64policy string into JSON and computes
// sha256-digest on the JSON string.
// NewSecurityPolicyDigest decodes base64 encoded policy string, computes
// sha256 digest on the resulting byte slice and returns it as a base64 encoded
// string.
func NewSecurityPolicyDigest(base64policy string) (string, error) {
jsonPolicy, err := base64.StdEncoding.DecodeString(base64policy)
if err != nil {
Expand Down
5 changes: 4 additions & 1 deletion test/vendor/github.com/Microsoft/hcsshim/Makefile

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

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

0 comments on commit 47a2fcf

Please sign in to comment.