mirror of
https://gitlab.com/libvirt/libvirt.git
synced 2025-02-08 12:41:29 +00:00
qemu: Implement the virDomainSetLaunchSecurityState API
Set a launch secret in guest memory using the sev-inject-launch-secret QMP API. Only supported with qemu >= 6.0.0 and SEV-enabled guests in a paused state. Signed-off-by: Jim Fehlig <jfehlig@suse.com> Reviewed-by: Daniel P. Berrangé <berrange@redhat.com>
This commit is contained in:
parent
a26d99c2b1
commit
00f324bc3c
@ -20083,6 +20083,105 @@ qemuDomainGetLaunchSecurityInfo(virDomainPtr domain,
|
|||||||
return ret;
|
return ret;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
static int
|
||||||
|
qemuDomainSetLaunchSecurityState(virDomainPtr domain,
|
||||||
|
virTypedParameterPtr params,
|
||||||
|
int nparams,
|
||||||
|
unsigned int flags)
|
||||||
|
{
|
||||||
|
virQEMUDriver *driver = domain->conn->privateData;
|
||||||
|
virDomainObj *vm;
|
||||||
|
int ret = -1;
|
||||||
|
int rc;
|
||||||
|
size_t i;
|
||||||
|
g_autoptr(virQEMUCaps) qemucaps = NULL;
|
||||||
|
g_autofree char *secrethdr = NULL;
|
||||||
|
g_autofree char *secret = NULL;
|
||||||
|
unsigned long long setaddr = 0;
|
||||||
|
bool hasSetaddr = false;
|
||||||
|
int state;
|
||||||
|
|
||||||
|
virCheckFlags(0, -1);
|
||||||
|
if (virTypedParamsValidate(params, nparams,
|
||||||
|
VIR_DOMAIN_LAUNCH_SECURITY_SEV_SECRET_HEADER,
|
||||||
|
VIR_TYPED_PARAM_STRING,
|
||||||
|
VIR_DOMAIN_LAUNCH_SECURITY_SEV_SECRET,
|
||||||
|
VIR_TYPED_PARAM_STRING,
|
||||||
|
VIR_DOMAIN_LAUNCH_SECURITY_SEV_SECRET_SET_ADDRESS,
|
||||||
|
VIR_TYPED_PARAM_ULLONG,
|
||||||
|
NULL) < 0)
|
||||||
|
return -1;
|
||||||
|
|
||||||
|
if (!(vm = qemuDomainObjFromDomain(domain)))
|
||||||
|
goto cleanup;
|
||||||
|
|
||||||
|
if (virDomainSetLaunchSecurityStateEnsureACL(domain->conn, vm->def) < 0)
|
||||||
|
goto cleanup;
|
||||||
|
|
||||||
|
/* Currently only SEV is supported */
|
||||||
|
if (!vm->def->sec ||
|
||||||
|
vm->def->sec->sectype != VIR_DOMAIN_LAUNCH_SECURITY_SEV) {
|
||||||
|
virReportError(VIR_ERR_OPERATION_UNSUPPORTED, "%s",
|
||||||
|
_("setting a launch secret is only supported in SEV-enabled domains"));
|
||||||
|
goto cleanup;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!(qemucaps = virQEMUCapsCacheLookupDefault(driver->qemuCapsCache,
|
||||||
|
NULL, NULL, NULL, NULL,
|
||||||
|
NULL, NULL, NULL)))
|
||||||
|
goto cleanup;
|
||||||
|
|
||||||
|
if (!virQEMUCapsGet(qemucaps, QEMU_CAPS_SEV_INJECT_LAUNCH_SECRET)) {
|
||||||
|
virReportError(VIR_ERR_OPERATION_UNSUPPORTED, "%s",
|
||||||
|
_("QEMU does not support setting a launch secret"));
|
||||||
|
goto cleanup;
|
||||||
|
}
|
||||||
|
|
||||||
|
for (i = 0; i < nparams; i++) {
|
||||||
|
virTypedParameterPtr param = ¶ms[i];
|
||||||
|
|
||||||
|
if (STREQ(param->field, VIR_DOMAIN_LAUNCH_SECURITY_SEV_SECRET_HEADER)) {
|
||||||
|
secrethdr = g_strdup(param->value.s);
|
||||||
|
} else if (STREQ(param->field, VIR_DOMAIN_LAUNCH_SECURITY_SEV_SECRET)) {
|
||||||
|
secret = g_strdup(param->value.s);
|
||||||
|
} else if (STREQ(param->field, VIR_DOMAIN_LAUNCH_SECURITY_SEV_SECRET_SET_ADDRESS)) {
|
||||||
|
setaddr = param->value.ul;
|
||||||
|
hasSetaddr = true;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if (qemuDomainObjBeginJob(driver, vm, QEMU_JOB_MODIFY) < 0)
|
||||||
|
goto cleanup;
|
||||||
|
|
||||||
|
if (virDomainObjCheckActive(vm) < 0)
|
||||||
|
goto endjob;
|
||||||
|
|
||||||
|
state = virDomainObjGetState(vm, NULL);
|
||||||
|
if (state != VIR_DOMAIN_PAUSED) {
|
||||||
|
virReportError(VIR_ERR_OPERATION_INVALID,
|
||||||
|
"%s", _("domain must be in a paused state"));
|
||||||
|
goto endjob;
|
||||||
|
}
|
||||||
|
|
||||||
|
qemuDomainObjEnterMonitor(driver, vm);
|
||||||
|
rc = qemuMonitorSetLaunchSecurityState(QEMU_DOMAIN_PRIVATE(vm)->mon,
|
||||||
|
secrethdr, secret, setaddr, hasSetaddr);
|
||||||
|
qemuDomainObjExitMonitor(driver, vm);
|
||||||
|
if (rc < 0)
|
||||||
|
goto endjob;
|
||||||
|
|
||||||
|
ret = 0;
|
||||||
|
|
||||||
|
endjob:
|
||||||
|
qemuDomainObjEndJob(driver, vm);
|
||||||
|
|
||||||
|
cleanup:
|
||||||
|
virDomainObjEndAPI(&vm);
|
||||||
|
return ret;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
static const unsigned int qemuDomainGetGuestInfoSupportedTypes =
|
static const unsigned int qemuDomainGetGuestInfoSupportedTypes =
|
||||||
VIR_DOMAIN_GUEST_INFO_USERS |
|
VIR_DOMAIN_GUEST_INFO_USERS |
|
||||||
VIR_DOMAIN_GUEST_INFO_OS |
|
VIR_DOMAIN_GUEST_INFO_OS |
|
||||||
@ -20956,6 +21055,7 @@ static virHypervisorDriver qemuHypervisorDriver = {
|
|||||||
.domainAuthorizedSSHKeysSet = qemuDomainAuthorizedSSHKeysSet, /* 6.10.0 */
|
.domainAuthorizedSSHKeysSet = qemuDomainAuthorizedSSHKeysSet, /* 6.10.0 */
|
||||||
.domainGetMessages = qemuDomainGetMessages, /* 7.1.0 */
|
.domainGetMessages = qemuDomainGetMessages, /* 7.1.0 */
|
||||||
.domainStartDirtyRateCalc = qemuDomainStartDirtyRateCalc, /* 7.2.0 */
|
.domainStartDirtyRateCalc = qemuDomainStartDirtyRateCalc, /* 7.2.0 */
|
||||||
|
.domainSetLaunchSecurityState = qemuDomainSetLaunchSecurityState, /* 8.0.0 */
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
||||||
|
@ -4379,6 +4379,20 @@ qemuMonitorGetSEVInfo(qemuMonitor *mon,
|
|||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
int
|
||||||
|
qemuMonitorSetLaunchSecurityState(qemuMonitor *mon,
|
||||||
|
const char *secrethdr,
|
||||||
|
const char *secret,
|
||||||
|
unsigned long long setaddr,
|
||||||
|
bool hasSetaddr)
|
||||||
|
{
|
||||||
|
QEMU_CHECK_MONITOR(mon);
|
||||||
|
|
||||||
|
return qemuMonitorJSONSetLaunchSecurityState(mon, secrethdr, secret,
|
||||||
|
setaddr, hasSetaddr);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
int
|
int
|
||||||
qemuMonitorGetPRManagerInfo(qemuMonitor *mon,
|
qemuMonitorGetPRManagerInfo(qemuMonitor *mon,
|
||||||
GHashTable **retinfo)
|
GHashTable **retinfo)
|
||||||
|
@ -1457,6 +1457,13 @@ qemuMonitorGetSEVInfo(qemuMonitor *mon,
|
|||||||
ATTRIBUTE_NONNULL(1) ATTRIBUTE_NONNULL(2) ATTRIBUTE_NONNULL(3)
|
ATTRIBUTE_NONNULL(1) ATTRIBUTE_NONNULL(2) ATTRIBUTE_NONNULL(3)
|
||||||
ATTRIBUTE_NONNULL(4) ATTRIBUTE_NONNULL(5);
|
ATTRIBUTE_NONNULL(4) ATTRIBUTE_NONNULL(5);
|
||||||
|
|
||||||
|
int
|
||||||
|
qemuMonitorSetLaunchSecurityState(qemuMonitor *mon,
|
||||||
|
const char *secrethdr,
|
||||||
|
const char *secret,
|
||||||
|
unsigned long long setaddr,
|
||||||
|
bool hasSetaddr);
|
||||||
|
|
||||||
typedef struct _qemuMonitorPRManagerInfo qemuMonitorPRManagerInfo;
|
typedef struct _qemuMonitorPRManagerInfo qemuMonitorPRManagerInfo;
|
||||||
struct _qemuMonitorPRManagerInfo {
|
struct _qemuMonitorPRManagerInfo {
|
||||||
bool connected;
|
bool connected;
|
||||||
|
@ -8266,6 +8266,51 @@ qemuMonitorJSONGetSEVInfo(qemuMonitor *mon,
|
|||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Set a launch secret in guest memory
|
||||||
|
*
|
||||||
|
* Example JSON:
|
||||||
|
*
|
||||||
|
* { "execute" : "sev-inject-launch-secret",
|
||||||
|
* "data": { "packet-header": "str", "secret": "str", "gpa": "uint64" } }
|
||||||
|
*
|
||||||
|
* The guest physical address (gpa) parameter is optional
|
||||||
|
*/
|
||||||
|
int
|
||||||
|
qemuMonitorJSONSetLaunchSecurityState(qemuMonitor *mon,
|
||||||
|
const char *secrethdr,
|
||||||
|
const char *secret,
|
||||||
|
unsigned long long setaddr,
|
||||||
|
bool hasSetaddr)
|
||||||
|
{
|
||||||
|
g_autoptr(virJSONValue) cmd = NULL;
|
||||||
|
g_autoptr(virJSONValue) reply = NULL;
|
||||||
|
|
||||||
|
if (hasSetaddr) {
|
||||||
|
cmd = qemuMonitorJSONMakeCommand("sev-inject-launch-secret",
|
||||||
|
"s:packet-header", secrethdr,
|
||||||
|
"s:secret", secret,
|
||||||
|
"U:gpa", setaddr,
|
||||||
|
NULL);
|
||||||
|
} else {
|
||||||
|
cmd = qemuMonitorJSONMakeCommand("sev-inject-launch-secret",
|
||||||
|
"s:packet-header", secrethdr,
|
||||||
|
"s:secret", secret,
|
||||||
|
NULL);
|
||||||
|
}
|
||||||
|
if (cmd == NULL)
|
||||||
|
return -1;
|
||||||
|
|
||||||
|
if (qemuMonitorJSONCommand(mon, cmd, &reply) < 0)
|
||||||
|
return -1;
|
||||||
|
|
||||||
|
if (qemuMonitorJSONCheckError(cmd, reply) < 0)
|
||||||
|
return -1;
|
||||||
|
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* Example return data
|
* Example return data
|
||||||
*
|
*
|
||||||
|
@ -476,6 +476,12 @@ qemuMonitorJSONGetVersion(qemuMonitor *mon,
|
|||||||
char **package)
|
char **package)
|
||||||
ATTRIBUTE_NONNULL(2) ATTRIBUTE_NONNULL(3) ATTRIBUTE_NONNULL(4);
|
ATTRIBUTE_NONNULL(2) ATTRIBUTE_NONNULL(3) ATTRIBUTE_NONNULL(4);
|
||||||
|
|
||||||
|
int qemuMonitorJSONSetLaunchSecurityState(qemuMonitor *mon,
|
||||||
|
const char *secrethdr,
|
||||||
|
const char *secret,
|
||||||
|
unsigned long long setaddr,
|
||||||
|
bool hasSetaddr);
|
||||||
|
|
||||||
int
|
int
|
||||||
qemuMonitorJSONGetMachines(qemuMonitor *mon,
|
qemuMonitorJSONGetMachines(qemuMonitor *mon,
|
||||||
qemuMonitorMachineInfo ***machines)
|
qemuMonitorMachineInfo ***machines)
|
||||||
|
@ -1196,6 +1196,8 @@ GEN_TEST_FUNC(qemuMonitorJSONSetAction,
|
|||||||
QEMU_MONITOR_ACTION_REBOOT_RESET,
|
QEMU_MONITOR_ACTION_REBOOT_RESET,
|
||||||
QEMU_MONITOR_ACTION_WATCHDOG_SHUTDOWN,
|
QEMU_MONITOR_ACTION_WATCHDOG_SHUTDOWN,
|
||||||
QEMU_MONITOR_ACTION_PANIC_SHUTDOWN)
|
QEMU_MONITOR_ACTION_PANIC_SHUTDOWN)
|
||||||
|
GEN_TEST_FUNC(qemuMonitorJSONSetLaunchSecurityState, "sev_secret_header",
|
||||||
|
"sev_secret", 0, true)
|
||||||
|
|
||||||
static int
|
static int
|
||||||
testQemuMonitorJSONqemuMonitorJSONNBDServerStart(const void *opaque)
|
testQemuMonitorJSONqemuMonitorJSONNBDServerStart(const void *opaque)
|
||||||
@ -3067,6 +3069,7 @@ mymain(void)
|
|||||||
DO_TEST_GEN(qemuMonitorJSONJobComplete);
|
DO_TEST_GEN(qemuMonitorJSONJobComplete);
|
||||||
DO_TEST_GEN(qemuMonitorJSONBlockJobCancel);
|
DO_TEST_GEN(qemuMonitorJSONBlockJobCancel);
|
||||||
DO_TEST_GEN(qemuMonitorJSONSetAction);
|
DO_TEST_GEN(qemuMonitorJSONSetAction);
|
||||||
|
DO_TEST_GEN(qemuMonitorJSONSetLaunchSecurityState);
|
||||||
DO_TEST(qemuMonitorJSONGetBalloonInfo);
|
DO_TEST(qemuMonitorJSONGetBalloonInfo);
|
||||||
DO_TEST(qemuMonitorJSONGetBlockInfo);
|
DO_TEST(qemuMonitorJSONGetBlockInfo);
|
||||||
DO_TEST(qemuMonitorJSONGetAllBlockStatsInfo);
|
DO_TEST(qemuMonitorJSONGetAllBlockStatsInfo);
|
||||||
|
Loading…
x
Reference in New Issue
Block a user