runtime: qemu: add support to use TDX QGS via Unix Domain Sockets

TDX Quote Generation Service (QGS) signs TDREPORT sent to it from
Qemu (GetQuote hypercall). Qemu needs quote-generation-socket
address configured for IPC.

Currently, Kata govmm only enables vsock based IPC for QGS but
QGS supports Unix Domain Sockets too which works well for host
process to process IPC (Qemu <-> QGS).

The QGS configuration to enable UDS is to run the service with "-port=0"
parameter. The same works well here too: setting
"tdx_quote_generation_service_socket_port=0" let's users to enable
UDS based IPC.

The socket path is fixed in QGS and cannot be configured: when "-port=0"
is used, the socket appears in /var/run/tdx-qgs/qgs.socket.

Signed-off-by: Mikko Ylinen <mikko.ylinen@intel.com>
This commit is contained in:
Mikko Ylinen 2025-03-20 14:11:15 +02:00
parent 7a704453b6
commit 85f3391bcf
2 changed files with 37 additions and 5 deletions

View File

@ -45,6 +45,8 @@ type Machine struct {
const (
// MachineTypeMicrovm is the QEMU microvm machine type for amd64
MachineTypeMicrovm string = "microvm"
// (fixed) Unix Domain Socket Path served by Intel TDX Quote Generation Service
qgsSocketPath string = "/var/run/tdx-qgs/qgs.socket"
)
const (
@ -316,7 +318,7 @@ type Object struct {
// Prealloc enables memory preallocation
Prealloc bool
// QgsPort defines Intel Quote Generation Service port exposed from the host
// QgsPort defines Intel TDX Quote Generation Service port configuration
QgsPort uint32
// SnpIdBlock is the 96-byte, base64-encoded blob to provide the ID Block structure
@ -336,7 +338,7 @@ func (object Object) Valid() bool {
case MemoryBackendEPC:
return object.ID != "" && object.Size != 0
case TDXGuest:
return object.ID != "" && object.File != "" && object.DeviceID != "" && object.QgsPort != 0
return object.ID != "" && object.File != "" && object.DeviceID != ""
case SEVGuest:
fallthrough
case SNPGuest:
@ -436,8 +438,9 @@ func (object Object) QemuParams(config *Config) []string {
type SocketAddress struct {
Type string `json:"type"`
Cid string `json:"cid"`
Port string `json:"port"`
Cid string `json:"cid,omitempty"`
Port string `json:"port,omitempty"`
Path string `json:"path,omitempty"`
}
type TdxQomObject struct {
@ -472,8 +475,16 @@ func (this *TdxQomObject) String() string {
return string(b)
}
func getQgsSocketAddress(portNum uint32) SocketAddress {
if portNum == 0 {
return SocketAddress{Type: "unix", Path: qgsSocketPath}
}
return SocketAddress{Type: "vsock", Cid: fmt.Sprint(VsockHostCid), Port: fmt.Sprint(portNum)}
}
func prepareTDXObject(object Object) string {
qgsSocket := SocketAddress{"vsock", fmt.Sprint(VsockHostCid), fmt.Sprint(object.QgsPort)}
qgsSocket := getQgsSocketAddress(object.QgsPort)
tdxObject := TdxQomObject{
string(object.Type), // qom-type
object.ID, // id

View File

@ -127,6 +127,27 @@ func TestAppendDeviceNVDIMM(t *testing.T) {
testAppend(object, deviceNVDIMMString, t)
}
var (
tdxObjectVsock = `-object {"qom-type":"tdx-guest","id":"tdx","quote-generation-socket":{"type":"vsock","cid":"2","port":"4050"}}`
tdxObjectUnix = `-object {"qom-type":"tdx-guest","id":"tdx","quote-generation-socket":{"type":"unix","path":"/var/run/tdx-qgs/qgs.socket"}}`
)
func TestTdxQuoteSocket(t *testing.T) {
object := Object{
Type: TDXGuest,
ID: "tdx",
File: "unused",
DeviceID: "unused",
QgsPort: 0,
}
testAppend(object, tdxObjectUnix, t)
object.QgsPort = 4050
testAppend(object, tdxObjectVsock, t)
}
var objectEPCString = "-object memory-backend-epc,id=epc0,size=65536,prealloc=on"
func TestAppendEPCObject(t *testing.T) {