From 56d47e84a1a12a1a1ef8ec00c239fae182101a08 Mon Sep 17 00:00:00 2001 From: Dionna Glaze Date: Sun, 19 Mar 2023 02:15:19 +0000 Subject: [PATCH] Add a workaround to Linux 6.1's sev-guest lockout The IV reuse fix 47894e0fa6a5 works against the host's throttling by making the sev-guest device useless when throttled. The x86/urgent fix 72f7754dcf31 that merged to tip on March 16 still hasn't made it to some distros, so this workaround is still needed temporarily. Issue #40 is to revert this change at the appropriate time. The same fix for #40 includes the fix for #5. Signed-off-by: Dionna Glaze --- client/client_linux.go | 26 +++++++++++++++++++++++--- 1 file changed, 23 insertions(+), 3 deletions(-) diff --git a/client/client_linux.go b/client/client_linux.go index 54ac5fd..1853e8c 100644 --- a/client/client_linux.go +++ b/client/client_linux.go @@ -19,17 +19,24 @@ package client import ( "fmt" + "time" labi "github.com/google/go-sev-guest/client/linuxabi" "golang.org/x/sys/unix" ) -// defaultSevGuestDevicePath is the platform's usual device path to the SEV guest. -const defaultSevGuestDevicePath = "/dev/sev-guest" +const ( + // defaultSevGuestDevicePath is the platform's usual device path to the SEV guest. + defaultSevGuestDevicePath = "/dev/sev-guest" + throttleDuration = 2 * time.Second + burstMax = 2 +) // LinuxDevice implements the Device interface with Linux ioctls. type LinuxDevice struct { - fd int + fd int + lastCmd time.Time + burst int } // Open opens the SEV-SNP guest device from a given path @@ -71,11 +78,24 @@ func (d *LinuxDevice) Close() error { // Ioctl sends a command with its wrapped request and response values to the Linux device. func (d *LinuxDevice) Ioctl(command uintptr, req any) (uintptr, error) { + // TODO(Issue #40): Remove the workaround to the ENOTTY lockout when throttled + // in Linux 6.1 by throttling ourselves first. + if d.burst == 0 { + sinceLast := time.Since(d.lastCmd) + // Self-throttle for tests without guest OS throttle detection + if sinceLast < throttleDuration { + time.Sleep(throttleDuration - sinceLast) + } + } switch sreq := req.(type) { case *labi.SnpUserGuestRequest: abi := sreq.ABI() result, _, errno := unix.Syscall(unix.SYS_IOCTL, uintptr(d.fd), command, uintptr(abi.Pointer())) abi.Finish(sreq) + d.burst = (d.burst + 1) % burstMax + if d.burst == 0 { + d.lastCmd = time.Now() + } // TODO(Issue #5): remove the work around for the kernel bug that writes // uninitialized memory back on non-EIO.