genprotimg: introduce new tool for the creation of PV images

Protected VMs (PVM) are KVM VMs, where KVM can't access the VM's state
like guest memory and guest registers anymore. Instead the PVMs are
mostly managed by a new entity called Ultravisor (UV), which provides
an API, so KVM and the PV can request management actions.

PVMs are encrypted at rest and protected from hypervisor access while
running. They switch from a normal operation into protected mode, so
we can still use the standard boot process to load an encrypted image
and then move it into protected mode.

This commit adds the tool 'genprotimg'. It takes a kernel, key files,
optionally an initrd, optionally a file with the kernel command line,
and it generates a single, loadable image file. The image consists of
a concatenation of a plain text boot loader, the encrypted components
for kernel, initrd, and cmdline, and the integrity-protected PV
header, containing metadata necessary for running the guest in PV
mode.

It's possible to use this image file as a kernel for zipl or for a
direct kernel boot using QEMU.

Reviewed-by: Bjoern Walk <bwalk@linux.ibm.com>
Acked-by: Patrick Steuer <patrick.steuer@de.ibm.com>
Reviewed-by: Claudio Imbrenda <imbrenda@linux.ibm.com>
Reviewed-by: Jan Höppner <hoeppner@linux.ibm.com>
Signed-off-by: Marc Hartmayer <mhartmay@linux.ibm.com>
Signed-off-by: Jan Höppner <hoeppner@linux.ibm.com>
This commit is contained in:
Marc Hartmayer
2020-03-02 13:17:01 +01:00
committed by Jan Höppner
parent 2c106425e8
commit 65b9fc442c
38 changed files with 4965 additions and 2 deletions

View File

@@ -0,0 +1,69 @@
/*
* Buffer functions
*
* Copyright IBM Corp. 2020
*
* s390-tools is free software; you can redistribute it and/or modify
* it under the terms of the MIT license. See LICENSE for details.
*/
#include <errno.h>
#include <glib.h>
#include <stdio.h>
#include <string.h>
#include "align.h"
#include "buffer.h"
#include "common.h"
#include "file_utils.h"
Buffer *buffer_alloc(gsize size)
{
Buffer *ret = g_new0(Buffer, 1);
ret->data = g_malloc0(size);
ret->size = size;
return ret;
}
Buffer *buffer_dup(const Buffer *buf, gboolean page_aligned)
{
Buffer *ret;
gsize size;
if (!buf)
return NULL;
size = buf->size;
if (page_aligned)
size = PAGE_ALIGN(size);
ret = buffer_alloc(size);
/* content will be 0-right-padded */
memcpy(ret->data, buf->data, buf->size);
return ret;
}
gint buffer_write(const Buffer *buf, FILE *file, GError **err)
{
return file_write(file, buf->data, buf->size, 1, NULL, err);
}
void buffer_free(Buffer *buf)
{
if (!buf)
return;
g_free(buf->data);
g_free(buf);
}
void buffer_clear(Buffer **buf)
{
if (!buf || !*buf)
return;
buffer_free(*buf);
*buf = NULL;
}