diff options
Diffstat (limited to 'import-layers/yocto-poky/meta/recipes-devtools/qemu')
20 files changed, 435 insertions, 2786 deletions
diff --git a/import-layers/yocto-poky/meta/recipes-devtools/qemu/nativesdk-qemu-helper_1.0.bb b/import-layers/yocto-poky/meta/recipes-devtools/qemu/nativesdk-qemu-helper_1.0.bb index 943ca5f89..cdc2f51c2 100644 --- a/import-layers/yocto-poky/meta/recipes-devtools/qemu/nativesdk-qemu-helper_1.0.bb +++ b/import-layers/yocto-poky/meta/recipes-devtools/qemu/nativesdk-qemu-helper_1.0.bb @@ -1,7 +1,7 @@ SUMMARY = "Qemu helper scripts" LICENSE = "GPLv2" -RDEPENDS_${PN} = "nativesdk-qemu nativesdk-python3-subprocess \ - nativesdk-python3-shell nativesdk-python3-fcntl \ +RDEPENDS_${PN} = "nativesdk-qemu \ + nativesdk-python3-shell nativesdk-python3-fcntl nativesdk-python3-logging \ " PR = "r9" diff --git a/import-layers/yocto-poky/meta/recipes-devtools/qemu/qemu.inc b/import-layers/yocto-poky/meta/recipes-devtools/qemu/qemu.inc index 2a1d14b31..dc73df813 100644 --- a/import-layers/yocto-poky/meta/recipes-devtools/qemu/qemu.inc +++ b/import-layers/yocto-poky/meta/recipes-devtools/qemu/qemu.inc @@ -28,7 +28,7 @@ EXTRA_OECONF = " \ --target-list=${@get_qemu_target_list(d)} \ --extra-cflags='${CFLAGS}' \ " -EXTRA_OECONF_append_class-native = " --python=${USRBINPATH}/python2.7" +EXTRA_OECONF_append_class-native = " --python=python2.7" EXTRA_OEMAKE_append_class-native = " LD='${LD}' AR='${AR}' OBJCOPY='${OBJCOPY}' LDFLAGS='${LDFLAGS}'" diff --git a/import-layers/yocto-poky/meta/recipes-devtools/qemu/qemu/0001-Provide-support-for-the-CUSE-TPM.patch b/import-layers/yocto-poky/meta/recipes-devtools/qemu/qemu/0001-Provide-support-for-the-CUSE-TPM.patch deleted file mode 100644 index 74dc6f5df..000000000 --- a/import-layers/yocto-poky/meta/recipes-devtools/qemu/qemu/0001-Provide-support-for-the-CUSE-TPM.patch +++ /dev/null @@ -1,870 +0,0 @@ -From 8737eef18f39ed087fd911d0a0886e8174d0468c Mon Sep 17 00:00:00 2001 -From: Stefan Berger <stefanb@linux.vnet.ibm.com> -Date: Sat, 31 Dec 2016 11:23:32 -0500 -Subject: [PATCH 1/4] Provide support for the CUSE TPM - -Rather than integrating TPM functionality into QEMU directly -using the TPM emulation of libtpms, we now integrate an external -emulated TPM device. This device is expected to implement a Linux -CUSE interface (CUSE = character device in userspace). - -QEMU talks to the CUSE TPM using much functionality of the -passthrough driver. For example, the TPM commands and responses -are sent to the CUSE TPM using the read()/write() interface. -However, some out-of-band control needs to be done using the CUSE -TPM's ioctls. The CUSE TPM currently defines and implements 15 -different ioctls for controlling certain life-cycle aspects of -the emulated TPM. The ioctls can be regarded as a replacement for -direct function calls to a TPM emulator if the TPM were to be -directly integrated into QEMU. - -One of the ioctls allows to get a bitmask of supported capabilities. -Each returned bit indicates which capabilities have been implemented. -An include file defining the various ioctls is added to QEMU. - -The CUSE TPM and associated tools can be found here: - -https://github.com/stefanberger/swtpm - -(please use the latest version) - -To use the external CUSE TPM, the CUSE TPM should be started as follows: - -/usr/bin/swtpm_ioctl -s /dev/vtpm-test - -/usr/bin/swtpm_cuse -n vtpm-test - -QEMU can then be started using the following parameters: - -qemu-system-x86_64 \ - [...] \ - -tpmdev cuse-tpm,id=tpm0,cancel-path=/dev/null,path=/dev/vtpm-test \ - -device tpm-tis,id=tpm0,tpmdev=tpm0 \ - [...] - -Signed-off-by: Stefan Berger <stefanb@linux.vnet.ibm.com> -Cc: Eric Blake <eblake@redhat.com> - -Conflicts: - docs/qmp-commands.txt - -Patch cherry-picked from https://github.com/stefanberger/qemu-tpm, branch v2.8.0+tpm, -commit 27d6cd856d5a14061955df7a93ee490697a7a174. Applied cleanly except for -docs/qmp-commands.txt which did not exist yet in qemu 2.7. - -Upstream-Status: Pending [https://lists.nongnu.org/archive/html/qemu-devel/2016-06/msg00252.html] -Signed-off-by: Patrick Ohly <patrick.ohly@intel.com> ---- - hmp.c | 6 ++ - hw/tpm/tpm_int.h | 1 + - hw/tpm/tpm_ioctl.h | 215 +++++++++++++++++++++++++++++++++++++ - hw/tpm/tpm_passthrough.c | 274 +++++++++++++++++++++++++++++++++++++++++++++-- - qapi-schema.json | 18 +++- - qemu-options.hx | 21 +++- - tpm.c | 11 +- - 7 files changed, 529 insertions(+), 17 deletions(-) - create mode 100644 hw/tpm/tpm_ioctl.h - -diff --git a/hmp.c b/hmp.c -index cc2056e9e2..277b45ef5a 100644 ---- a/hmp.c -+++ b/hmp.c -@@ -883,6 +883,12 @@ void hmp_info_tpm(Monitor *mon, const QDict *qdict) - tpo->has_cancel_path ? ",cancel-path=" : "", - tpo->has_cancel_path ? tpo->cancel_path : ""); - break; -+ case TPM_TYPE_OPTIONS_KIND_CUSE_TPM: -+ tpo = ti->options->u.passthrough.data; -+ monitor_printf(mon, "%s%s", -+ tpo->has_path ? ",path=" : "", -+ tpo->has_path ? tpo->path : ""); -+ break; - case TPM_TYPE_OPTIONS_KIND__MAX: - break; - } -diff --git a/hw/tpm/tpm_int.h b/hw/tpm/tpm_int.h -index f2f285b3cc..6b2c9c953a 100644 ---- a/hw/tpm/tpm_int.h -+++ b/hw/tpm/tpm_int.h -@@ -61,6 +61,7 @@ struct tpm_resp_hdr { - #define TPM_TAG_RSP_AUTH1_COMMAND 0xc5 - #define TPM_TAG_RSP_AUTH2_COMMAND 0xc6 - -+#define TPM_SUCCESS 0 - #define TPM_FAIL 9 - - #define TPM_ORD_ContinueSelfTest 0x53 -diff --git a/hw/tpm/tpm_ioctl.h b/hw/tpm/tpm_ioctl.h -new file mode 100644 -index 0000000000..a341e15741 ---- /dev/null -+++ b/hw/tpm/tpm_ioctl.h -@@ -0,0 +1,215 @@ -+/* -+ * tpm_ioctl.h -+ * -+ * (c) Copyright IBM Corporation 2014, 2015. -+ * -+ * This file is licensed under the terms of the 3-clause BSD license -+ */ -+#ifndef _TPM_IOCTL_H_ -+#define _TPM_IOCTL_H_ -+ -+#include <stdint.h> -+#include <sys/uio.h> -+#include <sys/types.h> -+#include <sys/ioctl.h> -+ -+/* -+ * Every response from a command involving a TPM command execution must hold -+ * the ptm_res as the first element. -+ * ptm_res corresponds to the error code of a command executed by the TPM. -+ */ -+ -+typedef uint32_t ptm_res; -+ -+/* PTM_GET_TPMESTABLISHED: get the establishment bit */ -+struct ptm_est { -+ union { -+ struct { -+ ptm_res tpm_result; -+ unsigned char bit; /* TPM established bit */ -+ } resp; /* response */ -+ } u; -+}; -+ -+/* PTM_RESET_TPMESTABLISHED: reset establishment bit */ -+struct ptm_reset_est { -+ union { -+ struct { -+ uint8_t loc; /* locality to use */ -+ } req; /* request */ -+ struct { -+ ptm_res tpm_result; -+ } resp; /* response */ -+ } u; -+}; -+ -+/* PTM_INIT */ -+struct ptm_init { -+ union { -+ struct { -+ uint32_t init_flags; /* see definitions below */ -+ } req; /* request */ -+ struct { -+ ptm_res tpm_result; -+ } resp; /* response */ -+ } u; -+}; -+ -+/* above init_flags */ -+#define PTM_INIT_FLAG_DELETE_VOLATILE (1 << 0) -+ /* delete volatile state file after reading it */ -+ -+/* PTM_SET_LOCALITY */ -+struct ptm_loc { -+ union { -+ struct { -+ uint8_t loc; /* locality to set */ -+ } req; /* request */ -+ struct { -+ ptm_res tpm_result; -+ } resp; /* response */ -+ } u; -+}; -+ -+/* PTM_HASH_DATA: hash given data */ -+struct ptm_hdata { -+ union { -+ struct { -+ uint32_t length; -+ uint8_t data[4096]; -+ } req; /* request */ -+ struct { -+ ptm_res tpm_result; -+ } resp; /* response */ -+ } u; -+}; -+ -+/* -+ * size of the TPM state blob to transfer; x86_64 can handle 8k, -+ * ppc64le only ~7k; keep the response below a 4k page size -+ */ -+#define PTM_STATE_BLOB_SIZE (3 * 1024) -+ -+/* -+ * The following is the data structure to get state blobs from the TPM. -+ * If the size of the state blob exceeds the PTM_STATE_BLOB_SIZE, multiple reads -+ * with this ioctl and with adjusted offset are necessary. All bytes -+ * must be transferred and the transfer is done once the last byte has been -+ * returned. -+ * It is possible to use the read() interface for reading the data; however, -+ * the first bytes of the state blob will be part of the response to the ioctl(); -+ * a subsequent read() is only necessary if the total length (totlength) exceeds -+ * the number of received bytes. seek() is not supported. -+ */ -+struct ptm_getstate { -+ union { -+ struct { -+ uint32_t state_flags; /* may be: PTM_STATE_FLAG_DECRYPTED */ -+ uint32_t type; /* which blob to pull */ -+ uint32_t offset; /* offset from where to read */ -+ } req; /* request */ -+ struct { -+ ptm_res tpm_result; -+ uint32_t state_flags; /* may be: PTM_STATE_FLAG_ENCRYPTED */ -+ uint32_t totlength; /* total length that will be transferred */ -+ uint32_t length; /* number of bytes in following buffer */ -+ uint8_t data[PTM_STATE_BLOB_SIZE]; -+ } resp; /* response */ -+ } u; -+}; -+ -+/* TPM state blob types */ -+#define PTM_BLOB_TYPE_PERMANENT 1 -+#define PTM_BLOB_TYPE_VOLATILE 2 -+#define PTM_BLOB_TYPE_SAVESTATE 3 -+ -+/* state_flags above : */ -+#define PTM_STATE_FLAG_DECRYPTED 1 /* on input: get decrypted state */ -+#define PTM_STATE_FLAG_ENCRYPTED 2 /* on output: state is encrypted */ -+ -+/* -+ * The following is the data structure to set state blobs in the TPM. -+ * If the size of the state blob exceeds the PTM_STATE_BLOB_SIZE, multiple -+ * 'writes' using this ioctl are necessary. The last packet is indicated -+ * by the length being smaller than the PTM_STATE_BLOB_SIZE. -+ * The very first packet may have a length indicator of '0' enabling -+ * a write() with all the bytes from a buffer. If the write() interface -+ * is used, a final ioctl with a non-full buffer must be made to indicate -+ * that all data were transferred (a write with 0 bytes would not work). -+ */ -+struct ptm_setstate { -+ union { -+ struct { -+ uint32_t state_flags; /* may be PTM_STATE_FLAG_ENCRYPTED */ -+ uint32_t type; /* which blob to set */ -+ uint32_t length; /* length of the data; -+ use 0 on the first packet to -+ transfer using write() */ -+ uint8_t data[PTM_STATE_BLOB_SIZE]; -+ } req; /* request */ -+ struct { -+ ptm_res tpm_result; -+ } resp; /* response */ -+ } u; -+}; -+ -+/* -+ * PTM_GET_CONFIG: Data structure to get runtime configuration information -+ * such as which keys are applied. -+ */ -+struct ptm_getconfig { -+ union { -+ struct { -+ ptm_res tpm_result; -+ uint32_t flags; -+ } resp; /* response */ -+ } u; -+}; -+ -+#define PTM_CONFIG_FLAG_FILE_KEY 0x1 -+#define PTM_CONFIG_FLAG_MIGRATION_KEY 0x2 -+ -+ -+typedef uint64_t ptm_cap; -+typedef struct ptm_est ptm_est; -+typedef struct ptm_reset_est ptm_reset_est; -+typedef struct ptm_loc ptm_loc; -+typedef struct ptm_hdata ptm_hdata; -+typedef struct ptm_init ptm_init; -+typedef struct ptm_getstate ptm_getstate; -+typedef struct ptm_setstate ptm_setstate; -+typedef struct ptm_getconfig ptm_getconfig; -+ -+/* capability flags returned by PTM_GET_CAPABILITY */ -+#define PTM_CAP_INIT (1) -+#define PTM_CAP_SHUTDOWN (1<<1) -+#define PTM_CAP_GET_TPMESTABLISHED (1<<2) -+#define PTM_CAP_SET_LOCALITY (1<<3) -+#define PTM_CAP_HASHING (1<<4) -+#define PTM_CAP_CANCEL_TPM_CMD (1<<5) -+#define PTM_CAP_STORE_VOLATILE (1<<6) -+#define PTM_CAP_RESET_TPMESTABLISHED (1<<7) -+#define PTM_CAP_GET_STATEBLOB (1<<8) -+#define PTM_CAP_SET_STATEBLOB (1<<9) -+#define PTM_CAP_STOP (1<<10) -+#define PTM_CAP_GET_CONFIG (1<<11) -+ -+enum { -+ PTM_GET_CAPABILITY = _IOR('P', 0, ptm_cap), -+ PTM_INIT = _IOWR('P', 1, ptm_init), -+ PTM_SHUTDOWN = _IOR('P', 2, ptm_res), -+ PTM_GET_TPMESTABLISHED = _IOR('P', 3, ptm_est), -+ PTM_SET_LOCALITY = _IOWR('P', 4, ptm_loc), -+ PTM_HASH_START = _IOR('P', 5, ptm_res), -+ PTM_HASH_DATA = _IOWR('P', 6, ptm_hdata), -+ PTM_HASH_END = _IOR('P', 7, ptm_res), -+ PTM_CANCEL_TPM_CMD = _IOR('P', 8, ptm_res), -+ PTM_STORE_VOLATILE = _IOR('P', 9, ptm_res), -+ PTM_RESET_TPMESTABLISHED = _IOWR('P', 10, ptm_reset_est), -+ PTM_GET_STATEBLOB = _IOWR('P', 11, ptm_getstate), -+ PTM_SET_STATEBLOB = _IOWR('P', 12, ptm_setstate), -+ PTM_STOP = _IOR('P', 13, ptm_res), -+ PTM_GET_CONFIG = _IOR('P', 14, ptm_getconfig), -+}; -+ -+#endif /* _TPM_IOCTL_H */ -diff --git a/hw/tpm/tpm_passthrough.c b/hw/tpm/tpm_passthrough.c -index e88c0d20bc..050f2ba850 100644 ---- a/hw/tpm/tpm_passthrough.c -+++ b/hw/tpm/tpm_passthrough.c -@@ -33,6 +33,7 @@ - #include "sysemu/tpm_backend_int.h" - #include "tpm_tis.h" - #include "tpm_util.h" -+#include "tpm_ioctl.h" - - #define DEBUG_TPM 0 - -@@ -45,6 +46,7 @@ - #define TYPE_TPM_PASSTHROUGH "tpm-passthrough" - #define TPM_PASSTHROUGH(obj) \ - OBJECT_CHECK(TPMPassthruState, (obj), TYPE_TPM_PASSTHROUGH) -+#define TYPE_TPM_CUSE "tpm-cuse" - - static const TPMDriverOps tpm_passthrough_driver; - -@@ -71,12 +73,18 @@ struct TPMPassthruState { - bool had_startup_error; - - TPMVersion tpm_version; -+ ptm_cap cuse_cap; /* capabilities of the CUSE TPM */ -+ uint8_t cur_locty_number; /* last set locality */ - }; - - typedef struct TPMPassthruState TPMPassthruState; - - #define TPM_PASSTHROUGH_DEFAULT_DEVICE "/dev/tpm0" - -+#define TPM_PASSTHROUGH_USES_CUSE_TPM(tpm_pt) (tpm_pt->cuse_cap != 0) -+ -+#define TPM_CUSE_IMPLEMENTS_ALL(S, cap) (((S)->cuse_cap & (cap)) == (cap)) -+ - /* functions */ - - static void tpm_passthrough_cancel_cmd(TPMBackend *tb); -@@ -148,7 +156,28 @@ static bool tpm_passthrough_is_selftest(const uint8_t *in, uint32_t in_len) - return false; - } - -+static int tpm_passthrough_set_locality(TPMPassthruState *tpm_pt, -+ uint8_t locty_number) -+{ -+ ptm_loc loc; -+ -+ if (TPM_PASSTHROUGH_USES_CUSE_TPM(tpm_pt)) { -+ if (tpm_pt->cur_locty_number != locty_number) { -+ loc.u.req.loc = locty_number; -+ if (ioctl(tpm_pt->tpm_fd, PTM_SET_LOCALITY, &loc) < 0) { -+ error_report("tpm_cuse: could not set locality on " -+ "CUSE TPM: %s", -+ strerror(errno)); -+ return -1; -+ } -+ tpm_pt->cur_locty_number = locty_number; -+ } -+ } -+ return 0; -+} -+ - static int tpm_passthrough_unix_tx_bufs(TPMPassthruState *tpm_pt, -+ uint8_t locality_number, - const uint8_t *in, uint32_t in_len, - uint8_t *out, uint32_t out_len, - bool *selftest_done) -@@ -157,6 +186,11 @@ static int tpm_passthrough_unix_tx_bufs(TPMPassthruState *tpm_pt, - bool is_selftest; - const struct tpm_resp_hdr *hdr; - -+ ret = tpm_passthrough_set_locality(tpm_pt, locality_number); -+ if (ret < 0) { -+ goto err_exit; -+ } -+ - tpm_pt->tpm_op_canceled = false; - tpm_pt->tpm_executing = true; - *selftest_done = false; -@@ -207,10 +241,12 @@ err_exit: - } - - static int tpm_passthrough_unix_transfer(TPMPassthruState *tpm_pt, -+ uint8_t locality_number, - const TPMLocality *locty_data, - bool *selftest_done) - { - return tpm_passthrough_unix_tx_bufs(tpm_pt, -+ locality_number, - locty_data->w_buffer.buffer, - locty_data->w_offset, - locty_data->r_buffer.buffer, -@@ -231,6 +267,7 @@ static void tpm_passthrough_worker_thread(gpointer data, - switch (cmd) { - case TPM_BACKEND_CMD_PROCESS_CMD: - tpm_passthrough_unix_transfer(tpm_pt, -+ thr_parms->tpm_state->locty_number, - thr_parms->tpm_state->locty_data, - &selftest_done); - -@@ -247,6 +284,93 @@ static void tpm_passthrough_worker_thread(gpointer data, - } - - /* -+ * Gracefully shut down the external CUSE TPM -+ */ -+static void tpm_passthrough_shutdown(TPMPassthruState *tpm_pt) -+{ -+ ptm_res res; -+ -+ if (TPM_PASSTHROUGH_USES_CUSE_TPM(tpm_pt)) { -+ if (ioctl(tpm_pt->tpm_fd, PTM_SHUTDOWN, &res) < 0) { -+ error_report("tpm_cuse: Could not cleanly shut down " -+ "the CUSE TPM: %s", -+ strerror(errno)); -+ } -+ } -+} -+ -+/* -+ * Probe for the CUSE TPM by sending an ioctl() requesting its -+ * capability flags. -+ */ -+static int tpm_passthrough_cuse_probe(TPMPassthruState *tpm_pt) -+{ -+ int rc = 0; -+ -+ if (ioctl(tpm_pt->tpm_fd, PTM_GET_CAPABILITY, &tpm_pt->cuse_cap) < 0) { -+ error_report("Error: CUSE TPM was requested, but probing failed"); -+ rc = -1; -+ } -+ -+ return rc; -+} -+ -+static int tpm_passthrough_cuse_check_caps(TPMPassthruState *tpm_pt) -+{ -+ int rc = 0; -+ ptm_cap caps = 0; -+ const char *tpm = NULL; -+ -+ /* check for min. required capabilities */ -+ switch (tpm_pt->tpm_version) { -+ case TPM_VERSION_1_2: -+ caps = PTM_CAP_INIT | PTM_CAP_SHUTDOWN | PTM_CAP_GET_TPMESTABLISHED | -+ PTM_CAP_SET_LOCALITY; -+ tpm = "1.2"; -+ break; -+ case TPM_VERSION_2_0: -+ caps = PTM_CAP_INIT | PTM_CAP_SHUTDOWN | PTM_CAP_GET_TPMESTABLISHED | -+ PTM_CAP_SET_LOCALITY | PTM_CAP_RESET_TPMESTABLISHED; -+ tpm = "2"; -+ break; -+ case TPM_VERSION_UNSPEC: -+ error_report("tpm_cuse: %s: TPM version has not been set", -+ __func__); -+ return -1; -+ } -+ -+ if (!TPM_CUSE_IMPLEMENTS_ALL(tpm_pt, caps)) { -+ error_report("tpm_cuse: TPM does not implement minimum set of required " -+ "capabilities for TPM %s (0x%x)", tpm, (int)caps); -+ rc = -1; -+ } -+ -+ return rc; -+} -+ -+/* -+ * Initialize the external CUSE TPM -+ */ -+static int tpm_passthrough_cuse_init(TPMPassthruState *tpm_pt) -+{ -+ int rc = 0; -+ ptm_init init = { -+ .u.req.init_flags = PTM_INIT_FLAG_DELETE_VOLATILE, -+ }; -+ -+ if (TPM_PASSTHROUGH_USES_CUSE_TPM(tpm_pt)) { -+ if (ioctl(tpm_pt->tpm_fd, PTM_INIT, &init) < 0) { -+ error_report("tpm_cuse: Detected CUSE TPM but could not " -+ "send INIT: %s", -+ strerror(errno)); -+ rc = -1; -+ } -+ } -+ -+ return rc; -+} -+ -+/* - * Start the TPM (thread). If it had been started before, then terminate - * and start it again. - */ -@@ -261,6 +385,8 @@ static int tpm_passthrough_startup_tpm(TPMBackend *tb) - tpm_passthrough_worker_thread, - &tpm_pt->tpm_thread_params); - -+ tpm_passthrough_cuse_init(tpm_pt); -+ - return 0; - } - -@@ -291,14 +417,43 @@ static int tpm_passthrough_init(TPMBackend *tb, TPMState *s, - - static bool tpm_passthrough_get_tpm_established_flag(TPMBackend *tb) - { -+ TPMPassthruState *tpm_pt = TPM_PASSTHROUGH(tb); -+ ptm_est est; -+ -+ if (TPM_PASSTHROUGH_USES_CUSE_TPM(tpm_pt)) { -+ if (ioctl(tpm_pt->tpm_fd, PTM_GET_TPMESTABLISHED, &est) < 0) { -+ error_report("tpm_cuse: Could not get the TPM established " -+ "flag from the CUSE TPM: %s", -+ strerror(errno)); -+ return false; -+ } -+ return (est.u.resp.bit != 0); -+ } - return false; - } - - static int tpm_passthrough_reset_tpm_established_flag(TPMBackend *tb, - uint8_t locty) - { -+ TPMPassthruState *tpm_pt = TPM_PASSTHROUGH(tb); -+ int rc = 0; -+ ptm_reset_est ptmreset_est; -+ - /* only a TPM 2.0 will support this */ -- return 0; -+ if (tpm_pt->tpm_version == TPM_VERSION_2_0) { -+ if (TPM_PASSTHROUGH_USES_CUSE_TPM(tpm_pt)) { -+ ptmreset_est.u.req.loc = tpm_pt->cur_locty_number; -+ -+ if (ioctl(tpm_pt->tpm_fd, PTM_RESET_TPMESTABLISHED, -+ &ptmreset_est) < 0) { -+ error_report("tpm_cuse: Could not reset the establishment bit " -+ "failed: %s", -+ strerror(errno)); -+ rc = -1; -+ } -+ } -+ } -+ return rc; - } - - static bool tpm_passthrough_get_startup_error(TPMBackend *tb) -@@ -329,7 +484,8 @@ static void tpm_passthrough_deliver_request(TPMBackend *tb) - static void tpm_passthrough_cancel_cmd(TPMBackend *tb) - { - TPMPassthruState *tpm_pt = TPM_PASSTHROUGH(tb); -- int n; -+ ptm_res res; -+ static bool error_printed; - - /* - * As of Linux 3.7 the tpm_tis driver does not properly cancel -@@ -338,17 +494,34 @@ static void tpm_passthrough_cancel_cmd(TPMBackend *tb) - * command, e.g., a command executed on the host. - */ - if (tpm_pt->tpm_executing) { -- if (tpm_pt->cancel_fd >= 0) { -- n = write(tpm_pt->cancel_fd, "-", 1); -- if (n != 1) { -- error_report("Canceling TPM command failed: %s", -- strerror(errno)); -- } else { -- tpm_pt->tpm_op_canceled = true; -+ if (TPM_PASSTHROUGH_USES_CUSE_TPM(tpm_pt)) { -+ if (TPM_CUSE_IMPLEMENTS_ALL(tpm_pt, PTM_CAP_CANCEL_TPM_CMD)) { -+ if (ioctl(tpm_pt->tpm_fd, PTM_CANCEL_TPM_CMD, &res) < 0) { -+ error_report("tpm_cuse: Could not cancel command on " -+ "CUSE TPM: %s", -+ strerror(errno)); -+ } else if (res != TPM_SUCCESS) { -+ if (!error_printed) { -+ error_report("TPM error code from command " -+ "cancellation of CUSE TPM: 0x%x", res); -+ error_printed = true; -+ } -+ } else { -+ tpm_pt->tpm_op_canceled = true; -+ } - } - } else { -- error_report("Cannot cancel TPM command due to missing " -- "TPM sysfs cancel entry"); -+ if (tpm_pt->cancel_fd >= 0) { -+ if (write(tpm_pt->cancel_fd, "-", 1) != 1) { -+ error_report("Canceling TPM command failed: %s", -+ strerror(errno)); -+ } else { -+ tpm_pt->tpm_op_canceled = true; -+ } -+ } else { -+ error_report("Cannot cancel TPM command due to missing " -+ "TPM sysfs cancel entry"); -+ } - } - } - } -@@ -378,6 +551,11 @@ static int tpm_passthrough_open_sysfs_cancel(TPMBackend *tb) - char *dev; - char path[PATH_MAX]; - -+ if (TPM_PASSTHROUGH_USES_CUSE_TPM(tpm_pt)) { -+ /* not needed, but so we have a fd */ -+ return qemu_open("/dev/null", O_WRONLY); -+ } -+ - if (tb->cancel_path) { - fd = qemu_open(tb->cancel_path, O_WRONLY); - if (fd < 0) { -@@ -412,12 +590,22 @@ static int tpm_passthrough_handle_device_opts(QemuOpts *opts, TPMBackend *tb) - { - TPMPassthruState *tpm_pt = TPM_PASSTHROUGH(tb); - const char *value; -+ bool have_cuse = false; -+ -+ value = qemu_opt_get(opts, "type"); -+ if (value != NULL && !strcmp("cuse-tpm", value)) { -+ have_cuse = true; -+ } - - value = qemu_opt_get(opts, "cancel-path"); - tb->cancel_path = g_strdup(value); - - value = qemu_opt_get(opts, "path"); - if (!value) { -+ if (have_cuse) { -+ error_report("Missing path to access CUSE TPM"); -+ goto err_free_parameters; -+ } - value = TPM_PASSTHROUGH_DEFAULT_DEVICE; - } - -@@ -432,15 +620,36 @@ static int tpm_passthrough_handle_device_opts(QemuOpts *opts, TPMBackend *tb) - goto err_free_parameters; - } - -+ tpm_pt->cur_locty_number = ~0; -+ -+ if (have_cuse) { -+ if (tpm_passthrough_cuse_probe(tpm_pt)) { -+ goto err_close_tpmdev; -+ } -+ /* init TPM for probing */ -+ if (tpm_passthrough_cuse_init(tpm_pt)) { -+ goto err_close_tpmdev; -+ } -+ } -+ - if (tpm_util_test_tpmdev(tpm_pt->tpm_fd, &tpm_pt->tpm_version)) { - error_report("'%s' is not a TPM device.", - tpm_pt->tpm_dev); - goto err_close_tpmdev; - } - -+ if (have_cuse) { -+ if (tpm_passthrough_cuse_check_caps(tpm_pt)) { -+ goto err_close_tpmdev; -+ } -+ } -+ -+ - return 0; - - err_close_tpmdev: -+ tpm_passthrough_shutdown(tpm_pt); -+ - qemu_close(tpm_pt->tpm_fd); - tpm_pt->tpm_fd = -1; - -@@ -491,6 +700,8 @@ static void tpm_passthrough_destroy(TPMBackend *tb) - - tpm_backend_thread_end(&tpm_pt->tbt); - -+ tpm_passthrough_shutdown(tpm_pt); -+ - qemu_close(tpm_pt->tpm_fd); - qemu_close(tpm_pt->cancel_fd); - -@@ -564,3 +775,44 @@ static void tpm_passthrough_register(void) - } - - type_init(tpm_passthrough_register) -+ -+/* CUSE TPM */ -+static const char *tpm_passthrough_cuse_create_desc(void) -+{ -+ return "CUSE TPM backend driver"; -+} -+ -+static const TPMDriverOps tpm_cuse_driver = { -+ .type = TPM_TYPE_CUSE_TPM, -+ .opts = tpm_passthrough_cmdline_opts, -+ .desc = tpm_passthrough_cuse_create_desc, -+ .create = tpm_passthrough_create, -+ .destroy = tpm_passthrough_destroy, -+ .init = tpm_passthrough_init, -+ .startup_tpm = tpm_passthrough_startup_tpm, -+ .realloc_buffer = tpm_passthrough_realloc_buffer, -+ .reset = tpm_passthrough_reset, -+ .had_startup_error = tpm_passthrough_get_startup_error, -+ .deliver_request = tpm_passthrough_deliver_request, -+ .cancel_cmd = tpm_passthrough_cancel_cmd, -+ .get_tpm_established_flag = tpm_passthrough_get_tpm_established_flag, -+ .reset_tpm_established_flag = tpm_passthrough_reset_tpm_established_flag, -+ .get_tpm_version = tpm_passthrough_get_tpm_version, -+}; -+ -+static const TypeInfo tpm_cuse_info = { -+ .name = TYPE_TPM_CUSE, -+ .parent = TYPE_TPM_BACKEND, -+ .instance_size = sizeof(TPMPassthruState), -+ .class_init = tpm_passthrough_class_init, -+ .instance_init = tpm_passthrough_inst_init, -+ .instance_finalize = tpm_passthrough_inst_finalize, -+}; -+ -+static void tpm_cuse_register(void) -+{ -+ type_register_static(&tpm_cuse_info); -+ tpm_register_driver(&tpm_cuse_driver); -+} -+ -+type_init(tpm_cuse_register) -diff --git a/qapi-schema.json b/qapi-schema.json -index 5658723b37..53120d0f63 100644 ---- a/qapi-schema.json -+++ b/qapi-schema.json -@@ -3522,10 +3522,12 @@ - # An enumeration of TPM types - # - # @passthrough: TPM passthrough type -+# @cuse-tpm: CUSE TPM type -+# Since: 2.6 - # - # Since: 1.5 - ## --{ 'enum': 'TpmType', 'data': [ 'passthrough' ] } -+{ 'enum': 'TpmType', 'data': [ 'passthrough', 'cuse-tpm' ] } - - ## - # @query-tpm-types: -@@ -3554,6 +3556,17 @@ - '*cancel-path' : 'str'} } - - ## -+# @TPMCuseOptions: -+# -+# Information about the CUSE TPM type -+# -+# @path: string describing the path used for accessing the TPM device -+# -+# Since: 2.6 -+## -+{ 'struct': 'TPMCuseOptions', 'data': { 'path' : 'str'}} -+ -+## - # @TpmTypeOptions: - # - # A union referencing different TPM backend types' configuration options -@@ -3563,7 +3576,8 @@ - # Since: 1.5 - ## - { 'union': 'TpmTypeOptions', -- 'data': { 'passthrough' : 'TPMPassthroughOptions' } } -+ 'data': { 'passthrough' : 'TPMPassthroughOptions', -+ 'cuse-tpm' : 'TPMCuseOptions' } } - - ## - # @TpmInfo: -diff --git a/qemu-options.hx b/qemu-options.hx -index a71aaf8ea8..e0f1d8e676 100644 ---- a/qemu-options.hx -+++ b/qemu-options.hx -@@ -2763,7 +2763,10 @@ DEF("tpmdev", HAS_ARG, QEMU_OPTION_tpmdev, \ - "-tpmdev passthrough,id=id[,path=path][,cancel-path=path]\n" - " use path to provide path to a character device; default is /dev/tpm0\n" - " use cancel-path to provide path to TPM's cancel sysfs entry; if\n" -- " not provided it will be searched for in /sys/class/misc/tpm?/device\n", -+ " not provided it will be searched for in /sys/class/misc/tpm?/device\n" -+ "-tpmdev cuse-tpm,id=id,path=path\n" -+ " use path to provide path to a character device to talk to the\n" -+ " TPM emulator providing a CUSE interface\n", - QEMU_ARCH_ALL) - STEXI - -@@ -2772,8 +2775,8 @@ The general form of a TPM device option is: - - @item -tpmdev @var{backend} ,id=@var{id} [,@var{options}] - @findex -tpmdev --Backend type must be: --@option{passthrough}. -+Backend type must be either one of the following: -+@option{passthrough}, @option{cuse-tpm}. - - The specific backend type will determine the applicable options. - The @code{-tpmdev} option creates the TPM backend and requires a -@@ -2823,6 +2826,18 @@ To create a passthrough TPM use the following two options: - Note that the @code{-tpmdev} id is @code{tpm0} and is referenced by - @code{tpmdev=tpm0} in the device option. - -+@item -tpmdev cuse-tpm, id=@var{id}, path=@var{path} -+ -+(Linux-host only) Enable access to a TPM emulator with a CUSE interface. -+ -+@option{path} specifies the path to the CUSE TPM character device. -+ -+To create a backend device accessing the CUSE TPM emulator using /dev/vtpm -+use the following two options: -+@example -+-tpmdev cuse-tpm,id=tpm0,path=/dev/vtpm -device tpm-tis,tpmdev=tpm0 -+@end example -+ - @end table - - ETEXI -diff --git a/tpm.c b/tpm.c -index 9a7c7114d3..5ec2373286 100644 ---- a/tpm.c -+++ b/tpm.c -@@ -25,7 +25,7 @@ static QLIST_HEAD(, TPMBackend) tpm_backends = - - - #define TPM_MAX_MODELS 1 --#define TPM_MAX_DRIVERS 1 -+#define TPM_MAX_DRIVERS 2 - - static TPMDriverOps const *be_drivers[TPM_MAX_DRIVERS] = { - NULL, -@@ -272,6 +272,15 @@ static TPMInfo *qmp_query_tpm_inst(TPMBackend *drv) - tpo->has_cancel_path = true; - } - break; -+ case TPM_TYPE_CUSE_TPM: -+ res->options->type = TPM_TYPE_OPTIONS_KIND_CUSE_TPM; -+ tpo = g_new0(TPMPassthroughOptions, 1); -+ res->options->u.passthrough.data = tpo; -+ if (drv->path) { -+ tpo->path = g_strdup(drv->path); -+ tpo->has_path = true; -+ } -+ break; - case TPM_TYPE__MAX: - break; - } --- -2.11.0 - diff --git a/import-layers/yocto-poky/meta/recipes-devtools/qemu/qemu/0001-arm-translate-a64-treat-DISAS_UPDATE-as-variant-of-D.patch b/import-layers/yocto-poky/meta/recipes-devtools/qemu/qemu/0001-arm-translate-a64-treat-DISAS_UPDATE-as-variant-of-D.patch new file mode 100644 index 000000000..f90cae694 --- /dev/null +++ b/import-layers/yocto-poky/meta/recipes-devtools/qemu/qemu/0001-arm-translate-a64-treat-DISAS_UPDATE-as-variant-of-D.patch @@ -0,0 +1,67 @@ +From a75a52d62418dafe462be4fe30485501d1010bb9 Mon Sep 17 00:00:00 2001 +From: Victor Kamensky <kamensky@cisco.com> +Date: Fri, 23 Mar 2018 18:26:45 +0000 +Subject: [PATCH] arm/translate-a64: treat DISAS_UPDATE as variant of + DISAS_EXIT +MIME-Version: 1.0 +Content-Type: text/plain; charset=UTF-8 +Content-Transfer-Encoding: 8bit + +In OE project 4.15 linux kernel boot hang was observed under +single cpu aarch64 qemu. Kernel code was in a loop waiting for +vtimer arrival, spinning in TC generated blocks, while interrupt +was pending unprocessed. This happened because when qemu tried to +handle vtimer interrupt target had interrupts disabled, as +result flag indicating TCG exit, cpu->icount_decr.u16.high, +was cleared but arm_cpu_exec_interrupt function did not call +arm_cpu_do_interrupt to process interrupt. Later when target +reenabled interrupts, it happened without exit into main loop, so +following code that waited for result of interrupt execution +run in infinite loop. + +To solve the problem instructions that operate on CPU sys state +(i.e enable/disable interrupt), and marked as DISAS_UPDATE, +should be considered as DISAS_EXIT variant, and should be +forced to exit back to main loop so qemu will have a chance +processing pending CPU state updates, including pending +interrupts. + +This change brings consistency with how DISAS_UPDATE is treated +in aarch32 case. + +CC: Peter Maydell <peter.maydell@linaro.org> +CC: Alex Bennée <alex.bennee@linaro.org> +CC: qemu-stable@nongnu.org +Suggested-by: Peter Maydell <peter.maydell@linaro.org> +Signed-off-by: Victor Kamensky <kamensky@cisco.com> +Reviewed-by: Richard Henderson <richard.henderson@linaro.org> +Message-id: 1521526368-1996-1-git-send-email-kamensky@cisco.com +Signed-off-by: Peter Maydell <peter.maydell@linaro.org> +Upstream-Status: Backport +--- + target/arm/translate-a64.c | 6 +++--- + 1 file changed, 3 insertions(+), 3 deletions(-) + +diff --git a/target/arm/translate-a64.c b/target/arm/translate-a64.c +index 31ff047..327513e 100644 +--- a/target/arm/translate-a64.c ++++ b/target/arm/translate-a64.c +@@ -13378,12 +13378,12 @@ static void aarch64_tr_tb_stop(DisasContextBase *dcbase, CPUState *cpu) + case DISAS_UPDATE: + gen_a64_set_pc_im(dc->pc); + /* fall through */ +- case DISAS_JUMP: +- tcg_gen_lookup_and_goto_ptr(); +- break; + case DISAS_EXIT: + tcg_gen_exit_tb(0); + break; ++ case DISAS_JUMP: ++ tcg_gen_lookup_and_goto_ptr(); ++ break; + case DISAS_NORETURN: + case DISAS_SWI: + break; +-- +2.7.4 + diff --git a/import-layers/yocto-poky/meta/recipes-devtools/qemu/qemu/0002-Introduce-condition-to-notify-waiters-of-completed-c.patch b/import-layers/yocto-poky/meta/recipes-devtools/qemu/qemu/0002-Introduce-condition-to-notify-waiters-of-completed-c.patch deleted file mode 100644 index c88c98e56..000000000 --- a/import-layers/yocto-poky/meta/recipes-devtools/qemu/qemu/0002-Introduce-condition-to-notify-waiters-of-completed-c.patch +++ /dev/null @@ -1,86 +0,0 @@ -From b5ffd3aa4e9bd4edb09cc84c46f78da72697a946 Mon Sep 17 00:00:00 2001 -From: Stefan Berger <stefanb@linux.vnet.ibm.com> -Date: Sat, 31 Dec 2016 11:23:32 -0500 -Subject: [PATCH 2/4] Introduce condition to notify waiters of completed - command - -Introduce a lock and a condition to notify anyone waiting for the completion -of the execution of a TPM command by the backend (thread). The backend -uses the condition to signal anyone waiting for command completion. -We need to place the condition in two locations: one is invoked by the -backend thread, the other by the bottom half thread. -We will use the signalling to wait for command completion before VM -suspend. - -Signed-off-by: Stefan Berger <stefanb@linux.vnet.ibm.com> - -Upstream-Status: Pending [https://lists.nongnu.org/archive/html/qemu-devel/2016-06/msg00252.html] -Signed-off-by: Patrick Ohly <patrick.ohly@intel.com> ---- - hw/tpm/tpm_int.h | 3 +++ - hw/tpm/tpm_tis.c | 14 ++++++++++++++ - 2 files changed, 17 insertions(+) - -diff --git a/hw/tpm/tpm_int.h b/hw/tpm/tpm_int.h -index 6b2c9c953a..70be1ad8d9 100644 ---- a/hw/tpm/tpm_int.h -+++ b/hw/tpm/tpm_int.h -@@ -30,6 +30,9 @@ struct TPMState { - char *backend; - TPMBackend *be_driver; - TPMVersion be_tpm_version; -+ -+ QemuMutex state_lock; -+ QemuCond cmd_complete; - }; - - #define TPM(obj) OBJECT_CHECK(TPMState, (obj), TYPE_TPM_TIS) -diff --git a/hw/tpm/tpm_tis.c b/hw/tpm/tpm_tis.c -index 381e7266ea..14d9e83ea2 100644 ---- a/hw/tpm/tpm_tis.c -+++ b/hw/tpm/tpm_tis.c -@@ -368,6 +368,8 @@ static void tpm_tis_receive_bh(void *opaque) - TPMTISEmuState *tis = &s->s.tis; - uint8_t locty = s->locty_number; - -+ qemu_mutex_lock(&s->state_lock); -+ - tpm_tis_sts_set(&tis->loc[locty], - TPM_TIS_STS_VALID | TPM_TIS_STS_DATA_AVAILABLE); - tis->loc[locty].state = TPM_TIS_STATE_COMPLETION; -@@ -384,6 +386,10 @@ static void tpm_tis_receive_bh(void *opaque) - tpm_tis_raise_irq(s, locty, - TPM_TIS_INT_DATA_AVAILABLE | TPM_TIS_INT_STS_VALID); - #endif -+ -+ /* notify of completed command */ -+ qemu_cond_signal(&s->cmd_complete); -+ qemu_mutex_unlock(&s->state_lock); - } - - /* -@@ -403,6 +409,11 @@ static void tpm_tis_receive_cb(TPMState *s, uint8_t locty, - } - } - -+ qemu_mutex_lock(&s->state_lock); -+ /* notify of completed command */ -+ qemu_cond_signal(&s->cmd_complete); -+ qemu_mutex_unlock(&s->state_lock); -+ - qemu_bh_schedule(tis->bh); - } - -@@ -1072,6 +1083,9 @@ static void tpm_tis_initfn(Object *obj) - memory_region_init_io(&s->mmio, OBJECT(s), &tpm_tis_memory_ops, - s, "tpm-tis-mmio", - TPM_TIS_NUM_LOCALITIES << TPM_TIS_LOCALITY_SHIFT); -+ -+ qemu_mutex_init(&s->state_lock); -+ qemu_cond_init(&s->cmd_complete); - } - - static void tpm_tis_class_init(ObjectClass *klass, void *data) --- -2.11.0 - diff --git a/import-layers/yocto-poky/meta/recipes-devtools/qemu/qemu/0003-Introduce-condition-in-TPM-backend-for-notification.patch b/import-layers/yocto-poky/meta/recipes-devtools/qemu/qemu/0003-Introduce-condition-in-TPM-backend-for-notification.patch deleted file mode 100644 index e58f01906..000000000 --- a/import-layers/yocto-poky/meta/recipes-devtools/qemu/qemu/0003-Introduce-condition-in-TPM-backend-for-notification.patch +++ /dev/null @@ -1,79 +0,0 @@ -From 732a8e046948fd62b32cd1dd76a6798eb1caf4d6 Mon Sep 17 00:00:00 2001 -From: Stefan Berger <stefanb@linux.vnet.ibm.com> -Date: Sat, 31 Dec 2016 11:23:32 -0500 -Subject: [PATCH 3/4] Introduce condition in TPM backend for notification - -TPM backends will suspend independently of the frontends. Also -here we need to be able to wait for the TPM command to have been -completely processed. - -Signed-off-by: Stefan Berger <stefanb@linux.vnet.ibm.com> - -Upstream-Status: Pending [https://lists.nongnu.org/archive/html/qemu-devel/2016-06/msg00252.html] -Signed-off-by: Patrick Ohly <patrick.ohly@intel.com> ---- - hw/tpm/tpm_passthrough.c | 20 ++++++++++++++++++++ - 1 file changed, 20 insertions(+) - -diff --git a/hw/tpm/tpm_passthrough.c b/hw/tpm/tpm_passthrough.c -index 050f2ba850..44739ebad2 100644 ---- a/hw/tpm/tpm_passthrough.c -+++ b/hw/tpm/tpm_passthrough.c -@@ -75,6 +75,10 @@ struct TPMPassthruState { - TPMVersion tpm_version; - ptm_cap cuse_cap; /* capabilities of the CUSE TPM */ - uint8_t cur_locty_number; /* last set locality */ -+ -+ QemuMutex state_lock; -+ QemuCond cmd_complete; /* singnaled once tpm_busy is false */ -+ bool tpm_busy; - }; - - typedef struct TPMPassthruState TPMPassthruState; -@@ -274,6 +278,11 @@ static void tpm_passthrough_worker_thread(gpointer data, - thr_parms->recv_data_callback(thr_parms->tpm_state, - thr_parms->tpm_state->locty_number, - selftest_done); -+ /* result delivered */ -+ qemu_mutex_lock(&tpm_pt->state_lock); -+ tpm_pt->tpm_busy = false; -+ qemu_cond_signal(&tpm_pt->cmd_complete); -+ qemu_mutex_unlock(&tpm_pt->state_lock); - break; - case TPM_BACKEND_CMD_INIT: - case TPM_BACKEND_CMD_END: -@@ -401,6 +410,7 @@ static void tpm_passthrough_reset(TPMBackend *tb) - tpm_backend_thread_end(&tpm_pt->tbt); - - tpm_pt->had_startup_error = false; -+ tpm_pt->tpm_busy = false; - } - - static int tpm_passthrough_init(TPMBackend *tb, TPMState *s, -@@ -478,6 +488,11 @@ static void tpm_passthrough_deliver_request(TPMBackend *tb) - { - TPMPassthruState *tpm_pt = TPM_PASSTHROUGH(tb); - -+ /* TPM considered busy once TPM Request scheduled for processing */ -+ qemu_mutex_lock(&tpm_pt->state_lock); -+ tpm_pt->tpm_busy = true; -+ qemu_mutex_unlock(&tpm_pt->state_lock); -+ - tpm_backend_thread_deliver_request(&tpm_pt->tbt); - } - -@@ -746,6 +761,11 @@ static const TPMDriverOps tpm_passthrough_driver = { - - static void tpm_passthrough_inst_init(Object *obj) - { -+ TPMBackend *tb = TPM_BACKEND(obj); -+ TPMPassthruState *tpm_pt = TPM_PASSTHROUGH(tb); -+ -+ qemu_mutex_init(&tpm_pt->state_lock); -+ qemu_cond_init(&tpm_pt->cmd_complete); - } - - static void tpm_passthrough_inst_finalize(Object *obj) --- -2.11.0 - diff --git a/import-layers/yocto-poky/meta/recipes-devtools/qemu/qemu/0004-Add-support-for-VM-suspend-resume-for-TPM-TIS-v2.9.patch b/import-layers/yocto-poky/meta/recipes-devtools/qemu/qemu/0004-Add-support-for-VM-suspend-resume-for-TPM-TIS-v2.9.patch deleted file mode 100644 index f1dbaffea..000000000 --- a/import-layers/yocto-poky/meta/recipes-devtools/qemu/qemu/0004-Add-support-for-VM-suspend-resume-for-TPM-TIS-v2.9.patch +++ /dev/null @@ -1,719 +0,0 @@ -From 5e9dd9063f514447ea4f54046793f4f01c297ed4 Mon Sep 17 00:00:00 2001 -From: Stefan Berger <stefanb@linux.vnet.ibm.com> -Date: Sat, 31 Dec 2016 11:23:32 -0500 -Subject: [PATCH 4/4] Add support for VM suspend/resume for TPM TIS - -Extend the TPM TIS code to support suspend/resume. In case a command -is being processed by the external TPM when suspending, wait for the command -to complete to catch the result. In case the bottom half did not run, -run the one function the bottom half is supposed to run. This then -makes the resume operation work. - -The passthrough backend does not support suspend/resume operation -and is therefore blocked from suspend/resume and migration. - -The CUSE TPM's supported capabilities are tested and if sufficient -capabilities are implemented, suspend/resume, snapshotting and -migration are supported by the CUSE TPM. - -Signed-off-by: Stefan Berger <stefanb@linux.vnet.ibm.com> - -Upstream-Status: Pending [https://lists.nongnu.org/archive/html/qemu-devel/2016-06/msg00252.html] -Signed-off-by: Patrick Ohly <patrick.ohly@intel.com> ---- - hw/tpm/tpm_passthrough.c | 130 +++++++++++++++++++++++-- - hw/tpm/tpm_tis.c | 137 +++++++++++++++++++++++++- - hw/tpm/tpm_tis.h | 2 + - hw/tpm/tpm_util.c | 223 +++++++++++++++++++++++++++++++++++++++++++ - hw/tpm/tpm_util.h | 7 ++ - include/sysemu/tpm_backend.h | 12 +++ - 6 files changed, 503 insertions(+), 8 deletions(-) - -diff --git a/hw/tpm/tpm_passthrough.c b/hw/tpm/tpm_passthrough.c -index 44739ebad2..bc8072d0bc 100644 ---- a/hw/tpm/tpm_passthrough.c -+++ b/hw/tpm/tpm_passthrough.c -@@ -34,6 +34,8 @@ - #include "tpm_tis.h" - #include "tpm_util.h" - #include "tpm_ioctl.h" -+#include "migration/migration.h" -+#include "qapi/error.h" - - #define DEBUG_TPM 0 - -@@ -49,6 +51,7 @@ - #define TYPE_TPM_CUSE "tpm-cuse" - - static const TPMDriverOps tpm_passthrough_driver; -+static const VMStateDescription vmstate_tpm_cuse; - - /* data structures */ - typedef struct TPMPassthruThreadParams { -@@ -79,6 +82,10 @@ struct TPMPassthruState { - QemuMutex state_lock; - QemuCond cmd_complete; /* singnaled once tpm_busy is false */ - bool tpm_busy; -+ -+ Error *migration_blocker; -+ -+ TPMBlobBuffers tpm_blobs; - }; - - typedef struct TPMPassthruState TPMPassthruState; -@@ -306,6 +313,10 @@ static void tpm_passthrough_shutdown(TPMPassthruState *tpm_pt) - strerror(errno)); - } - } -+ if (tpm_pt->migration_blocker) { -+ migrate_del_blocker(tpm_pt->migration_blocker); -+ error_free(tpm_pt->migration_blocker); -+ } - } - - /* -@@ -360,12 +371,14 @@ static int tpm_passthrough_cuse_check_caps(TPMPassthruState *tpm_pt) - /* - * Initialize the external CUSE TPM - */ --static int tpm_passthrough_cuse_init(TPMPassthruState *tpm_pt) -+static int tpm_passthrough_cuse_init(TPMPassthruState *tpm_pt, -+ bool is_resume) - { - int rc = 0; -- ptm_init init = { -- .u.req.init_flags = PTM_INIT_FLAG_DELETE_VOLATILE, -- }; -+ ptm_init init; -+ if (is_resume) { -+ init.u.req.init_flags = PTM_INIT_FLAG_DELETE_VOLATILE; -+ } - - if (TPM_PASSTHROUGH_USES_CUSE_TPM(tpm_pt)) { - if (ioctl(tpm_pt->tpm_fd, PTM_INIT, &init) < 0) { -@@ -394,7 +407,7 @@ static int tpm_passthrough_startup_tpm(TPMBackend *tb) - tpm_passthrough_worker_thread, - &tpm_pt->tpm_thread_params); - -- tpm_passthrough_cuse_init(tpm_pt); -+ tpm_passthrough_cuse_init(tpm_pt, false); - - return 0; - } -@@ -466,6 +479,32 @@ static int tpm_passthrough_reset_tpm_established_flag(TPMBackend *tb, - return rc; - } - -+static int tpm_cuse_get_state_blobs(TPMBackend *tb, -+ bool decrypted_blobs, -+ TPMBlobBuffers *tpm_blobs) -+{ -+ TPMPassthruState *tpm_pt = TPM_PASSTHROUGH(tb); -+ -+ assert(TPM_PASSTHROUGH_USES_CUSE_TPM(tpm_pt)); -+ -+ return tpm_util_cuse_get_state_blobs(tpm_pt->tpm_fd, decrypted_blobs, -+ tpm_blobs); -+} -+ -+static int tpm_cuse_set_state_blobs(TPMBackend *tb, -+ TPMBlobBuffers *tpm_blobs) -+{ -+ TPMPassthruState *tpm_pt = TPM_PASSTHROUGH(tb); -+ -+ assert(TPM_PASSTHROUGH_USES_CUSE_TPM(tpm_pt)); -+ -+ if (tpm_util_cuse_set_state_blobs(tpm_pt->tpm_fd, tpm_blobs)) { -+ return 1; -+ } -+ -+ return tpm_passthrough_cuse_init(tpm_pt, true); -+} -+ - static bool tpm_passthrough_get_startup_error(TPMBackend *tb) - { - TPMPassthruState *tpm_pt = TPM_PASSTHROUGH(tb); -@@ -488,7 +527,7 @@ static void tpm_passthrough_deliver_request(TPMBackend *tb) - { - TPMPassthruState *tpm_pt = TPM_PASSTHROUGH(tb); - -- /* TPM considered busy once TPM Request scheduled for processing */ -+ /* TPM considered busy once TPM request scheduled for processing */ - qemu_mutex_lock(&tpm_pt->state_lock); - tpm_pt->tpm_busy = true; - qemu_mutex_unlock(&tpm_pt->state_lock); -@@ -601,6 +640,25 @@ static int tpm_passthrough_open_sysfs_cancel(TPMBackend *tb) - return fd; - } - -+static void tpm_passthrough_block_migration(TPMPassthruState *tpm_pt) -+{ -+ ptm_cap caps; -+ -+ if (TPM_PASSTHROUGH_USES_CUSE_TPM(tpm_pt)) { -+ caps = PTM_CAP_GET_STATEBLOB | PTM_CAP_SET_STATEBLOB | -+ PTM_CAP_STOP; -+ if (!TPM_CUSE_IMPLEMENTS_ALL(tpm_pt, caps)) { -+ error_setg(&tpm_pt->migration_blocker, -+ "Migration disabled: CUSE TPM lacks necessary capabilities"); -+ migrate_add_blocker(tpm_pt->migration_blocker); -+ } -+ } else { -+ error_setg(&tpm_pt->migration_blocker, -+ "Migration disabled: Passthrough TPM does not support migration"); -+ migrate_add_blocker(tpm_pt->migration_blocker); -+ } -+} -+ - static int tpm_passthrough_handle_device_opts(QemuOpts *opts, TPMBackend *tb) - { - TPMPassthruState *tpm_pt = TPM_PASSTHROUGH(tb); -@@ -642,7 +700,7 @@ static int tpm_passthrough_handle_device_opts(QemuOpts *opts, TPMBackend *tb) - goto err_close_tpmdev; - } - /* init TPM for probing */ -- if (tpm_passthrough_cuse_init(tpm_pt)) { -+ if (tpm_passthrough_cuse_init(tpm_pt, false)) { - goto err_close_tpmdev; - } - } -@@ -659,6 +717,7 @@ static int tpm_passthrough_handle_device_opts(QemuOpts *opts, TPMBackend *tb) - } - } - -+ tpm_passthrough_block_migration(tpm_pt); - - return 0; - -@@ -766,10 +825,13 @@ static void tpm_passthrough_inst_init(Object *obj) - - qemu_mutex_init(&tpm_pt->state_lock); - qemu_cond_init(&tpm_pt->cmd_complete); -+ -+ vmstate_register(NULL, -1, &vmstate_tpm_cuse, obj); - } - - static void tpm_passthrough_inst_finalize(Object *obj) - { -+ vmstate_unregister(NULL, &vmstate_tpm_cuse, obj); - } - - static void tpm_passthrough_class_init(ObjectClass *klass, void *data) -@@ -802,6 +864,60 @@ static const char *tpm_passthrough_cuse_create_desc(void) - return "CUSE TPM backend driver"; - } - -+static void tpm_cuse_pre_save(void *opaque) -+{ -+ TPMPassthruState *tpm_pt = opaque; -+ TPMBackend *tb = &tpm_pt->parent; -+ -+ qemu_mutex_lock(&tpm_pt->state_lock); -+ /* wait for TPM to finish processing */ -+ if (tpm_pt->tpm_busy) { -+ qemu_cond_wait(&tpm_pt->cmd_complete, &tpm_pt->state_lock); -+ } -+ qemu_mutex_unlock(&tpm_pt->state_lock); -+ -+ /* get the decrypted state blobs from the TPM */ -+ tpm_cuse_get_state_blobs(tb, TRUE, &tpm_pt->tpm_blobs); -+} -+ -+static int tpm_cuse_post_load(void *opaque, -+ int version_id __attribute__((unused))) -+{ -+ TPMPassthruState *tpm_pt = opaque; -+ TPMBackend *tb = &tpm_pt->parent; -+ -+ return tpm_cuse_set_state_blobs(tb, &tpm_pt->tpm_blobs); -+} -+ -+static const VMStateDescription vmstate_tpm_cuse = { -+ .name = "cuse-tpm", -+ .version_id = 1, -+ .minimum_version_id = 0, -+ .minimum_version_id_old = 0, -+ .pre_save = tpm_cuse_pre_save, -+ .post_load = tpm_cuse_post_load, -+ .fields = (VMStateField[]) { -+ VMSTATE_UINT32(tpm_blobs.permanent_flags, TPMPassthruState), -+ VMSTATE_UINT32(tpm_blobs.permanent.size, TPMPassthruState), -+ VMSTATE_VBUFFER_ALLOC_UINT32(tpm_blobs.permanent.buffer, -+ TPMPassthruState, 1, NULL, -+ tpm_blobs.permanent.size), -+ -+ VMSTATE_UINT32(tpm_blobs.volatil_flags, TPMPassthruState), -+ VMSTATE_UINT32(tpm_blobs.volatil.size, TPMPassthruState), -+ VMSTATE_VBUFFER_ALLOC_UINT32(tpm_blobs.volatil.buffer, -+ TPMPassthruState, 1, NULL, -+ tpm_blobs.volatil.size), -+ -+ VMSTATE_UINT32(tpm_blobs.savestate_flags, TPMPassthruState), -+ VMSTATE_UINT32(tpm_blobs.savestate.size, TPMPassthruState), -+ VMSTATE_VBUFFER_ALLOC_UINT32(tpm_blobs.savestate.buffer, -+ TPMPassthruState, 1, NULL, -+ tpm_blobs.savestate.size), -+ VMSTATE_END_OF_LIST() -+ } -+}; -+ - static const TPMDriverOps tpm_cuse_driver = { - .type = TPM_TYPE_CUSE_TPM, - .opts = tpm_passthrough_cmdline_opts, -diff --git a/hw/tpm/tpm_tis.c b/hw/tpm/tpm_tis.c -index 14d9e83ea2..9b660cf737 100644 ---- a/hw/tpm/tpm_tis.c -+++ b/hw/tpm/tpm_tis.c -@@ -368,6 +368,8 @@ static void tpm_tis_receive_bh(void *opaque) - TPMTISEmuState *tis = &s->s.tis; - uint8_t locty = s->locty_number; - -+ tis->bh_scheduled = false; -+ - qemu_mutex_lock(&s->state_lock); - - tpm_tis_sts_set(&tis->loc[locty], -@@ -415,6 +417,8 @@ static void tpm_tis_receive_cb(TPMState *s, uint8_t locty, - qemu_mutex_unlock(&s->state_lock); - - qemu_bh_schedule(tis->bh); -+ -+ tis->bh_scheduled = true; - } - - /* -@@ -1030,9 +1034,140 @@ static void tpm_tis_reset(DeviceState *dev) - tpm_tis_do_startup_tpm(s); - } - -+ -+/* persistent state handling */ -+ -+static void tpm_tis_pre_save(void *opaque) -+{ -+ TPMState *s = opaque; -+ TPMTISEmuState *tis = &s->s.tis; -+ uint8_t locty = tis->active_locty; -+ -+ DPRINTF("tpm_tis: suspend: locty = %d : r_offset = %d, w_offset = %d\n", -+ locty, tis->loc[0].r_offset, tis->loc[0].w_offset); -+#ifdef DEBUG_TIS -+ tpm_tis_dump_state(opaque, 0); -+#endif -+ -+ qemu_mutex_lock(&s->state_lock); -+ -+ /* wait for outstanding request to complete */ -+ if (TPM_TIS_IS_VALID_LOCTY(locty) && -+ tis->loc[locty].state == TPM_TIS_STATE_EXECUTION) { -+ /* -+ * If we get here when the bh is scheduled but did not run, -+ * we won't get notified... -+ */ -+ if (!tis->bh_scheduled) { -+ /* backend thread to notify us */ -+ qemu_cond_wait(&s->cmd_complete, &s->state_lock); -+ } -+ if (tis->loc[locty].state == TPM_TIS_STATE_EXECUTION) { -+ /* bottom half did not run - run its function */ -+ qemu_mutex_unlock(&s->state_lock); -+ tpm_tis_receive_bh(opaque); -+ qemu_mutex_lock(&s->state_lock); -+ } -+ } -+ -+ qemu_mutex_unlock(&s->state_lock); -+ -+ /* copy current active read or write buffer into the buffer -+ written to disk */ -+ if (TPM_TIS_IS_VALID_LOCTY(locty)) { -+ switch (tis->loc[locty].state) { -+ case TPM_TIS_STATE_RECEPTION: -+ memcpy(tis->buf, -+ tis->loc[locty].w_buffer.buffer, -+ MIN(sizeof(tis->buf), -+ tis->loc[locty].w_buffer.size)); -+ tis->offset = tis->loc[locty].w_offset; -+ break; -+ case TPM_TIS_STATE_COMPLETION: -+ memcpy(tis->buf, -+ tis->loc[locty].r_buffer.buffer, -+ MIN(sizeof(tis->buf), -+ tis->loc[locty].r_buffer.size)); -+ tis->offset = tis->loc[locty].r_offset; -+ break; -+ default: -+ /* leak nothing */ -+ memset(tis->buf, 0x0, sizeof(tis->buf)); -+ break; -+ } -+ } -+} -+ -+static int tpm_tis_post_load(void *opaque, -+ int version_id __attribute__((unused))) -+{ -+ TPMState *s = opaque; -+ TPMTISEmuState *tis = &s->s.tis; -+ -+ uint8_t locty = tis->active_locty; -+ -+ if (TPM_TIS_IS_VALID_LOCTY(locty)) { -+ switch (tis->loc[locty].state) { -+ case TPM_TIS_STATE_RECEPTION: -+ memcpy(tis->loc[locty].w_buffer.buffer, -+ tis->buf, -+ MIN(sizeof(tis->buf), -+ tis->loc[locty].w_buffer.size)); -+ tis->loc[locty].w_offset = tis->offset; -+ break; -+ case TPM_TIS_STATE_COMPLETION: -+ memcpy(tis->loc[locty].r_buffer.buffer, -+ tis->buf, -+ MIN(sizeof(tis->buf), -+ tis->loc[locty].r_buffer.size)); -+ tis->loc[locty].r_offset = tis->offset; -+ break; -+ default: -+ break; -+ } -+ } -+ -+ DPRINTF("tpm_tis: resume : locty = %d : r_offset = %d, w_offset = %d\n", -+ locty, tis->loc[0].r_offset, tis->loc[0].w_offset); -+ -+ return 0; -+} -+ -+static const VMStateDescription vmstate_locty = { -+ .name = "loc", -+ .version_id = 1, -+ .minimum_version_id = 0, -+ .minimum_version_id_old = 0, -+ .fields = (VMStateField[]) { -+ VMSTATE_UINT32(state, TPMLocality), -+ VMSTATE_UINT32(inte, TPMLocality), -+ VMSTATE_UINT32(ints, TPMLocality), -+ VMSTATE_UINT8(access, TPMLocality), -+ VMSTATE_UINT32(sts, TPMLocality), -+ VMSTATE_UINT32(iface_id, TPMLocality), -+ VMSTATE_END_OF_LIST(), -+ } -+}; -+ - static const VMStateDescription vmstate_tpm_tis = { - .name = "tpm", -- .unmigratable = 1, -+ .version_id = 1, -+ .minimum_version_id = 0, -+ .minimum_version_id_old = 0, -+ .pre_save = tpm_tis_pre_save, -+ .post_load = tpm_tis_post_load, -+ .fields = (VMStateField[]) { -+ VMSTATE_UINT32(s.tis.offset, TPMState), -+ VMSTATE_BUFFER(s.tis.buf, TPMState), -+ VMSTATE_UINT8(s.tis.active_locty, TPMState), -+ VMSTATE_UINT8(s.tis.aborting_locty, TPMState), -+ VMSTATE_UINT8(s.tis.next_locty, TPMState), -+ -+ VMSTATE_STRUCT_ARRAY(s.tis.loc, TPMState, TPM_TIS_NUM_LOCALITIES, 1, -+ vmstate_locty, TPMLocality), -+ -+ VMSTATE_END_OF_LIST() -+ } - }; - - static Property tpm_tis_properties[] = { -diff --git a/hw/tpm/tpm_tis.h b/hw/tpm/tpm_tis.h -index a1df41fa21..b7fc0ea1a9 100644 ---- a/hw/tpm/tpm_tis.h -+++ b/hw/tpm/tpm_tis.h -@@ -54,6 +54,8 @@ typedef struct TPMLocality { - - typedef struct TPMTISEmuState { - QEMUBH *bh; -+ bool bh_scheduled; /* bh scheduled but did not run yet */ -+ - uint32_t offset; - uint8_t buf[TPM_TIS_BUFFER_MAX]; - -diff --git a/hw/tpm/tpm_util.c b/hw/tpm/tpm_util.c -index 7b35429725..b6ff74d946 100644 ---- a/hw/tpm/tpm_util.c -+++ b/hw/tpm/tpm_util.c -@@ -22,6 +22,17 @@ - #include "qemu/osdep.h" - #include "tpm_util.h" - #include "tpm_int.h" -+#include "tpm_ioctl.h" -+#include "qemu/error-report.h" -+ -+#define DEBUG_TPM 0 -+ -+#define DPRINTF(fmt, ...) do { \ -+ if (DEBUG_TPM) { \ -+ fprintf(stderr, fmt, ## __VA_ARGS__); \ -+ } \ -+} while (0) -+ - - /* - * A basic test of a TPM device. We expect a well formatted response header -@@ -125,3 +136,215 @@ int tpm_util_test_tpmdev(int tpm_fd, TPMVersion *tpm_version) - - return 1; - } -+ -+static void tpm_sized_buffer_reset(TPMSizedBuffer *tsb) -+{ -+ g_free(tsb->buffer); -+ tsb->buffer = NULL; -+ tsb->size = 0; -+} -+ -+/* -+ * Transfer a TPM state blob from the TPM into a provided buffer. -+ * -+ * @fd: file descriptor to talk to the CUSE TPM -+ * @type: the type of blob to transfer -+ * @decrypted_blob: whether we request to receive decrypted blobs -+ * @tsb: the TPMSizeBuffer to fill with the blob -+ * @flags: the flags to return to the caller -+ */ -+static int tpm_util_cuse_get_state_blob(int fd, -+ uint8_t type, -+ bool decrypted_blob, -+ TPMSizedBuffer *tsb, -+ uint32_t *flags) -+{ -+ ptm_getstate pgs; -+ uint16_t offset = 0; -+ ptm_res res; -+ ssize_t n; -+ size_t to_read; -+ -+ tpm_sized_buffer_reset(tsb); -+ -+ pgs.u.req.state_flags = (decrypted_blob) ? PTM_STATE_FLAG_DECRYPTED : 0; -+ pgs.u.req.type = type; -+ pgs.u.req.offset = offset; -+ -+ if (ioctl(fd, PTM_GET_STATEBLOB, &pgs) < 0) { -+ error_report("CUSE TPM PTM_GET_STATEBLOB ioctl failed: %s", -+ strerror(errno)); -+ goto err_exit; -+ } -+ res = pgs.u.resp.tpm_result; -+ if (res != 0 && (res & 0x800) == 0) { -+ error_report("Getting the stateblob (type %d) failed with a TPM " -+ "error 0x%x", type, res); -+ goto err_exit; -+ } -+ -+ *flags = pgs.u.resp.state_flags; -+ -+ tsb->buffer = g_malloc(pgs.u.resp.totlength); -+ memcpy(tsb->buffer, pgs.u.resp.data, pgs.u.resp.length); -+ tsb->size = pgs.u.resp.length; -+ -+ /* if there are bytes left to get use read() interface */ -+ while (tsb->size < pgs.u.resp.totlength) { -+ to_read = pgs.u.resp.totlength - tsb->size; -+ if (unlikely(to_read > SSIZE_MAX)) { -+ to_read = SSIZE_MAX; -+ } -+ -+ n = read(fd, &tsb->buffer[tsb->size], to_read); -+ if (n != to_read) { -+ error_report("Could not read stateblob (type %d) : %s", -+ type, strerror(errno)); -+ goto err_exit; -+ } -+ tsb->size += to_read; -+ } -+ -+ DPRINTF("tpm_util: got state blob type %d, %d bytes, flags 0x%08x, " -+ "decrypted=%d\n", type, tsb->size, *flags, decrypted_blob); -+ -+ return 0; -+ -+err_exit: -+ return 1; -+} -+ -+int tpm_util_cuse_get_state_blobs(int tpm_fd, -+ bool decrypted_blobs, -+ TPMBlobBuffers *tpm_blobs) -+{ -+ if (tpm_util_cuse_get_state_blob(tpm_fd, PTM_BLOB_TYPE_PERMANENT, -+ decrypted_blobs, -+ &tpm_blobs->permanent, -+ &tpm_blobs->permanent_flags) || -+ tpm_util_cuse_get_state_blob(tpm_fd, PTM_BLOB_TYPE_VOLATILE, -+ decrypted_blobs, -+ &tpm_blobs->volatil, -+ &tpm_blobs->volatil_flags) || -+ tpm_util_cuse_get_state_blob(tpm_fd, PTM_BLOB_TYPE_SAVESTATE, -+ decrypted_blobs, -+ &tpm_blobs->savestate, -+ &tpm_blobs->savestate_flags)) { -+ goto err_exit; -+ } -+ -+ return 0; -+ -+ err_exit: -+ tpm_sized_buffer_reset(&tpm_blobs->volatil); -+ tpm_sized_buffer_reset(&tpm_blobs->permanent); -+ tpm_sized_buffer_reset(&tpm_blobs->savestate); -+ -+ return 1; -+} -+ -+static int tpm_util_cuse_do_set_stateblob_ioctl(int fd, -+ uint32_t flags, -+ uint32_t type, -+ uint32_t length) -+{ -+ ptm_setstate pss; -+ -+ pss.u.req.state_flags = flags; -+ pss.u.req.type = type; -+ pss.u.req.length = length; -+ -+ if (ioctl(fd, PTM_SET_STATEBLOB, &pss) < 0) { -+ error_report("CUSE TPM PTM_SET_STATEBLOB ioctl failed: %s", -+ strerror(errno)); -+ return 1; -+ } -+ -+ if (pss.u.resp.tpm_result != 0) { -+ error_report("Setting the stateblob (type %d) failed with a TPM " -+ "error 0x%x", type, pss.u.resp.tpm_result); -+ return 1; -+ } -+ -+ return 0; -+} -+ -+ -+/* -+ * Transfer a TPM state blob to the CUSE TPM. -+ * -+ * @fd: file descriptor to talk to the CUSE TPM -+ * @type: the type of TPM state blob to transfer -+ * @tsb: TPMSizeBuffer containing the TPM state blob -+ * @flags: Flags describing the (encryption) state of the TPM state blob -+ */ -+static int tpm_util_cuse_set_state_blob(int fd, -+ uint32_t type, -+ TPMSizedBuffer *tsb, -+ uint32_t flags) -+{ -+ uint32_t offset = 0; -+ ssize_t n; -+ size_t to_write; -+ -+ /* initiate the transfer to the CUSE TPM */ -+ if (tpm_util_cuse_do_set_stateblob_ioctl(fd, flags, type, 0)) { -+ return 1; -+ } -+ -+ /* use the write() interface for transferring the state blob */ -+ while (offset < tsb->size) { -+ to_write = tsb->size - offset; -+ if (unlikely(to_write > SSIZE_MAX)) { -+ to_write = SSIZE_MAX; -+ } -+ -+ n = write(fd, &tsb->buffer[offset], to_write); -+ if (n != to_write) { -+ error_report("Writing the stateblob (type %d) failed: %s", -+ type, strerror(errno)); -+ goto err_exit; -+ } -+ offset += to_write; -+ } -+ -+ /* inidicate that the transfer is finished */ -+ if (tpm_util_cuse_do_set_stateblob_ioctl(fd, flags, type, 0)) { -+ goto err_exit; -+ } -+ -+ DPRINTF("tpm_util: set the state blob type %d, %d bytes, flags 0x%08x\n", -+ type, tsb->size, flags); -+ -+ return 0; -+ -+err_exit: -+ return 1; -+} -+ -+int tpm_util_cuse_set_state_blobs(int tpm_fd, -+ TPMBlobBuffers *tpm_blobs) -+{ -+ ptm_res res; -+ -+ if (ioctl(tpm_fd, PTM_STOP, &res) < 0) { -+ error_report("tpm_passthrough: Could not stop " -+ "the CUSE TPM: %s (%i)", -+ strerror(errno), errno); -+ return 1; -+ } -+ -+ if (tpm_util_cuse_set_state_blob(tpm_fd, PTM_BLOB_TYPE_PERMANENT, -+ &tpm_blobs->permanent, -+ tpm_blobs->permanent_flags) || -+ tpm_util_cuse_set_state_blob(tpm_fd, PTM_BLOB_TYPE_VOLATILE, -+ &tpm_blobs->volatil, -+ tpm_blobs->volatil_flags) || -+ tpm_util_cuse_set_state_blob(tpm_fd, PTM_BLOB_TYPE_SAVESTATE, -+ &tpm_blobs->savestate, -+ tpm_blobs->savestate_flags)) { -+ return 1; -+ } -+ -+ return 0; -+} -diff --git a/hw/tpm/tpm_util.h b/hw/tpm/tpm_util.h -index df76245e6e..c24071d812 100644 ---- a/hw/tpm/tpm_util.h -+++ b/hw/tpm/tpm_util.h -@@ -26,4 +26,11 @@ - - int tpm_util_test_tpmdev(int tpm_fd, TPMVersion *tpm_version); - -+int tpm_util_cuse_get_state_blobs(int tpm_fd, -+ bool decrypted_blobs, -+ TPMBlobBuffers *tpm_blobs); -+ -+int tpm_util_cuse_set_state_blobs(int tpm_fd, -+ TPMBlobBuffers *tpm_blobs); -+ - #endif /* TPM_TPM_UTIL_H */ -diff --git a/include/sysemu/tpm_backend.h b/include/sysemu/tpm_backend.h -index b58f52d39f..3403821b9d 100644 ---- a/include/sysemu/tpm_backend.h -+++ b/include/sysemu/tpm_backend.h -@@ -62,6 +62,18 @@ typedef struct TPMSizedBuffer { - uint8_t *buffer; - } TPMSizedBuffer; - -+/* blobs from the TPM; part of VM state when migrating */ -+typedef struct TPMBlobBuffers { -+ uint32_t permanent_flags; -+ TPMSizedBuffer permanent; -+ -+ uint32_t volatil_flags; -+ TPMSizedBuffer volatil; -+ -+ uint32_t savestate_flags; -+ TPMSizedBuffer savestate; -+} TPMBlobBuffers; -+ - struct TPMDriverOps { - enum TpmType type; - const QemuOptDesc *opts; --- -2.11.0 - diff --git a/import-layers/yocto-poky/meta/recipes-devtools/qemu/qemu/CVE-2017-13672.patch b/import-layers/yocto-poky/meta/recipes-devtools/qemu/qemu/CVE-2017-13672.patch deleted file mode 100644 index ce0b1ee3e..000000000 --- a/import-layers/yocto-poky/meta/recipes-devtools/qemu/qemu/CVE-2017-13672.patch +++ /dev/null @@ -1,504 +0,0 @@ -From 3d90c6254863693a6b13d918d2b8682e08bbc681 Mon Sep 17 00:00:00 2001 -From: Gerd Hoffmann <kraxel@redhat.com> -Date: Mon, 28 Aug 2017 14:29:06 +0200 -Subject: [PATCH] vga: stop passing pointers to vga_draw_line* functions - -Instead pass around the address (aka offset into vga memory). -Add vga_read_* helper functions which apply vbe_size_mask to -the address, to make sure the address stays within the valid -range, similar to the cirrus blitter fixes (commits ffaf857778 -and 026aeffcb4). - -Impact: DoS for privileged guest users. qemu crashes with -a segfault, when hitting the guard page after vga memory -allocation, while reading vga memory for display updates. - -Fixes: CVE-2017-13672 -Cc: P J P <ppandit@redhat.com> -Reported-by: David Buchanan <d@vidbuchanan.co.uk> -Signed-off-by: Gerd Hoffmann <kraxel@redhat.com> -Message-id: 20170828122906.18993-1-kraxel@redhat.com - -Upstream-Status: Backport -[https://git.qemu.org/?p=qemu.git;a=commit;h=3d90c6254863693a6b13d918d2b8682e08bbc681] - -CVE: CVE-2017-13672 - -Signed-off-by: Yi Zhao <yi.zhao@windriver.com> ---- - hw/display/vga-helpers.h | 202 ++++++++++++++++++++++++++--------------------- - hw/display/vga.c | 5 +- - hw/display/vga_int.h | 1 + - 3 files changed, 114 insertions(+), 94 deletions(-) - -diff --git a/hw/display/vga-helpers.h b/hw/display/vga-helpers.h -index 94f6de2..5a752b3 100644 ---- a/hw/display/vga-helpers.h -+++ b/hw/display/vga-helpers.h -@@ -95,20 +95,46 @@ static void vga_draw_glyph9(uint8_t *d, int linesize, - } while (--h); - } - -+static inline uint8_t vga_read_byte(VGACommonState *vga, uint32_t addr) -+{ -+ return vga->vram_ptr[addr & vga->vbe_size_mask]; -+} -+ -+static inline uint16_t vga_read_word_le(VGACommonState *vga, uint32_t addr) -+{ -+ uint32_t offset = addr & vga->vbe_size_mask & ~1; -+ uint16_t *ptr = (uint16_t *)(vga->vram_ptr + offset); -+ return lduw_le_p(ptr); -+} -+ -+static inline uint16_t vga_read_word_be(VGACommonState *vga, uint32_t addr) -+{ -+ uint32_t offset = addr & vga->vbe_size_mask & ~1; -+ uint16_t *ptr = (uint16_t *)(vga->vram_ptr + offset); -+ return lduw_be_p(ptr); -+} -+ -+static inline uint32_t vga_read_dword_le(VGACommonState *vga, uint32_t addr) -+{ -+ uint32_t offset = addr & vga->vbe_size_mask & ~3; -+ uint32_t *ptr = (uint32_t *)(vga->vram_ptr + offset); -+ return ldl_le_p(ptr); -+} -+ - /* - * 4 color mode - */ --static void vga_draw_line2(VGACommonState *s1, uint8_t *d, -- const uint8_t *s, int width) -+static void vga_draw_line2(VGACommonState *vga, uint8_t *d, -+ uint32_t addr, int width) - { - uint32_t plane_mask, *palette, data, v; - int x; - -- palette = s1->last_palette; -- plane_mask = mask16[s1->ar[VGA_ATC_PLANE_ENABLE] & 0xf]; -+ palette = vga->last_palette; -+ plane_mask = mask16[vga->ar[VGA_ATC_PLANE_ENABLE] & 0xf]; - width >>= 3; - for(x = 0; x < width; x++) { -- data = ((uint32_t *)s)[0]; -+ data = vga_read_dword_le(vga, addr); - data &= plane_mask; - v = expand2[GET_PLANE(data, 0)]; - v |= expand2[GET_PLANE(data, 2)] << 2; -@@ -124,7 +150,7 @@ static void vga_draw_line2(VGACommonState *s1, uint8_t *d, - ((uint32_t *)d)[6] = palette[(v >> 4) & 0xf]; - ((uint32_t *)d)[7] = palette[(v >> 0) & 0xf]; - d += 32; -- s += 4; -+ addr += 4; - } - } - -@@ -134,17 +160,17 @@ static void vga_draw_line2(VGACommonState *s1, uint8_t *d, - /* - * 4 color mode, dup2 horizontal - */ --static void vga_draw_line2d2(VGACommonState *s1, uint8_t *d, -- const uint8_t *s, int width) -+static void vga_draw_line2d2(VGACommonState *vga, uint8_t *d, -+ uint32_t addr, int width) - { - uint32_t plane_mask, *palette, data, v; - int x; - -- palette = s1->last_palette; -- plane_mask = mask16[s1->ar[VGA_ATC_PLANE_ENABLE] & 0xf]; -+ palette = vga->last_palette; -+ plane_mask = mask16[vga->ar[VGA_ATC_PLANE_ENABLE] & 0xf]; - width >>= 3; - for(x = 0; x < width; x++) { -- data = ((uint32_t *)s)[0]; -+ data = vga_read_dword_le(vga, addr); - data &= plane_mask; - v = expand2[GET_PLANE(data, 0)]; - v |= expand2[GET_PLANE(data, 2)] << 2; -@@ -160,24 +186,24 @@ static void vga_draw_line2d2(VGACommonState *s1, uint8_t *d, - PUT_PIXEL2(d, 6, palette[(v >> 4) & 0xf]); - PUT_PIXEL2(d, 7, palette[(v >> 0) & 0xf]); - d += 64; -- s += 4; -+ addr += 4; - } - } - - /* - * 16 color mode - */ --static void vga_draw_line4(VGACommonState *s1, uint8_t *d, -- const uint8_t *s, int width) -+static void vga_draw_line4(VGACommonState *vga, uint8_t *d, -+ uint32_t addr, int width) - { - uint32_t plane_mask, data, v, *palette; - int x; - -- palette = s1->last_palette; -- plane_mask = mask16[s1->ar[VGA_ATC_PLANE_ENABLE] & 0xf]; -+ palette = vga->last_palette; -+ plane_mask = mask16[vga->ar[VGA_ATC_PLANE_ENABLE] & 0xf]; - width >>= 3; - for(x = 0; x < width; x++) { -- data = ((uint32_t *)s)[0]; -+ data = vga_read_dword_le(vga, addr); - data &= plane_mask; - v = expand4[GET_PLANE(data, 0)]; - v |= expand4[GET_PLANE(data, 1)] << 1; -@@ -192,24 +218,24 @@ static void vga_draw_line4(VGACommonState *s1, uint8_t *d, - ((uint32_t *)d)[6] = palette[(v >> 4) & 0xf]; - ((uint32_t *)d)[7] = palette[(v >> 0) & 0xf]; - d += 32; -- s += 4; -+ addr += 4; - } - } - - /* - * 16 color mode, dup2 horizontal - */ --static void vga_draw_line4d2(VGACommonState *s1, uint8_t *d, -- const uint8_t *s, int width) -+static void vga_draw_line4d2(VGACommonState *vga, uint8_t *d, -+ uint32_t addr, int width) - { - uint32_t plane_mask, data, v, *palette; - int x; - -- palette = s1->last_palette; -- plane_mask = mask16[s1->ar[VGA_ATC_PLANE_ENABLE] & 0xf]; -+ palette = vga->last_palette; -+ plane_mask = mask16[vga->ar[VGA_ATC_PLANE_ENABLE] & 0xf]; - width >>= 3; - for(x = 0; x < width; x++) { -- data = ((uint32_t *)s)[0]; -+ data = vga_read_dword_le(vga, addr); - data &= plane_mask; - v = expand4[GET_PLANE(data, 0)]; - v |= expand4[GET_PLANE(data, 1)] << 1; -@@ -224,7 +250,7 @@ static void vga_draw_line4d2(VGACommonState *s1, uint8_t *d, - PUT_PIXEL2(d, 6, palette[(v >> 4) & 0xf]); - PUT_PIXEL2(d, 7, palette[(v >> 0) & 0xf]); - d += 64; -- s += 4; -+ addr += 4; - } - } - -@@ -233,21 +259,21 @@ static void vga_draw_line4d2(VGACommonState *s1, uint8_t *d, - * - * XXX: add plane_mask support (never used in standard VGA modes) - */ --static void vga_draw_line8d2(VGACommonState *s1, uint8_t *d, -- const uint8_t *s, int width) -+static void vga_draw_line8d2(VGACommonState *vga, uint8_t *d, -+ uint32_t addr, int width) - { - uint32_t *palette; - int x; - -- palette = s1->last_palette; -+ palette = vga->last_palette; - width >>= 3; - for(x = 0; x < width; x++) { -- PUT_PIXEL2(d, 0, palette[s[0]]); -- PUT_PIXEL2(d, 1, palette[s[1]]); -- PUT_PIXEL2(d, 2, palette[s[2]]); -- PUT_PIXEL2(d, 3, palette[s[3]]); -+ PUT_PIXEL2(d, 0, palette[vga_read_byte(vga, addr + 0)]); -+ PUT_PIXEL2(d, 1, palette[vga_read_byte(vga, addr + 1)]); -+ PUT_PIXEL2(d, 2, palette[vga_read_byte(vga, addr + 2)]); -+ PUT_PIXEL2(d, 3, palette[vga_read_byte(vga, addr + 3)]); - d += 32; -- s += 4; -+ addr += 4; - } - } - -@@ -256,63 +282,63 @@ static void vga_draw_line8d2(VGACommonState *s1, uint8_t *d, - * - * XXX: add plane_mask support (never used in standard VGA modes) - */ --static void vga_draw_line8(VGACommonState *s1, uint8_t *d, -- const uint8_t *s, int width) -+static void vga_draw_line8(VGACommonState *vga, uint8_t *d, -+ uint32_t addr, int width) - { - uint32_t *palette; - int x; - -- palette = s1->last_palette; -+ palette = vga->last_palette; - width >>= 3; - for(x = 0; x < width; x++) { -- ((uint32_t *)d)[0] = palette[s[0]]; -- ((uint32_t *)d)[1] = palette[s[1]]; -- ((uint32_t *)d)[2] = palette[s[2]]; -- ((uint32_t *)d)[3] = palette[s[3]]; -- ((uint32_t *)d)[4] = palette[s[4]]; -- ((uint32_t *)d)[5] = palette[s[5]]; -- ((uint32_t *)d)[6] = palette[s[6]]; -- ((uint32_t *)d)[7] = palette[s[7]]; -+ ((uint32_t *)d)[0] = palette[vga_read_byte(vga, addr + 0)]; -+ ((uint32_t *)d)[1] = palette[vga_read_byte(vga, addr + 1)]; -+ ((uint32_t *)d)[2] = palette[vga_read_byte(vga, addr + 2)]; -+ ((uint32_t *)d)[3] = palette[vga_read_byte(vga, addr + 3)]; -+ ((uint32_t *)d)[4] = palette[vga_read_byte(vga, addr + 4)]; -+ ((uint32_t *)d)[5] = palette[vga_read_byte(vga, addr + 5)]; -+ ((uint32_t *)d)[6] = palette[vga_read_byte(vga, addr + 6)]; -+ ((uint32_t *)d)[7] = palette[vga_read_byte(vga, addr + 7)]; - d += 32; -- s += 8; -+ addr += 8; - } - } - - /* - * 15 bit color - */ --static void vga_draw_line15_le(VGACommonState *s1, uint8_t *d, -- const uint8_t *s, int width) -+static void vga_draw_line15_le(VGACommonState *vga, uint8_t *d, -+ uint32_t addr, int width) - { - int w; - uint32_t v, r, g, b; - - w = width; - do { -- v = lduw_le_p((void *)s); -+ v = vga_read_word_le(vga, addr); - r = (v >> 7) & 0xf8; - g = (v >> 2) & 0xf8; - b = (v << 3) & 0xf8; - ((uint32_t *)d)[0] = rgb_to_pixel32(r, g, b); -- s += 2; -+ addr += 2; - d += 4; - } while (--w != 0); - } - --static void vga_draw_line15_be(VGACommonState *s1, uint8_t *d, -- const uint8_t *s, int width) -+static void vga_draw_line15_be(VGACommonState *vga, uint8_t *d, -+ uint32_t addr, int width) - { - int w; - uint32_t v, r, g, b; - - w = width; - do { -- v = lduw_be_p((void *)s); -+ v = vga_read_word_be(vga, addr); - r = (v >> 7) & 0xf8; - g = (v >> 2) & 0xf8; - b = (v << 3) & 0xf8; - ((uint32_t *)d)[0] = rgb_to_pixel32(r, g, b); -- s += 2; -+ addr += 2; - d += 4; - } while (--w != 0); - } -@@ -320,38 +346,38 @@ static void vga_draw_line15_be(VGACommonState *s1, uint8_t *d, - /* - * 16 bit color - */ --static void vga_draw_line16_le(VGACommonState *s1, uint8_t *d, -- const uint8_t *s, int width) -+static void vga_draw_line16_le(VGACommonState *vga, uint8_t *d, -+ uint32_t addr, int width) - { - int w; - uint32_t v, r, g, b; - - w = width; - do { -- v = lduw_le_p((void *)s); -+ v = vga_read_word_le(vga, addr); - r = (v >> 8) & 0xf8; - g = (v >> 3) & 0xfc; - b = (v << 3) & 0xf8; - ((uint32_t *)d)[0] = rgb_to_pixel32(r, g, b); -- s += 2; -+ addr += 2; - d += 4; - } while (--w != 0); - } - --static void vga_draw_line16_be(VGACommonState *s1, uint8_t *d, -- const uint8_t *s, int width) -+static void vga_draw_line16_be(VGACommonState *vga, uint8_t *d, -+ uint32_t addr, int width) - { - int w; - uint32_t v, r, g, b; - - w = width; - do { -- v = lduw_be_p((void *)s); -+ v = vga_read_word_be(vga, addr); - r = (v >> 8) & 0xf8; - g = (v >> 3) & 0xfc; - b = (v << 3) & 0xf8; - ((uint32_t *)d)[0] = rgb_to_pixel32(r, g, b); -- s += 2; -+ addr += 2; - d += 4; - } while (--w != 0); - } -@@ -359,36 +385,36 @@ static void vga_draw_line16_be(VGACommonState *s1, uint8_t *d, - /* - * 24 bit color - */ --static void vga_draw_line24_le(VGACommonState *s1, uint8_t *d, -- const uint8_t *s, int width) -+static void vga_draw_line24_le(VGACommonState *vga, uint8_t *d, -+ uint32_t addr, int width) - { - int w; - uint32_t r, g, b; - - w = width; - do { -- b = s[0]; -- g = s[1]; -- r = s[2]; -+ b = vga_read_byte(vga, addr + 0); -+ g = vga_read_byte(vga, addr + 1); -+ r = vga_read_byte(vga, addr + 2); - ((uint32_t *)d)[0] = rgb_to_pixel32(r, g, b); -- s += 3; -+ addr += 3; - d += 4; - } while (--w != 0); - } - --static void vga_draw_line24_be(VGACommonState *s1, uint8_t *d, -- const uint8_t *s, int width) -+static void vga_draw_line24_be(VGACommonState *vga, uint8_t *d, -+ uint32_t addr, int width) - { - int w; - uint32_t r, g, b; - - w = width; - do { -- r = s[0]; -- g = s[1]; -- b = s[2]; -+ r = vga_read_byte(vga, addr + 0); -+ g = vga_read_byte(vga, addr + 1); -+ b = vga_read_byte(vga, addr + 2); - ((uint32_t *)d)[0] = rgb_to_pixel32(r, g, b); -- s += 3; -+ addr += 3; - d += 4; - } while (--w != 0); - } -@@ -396,44 +422,36 @@ static void vga_draw_line24_be(VGACommonState *s1, uint8_t *d, - /* - * 32 bit color - */ --static void vga_draw_line32_le(VGACommonState *s1, uint8_t *d, -- const uint8_t *s, int width) -+static void vga_draw_line32_le(VGACommonState *vga, uint8_t *d, -+ uint32_t addr, int width) - { --#ifndef HOST_WORDS_BIGENDIAN -- memcpy(d, s, width * 4); --#else - int w; - uint32_t r, g, b; - - w = width; - do { -- b = s[0]; -- g = s[1]; -- r = s[2]; -+ b = vga_read_byte(vga, addr + 0); -+ g = vga_read_byte(vga, addr + 1); -+ r = vga_read_byte(vga, addr + 2); - ((uint32_t *)d)[0] = rgb_to_pixel32(r, g, b); -- s += 4; -+ addr += 4; - d += 4; - } while (--w != 0); --#endif - } - --static void vga_draw_line32_be(VGACommonState *s1, uint8_t *d, -- const uint8_t *s, int width) -+static void vga_draw_line32_be(VGACommonState *vga, uint8_t *d, -+ uint32_t addr, int width) - { --#ifdef HOST_WORDS_BIGENDIAN -- memcpy(d, s, width * 4); --#else - int w; - uint32_t r, g, b; - - w = width; - do { -- r = s[1]; -- g = s[2]; -- b = s[3]; -+ r = vga_read_byte(vga, addr + 1); -+ g = vga_read_byte(vga, addr + 2); -+ b = vga_read_byte(vga, addr + 3); - ((uint32_t *)d)[0] = rgb_to_pixel32(r, g, b); -- s += 4; -+ addr += 4; - d += 4; - } while (--w != 0); --#endif - } -diff --git a/hw/display/vga.c b/hw/display/vga.c -index ad7a465..6fc8c87 100644 ---- a/hw/display/vga.c -+++ b/hw/display/vga.c -@@ -1005,7 +1005,7 @@ void vga_mem_writeb(VGACommonState *s, hwaddr addr, uint32_t val) - } - - typedef void vga_draw_line_func(VGACommonState *s1, uint8_t *d, -- const uint8_t *s, int width); -+ uint32_t srcaddr, int width); - - #include "vga-helpers.h" - -@@ -1666,7 +1666,7 @@ static void vga_draw_graphic(VGACommonState *s, int full_update) - if (y_start < 0) - y_start = y; - if (!(is_buffer_shared(surface))) { -- vga_draw_line(s, d, s->vram_ptr + addr, width); -+ vga_draw_line(s, d, addr, width); - if (s->cursor_draw_line) - s->cursor_draw_line(s, d, y); - } -@@ -2170,6 +2170,7 @@ void vga_common_init(VGACommonState *s, Object *obj, bool global_vmstate) - if (!s->vbe_size) { - s->vbe_size = s->vram_size; - } -+ s->vbe_size_mask = s->vbe_size - 1; - - s->is_vbe_vmstate = 1; - memory_region_init_ram_nomigrate(&s->vram, obj, "vga.vram", s->vram_size, -diff --git a/hw/display/vga_int.h b/hw/display/vga_int.h -index dd6c958..ad34a1f 100644 ---- a/hw/display/vga_int.h -+++ b/hw/display/vga_int.h -@@ -94,6 +94,7 @@ typedef struct VGACommonState { - uint32_t vram_size; - uint32_t vram_size_mb; /* property */ - uint32_t vbe_size; -+ uint32_t vbe_size_mask; - uint32_t latch; - bool has_chain4_alias; - MemoryRegion chain4_alias; --- -2.7.4 - diff --git a/import-layers/yocto-poky/meta/recipes-devtools/qemu/qemu/CVE-2017-13673.patch b/import-layers/yocto-poky/meta/recipes-devtools/qemu/qemu/CVE-2017-13673.patch deleted file mode 100644 index 3d0695fd6..000000000 --- a/import-layers/yocto-poky/meta/recipes-devtools/qemu/qemu/CVE-2017-13673.patch +++ /dev/null @@ -1,53 +0,0 @@ -From e65294157d4b69393b3f819c99f4f647452b48e3 Mon Sep 17 00:00:00 2001 -From: Gerd Hoffmann <kraxel@redhat.com> -Date: Mon, 28 Aug 2017 14:33:07 +0200 -Subject: [PATCH] vga: fix display update region calculation (split screen) - -vga display update mis-calculated the region for the dirty bitmap -snapshot in case split screen mode is used. This can trigger an -assert in cpu_physical_memory_snapshot_get_dirty(). - -Impact: DoS for privileged guest users. - -Fixes: CVE-2017-13673 -Fixes: fec5e8c92becad223df9d972770522f64aafdb72 -Cc: P J P <ppandit@redhat.com> -Reported-by: David Buchanan <d@vidbuchanan.co.uk> -Signed-off-by: Gerd Hoffmann <kraxel@redhat.com> -Message-id: 20170828123307.15392-1-kraxel@redhat.com - -Upstream-Status: Backport -[https://git.qemu.org/?p=qemu.git;a=commit;h=e65294157d4b69393b3f819c99f4f647452b48e3] - -CVE: CVE-2017-13673 - -Signed-off-by: Yi Zhao <yi.zhao@windriver.com> ---- - hw/display/vga.c | 10 ++++++++-- - 1 file changed, 8 insertions(+), 2 deletions(-) - -diff --git a/hw/display/vga.c b/hw/display/vga.c -index 3433102..ad7a465 100644 ---- a/hw/display/vga.c -+++ b/hw/display/vga.c -@@ -1628,9 +1628,15 @@ static void vga_draw_graphic(VGACommonState *s, int full_update) - y1 = 0; - - if (!full_update) { -+ ram_addr_t region_start = addr1; -+ ram_addr_t region_end = addr1 + line_offset * height; - vga_sync_dirty_bitmap(s); -- snap = memory_region_snapshot_and_clear_dirty(&s->vram, addr1, -- line_offset * height, -+ if (s->line_compare < height) { -+ /* split screen mode */ -+ region_start = 0; -+ } -+ snap = memory_region_snapshot_and_clear_dirty(&s->vram, region_start, -+ region_end - region_start, - DIRTY_MEMORY_VGA); - } - --- -2.7.4 - diff --git a/import-layers/yocto-poky/meta/recipes-devtools/qemu/qemu/CVE-2017-13711.patch b/import-layers/yocto-poky/meta/recipes-devtools/qemu/qemu/CVE-2017-13711.patch deleted file mode 100644 index 352f73f62..000000000 --- a/import-layers/yocto-poky/meta/recipes-devtools/qemu/qemu/CVE-2017-13711.patch +++ /dev/null @@ -1,87 +0,0 @@ -From 1201d308519f1e915866d7583d5136d03cc1d384 Mon Sep 17 00:00:00 2001 -From: Samuel Thibault <samuel.thibault@ens-lyon.org> -Date: Fri, 25 Aug 2017 01:35:53 +0200 -Subject: [PATCH] slirp: fix clearing ifq_so from pending packets -MIME-Version: 1.0 -Content-Type: text/plain; charset=UTF-8 -Content-Transfer-Encoding: 8bit - -The if_fastq and if_batchq contain not only packets, but queues of packets -for the same socket. When sofree frees a socket, it thus has to clear ifq_so -from all the packets from the queues, not only the first. - -Signed-off-by: Samuel Thibault <samuel.thibault@ens-lyon.org> -Reviewed-by: Philippe Mathieu-Daudé <f4bug@amsat.org> -Cc: qemu-stable@nongnu.org -Signed-off-by: Peter Maydell <peter.maydell@linaro.org> - -Upstream-Status: Backport -[https://git.qemu.org/?p=qemu.git;a=commit;h=1201d308519f1e915866d7583d5136d03cc1d384] - -CVE: CVE-2017-13711 - -Signed-off-by: Yi Zhao <yi.zhao@windriver.com> ---- - slirp/socket.c | 39 +++++++++++++++++++++++---------------- - 1 file changed, 23 insertions(+), 16 deletions(-) - -diff --git a/slirp/socket.c b/slirp/socket.c -index ecec029..cb7b5b6 100644 ---- a/slirp/socket.c -+++ b/slirp/socket.c -@@ -60,29 +60,36 @@ socreate(Slirp *slirp) - } - - /* -+ * Remove references to so from the given message queue. -+ */ -+static void -+soqfree(struct socket *so, struct quehead *qh) -+{ -+ struct mbuf *ifq; -+ -+ for (ifq = (struct mbuf *) qh->qh_link; -+ (struct quehead *) ifq != qh; -+ ifq = ifq->ifq_next) { -+ if (ifq->ifq_so == so) { -+ struct mbuf *ifm; -+ ifq->ifq_so = NULL; -+ for (ifm = ifq->ifs_next; ifm != ifq; ifm = ifm->ifs_next) { -+ ifm->ifq_so = NULL; -+ } -+ } -+ } -+} -+ -+/* - * remque and free a socket, clobber cache - */ - void - sofree(struct socket *so) - { - Slirp *slirp = so->slirp; -- struct mbuf *ifm; - -- for (ifm = (struct mbuf *) slirp->if_fastq.qh_link; -- (struct quehead *) ifm != &slirp->if_fastq; -- ifm = ifm->ifq_next) { -- if (ifm->ifq_so == so) { -- ifm->ifq_so = NULL; -- } -- } -- -- for (ifm = (struct mbuf *) slirp->if_batchq.qh_link; -- (struct quehead *) ifm != &slirp->if_batchq; -- ifm = ifm->ifq_next) { -- if (ifm->ifq_so == so) { -- ifm->ifq_so = NULL; -- } -- } -+ soqfree(so, &slirp->if_fastq); -+ soqfree(so, &slirp->if_batchq); - - if (so->so_emu==EMU_RSH && so->extra) { - sofree(so->extra); --- -2.7.4 - diff --git a/import-layers/yocto-poky/meta/recipes-devtools/qemu/qemu/CVE-2017-14167.patch b/import-layers/yocto-poky/meta/recipes-devtools/qemu/qemu/CVE-2017-14167.patch deleted file mode 100644 index 969ad877d..000000000 --- a/import-layers/yocto-poky/meta/recipes-devtools/qemu/qemu/CVE-2017-14167.patch +++ /dev/null @@ -1,70 +0,0 @@ -From ed4f86e8b6eff8e600c69adee68c7cd34dd2cccb Mon Sep 17 00:00:00 2001 -From: Prasad J Pandit <pjp@fedoraproject.org> -Date: Thu, 7 Sep 2017 12:02:56 +0530 -Subject: [PATCH] multiboot: validate multiboot header address values - -While loading kernel via multiboot-v1 image, (flags & 0x00010000) -indicates that multiboot header contains valid addresses to load -the kernel image. These addresses are used to compute kernel -size and kernel text offset in the OS image. Validate these -address values to avoid an OOB access issue. - -This is CVE-2017-14167. - -Reported-by: Thomas Garnier <thgarnie@google.com> -Signed-off-by: Prasad J Pandit <pjp@fedoraproject.org> -Message-Id: <20170907063256.7418-1-ppandit@redhat.com> -Signed-off-by: Paolo Bonzini <pbonzini@redhat.com> - -Upstream-Status: Backport -[https://git.qemu.org/?p=qemu.git;a=commit;h=ed4f86e8b6eff8e600c69adee68c7cd34dd2cccb] - -CVE: CVE-2017-14167 - -Signed-off-by: Yi Zhao <yi.zhao@windriver.com> ---- - hw/i386/multiboot.c | 19 +++++++++++++++++++ - 1 file changed, 19 insertions(+) - -diff --git a/hw/i386/multiboot.c b/hw/i386/multiboot.c -index 6001f4c..c7b70c9 100644 ---- a/hw/i386/multiboot.c -+++ b/hw/i386/multiboot.c -@@ -221,15 +221,34 @@ int load_multiboot(FWCfgState *fw_cfg, - uint32_t mh_header_addr = ldl_p(header+i+12); - uint32_t mh_load_end_addr = ldl_p(header+i+20); - uint32_t mh_bss_end_addr = ldl_p(header+i+24); -+ - mh_load_addr = ldl_p(header+i+16); -+ if (mh_header_addr < mh_load_addr) { -+ fprintf(stderr, "invalid mh_load_addr address\n"); -+ exit(1); -+ } -+ - uint32_t mb_kernel_text_offset = i - (mh_header_addr - mh_load_addr); - uint32_t mb_load_size = 0; - mh_entry_addr = ldl_p(header+i+28); - - if (mh_load_end_addr) { -+ if (mh_bss_end_addr < mh_load_addr) { -+ fprintf(stderr, "invalid mh_bss_end_addr address\n"); -+ exit(1); -+ } - mb_kernel_size = mh_bss_end_addr - mh_load_addr; -+ -+ if (mh_load_end_addr < mh_load_addr) { -+ fprintf(stderr, "invalid mh_load_end_addr address\n"); -+ exit(1); -+ } - mb_load_size = mh_load_end_addr - mh_load_addr; - } else { -+ if (kernel_file_size < mb_kernel_text_offset) { -+ fprintf(stderr, "invalid kernel_file_size\n"); -+ exit(1); -+ } - mb_kernel_size = kernel_file_size - mb_kernel_text_offset; - mb_load_size = mb_kernel_size; - } --- -2.7.4 - diff --git a/import-layers/yocto-poky/meta/recipes-devtools/qemu/qemu/apic-fixup-fallthrough-to-PIC.patch b/import-layers/yocto-poky/meta/recipes-devtools/qemu/qemu/apic-fixup-fallthrough-to-PIC.patch index 9bbbc6f76..d6a3522ed 100644 --- a/import-layers/yocto-poky/meta/recipes-devtools/qemu/qemu/apic-fixup-fallthrough-to-PIC.patch +++ b/import-layers/yocto-poky/meta/recipes-devtools/qemu/qemu/apic-fixup-fallthrough-to-PIC.patch @@ -28,12 +28,12 @@ Signed-off-by: He Zhe <zhe.he@windriver.com> hw/intc/apic.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) -diff --git a/hw/intc/apic.c b/hw/intc/apic.c -index 45887d99..c5ae4087 100644 ---- a/hw/intc/apic.c -+++ b/hw/intc/apic.c -@@ -587,7 +587,7 @@ int apic_accept_pic_intr(DeviceState *dev) - APICCommonState *s = APIC_COMMON(dev); +Index: qemu-2.11.1/hw/intc/apic.c +=================================================================== +--- qemu-2.11.1.orig/hw/intc/apic.c ++++ qemu-2.11.1/hw/intc/apic.c +@@ -591,7 +591,7 @@ int apic_accept_pic_intr(DeviceState *de + APICCommonState *s = APIC(dev); uint32_t lvt0; - if (!s) @@ -41,6 +41,3 @@ index 45887d99..c5ae4087 100644 return -1; lvt0 = s->lvt[APIC_LVT_LINT0]; --- -2.11.0 - diff --git a/import-layers/yocto-poky/meta/recipes-devtools/qemu/qemu/chardev-connect-socket-to-a-spawned-command.patch b/import-layers/yocto-poky/meta/recipes-devtools/qemu/qemu/chardev-connect-socket-to-a-spawned-command.patch new file mode 100644 index 000000000..6e6bf95c1 --- /dev/null +++ b/import-layers/yocto-poky/meta/recipes-devtools/qemu/qemu/chardev-connect-socket-to-a-spawned-command.patch @@ -0,0 +1,242 @@ +From 3bb3100c22eb30146a69656480bdffeef8663575 Mon Sep 17 00:00:00 2001 +From: Alistair Francis <alistair.francis@xilinx.com> +Date: Thu, 21 Dec 2017 11:35:16 -0800 +Subject: [PATCH] chardev: connect socket to a spawned command + +The command is started in a shell (sh -c) with stdin connect to QEMU +via a Unix domain stream socket. QEMU then exchanges data via its own +end of the socket, just like it normally does. + +"-chardev socket" supports some ways of connecting via protocols like +telnet, but that is only a subset of the functionality supported by +tools socat. To use socat instead, for example to connect via a socks +proxy, use: + + -chardev 'socket,id=socat,cmd=exec socat FD:0 SOCKS4A:socks-proxy.localdomain:example.com:9999,,socksuser=nobody' \ + -device usb-serial,chardev=socat + +Beware that commas in the command must be escaped as double commas. + +Or interactively in the console: + (qemu) chardev-add socket,id=cat,cmd=cat + (qemu) device_add usb-serial,chardev=cat + ^ac + # cat >/dev/ttyUSB0 + hello + hello + +Another usage is starting swtpm from inside QEMU. swtpm will +automatically shut down once it looses the connection to the parent +QEMU, so there is no risk of lingering processes: + + -chardev 'socket,id=chrtpm0,cmd=exec swtpm socket --terminate --ctrl type=unixio,,clientfd=0 --tpmstate dir=... --log file=swtpm.log' \ + -tpmdev emulator,id=tpm0,chardev=chrtpm0 \ + -device tpm-tis,tpmdev=tpm0 + +The patch was discussed upstream, but QEMU developers believe that the +code calling QEMU should be responsible for managing additional +processes. In OE-core, that would imply enhancing runqemu and +oeqa. This patch is a simpler solution. + +Because it is not going upstream, the patch was written so that it is +as simple as possible. + +Upstream-Status: Inappropriate [embedded specific] + +Signed-off-by: Patrick Ohly <patrick.ohly@intel.com> +--- + chardev/char-socket.c | 86 ++++++++++++++++++++++++++++++++++++++++++++++++--- + chardev/char.c | 3 ++ + qapi/char.json | 5 +++ + 3 files changed, 90 insertions(+), 4 deletions(-) + +diff --git a/chardev/char-socket.c b/chardev/char-socket.c +index 53eda8ef00..f566107c35 100644 +--- a/chardev/char-socket.c ++++ b/chardev/char-socket.c +@@ -852,6 +852,68 @@ static gboolean socket_reconnect_timeout(gpointer opaque) + return false; + } + ++#ifndef _WIN32 ++static void chardev_open_socket_cmd(Chardev *chr, ++ const char *cmd, ++ Error **errp) ++{ ++ int fds[2] = { -1, -1 }; ++ QIOChannelSocket *sioc = NULL; ++ pid_t pid = -1; ++ const char *argv[] = { "/bin/sh", "-c", cmd, NULL }; ++ ++ /* ++ * We need a Unix domain socket for commands like swtpm and a single ++ * connection, therefore we cannot use qio_channel_command_new_spawn() ++ * without patching it first. Duplicating the functionality is easier. ++ */ ++ if (socketpair(AF_UNIX, SOCK_STREAM|SOCK_CLOEXEC, 0, fds)) { ++ error_setg_errno(errp, errno, "Error creating socketpair(AF_UNIX, SOCK_STREAM|SOCK_CLOEXEC)"); ++ goto error; ++ } ++ ++ pid = qemu_fork(errp); ++ if (pid < 0) { ++ goto error; ++ } ++ ++ if (!pid) { ++ /* child */ ++ dup2(fds[1], STDIN_FILENO); ++ execv(argv[0], (char * const *)argv); ++ _exit(1); ++ } ++ ++ /* ++ * Hand over our end of the socket pair to the qio channel. ++ * ++ * We don't reap the child because it is expected to keep ++ * running. We also don't support the "reconnect" option for the ++ * same reason. ++ */ ++ sioc = qio_channel_socket_new_fd(fds[0], errp); ++ if (!sioc) { ++ goto error; ++ } ++ fds[0] = -1; ++ ++ g_free(chr->filename); ++ chr->filename = g_strdup_printf("cmd:%s", cmd); ++ tcp_chr_new_client(chr, sioc); ++ ++ error: ++ if (fds[0] >= 0) { ++ close(fds[0]); ++ } ++ if (fds[1] >= 0) { ++ close(fds[1]); ++ } ++ if (sioc) { ++ object_unref(OBJECT(sioc)); ++ } ++} ++#endif ++ + static void qmp_chardev_open_socket(Chardev *chr, + ChardevBackend *backend, + bool *be_opened, +@@ -859,6 +921,9 @@ + { + SocketChardev *s = SOCKET_CHARDEV(chr); + ChardevSocket *sock = backend->u.socket.data; ++#ifndef _WIN32 ++ const char *cmd = sock->cmd; ++#endif + bool do_nodelay = sock->has_nodelay ? sock->nodelay : false; + bool is_listen = sock->has_server ? sock->server : true; + bool is_telnet = sock->has_telnet ? sock->telnet : false; +@@ -925,7 +990,14 @@ + } else if (reconnect > 0) { + s->reconnect_time = reconnect; + } +- ++#ifndef _WIN32 ++ if (cmd) { ++ chardev_open_socket_cmd(chr, cmd, errp); ++ ++ /* everything ready (or failed permanently) before we return */ ++ *be_opened = true; ++ } else ++#endif + if (s->reconnect_time) { + sioc = qio_channel_socket_new(); + tcp_chr_set_client_ioc_name(chr, sioc); +@@ -985,10 +1057,26 @@ + const char *host = qemu_opt_get(opts, "host"); + const char *port = qemu_opt_get(opts, "port"); + const char *tls_creds = qemu_opt_get(opts, "tls-creds"); ++#ifndef _WIN32 ++ const char *cmd = qemu_opt_get(opts, "cmd"); ++#endif + SocketAddressLegacy *addr; + ChardevSocket *sock; + + backend->type = CHARDEV_BACKEND_KIND_SOCKET; ++#ifndef _WIN32 ++ if (cmd) { ++ /* ++ * Here we have to ensure that no options are set which are incompatible with ++ * spawning a command, otherwise unmodified code that doesn't know about ++ * command spawning (like socket_reconnect_timeout()) might get called. ++ */ ++ if (path || is_listen || is_telnet || is_tn3270 || reconnect || host || port || tls_creds) { ++ error_setg(errp, "chardev: socket: cmd does not support any additional options"); ++ return; ++ } ++ } else ++#endif + if (!path) { + if (!host) { + error_setg(errp, "chardev: socket: no host given"); +@@ -1021,13 +1109,24 @@ + sock->has_reconnect = true; + sock->reconnect = reconnect; + sock->tls_creds = g_strdup(tls_creds); ++#ifndef _WIN32 ++ sock->cmd = g_strdup(cmd); ++#endif + + addr = g_new0(SocketAddressLegacy, 1); ++#ifndef _WIN32 ++ if (path || cmd) { ++#else + if (path) { ++#endif + UnixSocketAddress *q_unix; + addr->type = SOCKET_ADDRESS_LEGACY_KIND_UNIX; + q_unix = addr->u.q_unix.data = g_new0(UnixSocketAddress, 1); ++#ifndef _WIN32 ++ q_unix->path = cmd ? g_strdup_printf("cmd:%s", cmd) : g_strdup(path); ++#else + q_unix->path = g_strdup(path); ++#endif + } else { + addr->type = SOCKET_ADDRESS_LEGACY_KIND_INET; + addr->u.inet.data = g_new(InetSocketAddress, 1); +diff --git a/chardev/char.c b/chardev/char.c +index 2ae4f465ec..5d52cd5de5 100644 +--- a/chardev/char.c ++++ b/chardev/char.c +@@ -792,6 +792,9 @@ QemuOptsList qemu_chardev_opts = { + },{ + .name = "path", + .type = QEMU_OPT_STRING, ++ },{ ++ .name = "cmd", ++ .type = QEMU_OPT_STRING, + },{ + .name = "host", + .type = QEMU_OPT_STRING, +diff --git a/qapi/char.json b/qapi/char.json +index ae19dcd1ed..6de0f29bcd 100644 +--- a/qapi/char.json ++++ b/qapi/char.json +@@ -241,6 +241,10 @@ + # + # @addr: socket address to listen on (server=true) + # or connect to (server=false) ++# @cmd: command to run via "sh -c" with stdin as one end of ++# a AF_UNIX SOCK_DSTREAM socket pair. The other end ++# is used by the chardev. Either an addr or a cmd can ++# be specified, but not both. + # @tls-creds: the ID of the TLS credentials object (since 2.6) + # @server: create server socket (default: true) + # @wait: wait for incoming connection on server +@@ -258,6 +262,7 @@ + # Since: 1.4 + ## + { 'struct': 'ChardevSocket', 'data': { 'addr' : 'SocketAddressLegacy', ++ '*cmd' : 'str', + '*tls-creds' : 'str', + '*server' : 'bool', + '*wait' : 'bool', +-- +2.14.1 diff --git a/import-layers/yocto-poky/meta/recipes-devtools/qemu/qemu/check-PS2Queue-pointers-in-post_load-routine.patch b/import-layers/yocto-poky/meta/recipes-devtools/qemu/qemu/check-PS2Queue-pointers-in-post_load-routine.patch new file mode 100644 index 000000000..f8d7f66ac --- /dev/null +++ b/import-layers/yocto-poky/meta/recipes-devtools/qemu/qemu/check-PS2Queue-pointers-in-post_load-routine.patch @@ -0,0 +1,63 @@ +From ee9a17d0e12143971a9676227cce953c0dbe52fb Mon Sep 17 00:00:00 2001 +From: Prasad J Pandit <pjp@fedoraproject.org> +Date: Thu, 16 Nov 2017 13:21:55 +0530 +Subject: [PATCH] ps2: check PS2Queue pointers in post_load routine + +During Qemu guest migration, a destination process invokes ps2 +post_load function. In that, if 'rptr' and 'count' values were +invalid, it could lead to OOB access or infinite loop issue. +Add check to avoid it. + +Reported-by: Cyrille Chatras <cyrille.chatras@orange.com> +Signed-off-by: Prasad J Pandit <pjp@fedoraproject.org> +Message-id: 20171116075155.22378-1-ppandit@redhat.com +Signed-off-by: Gerd Hoffmann <kraxel@redhat.com> + +CVE: CVE-2017-16845 +Upstream-Status: Backport +Signed-off-by: Hongxu Jia <hongxu.jia@windriver.com> +--- + hw/input/ps2.c | 21 +++++++++------------ + 1 file changed, 9 insertions(+), 12 deletions(-) + +diff --git a/hw/input/ps2.c b/hw/input/ps2.c +index f388a23..de171a2 100644 +--- a/hw/input/ps2.c ++++ b/hw/input/ps2.c +@@ -1225,24 +1225,21 @@ static void ps2_common_reset(PS2State *s) + static void ps2_common_post_load(PS2State *s) + { + PS2Queue *q = &s->queue; +- int size; +- int i; +- int tmp_data[PS2_QUEUE_SIZE]; ++ uint8_t i, size; ++ uint8_t tmp_data[PS2_QUEUE_SIZE]; + + /* set the useful data buffer queue size, < PS2_QUEUE_SIZE */ +- size = q->count > PS2_QUEUE_SIZE ? 0 : q->count; ++ size = (q->count < 0 || q->count > PS2_QUEUE_SIZE) ? 0 : q->count; + + /* move the queue elements to the start of data array */ +- if (size > 0) { +- for (i = 0; i < size; i++) { +- /* move the queue elements to the temporary buffer */ +- tmp_data[i] = q->data[q->rptr]; +- if (++q->rptr == 256) { +- q->rptr = 0; +- } ++ for (i = 0; i < size; i++) { ++ if (q->rptr < 0 || q->rptr >= sizeof(q->data)) { ++ q->rptr = 0; + } +- memcpy(q->data, tmp_data, size); ++ tmp_data[i] = q->data[q->rptr++]; + } ++ memcpy(q->data, tmp_data, size); ++ + /* reset rptr/wptr/count */ + q->rptr = 0; + q->wptr = size; +-- +2.7.4 + diff --git a/import-layers/yocto-poky/meta/recipes-devtools/qemu/qemu/disable-grabs.patch b/import-layers/yocto-poky/meta/recipes-devtools/qemu/qemu/disable-grabs.patch index 123833f82..77117890f 100644 --- a/import-layers/yocto-poky/meta/recipes-devtools/qemu/qemu/disable-grabs.patch +++ b/import-layers/yocto-poky/meta/recipes-devtools/qemu/qemu/disable-grabs.patch @@ -24,11 +24,11 @@ Signed-off-by: Eric Bénard <eric@eukrea.com> ui/sdl.c | 12 ++++++++++-- 1 file changed, 10 insertions(+), 2 deletions(-) -diff --git a/ui/sdl.c b/ui/sdl.c -index 39a42d6..9b8abe5 100644 ---- a/ui/sdl.c -+++ b/ui/sdl.c -@@ -59,6 +59,10 @@ static SDL_Cursor *guest_sprite = NULL; +Index: qemu-2.11.1/ui/sdl.c +=================================================================== +--- qemu-2.11.1.orig/ui/sdl.c ++++ qemu-2.11.1/ui/sdl.c +@@ -63,6 +63,10 @@ static SDL_PixelFormat host_format; static int scaling_active = 0; static Notifier mouse_mode_notifier; static int idle_counter; @@ -37,10 +37,10 @@ index 39a42d6..9b8abe5 100644 +#endif +static doing_grabs = True; - static void sdl_update(DisplayChangeListener *dcl, - int x, int y, int w, int h) -@@ -384,14 +388,16 @@ static void sdl_grab_start(void) - } + #define SDL_REFRESH_INTERVAL_BUSY 10 + #define SDL_MAX_IDLE_COUNT (2 * GUI_REFRESH_INTERVAL_DEFAULT \ +@@ -431,14 +435,16 @@ static void sdl_grab_start(void) + } } else sdl_hide_cursor(); - SDL_WM_GrabInput(SDL_GRAB_ON); @@ -58,7 +58,7 @@ index 39a42d6..9b8abe5 100644 gui_grab = 0; sdl_show_cursor(); sdl_update_caption(); -@@ -909,6 +915,8 @@ void sdl_display_init(DisplayState *ds, int full_screen, int no_frame) +@@ -986,6 +992,8 @@ void sdl_display_init(DisplayState *ds, * This requires SDL >= 1.2.14. */ setenv("SDL_DISABLE_LOCK_KEYS", "1", 1); @@ -67,6 +67,3 @@ index 39a42d6..9b8abe5 100644 flags = SDL_INIT_VIDEO | SDL_INIT_NOPARACHUTE; if (SDL_Init (flags)) { fprintf(stderr, "Could not initialize SDL(%s) - exiting\n", --- -1.8.3.1 - diff --git a/import-layers/yocto-poky/meta/recipes-devtools/qemu/qemu/exclude-some-arm-EABI-obsolete-syscalls.patch b/import-layers/yocto-poky/meta/recipes-devtools/qemu/qemu/exclude-some-arm-EABI-obsolete-syscalls.patch deleted file mode 100644 index f593cf9ae..000000000 --- a/import-layers/yocto-poky/meta/recipes-devtools/qemu/qemu/exclude-some-arm-EABI-obsolete-syscalls.patch +++ /dev/null @@ -1,87 +0,0 @@ -[PATCH] exclude some arm EABI obsolete syscalls - -Upstream-Status: Pending - -some syscalls are obsolete and no longer available for EABI, exclude them to -fix the below error: - In file included from qemu-seccomp.c:16:0: - qemu-seccomp.c:28:7: error: '__NR_select' undeclared here (not in a function) - { SCMP_SYS(select), 252 }, - ^ - qemu-seccomp.c:36:7: error: '__NR_mmap' undeclared here (not in a function) - { SCMP_SYS(mmap), 247 }, - ^ - qemu-seccomp.c:57:7: error: '__NR_getrlimit' undeclared here (not in a function) - { SCMP_SYS(getrlimit), 245 }, - ^ - qemu-seccomp.c:96:7: error: '__NR_time' undeclared here (not in a function) - { SCMP_SYS(time), 245 }, - ^ - qemu-seccomp.c:185:7: error: '__NR_alarm' undeclared here (not in a function) - { SCMP_SYS(alarm), 241 }, - -please refer source files: - arch/arm/include/uapi/asm/unistd.h -or kernel header: - /usr/include/asm/unistd.h - -Signed-off-by: Roy.Li <rongqing.li@windriver.com> ---- - qemu-seccomp.c | 13 ++++++++----- - 1 file changed, 8 insertions(+), 5 deletions(-) - -diff --git a/qemu-seccomp.c b/qemu-seccomp.c -index df75d9c..0e577f8 100644 ---- a/qemu-seccomp.c -+++ b/qemu-seccomp.c -@@ -35,15 +35,21 @@ static const struct QemuSeccompSyscall seccomp_whitelist[] = { - { SCMP_SYS(timer_settime), 255 }, - { SCMP_SYS(timer_gettime), 254 }, - { SCMP_SYS(futex), 253 }, -+#if !defined(__ARM_EABI__) - { SCMP_SYS(select), 252 }, -+ { SCMP_SYS(time), 245 }, -+ { SCMP_SYS(alarm), 241 }, -+ { SCMP_SYS(getrlimit), 245 }, -+ { SCMP_SYS(mmap), 247 }, -+ { SCMP_SYS(socketcall), 250 }, -+ { SCMP_SYS(ipc), 245 }, -+#endif - { SCMP_SYS(recvfrom), 251 }, - { SCMP_SYS(sendto), 250 }, -- { SCMP_SYS(socketcall), 250 }, - { SCMP_SYS(read), 249 }, - { SCMP_SYS(io_submit), 249 }, - { SCMP_SYS(brk), 248 }, - { SCMP_SYS(clone), 247 }, -- { SCMP_SYS(mmap), 247 }, - { SCMP_SYS(mprotect), 246 }, - { SCMP_SYS(execve), 245 }, - { SCMP_SYS(open), 245 }, -@@ -58,7 +64,6 @@ static const struct QemuSeccompSyscall seccomp_whitelist[] = { - { SCMP_SYS(bind), 245 }, - { SCMP_SYS(listen), 245 }, - { SCMP_SYS(semget), 245 }, -- { SCMP_SYS(ipc), 245 }, - { SCMP_SYS(gettimeofday), 245 }, - { SCMP_SYS(readlink), 245 }, - { SCMP_SYS(access), 245 }, -@@ -104,7 +109,6 @@ static const struct QemuSeccompSyscall seccomp_whitelist[] = { - { SCMP_SYS(times), 245 }, - { SCMP_SYS(exit), 245 }, - { SCMP_SYS(clock_gettime), 245 }, -- { SCMP_SYS(time), 245 }, - { SCMP_SYS(restart_syscall), 245 }, - { SCMP_SYS(pwrite64), 245 }, - { SCMP_SYS(nanosleep), 245 }, -@@ -194,7 +198,6 @@ static const struct QemuSeccompSyscall seccomp_whitelist[] = { - { SCMP_SYS(lstat64), 241 }, - { SCMP_SYS(sendfile64), 241 }, - { SCMP_SYS(ugetrlimit), 241 }, -- { SCMP_SYS(alarm), 241 }, - { SCMP_SYS(rt_sigsuspend), 241 }, - { SCMP_SYS(rt_sigqueueinfo), 241 }, - { SCMP_SYS(rt_tgsigqueueinfo), 241 }, --- -2.1.4 - diff --git a/import-layers/yocto-poky/meta/recipes-devtools/qemu/qemu/glibc-2.25.patch b/import-layers/yocto-poky/meta/recipes-devtools/qemu/qemu/glibc-2.25.patch deleted file mode 100644 index a6908bdbf..000000000 --- a/import-layers/yocto-poky/meta/recipes-devtools/qemu/qemu/glibc-2.25.patch +++ /dev/null @@ -1,88 +0,0 @@ -From: Christopher Covington -Date: Wed, 28 Dec 2016 15:04:33 -0500 -Subject: [Qemu-devel] [PATCH v3] build: include sys/sysmacros.h for major() and minor()a - -The definition of the major() and minor() macros are moving within glibc to -<sys/sysmacros.h>. Include this header when it is available to avoid the -following sorts of build-stopping messages: - -qga/commands-posix.c: In function ‘dev_major_minor’: -qga/commands-posix.c:656:13: error: In the GNU C Library, "major" is defined - by <sys/sysmacros.h>. For historical compatibility, it is - currently defined by <sys/types.h> as well, but we plan to - remove this soon. To use "major", include <sys/sysmacros.h> - directly. If you did not intend to use a system-defined macro - "major", you should undefine it after including <sys/types.h>. [-Werror] - *devmajor = major(st.st_rdev); - ^~~~~~~~~~~~~~~~~~~~~~~~~~ - -qga/commands-posix.c:657:13: error: In the GNU C Library, "minor" is defined - by <sys/sysmacros.h>. For historical compatibility, it is - currently defined by <sys/types.h> as well, but we plan to - remove this soon. To use "minor", include <sys/sysmacros.h> - directly. If you did not intend to use a system-defined macro - "minor", you should undefine it after including <sys/types.h>. [-Werror] - *devminor = minor(st.st_rdev); - ^~~~~~~~~~~~~~~~~~~~~~~~~~ - -The additional include allows the build to complete on Fedora 26 (Rawhide) -with glibc version 2.24.90. - -Signed-off-by: Christopher Covington <address@hidden> -Signed-off-by: Martin Jansa <Martin.Jansa@gmail.com> - -Upstream-Status: Submitted https://lists.gnu.org/archive/html/qemu-devel/2016-12/msg03548.html - -diff -uNr qemu-2.8.0.orig/configure qemu-2.8.0/configure ---- qemu-2.8.0.orig/configure 2017-02-21 19:05:13.180094708 +0100 -+++ qemu-2.8.0/configure 2017-02-21 19:08:53.114087084 +0100 -@@ -4727,6 +4727,20 @@ - then - fi - - ########################################## -+# check for sysmacros.h -+ -+have_sysmacros=no -+cat > $TMPC << EOF -+#include <sys/sysmacros.h> -+int main(void) { -+ return makedev(0, 0); -+} -+EOF -+if compile_prog "" "" ; then -+ have_sysmacros=yes -+fi -+ -+########################################## - # End of CC checks - # After here, no more $cc or $ld runs - -diff -uNr qemu-2.8.0.orig/configure qemu-2.8.0/configure ---- qemu-2.8.0.orig/configure 2017-02-21 19:05:13.180094708 +0100 -+++ qemu-2.8.0/configure 2017-02-21 19:08:53.114087084 +0100 -@@ -5695,6 +5709,10 @@ - echo "CONFIG_AF_VSOCK=y" >> $config_host_mak - fi - -+if test "$have_sysmacros" = "yes" ; then -+ echo "CONFIG_SYSMACROS=y" >> $config_host_mak -+fi -+ - # Hold two types of flag: - # CONFIG_THREAD_SETNAME_BYTHREAD - we've got a way of setting the name on - # a thread we have a handle to -diff -uNr qemu-2.8.0.orig/include/sysemu/os-posix.h qemu-2.8.0/include/sysemu/os-posix.h ---- qemu-2.8.0.orig/include/sysemu/os-posix.h 2016-12-20 21:16:48.000000000 +0100 -+++ qemu-2.8.0/include/sysemu/os-posix.h 2017-02-21 19:07:18.009090381 +0100 -@@ -34,6 +34,10 @@ - #include <netdb.h> - #include <sys/un.h> - -+#ifdef CONFIG_SYSMACROS -+#include <sys/sysmacros.h> -+#endif -+ - void os_set_line_buffering(void); - void os_set_proc_name(const char *s); - void os_setup_signal_handling(void); diff --git a/import-layers/yocto-poky/meta/recipes-devtools/qemu/qemu/linux-user-Fix-webkitgtk-hangs-on-32-bit-x86-target.patch b/import-layers/yocto-poky/meta/recipes-devtools/qemu/qemu/linux-user-Fix-webkitgtk-hangs-on-32-bit-x86-target.patch new file mode 100644 index 000000000..d2c52252f --- /dev/null +++ b/import-layers/yocto-poky/meta/recipes-devtools/qemu/qemu/linux-user-Fix-webkitgtk-hangs-on-32-bit-x86-target.patch @@ -0,0 +1,35 @@ +From 4fa4aae4176ef6d8f4d4b8323d061e2433918a26 Mon Sep 17 00:00:00 2001 +From: Alistair Francis <alistair.francis@xilinx.com> +Date: Wed, 17 Jan 2018 10:51:49 -0800 +Subject: [PATCH] linux-user: Fix webkitgtk hangs on 32-bit x86 target + +Since commit "linux-user: Tidy and enforce reserved_va initialization" +(18e80c55bb6ec17c05ec0ba717ec83933c2bfc07) the Yocto webkitgtk build +hangs when cross compiling for 32-bit x86 on a 64-bit x86 machine using +musl. + +To fix the issue reduce the MAX_RESERVED_VA macro to be a closer match +to what it was before the problematic commit. + +Upstream-Status: Submitted http://lists.gnu.org/archive/html/qemu-devel/2018-01/msg04185.html +Signed-off-by: Alistair Francis <alistair.francis@xilinx.com> +--- + linux-user/main.c | 2 +- + 1 file changed, 1 insertion(+), 1 deletion(-) + +diff --git a/linux-user/main.c b/linux-user/main.c +index 450eb3ce65..c7cc0a184e 100644 +--- a/linux-user/main.c ++++ b/linux-user/main.c +@@ -77,7 +77,7 @@ do { \ + (TARGET_LONG_BITS == 32 || defined(TARGET_ABI32)) + /* There are a number of places where we assign reserved_va to a variable + of type abi_ulong and expect it to fit. Avoid the last page. */ +-# define MAX_RESERVED_VA (0xfffffffful & TARGET_PAGE_MASK) ++# define MAX_RESERVED_VA (0x7ffffffful & TARGET_PAGE_MASK) + # else + # define MAX_RESERVED_VA (1ul << TARGET_VIRT_ADDR_SPACE_BITS) + # endif +-- +2.14.1 + diff --git a/import-layers/yocto-poky/meta/recipes-devtools/qemu/qemu/ppc_locking.patch b/import-layers/yocto-poky/meta/recipes-devtools/qemu/qemu/ppc_locking.patch deleted file mode 100644 index 6f722433d..000000000 --- a/import-layers/yocto-poky/meta/recipes-devtools/qemu/qemu/ppc_locking.patch +++ /dev/null @@ -1,105 +0,0 @@ -I've tracked down what I think is a problem causing qemu-system-ppc -to hang whilst booting images. - -I believe the decrementer timer stops receiving interrupts so -tasks in our images hang indefinitely as the timer stopped. - -It can be summed up with this line of debug: - -ppc_set_irq: 0x55b4e0d562f0 n_IRQ 8 level 1 => pending 00000100req 00000004 - -It should normally read: - -ppc_set_irq: 0x55b4e0d562f0 n_IRQ 8 level 1 => pending 00000100req 00000002 - -The question is why CPU_INTERRUPT_EXITTB ends up being set when the -lines above this log message clearly sets CPU_INTERRUPT_HARD (via -cpu_interrupt() ). - -I note in cpu.h: - - /* updates protected by BQL */ - uint32_t interrupt_request; - -(for struct CPUState) - -The ppc code does "cs->interrupt_request |= CPU_INTERRUPT_EXITTB" in 5 -places, 3 in excp_helper.c and 2 in helper_regs.h. In all cases, -g_assert(qemu_mutex_iothread_locked()); fails. If I do something like: - -if (!qemu_mutex_iothread_locked()) { - qemu_mutex_lock_iothread(); - cpu_interrupt(cs, CPU_INTERRUPT_EXITTB); - qemu_mutex_unlock_iothread(); -} else { - cpu_interrupt(cs, CPU_INTERRUPT_EXITTB); -} - -in these call sites then I can no longer lock qemu up with my test -case. - -I suspect the _HARD setting gets overwritten which stops the -decrementer interrupts being delivered. - -Upstream-Status: Submitted [Issue discussed on qemu mailing list 2017/11/20] -RP 2017/11/20 - -Index: qemu-2.10.1/target/ppc/excp_helper.c -=================================================================== ---- qemu-2.10.1.orig/target/ppc/excp_helper.c -+++ qemu-2.10.1/target/ppc/excp_helper.c -@@ -207,7 +207,9 @@ static inline void powerpc_excp(PowerPCC - "Entering checkstop state\n"); - } - cs->halted = 1; -- cs->interrupt_request |= CPU_INTERRUPT_EXITTB; -+ qemu_mutex_lock_iothread(); -+ cpu_interrupt(cs, CPU_INTERRUPT_EXITTB); -+ qemu_mutex_unlock_iothread(); - } - if (env->msr_mask & MSR_HVB) { - /* ISA specifies HV, but can be delivered to guest with HV clear -@@ -940,7 +942,9 @@ void helper_store_msr(CPUPPCState *env, - - if (excp != 0) { - CPUState *cs = CPU(ppc_env_get_cpu(env)); -- cs->interrupt_request |= CPU_INTERRUPT_EXITTB; -+ qemu_mutex_lock_iothread(); -+ cpu_interrupt(cs, CPU_INTERRUPT_EXITTB); -+ qemu_mutex_unlock_iothread(); - raise_exception(env, excp); - } - } -@@ -995,7 +999,9 @@ static inline void do_rfi(CPUPPCState *e - /* No need to raise an exception here, - * as rfi is always the last insn of a TB - */ -- cs->interrupt_request |= CPU_INTERRUPT_EXITTB; -+ qemu_mutex_lock_iothread(); -+ cpu_interrupt(cs, CPU_INTERRUPT_EXITTB); -+ qemu_mutex_unlock_iothread(); - - /* Reset the reservation */ - env->reserve_addr = -1; -Index: qemu-2.10.1/target/ppc/helper_regs.h -=================================================================== ---- qemu-2.10.1.orig/target/ppc/helper_regs.h -+++ qemu-2.10.1/target/ppc/helper_regs.h -@@ -114,11 +114,15 @@ static inline int hreg_store_msr(CPUPPCS - } - if (((value >> MSR_IR) & 1) != msr_ir || - ((value >> MSR_DR) & 1) != msr_dr) { -- cs->interrupt_request |= CPU_INTERRUPT_EXITTB; -+ qemu_mutex_lock_iothread(); -+ cpu_interrupt(cs, CPU_INTERRUPT_EXITTB); -+ qemu_mutex_unlock_iothread(); - } - if ((env->mmu_model & POWERPC_MMU_BOOKE) && - ((value >> MSR_GS) & 1) != msr_gs) { -- cs->interrupt_request |= CPU_INTERRUPT_EXITTB; -+ qemu_mutex_lock_iothread(); -+ cpu_interrupt(cs, CPU_INTERRUPT_EXITTB); -+ qemu_mutex_unlock_iothread(); - } - if (unlikely((env->flags & POWERPC_FLAG_TGPR) && - ((value ^ env->msr) & (1 << MSR_TGPR)))) { diff --git a/import-layers/yocto-poky/meta/recipes-devtools/qemu/qemu_2.10.0.bb b/import-layers/yocto-poky/meta/recipes-devtools/qemu/qemu_2.11.1.bb index bdf6c21f8..ab82c5fe5 100644 --- a/import-layers/yocto-poky/meta/recipes-devtools/qemu/qemu_2.10.0.bb +++ b/import-layers/yocto-poky/meta/recipes-devtools/qemu/qemu_2.11.1.bb @@ -10,7 +10,6 @@ LIC_FILES_CHKSUM = "file://COPYING;md5=441c28d2cf86e15a37fa47e15a72fbac \ SRC_URI = "http://wiki.qemu-project.org/download/${BP}.tar.bz2 \ file://powerpc_rom.bin \ file://disable-grabs.patch \ - file://exclude-some-arm-EABI-obsolete-syscalls.patch \ file://wacom.patch \ file://add-ptest-in-makefile-v10.patch \ file://run-ptest \ @@ -18,18 +17,12 @@ SRC_URI = "http://wiki.qemu-project.org/download/${BP}.tar.bz2 \ file://no-valgrind.patch \ file://pathlimit.patch \ file://qemu-2.5.0-cflags.patch \ - file://glibc-2.25.patch \ - file://0001-Provide-support-for-the-CUSE-TPM.patch \ - file://0002-Introduce-condition-to-notify-waiters-of-completed-c.patch \ - file://0003-Introduce-condition-in-TPM-backend-for-notification.patch \ - file://0004-Add-support-for-VM-suspend-resume-for-TPM-TIS-v2.9.patch \ + file://chardev-connect-socket-to-a-spawned-command.patch \ file://apic-fixup-fallthrough-to-PIC.patch \ - file://CVE-2017-13711.patch \ - file://CVE-2017-13673.patch \ - file://CVE-2017-13672.patch \ - file://CVE-2017-14167.patch \ - file://ppc_locking.patch \ + file://linux-user-Fix-webkitgtk-hangs-on-32-bit-x86-target.patch \ file://memfd.patch \ + file://0001-arm-translate-a64-treat-DISAS_UPDATE-as-variant-of-D.patch \ + file://check-PS2Queue-pointers-in-post_load-routine.patch \ " UPSTREAM_CHECK_REGEX = "qemu-(?P<pver>\d+\..*)\.tar" @@ -39,8 +32,8 @@ SRC_URI_append_class-native = " \ file://cpus.c-qemu_cpu_kick_thread_debugging.patch \ " -SRC_URI[md5sum] = "ca73441de73a9b52c6c49c97190d2185" -SRC_URI[sha256sum] = "7e9f39e1306e6dcc595494e91c1464d4b03f55ddd2053183e0e1b69f7f776d48" +SRC_URI[md5sum] = "61cf862b6007eba4ac98247776af2e27" +SRC_URI[sha256sum] = "d9df2213ceed32e91dab7bc9dd19c1af83f91ba72c7aeef7605dfaaf81732ccb" COMPATIBLE_HOST_mipsarchn32 = "null" COMPATIBLE_HOST_mipsarchn64 = "null" @@ -60,4 +53,7 @@ do_install_ptest() { find ${D}${PTEST_PATH}/tests -type f -name "*.[Sshcod]" | xargs -i rm -rf {} cp ${S}/tests/Makefile.include ${D}${PTEST_PATH}/tests + # Don't check the file genreated by configure + sed -i -e '/wildcard config-host.mak/d' \ + -e '$ {/endif/d}' ${D}${PTEST_PATH}/tests/Makefile.include } |