mirror of
https://github.com/kata-containers/kata-containers.git
synced 2026-07-01 22:50:54 +00:00
Merge pull request #12436 from mythi/tdx-updates-2026-3
runtime(-rs): tdx: use TDX QGS via unix-domain-socket by default
This commit is contained in:
@@ -214,7 +214,7 @@ DEFVFIOMODE := guest-kernel
|
||||
DEFBINDMOUNTS := []
|
||||
DEFDANCONF := /run/kata-containers/dans
|
||||
DEFFORCEGUESTPULL := false
|
||||
QEMUTDXQUOTEGENERATIONSERVICESOCKETPORT := 4050
|
||||
QEMUTDXQUOTEGENERATIONSERVICESOCKETPORT := 0
|
||||
|
||||
# Create Container Timeout in seconds
|
||||
DEFCREATECONTAINERTIMEOUT ?= 30
|
||||
|
||||
@@ -433,6 +433,7 @@ guest_hook_path = ""
|
||||
# It's important to note that setting "tdx_quote_generation_service_socket_port" to 0 enables communication via Unix Domain Sockets (UDS).
|
||||
# To activate UDS, the QGS service itself must be launched with the "-port=0" parameter and the UDS will always be located at /var/run/tdx-qgs/qgs.socket.
|
||||
# -object '{"qom-type":"tdx-guest","id":"tdx","quote-generation-socket":{"type":"unix","path":"/var/run/tdx-qgs/qgs.socket"}}'
|
||||
# If port is set to 0 but /var/run/tdx-qgs/qgs.socket does not exist on the host, Kata will automatically fall back to vsock port 4050 for backwards compatibility.
|
||||
tdx_quote_generation_service_socket_port = @QEMUTDXQUOTEGENERATIONSERVICESOCKETPORT@
|
||||
|
||||
#
|
||||
|
||||
@@ -18,6 +18,8 @@ kernel = "@KERNELPATH_COCO@"
|
||||
image = "@IMAGECONFIDENTIALPATH@"
|
||||
# initrd = "@INITRDPATH@"
|
||||
machine_type = "@MACHINETYPE@"
|
||||
# Set to 0 to use Unix Domain Socket (/var/run/tdx-qgs/qgs.socket) instead of vsock.
|
||||
# If port is 0 but the socket does not exist, Kata falls back to vsock port 4050.
|
||||
tdx_quote_generation_service_socket_port = @QEMUTDXQUOTEGENERATIONSERVICESOCKETPORT@
|
||||
|
||||
# rootfs filesystem type:
|
||||
|
||||
@@ -334,20 +334,51 @@ pub struct SocketAddress {
|
||||
|
||||
impl SocketAddress {
|
||||
pub fn new(port: u32) -> Self {
|
||||
Self::new_with_socket_path(port, QGS_SOCKET_PATH)
|
||||
}
|
||||
|
||||
fn new_with_socket_path(port: u32, socket_path: &str) -> Self {
|
||||
if port == 0 {
|
||||
Self {
|
||||
typ: "unix".to_string(),
|
||||
cid: "".to_string(),
|
||||
port: "".to_string(),
|
||||
path: QGS_SOCKET_PATH.to_string(),
|
||||
match std::fs::metadata(socket_path) {
|
||||
Ok(_) => {
|
||||
return Self {
|
||||
typ: "unix".to_string(),
|
||||
cid: "".to_string(),
|
||||
port: "".to_string(),
|
||||
path: socket_path.to_string(),
|
||||
};
|
||||
}
|
||||
Err(e) if e.kind() == std::io::ErrorKind::NotFound => {
|
||||
// Socket not present; fall back to vsock for backwards compatibility.
|
||||
warn!(
|
||||
sl!(),
|
||||
"QGS socket {} not found, falling back to vsock port 4050", socket_path
|
||||
);
|
||||
}
|
||||
Err(e) => {
|
||||
// Unexpected error (e.g. permission denied) — log it so misconfiguration
|
||||
// is not silently masked, then fall back to vsock.
|
||||
warn!(
|
||||
sl!(),
|
||||
"QGS socket {} inaccessible ({}), falling back to vsock port 4050",
|
||||
socket_path,
|
||||
e
|
||||
);
|
||||
}
|
||||
}
|
||||
} else {
|
||||
Self {
|
||||
return Self {
|
||||
typ: "vsock".to_string(),
|
||||
cid: format!("{}", 2),
|
||||
port: port.to_string(),
|
||||
port: "4050".to_string(),
|
||||
path: "".to_string(),
|
||||
}
|
||||
};
|
||||
}
|
||||
|
||||
Self {
|
||||
typ: "vsock".to_string(),
|
||||
cid: format!("{}", 2),
|
||||
port: port.to_string(),
|
||||
path: "".to_string(),
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -462,9 +493,20 @@ mod tests {
|
||||
|
||||
#[test]
|
||||
fn test_unix_address_new() {
|
||||
let socket = SocketAddress::new(0);
|
||||
let dir = TempDir::new().unwrap();
|
||||
let sock = dir.path().join("qgs.socket");
|
||||
std::fs::File::create(&sock).unwrap();
|
||||
|
||||
// Socket present: must return unix type
|
||||
let socket = SocketAddress::new_with_socket_path(0, sock.to_str().unwrap());
|
||||
assert_eq!(socket.typ, "unix");
|
||||
assert_eq!(socket.path, "/var/run/tdx-qgs/qgs.socket");
|
||||
assert_eq!(socket.path, sock.to_str().unwrap());
|
||||
|
||||
// Socket absent: must fall back to vsock port 4050
|
||||
let socket = SocketAddress::new_with_socket_path(0, "/nonexistent/qgs.socket");
|
||||
assert_eq!(socket.typ, "vsock");
|
||||
assert_eq!(socket.cid, "2");
|
||||
assert_eq!(socket.port, "4050");
|
||||
}
|
||||
|
||||
#[test]
|
||||
@@ -476,9 +518,21 @@ mod tests {
|
||||
|
||||
#[test]
|
||||
fn test_socket_address_serialize_deserialize() {
|
||||
let socket = SocketAddress::new(0);
|
||||
let dir = TempDir::new().unwrap();
|
||||
let sock = dir.path().join("qgs.socket");
|
||||
std::fs::File::create(&sock).unwrap();
|
||||
let sock_str = sock.to_str().unwrap();
|
||||
|
||||
// Socket present: unix type
|
||||
let socket = SocketAddress::new_with_socket_path(0, sock_str);
|
||||
let serialized = serde_json::to_string(&socket).unwrap();
|
||||
let expected_json = r#"{"type":"unix","path":"/var/run/tdx-qgs/qgs.socket"}"#;
|
||||
let expected_json = format!(r#"{{"type":"unix","path":"{sock_str}"}}"#);
|
||||
assert_eq!(expected_json, serialized);
|
||||
|
||||
// Socket absent: vsock fallback
|
||||
let socket = SocketAddress::new_with_socket_path(0, "/nonexistent/qgs.socket");
|
||||
let serialized = serde_json::to_string(&socket).unwrap();
|
||||
let expected_json = r#"{"type":"vsock","cid":"2","port":"4050"}"#;
|
||||
assert_eq!(expected_json, serialized);
|
||||
}
|
||||
|
||||
|
||||
@@ -186,7 +186,7 @@ QEMUTDXEXPERIMENTALVALIDHYPERVISORPATHS := [\"$(QEMUTDXEXPERIMENTALPATH)\"]
|
||||
QEMUCCAEXPERIMENTALPATH := $(QEMUBINDIR)/$(QEMUCCAEXPERIMENTALCMD)
|
||||
QEMUCCAEXPERIMENTALVALIDHYPERVISORPATHS := [\"$(QEMUCCAEXPERIMENTALPATH)\"]
|
||||
|
||||
QEMUTDXQUOTEGENERATIONSERVICESOCKETPORT := 4050
|
||||
QEMUTDXQUOTEGENERATIONSERVICESOCKETPORT := 0
|
||||
|
||||
QEMUSNPPATH := $(QEMUBINDIR)/$(QEMUSNPCMD)
|
||||
QEMUSNPVALIDHYPERVISORPATHS := [\"$(QEMUSNPPATH)\"]
|
||||
|
||||
@@ -46,10 +46,12 @@ 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"
|
||||
)
|
||||
|
||||
// qgsSocketPath is the Unix Domain Socket path served by the Intel TDX Quote
|
||||
// Generation Service. Declared as a var so tests can override it.
|
||||
var qgsSocketPath = "/var/run/tdx-qgs/qgs.socket"
|
||||
|
||||
// hasPCIeRoot reports whether the configured QEMU machine type exposes a
|
||||
// `pcie.0` root complex (q35 on x86, virt on arm64). Machines such as
|
||||
// pseries (ppc64le -> pci.0), s390-ccw-virtio (s390x -> CCW transport)
|
||||
@@ -538,7 +540,13 @@ func (t *TdxQomObject) String() string {
|
||||
|
||||
func getQgsSocketAddress(portNum uint32) SocketAddress {
|
||||
if portNum == 0 {
|
||||
return SocketAddress{Type: "unix", Path: qgsSocketPath}
|
||||
// Check if the Unix socket exists
|
||||
if _, err := os.Stat(qgsSocketPath); err == nil {
|
||||
return SocketAddress{Type: "unix", Path: qgsSocketPath}
|
||||
}
|
||||
// Fall back to port 4050 with vsock for backwards compatibility
|
||||
log.Printf("Warning: QGS socket %s not found, falling back to vsock port 4050", qgsSocketPath)
|
||||
return SocketAddress{Type: "vsock", Cid: fmt.Sprint(VsockHostCid), Port: "4050"}
|
||||
}
|
||||
|
||||
return SocketAddress{Type: "vsock", Cid: fmt.Sprint(VsockHostCid), Port: fmt.Sprint(portNum)}
|
||||
|
||||
@@ -139,10 +139,23 @@ func TestAppendDeviceNVDIMM(t *testing.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) {
|
||||
// Create a temp socket file so the unix path is always exercised.
|
||||
dir := t.TempDir()
|
||||
origPath := qgsSocketPath
|
||||
qgsSocketPath = dir + "/qgs.socket"
|
||||
defer func() { qgsSocketPath = origPath }()
|
||||
|
||||
f, err := os.Create(qgsSocketPath)
|
||||
if err != nil {
|
||||
t.Fatalf("failed to create temp socket file: %v", err)
|
||||
}
|
||||
f.Close()
|
||||
|
||||
tdxObjectUnix := fmt.Sprintf(`-object {"qom-type":"tdx-guest","id":"tdx","quote-generation-socket":{"type":"unix","path":"%s"}}`, qgsSocketPath)
|
||||
|
||||
object := Object{
|
||||
Type: TDXGuest,
|
||||
ID: "tdx",
|
||||
@@ -151,10 +164,15 @@ func TestTdxQuoteSocket(t *testing.T) {
|
||||
QgsPort: 0,
|
||||
}
|
||||
|
||||
// port=0 with socket present: use Unix socket
|
||||
testAppend(object, tdxObjectUnix, t)
|
||||
|
||||
object.QgsPort = 4050
|
||||
// port=0 without socket present: fall back to vsock port 4050
|
||||
qgsSocketPath = dir + "/missing.socket"
|
||||
testAppend(object, tdxObjectVsock, t)
|
||||
|
||||
// Explicit vsock port
|
||||
object.QgsPort = 4050
|
||||
testAppend(object, tdxObjectVsock, t)
|
||||
}
|
||||
|
||||
|
||||
Reference in New Issue
Block a user