From nobody Mon Apr 29 09:01:19 2024 Delivered-To: importer@patchew.org Received-SPF: pass (zoho.com: domain of redhat.com designates 209.132.183.28 as permitted sender) client-ip=209.132.183.28; envelope-from=libvir-list-bounces@redhat.com; helo=mx1.redhat.com; Authentication-Results: mx.zohomail.com; spf=pass (zoho.com: domain of redhat.com designates 209.132.183.28 as permitted sender) smtp.mailfrom=libvir-list-bounces@redhat.com Return-Path: Received: from mx1.redhat.com (mx1.redhat.com [209.132.183.28]) by mx.zohomail.com with SMTPS id 1523415030382355.65128607084716; Tue, 10 Apr 2018 19:50:30 -0700 (PDT) Received: from smtp.corp.redhat.com (int-mx02.intmail.prod.int.phx2.redhat.com [10.5.11.12]) (using TLSv1.2 with cipher AECDH-AES256-SHA (256/256 bits)) (No client certificate requested) by mx1.redhat.com (Postfix) with ESMTPS id D26B13DE3D; Wed, 11 Apr 2018 02:50:28 +0000 (UTC) Received: from colo-mx.corp.redhat.com (colo-mx02.intmail.prod.int.phx2.redhat.com [10.5.11.21]) by smtp.corp.redhat.com (Postfix) with ESMTPS id E7EB7662F7; Wed, 11 Apr 2018 02:50:27 +0000 (UTC) Received: from lists01.pubmisc.prod.ext.phx2.redhat.com (lists01.pubmisc.prod.ext.phx2.redhat.com [10.5.19.33]) by colo-mx.corp.redhat.com (Postfix) with ESMTP id E49F64CA97; Wed, 11 Apr 2018 02:50:24 +0000 (UTC) Received: from smtp.corp.redhat.com (int-mx03.intmail.prod.int.phx2.redhat.com [10.5.11.13]) by lists01.pubmisc.prod.ext.phx2.redhat.com (8.13.8/8.13.8) with ESMTP id w3B2oNAD009917 for ; Tue, 10 Apr 2018 22:50:23 -0400 Received: by smtp.corp.redhat.com (Postfix) id 70FCA6607A; Wed, 11 Apr 2018 02:50:23 +0000 (UTC) Received: from mx1.redhat.com (ext-mx01.extmail.prod.ext.phx2.redhat.com [10.5.110.25]) by smtp.corp.redhat.com (Postfix) with ESMTPS id 6A79E66064 for ; Wed, 11 Apr 2018 02:50:20 +0000 (UTC) Received: from mx0a-001b2d01.pphosted.com (mx0b-001b2d01.pphosted.com [148.163.158.5]) (using TLSv1.2 with cipher ECDHE-RSA-AES256-GCM-SHA384 (256/256 bits)) (No client certificate requested) by mx1.redhat.com (Postfix) with ESMTPS id BBE7481DE9 for ; Wed, 11 Apr 2018 02:50:19 +0000 (UTC) Received: from pps.filterd (m0098416.ppops.net [127.0.0.1]) by mx0b-001b2d01.pphosted.com (8.16.0.22/8.16.0.22) with SMTP id w3B2neHD005922 for ; Tue, 10 Apr 2018 22:50:19 -0400 Received: from e36.co.us.ibm.com (e36.co.us.ibm.com [32.97.110.154]) by mx0b-001b2d01.pphosted.com with ESMTP id 2h99ays53j-1 (version=TLSv1.2 cipher=AES256-SHA256 bits=256 verify=NOT) for ; Tue, 10 Apr 2018 22:50:18 -0400 Received: from localhost by e36.co.us.ibm.com with IBM ESMTP SMTP Gateway: Authorized Use Only! Violators will be prosecuted for from ; Tue, 10 Apr 2018 20:50:18 -0600 Received: from b03cxnp08028.gho.boulder.ibm.com (9.17.130.20) by e36.co.us.ibm.com (192.168.1.136) with IBM ESMTP SMTP Gateway: Authorized Use Only! Violators will be prosecuted; Tue, 10 Apr 2018 20:50:15 -0600 Received: from b03ledav005.gho.boulder.ibm.com (b03ledav005.gho.boulder.ibm.com [9.17.130.236]) by b03cxnp08028.gho.boulder.ibm.com (8.14.9/8.14.9/NCO v10.0) with ESMTP id w3B2oEvn3998148; Tue, 10 Apr 2018 19:50:14 -0700 Received: from b03ledav005.gho.boulder.ibm.com (unknown [127.0.0.1]) by IMSVA (Postfix) with ESMTP id 92C72BE03A; Tue, 10 Apr 2018 20:50:14 -0600 (MDT) Received: from sbct-3.watson.ibm.com (unknown [9.47.158.153]) by b03ledav005.gho.boulder.ibm.com (Postfix) with ESMTP id 50F07BE038; Tue, 10 Apr 2018 20:50:14 -0600 (MDT) From: Stefan Berger To: libvir-list@redhat.com Date: Tue, 10 Apr 2018 22:50:00 -0400 In-Reply-To: <1523415005-30661-1-git-send-email-stefanb@linux.vnet.ibm.com> References: <1523415005-30661-1-git-send-email-stefanb@linux.vnet.ibm.com> X-TM-AS-GCONF: 00 x-cbid: 18041102-0020-0000-0000-00000DB8AB97 X-IBM-SpamModules-Scores: X-IBM-SpamModules-Versions: BY=3.00008834; HX=3.00000241; KW=3.00000007; PH=3.00000004; SC=3.00000256; SDB=6.01016139; UDB=6.00518173; IPR=6.00795386; MB=3.00020511; MTD=3.00000008; XFM=3.00000015; UTC=2018-04-11 02:50:16 X-IBM-AV-DETECTION: SAVI=unused REMOTE=unused XFE=unused x-cbparentid: 18041102-0021-0000-0000-000060DB718E Message-Id: <1523415005-30661-2-git-send-email-stefanb@linux.vnet.ibm.com> X-Proofpoint-Virus-Version: vendor=fsecure engine=2.50.10434:, , definitions=2018-04-11_01:, , signatures=0 X-Proofpoint-Spam-Details: rule=outbound_notspam policy=outbound score=0 priorityscore=1501 malwarescore=0 suspectscore=15 phishscore=0 bulkscore=0 spamscore=0 clxscore=1015 lowpriorityscore=0 impostorscore=0 adultscore=0 classifier=spam adjust=0 reason=mlx scancount=1 engine=8.0.1-1709140000 definitions=main-1804110026 X-Greylist: Sender passed SPF test, Sender IP whitelisted by DNSRBL, ACL 207 matched, not delayed by milter-greylist-4.5.16 (mx1.redhat.com [10.5.110.25]); Wed, 11 Apr 2018 02:50:19 +0000 (UTC) X-Greylist: inspected by milter-greylist-4.5.16 (mx1.redhat.com [10.5.110.25]); Wed, 11 Apr 2018 02:50:19 +0000 (UTC) for IP:'148.163.158.5' DOMAIN:'mx0b-001b2d01.pphosted.com' HELO:'mx0a-001b2d01.pphosted.com' FROM:'stefanb@linux.vnet.ibm.com' RCPT:'' X-RedHat-Spam-Score: -0.7 (RCVD_IN_DNSWL_LOW) 148.163.158.5 mx0b-001b2d01.pphosted.com 148.163.158.5 mx0b-001b2d01.pphosted.com X-Scanned-By: MIMEDefang 2.83 on 10.5.110.25 X-Scanned-By: MIMEDefang 2.79 on 10.5.11.13 X-loop: libvir-list@redhat.com Subject: [libvirt] [PATCH v2 1/6] tpm: Enable TPM CRB interface X-BeenThere: libvir-list@redhat.com X-Mailman-Version: 2.1.12 Precedence: junk List-Id: Development discussions about the libvirt library & tools List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , MIME-Version: 1.0 Content-Transfer-Encoding: quoted-printable Sender: libvir-list-bounces@redhat.com Errors-To: libvir-list-bounces@redhat.com X-Scanned-By: MIMEDefang 2.79 on 10.5.11.12 X-Greylist: Sender IP whitelisted, not delayed by milter-greylist-4.5.16 (mx1.redhat.com [10.5.110.29]); Wed, 11 Apr 2018 02:50:29 +0000 (UTC) X-ZohoMail: RSF_0 Z_629925259 SPT_0 Content-Type: text/plain; charset="utf-8" Enable the TPM CRB interface added in QEMU 2.12. the TPM CRB interface is a simpler interface than the TPM TIS and is only available for TPM 2. Signed-off-by: Stefan Berger --- docs/formatdomain.html.in | 2 ++ docs/schemas/domaincommon.rng | 5 +++- src/conf/domain_conf.c | 5 ++-- src/conf/domain_conf.h | 1 + src/qemu/qemu_capabilities.c | 5 ++++ src/qemu/qemu_capabilities.h | 1 + tests/qemucapabilitiesdata/caps_2.12.0.x86_64.xml | 1 + tests/qemuxml2argvdata/tpm-passthrough-crb.args | 24 +++++++++++++++ tests/qemuxml2argvdata/tpm-passthrough-crb.xml | 32 ++++++++++++++++++++ tests/qemuxml2argvtest.c | 3 ++ tests/qemuxml2xmloutdata/tpm-passthrough-crb.xml | 36 +++++++++++++++++++= ++++ 11 files changed, 111 insertions(+), 4 deletions(-) create mode 100644 tests/qemuxml2argvdata/tpm-passthrough-crb.args create mode 100644 tests/qemuxml2argvdata/tpm-passthrough-crb.xml create mode 100644 tests/qemuxml2xmloutdata/tpm-passthrough-crb.xml diff --git a/docs/formatdomain.html.in b/docs/formatdomain.html.in index 08dc74b..16fc7db 100644 --- a/docs/formatdomain.html.in +++ b/docs/formatdomain.html.in @@ -7628,6 +7628,8 @@ qemu-kvm -net nic,model=3D? /dev/null The model attribute specifies what device model QEMU provides to the guest. If no model name is provided, tpm-tis will automatically be chosen. + Another available choice is the tpm-crb, which + should only be used when the backend is a TPM 2.

backend
diff --git a/docs/schemas/domaincommon.rng b/docs/schemas/domaincommon.rng index 8165e69..be5c628 100644 --- a/docs/schemas/domaincommon.rng +++ b/docs/schemas/domaincommon.rng @@ -4112,7 +4112,10 @@ - tpm-tis + + tpm-tis + tpm-crb + diff --git a/src/conf/domain_conf.c b/src/conf/domain_conf.c index ae7c0d9..232174a 100644 --- a/src/conf/domain_conf.c +++ b/src/conf/domain_conf.c @@ -858,7 +858,8 @@ VIR_ENUM_IMPL(virDomainRNGBackend, "egd"); =20 VIR_ENUM_IMPL(virDomainTPMModel, VIR_DOMAIN_TPM_MODEL_LAST, - "tpm-tis") + "tpm-tis", + "tpm-crb") =20 VIR_ENUM_IMPL(virDomainTPMBackend, VIR_DOMAIN_TPM_TYPE_LAST, "passthrough") @@ -12549,8 +12550,6 @@ virDomainTPMDefParseXML(virDomainXMLOptionPtr xmlop= t, virReportError(VIR_ERR_CONFIG_UNSUPPORTED, _("Unknown TPM frontend model '%s'"), model); goto error; - } else { - def->model =3D VIR_DOMAIN_TPM_MODEL_TIS; } =20 ctxt->node =3D node; diff --git a/src/conf/domain_conf.h b/src/conf/domain_conf.h index 61379e5..1724340 100644 --- a/src/conf/domain_conf.h +++ b/src/conf/domain_conf.h @@ -1277,6 +1277,7 @@ struct _virDomainHubDef { =20 typedef enum { VIR_DOMAIN_TPM_MODEL_TIS, + VIR_DOMAIN_TPM_MODEL_CRB, =20 VIR_DOMAIN_TPM_MODEL_LAST } virDomainTPMModel; diff --git a/src/qemu/qemu_capabilities.c b/src/qemu/qemu_capabilities.c index e54dde6..0952663 100644 --- a/src/qemu/qemu_capabilities.c +++ b/src/qemu/qemu_capabilities.c @@ -466,6 +466,7 @@ VIR_ENUM_IMPL(virQEMUCaps, QEMU_CAPS_LAST, /* 285 */ "virtio-mouse-ccw", "virtio-tablet-ccw", + "tpm-crb", ); =20 =20 @@ -3104,6 +3105,10 @@ const struct tpmTypeToCaps virQEMUCapsTPMModelsToCap= s[] =3D { .type =3D VIR_DOMAIN_TPM_MODEL_TIS, .caps =3D QEMU_CAPS_DEVICE_TPM_TIS, }, + { + .type =3D VIR_DOMAIN_TPM_MODEL_CRB, + .caps =3D QEMU_CAPS_DEVICE_TPM_CRB, + }, }; =20 static int diff --git a/src/qemu/qemu_capabilities.h b/src/qemu/qemu_capabilities.h index 3f3c29f..604525a 100644 --- a/src/qemu/qemu_capabilities.h +++ b/src/qemu/qemu_capabilities.h @@ -450,6 +450,7 @@ typedef enum { /* 285 */ QEMU_CAPS_DEVICE_VIRTIO_MOUSE_CCW, /* -device virtio-mouse-ccw */ QEMU_CAPS_DEVICE_VIRTIO_TABLET_CCW, /* -device virtio-tablet-ccw */ + QEMU_CAPS_DEVICE_TPM_CRB, /* -device tpm-crb */ =20 QEMU_CAPS_LAST /* this must always be the last item */ } virQEMUCapsFlags; diff --git a/tests/qemucapabilitiesdata/caps_2.12.0.x86_64.xml b/tests/qemu= capabilitiesdata/caps_2.12.0.x86_64.xml index 334296e..39ee4f4 100644 --- a/tests/qemucapabilitiesdata/caps_2.12.0.x86_64.xml +++ b/tests/qemucapabilitiesdata/caps_2.12.0.x86_64.xml @@ -225,6 +225,7 @@ + 2011090 0 390060 diff --git a/tests/qemuxml2argvdata/tpm-passthrough-crb.args b/tests/qemuxm= l2argvdata/tpm-passthrough-crb.args new file mode 100644 index 0000000..ae052b4 --- /dev/null +++ b/tests/qemuxml2argvdata/tpm-passthrough-crb.args @@ -0,0 +1,24 @@ +LC_ALL=3DC \ +PATH=3D/bin \ +HOME=3D/home/test \ +USER=3Dtest \ +LOGNAME=3Dtest \ +QEMU_AUDIO_DRV=3Dnone \ +/usr/bin/qemu-system-x86_64 \ +-name TPM-VM \ +-S \ +-M pc-0.12 \ +-m 2048 \ +-smp 1,sockets=3D1,cores=3D1,threads=3D1 \ +-uuid 11d7cd22-da89-3094-6212-079a48a309a1 \ +-nographic \ +-nodefaults \ +-chardev socket,id=3Dcharmonitor,path=3D/tmp/lib/domain--1-TPM-VM/monitor.= sock,\ +server,nowait \ +-mon chardev=3Dcharmonitor,id=3Dmonitor,mode=3Dreadline \ +-boot c \ +-usb \ +-tpmdev passthrough,id=3Dtpm-tpm0,path=3D/dev/tpm0,\ +cancel-path=3D/sys/class/misc/tpm0/device/cancel \ +-device tpm-crb,tpmdev=3Dtpm-tpm0,id=3Dtpm0 \ +-device virtio-balloon-pci,id=3Dballoon0,bus=3Dpci.0,addr=3D0x3 diff --git a/tests/qemuxml2argvdata/tpm-passthrough-crb.xml b/tests/qemuxml= 2argvdata/tpm-passthrough-crb.xml new file mode 100644 index 0000000..d4f3873 --- /dev/null +++ b/tests/qemuxml2argvdata/tpm-passthrough-crb.xml @@ -0,0 +1,32 @@ + + TPM-VM + 11d7cd22-da89-3094-6212-079a48a309a1 + 2097152 + 512288 + 1 + + hvm + + + + + + + + destroy + restart + destroy + + /usr/bin/qemu-system-x86_64 + + + + + + + + + + + + diff --git a/tests/qemuxml2argvtest.c b/tests/qemuxml2argvtest.c index 308d71f..2992197 100644 --- a/tests/qemuxml2argvtest.c +++ b/tests/qemuxml2argvtest.c @@ -2134,6 +2134,9 @@ mymain(void) =20 DO_TEST("tpm-passthrough", QEMU_CAPS_DEVICE_TPM_PASSTHROUGH, QEMU_CAPS_DEVICE_TPM_TIS); + DO_TEST("tpm-passthrough-crb", + QEMU_CAPS_DEVICE_TPM_PASSTHROUGH, QEMU_CAPS_DEVICE_TPM_TIS, + QEMU_CAPS_DEVICE_TPM_CRB); DO_TEST_PARSE_ERROR("tpm-no-backend-invalid", QEMU_CAPS_DEVICE_TPM_PASSTHROUGH, QEMU_CAPS_DEVICE= _TPM_TIS); =20 diff --git a/tests/qemuxml2xmloutdata/tpm-passthrough-crb.xml b/tests/qemux= ml2xmloutdata/tpm-passthrough-crb.xml new file mode 100644 index 0000000..ad094a4 --- /dev/null +++ b/tests/qemuxml2xmloutdata/tpm-passthrough-crb.xml @@ -0,0 +1,36 @@ + + TPM-VM + 11d7cd22-da89-3094-6212-079a48a309a1 + 2097152 + 512288 + 1 + + hvm + + + + + + + + destroy + restart + destroy + + /usr/bin/qemu-system-x86_64 + +
+ + + + + + + + + + +
+ + + --=20 2.5.5 -- libvir-list mailing list libvir-list@redhat.com https://www.redhat.com/mailman/listinfo/libvir-list From nobody Mon Apr 29 09:01:19 2024 Delivered-To: importer@patchew.org Received-SPF: pass (zoho.com: domain of redhat.com designates 209.132.183.28 as permitted sender) client-ip=209.132.183.28; envelope-from=libvir-list-bounces@redhat.com; helo=mx1.redhat.com; Authentication-Results: mx.zohomail.com; spf=pass (zoho.com: domain of redhat.com designates 209.132.183.28 as permitted sender) smtp.mailfrom=libvir-list-bounces@redhat.com Return-Path: Received: from mx1.redhat.com (mx1.redhat.com [209.132.183.28]) by mx.zohomail.com with SMTPS id 1523415044817259.97797339129556; Tue, 10 Apr 2018 19:50:44 -0700 (PDT) Received: from smtp.corp.redhat.com (int-mx02.intmail.prod.int.phx2.redhat.com [10.5.11.12]) (using TLSv1.2 with cipher AECDH-AES256-SHA (256/256 bits)) (No client certificate requested) by mx1.redhat.com (Postfix) with ESMTPS id 4AEB7A916; Wed, 11 Apr 2018 02:50:43 +0000 (UTC) Received: from colo-mx.corp.redhat.com (colo-mx01.intmail.prod.int.phx2.redhat.com [10.5.11.20]) by smtp.corp.redhat.com (Postfix) with ESMTPS id 1C0368D677; Wed, 11 Apr 2018 02:50:43 +0000 (UTC) Received: from lists01.pubmisc.prod.ext.phx2.redhat.com (lists01.pubmisc.prod.ext.phx2.redhat.com [10.5.19.33]) by colo-mx.corp.redhat.com (Postfix) with ESMTP id D0BC81800CAB; Wed, 11 Apr 2018 02:50:42 +0000 (UTC) Received: from smtp.corp.redhat.com (int-mx04.intmail.prod.int.phx2.redhat.com [10.5.11.14]) by lists01.pubmisc.prod.ext.phx2.redhat.com (8.13.8/8.13.8) with ESMTP id w3B2oV1c009983 for ; Tue, 10 Apr 2018 22:50:31 -0400 Received: by smtp.corp.redhat.com (Postfix) id 0F05E5E50E; Wed, 11 Apr 2018 02:50:31 +0000 (UTC) Received: from mx1.redhat.com (ext-mx07.extmail.prod.ext.phx2.redhat.com [10.5.110.31]) by smtp.corp.redhat.com (Postfix) with ESMTPS id 06E905E4FF for ; Wed, 11 Apr 2018 02:50:27 +0000 (UTC) Received: from mx0a-001b2d01.pphosted.com (mx0a-001b2d01.pphosted.com [148.163.156.1]) (using TLSv1.2 with cipher ECDHE-RSA-AES256-GCM-SHA384 (256/256 bits)) (No client certificate requested) by mx1.redhat.com (Postfix) with ESMTPS id CFC56C049D5B for ; Wed, 11 Apr 2018 02:50:20 +0000 (UTC) Received: from pps.filterd (m0098410.ppops.net [127.0.0.1]) by mx0a-001b2d01.pphosted.com (8.16.0.22/8.16.0.22) with SMTP id w3B2nkYJ077357 for ; Tue, 10 Apr 2018 22:50:20 -0400 Received: from e38.co.us.ibm.com (e38.co.us.ibm.com [32.97.110.159]) by mx0a-001b2d01.pphosted.com with ESMTP id 2h94jh3gst-1 (version=TLSv1.2 cipher=AES256-SHA256 bits=256 verify=NOT) for ; Tue, 10 Apr 2018 22:50:19 -0400 Received: from localhost by e38.co.us.ibm.com with IBM ESMTP SMTP Gateway: Authorized Use Only! Violators will be prosecuted for from ; Tue, 10 Apr 2018 20:50:19 -0600 Received: from b03cxnp08028.gho.boulder.ibm.com (9.17.130.20) by e38.co.us.ibm.com (192.168.1.138) with IBM ESMTP SMTP Gateway: Authorized Use Only! Violators will be prosecuted; Tue, 10 Apr 2018 20:50:16 -0600 Received: from b03ledav005.gho.boulder.ibm.com (b03ledav005.gho.boulder.ibm.com [9.17.130.236]) by b03cxnp08028.gho.boulder.ibm.com (8.14.9/8.14.9/NCO v10.0) with ESMTP id w3B2oGaP6160872; Tue, 10 Apr 2018 19:50:16 -0700 Received: from b03ledav005.gho.boulder.ibm.com (unknown [127.0.0.1]) by IMSVA (Postfix) with ESMTP id 083E5BE039; Tue, 10 Apr 2018 20:50:16 -0600 (MDT) Received: from sbct-3.watson.ibm.com (unknown [9.47.158.153]) by b03ledav005.gho.boulder.ibm.com (Postfix) with ESMTP id A4FB6BE040; Tue, 10 Apr 2018 20:50:15 -0600 (MDT) From: Stefan Berger To: libvir-list@redhat.com Date: Tue, 10 Apr 2018 22:50:01 -0400 In-Reply-To: <1523415005-30661-1-git-send-email-stefanb@linux.vnet.ibm.com> References: <1523415005-30661-1-git-send-email-stefanb@linux.vnet.ibm.com> X-TM-AS-GCONF: 00 x-cbid: 18041102-0028-0000-0000-0000096DBFE7 X-IBM-SpamModules-Scores: X-IBM-SpamModules-Versions: BY=3.00008834; HX=3.00000241; KW=3.00000007; PH=3.00000004; SC=3.00000256; SDB=6.01016139; UDB=6.00518174; IPR=6.00795386; MB=3.00020511; MTD=3.00000008; XFM=3.00000015; UTC=2018-04-11 02:50:17 X-IBM-AV-DETECTION: SAVI=unused REMOTE=unused XFE=unused x-cbparentid: 18041102-0029-0000-0000-00003A53697D Message-Id: <1523415005-30661-3-git-send-email-stefanb@linux.vnet.ibm.com> X-Proofpoint-Virus-Version: vendor=fsecure engine=2.50.10434:, , definitions=2018-04-11_01:, , signatures=0 X-Proofpoint-Spam-Details: rule=outbound_notspam policy=outbound score=0 priorityscore=1501 malwarescore=0 suspectscore=43 phishscore=0 bulkscore=0 spamscore=0 clxscore=1015 lowpriorityscore=0 impostorscore=0 adultscore=0 classifier=spam adjust=0 reason=mlx scancount=1 engine=8.0.1-1709140000 definitions=main-1804110026 X-Greylist: Sender passed SPF test, Sender IP whitelisted by DNSRBL, ACL 207 matched, not delayed by milter-greylist-4.5.16 (mx1.redhat.com [10.5.110.31]); Wed, 11 Apr 2018 02:50:21 +0000 (UTC) X-Greylist: inspected by milter-greylist-4.5.16 (mx1.redhat.com [10.5.110.31]); Wed, 11 Apr 2018 02:50:21 +0000 (UTC) for IP:'148.163.156.1' DOMAIN:'mx0a-001b2d01.pphosted.com' HELO:'mx0a-001b2d01.pphosted.com' FROM:'stefanb@linux.vnet.ibm.com' RCPT:'' X-RedHat-Spam-Score: -1.71 (RCVD_IN_DNSWL_LOW, RCVD_IN_MSPIKE_H5, RCVD_IN_MSPIKE_WL) 148.163.156.1 mx0a-001b2d01.pphosted.com 148.163.156.1 mx0a-001b2d01.pphosted.com X-Scanned-By: MIMEDefang 2.78 on 10.5.110.31 X-Scanned-By: MIMEDefang 2.79 on 10.5.11.14 X-loop: libvir-list@redhat.com Subject: [libvirt] [PATCH v2 2/6] tpm: Add support for external swtpm TPM emulator X-BeenThere: libvir-list@redhat.com X-Mailman-Version: 2.1.12 Precedence: junk List-Id: Development discussions about the libvirt library & tools List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , MIME-Version: 1.0 Content-Transfer-Encoding: quoted-printable Sender: libvir-list-bounces@redhat.com Errors-To: libvir-list-bounces@redhat.com X-Scanned-By: MIMEDefang 2.79 on 10.5.11.12 X-Greylist: Sender IP whitelisted, not delayed by milter-greylist-4.5.16 (mx1.redhat.com [10.5.110.29]); Wed, 11 Apr 2018 02:50:43 +0000 (UTC) X-ZohoMail: RSF_0 Z_629925259 SPT_0 Content-Type: text/plain; charset="utf-8" This patch adds support for an external swtpm TPM emulator. The XML for this type of TPM looks as follows: The XML will currently only start a TPM 1.2. Upon first start, libvirt will run `swtpm_setup`, which will simulate the manufacturing of a TPM and create certificates for it and write them into NVRAM locations of the emulated TPM. After that libvirt starts the swtpm TPM emulator using the `swtpm` executab= le. Once the VM terminates, libvirt uses the swtpm_ioctl executable to graceful= ly shut down the `swtpm` in case it is still running (QEMU did not send shutdo= wn) or clean up the socket file. The above mentioned executables must be found in the PATH. The executables can either be run as root or started as root and switch to the tss user. The requirement for the tss user comes through 'tcsd', which is used for the simulation of the manufacturing. Which user is used can be configured through qemu.conf. By default 'tss' is used. The swtpm writes out state into files. The state is kept in /var/lib/libvir= t/swtpm: [root@localhost libvirt]# ls -lZ | grep swtpm drwx--x--x. 7 root root unconfined_u:object_r:virt_var_lib_t:s0 4096 Apr 5= 16:22 swtpm The directory /var/lib/libvirt/swtpm maintains per-TPM state directories. [root@localhost swtpm]# ls -lZ total 4 drwx------. 2 tss tss system_u:object_r:virt_var_lib_t:s0 4096 A= pr 5 16:46 testvm [root@localhost testvm]# ls -lZ total 4 drwx------. 2 tss tss system_u:object_r:virt_var_lib_t:s0 4096 Apr 10 21:34= tpm1.2 [root@localhost tpm1.2]# ls -lZ total 8 -rw-r--r--. 1 tss tss system_u:object_r:virt_var_lib_t:s0 3648 Apr 5 16:46= tpm-00.permall The directory /var/run/libvirt/qemu/swtpm/domain-1-testvm hosts the swtpm.s= ock that QEMU uses to communicate with the swtpm: root@localhost domain-1-testvm]# ls -lZ total 0 srw-------. 1 qemu qemu system_u:object_r:svirt_image_t:s0:c597,c632 0 Apr= 6 10:24 swtpm.sock The logfile for the swtpm is in /var/log/swtpm/libvirt/qemu: [root@localhost-3 qemu]# ls -lZ total 4 -rw-------. 1 tss tss unconfined_u:object_r:var_log_t:s0 2199 Apr 6 14:01 = testvm-swtpm.log The processes are labeled as follows: [root@localhost 485d0004-a48f-436a-8457-8a3b73e28567]# ps auxZ | grep swtpm= | grep socket | grep -v grep system_u:system_r:virtd_t:s0-s0:c0.c1023 tss 18697 0.0 0.0 28172 3892 ? = Ss 16:46 0:00 /usr/bin/swtpm socket --daemon --ctrl type=3Dunixio,p= ath=3D/var/run/libvirt/qemu/swtpm/testvm-swtpm.sock,mode=3D0660 --tpmstate = dir=3D/var/lib/libvirt/swtpm/testvm/tpm1.2 --log file=3D/var/log/swtpm/libv= irt/qemu/testvm-swtpm.log [root@localhost 485d0004-a48f-436a-8457-8a3b73e28567]# ps auxZ | grep qemu = | grep tpm | grep -v grep system_u:system_r:svirt_t:s0:c413,c430 qemu 18702 2.5 0.0 3036052 48676 ? = Sl 16:46 0:08 /bin/qemu-system-x86_64 [...] Signed-off-by: Stefan Berger --- docs/formatdomain.html.in | 30 +++ docs/schemas/domaincommon.rng | 5 + src/conf/domain_audit.c | 2 + src/conf/domain_conf.c | 49 +++- src/conf/domain_conf.h | 7 + src/libvirt_private.syms | 7 + src/qemu/Makefile.inc.am | 2 + src/qemu/libvirtd_qemu.aug | 3 + src/qemu/qemu.conf | 7 + src/qemu/qemu_capabilities.c | 5 + src/qemu/qemu_capabilities.h | 1 + src/qemu/qemu_cgroup.c | 1 + src/qemu/qemu_command.c | 52 +++- src/qemu/qemu_conf.c | 35 ++- src/qemu/qemu_conf.h | 5 + src/qemu/qemu_domain.c | 4 + src/qemu/qemu_driver.c | 7 + src/qemu/qemu_extdevice.c | 264 ++++++++++++++++++++ src/qemu/qemu_extdevice.h | 44 ++++ src/qemu/qemu_process.c | 12 + src/qemu/test_libvirtd_qemu.aug.in | 1 + src/security/security_dac.c | 6 + src/security/security_selinux.c | 7 + src/util/virfile.c | 60 +++++ src/util/virfile.h | 2 + src/util/virtpm.c | 493 +++++++++++++++++++++++++++++++++= +++- src/util/virtpm.h | 25 +- 27 files changed, 1121 insertions(+), 15 deletions(-) create mode 100644 src/qemu/qemu_extdevice.c create mode 100644 src/qemu/qemu_extdevice.h diff --git a/docs/formatdomain.html.in b/docs/formatdomain.html.in index 16fc7db..bd6fedc 100644 --- a/docs/formatdomain.html.in +++ b/docs/formatdomain.html.in @@ -7621,6 +7621,26 @@ qemu-kvm -net nic,model=3D? /dev/null </devices> ... + +

+ The emulator device type gives access to a TPM emulator providing + TPM functionlity for each VM. QEMU talks to it over a UnixIO socket.= With + the emulator device type each guest gets its own private TPM. + 'emulator' since 4.x.y +

+

+ Example: usage of the TPM Emulator +

+
+  ...
+  <devices>
+    <tpm model=3D'tpm-tis'>
+      <backend type=3D'emulator'>
+      </backend>
+    </tpm>
+  </devices>
+  ...
+
model
@@ -7653,6 +7673,16 @@ qemu-kvm -net nic,model=3D? /dev/null

+
+
emulator
+
+

+ For this backend type the 'swtpm' TPM Emulator must be insta= lled on the + host. Libvirt will automatically start an independent TPM em= ulator + for each QEMU guest requesting access to it. +

+
+
=20 diff --git a/docs/schemas/domaincommon.rng b/docs/schemas/domaincommon.rng index be5c628..d628444 100644 --- a/docs/schemas/domaincommon.rng +++ b/docs/schemas/domaincommon.rng @@ -4134,6 +4134,11 @@ + + + emulator + + diff --git a/src/conf/domain_audit.c b/src/conf/domain_audit.c index 82868bc..25cccdd 100644 --- a/src/conf/domain_audit.c +++ b/src/conf/domain_audit.c @@ -586,6 +586,8 @@ virDomainAuditTPM(virDomainObjPtr vm, virDomainTPMDefPt= r tpm, "virt=3D%s resrc=3Ddev reason=3D%s %s uuid=3D%s %s", virt, reason, vmname, uuidstr, device); break; + case VIR_DOMAIN_TPM_TYPE_EMULATOR: + break; case VIR_DOMAIN_TPM_TYPE_LAST: default: break; diff --git a/src/conf/domain_conf.c b/src/conf/domain_conf.c index 232174a..b5f1c3f 100644 --- a/src/conf/domain_conf.c +++ b/src/conf/domain_conf.c @@ -862,7 +862,8 @@ VIR_ENUM_IMPL(virDomainTPMModel, VIR_DOMAIN_TPM_MODEL_L= AST, "tpm-crb") =20 VIR_ENUM_IMPL(virDomainTPMBackend, VIR_DOMAIN_TPM_TYPE_LAST, - "passthrough") + "passthrough", + "emulator") =20 VIR_ENUM_IMPL(virDomainIOMMUModel, VIR_DOMAIN_IOMMU_MODEL_LAST, "intel") @@ -2588,6 +2589,24 @@ void virDomainHostdevDefClear(virDomainHostdevDefPtr= def) } } =20 +void virDomainTPMDelete(virDomainDefPtr def) +{ + virDomainTPMDefPtr tpm =3D def->tpm; + + if (!tpm) + return; + + switch (tpm->type) { + case VIR_DOMAIN_TPM_TYPE_EMULATOR: + virTPMDeleteEmulatorStorage(tpm); + break; + case VIR_DOMAIN_TPM_TYPE_PASSTHROUGH: + case VIR_DOMAIN_TPM_TYPE_LAST: + /* nothing to do */ + break; + } +} + void virDomainTPMDefFree(virDomainTPMDefPtr def) { if (!def) @@ -2597,6 +2616,11 @@ void virDomainTPMDefFree(virDomainTPMDefPtr def) case VIR_DOMAIN_TPM_TYPE_PASSTHROUGH: VIR_FREE(def->data.passthrough.source.data.file.path); break; + case VIR_DOMAIN_TPM_TYPE_EMULATOR: + VIR_FREE(def->data.emulator.source.data.nix.path); + VIR_FREE(def->data.emulator.storagepath); + VIR_FREE(def->data.emulator.logfile); + break; case VIR_DOMAIN_TPM_TYPE_LAST: break; } @@ -12525,6 +12549,11 @@ virDomainSmartcardDefParseXML(virDomainXMLOptionPt= r xmlopt, * * * + * or like this: + * + * + * + * */ static virDomainTPMDefPtr virDomainTPMDefParseXML(virDomainXMLOptionPtr xmlopt, @@ -12591,6 +12620,8 @@ virDomainTPMDefParseXML(virDomainXMLOptionPtr xmlop= t, def->data.passthrough.source.type =3D VIR_DOMAIN_CHR_TYPE_DEV; path =3D NULL; break; + case VIR_DOMAIN_TPM_TYPE_EMULATOR: + break; case VIR_DOMAIN_TPM_TYPE_LAST: goto error; } @@ -24760,24 +24791,32 @@ virDomainTPMDefFormat(virBufferPtr buf, virDomainTPMDefPtr def, unsigned int flags) { + bool did_nl =3D false; + virBufferAsprintf(buf, "\n", virDomainTPMModelTypeToString(def->model)); virBufferAdjustIndent(buf, 2); - virBufferAsprintf(buf, "\n", + virBufferAsprintf(buf, "type)); virBufferAdjustIndent(buf, 2); =20 switch (def->type) { case VIR_DOMAIN_TPM_TYPE_PASSTHROUGH: + virBufferAddLit(buf, ">\n"); + did_nl =3D true; virBufferEscapeString(buf, "\n", def->data.passthrough.source.data.file.path); break; + case VIR_DOMAIN_TPM_TYPE_EMULATOR: case VIR_DOMAIN_TPM_TYPE_LAST: break; } =20 virBufferAdjustIndent(buf, -2); - virBufferAddLit(buf, "\n"); + if (did_nl) + virBufferAddLit(buf, "\n"); + else + virBufferAddLit(buf, "/>\n"); =20 virDomainDeviceInfoFormat(buf, &def->info, flags); =20 @@ -27548,6 +27587,10 @@ virDomainDeleteConfig(const char *configDir, goto cleanup; } =20 + /* in case domain is NOT running, remove any TPM storage */ + if (!dom->persistent) + virDomainTPMDelete(dom->def); + ret =3D 0; =20 cleanup: diff --git a/src/conf/domain_conf.h b/src/conf/domain_conf.h index 1724340..f632184 100644 --- a/src/conf/domain_conf.h +++ b/src/conf/domain_conf.h @@ -1284,6 +1284,7 @@ typedef enum { =20 typedef enum { VIR_DOMAIN_TPM_TYPE_PASSTHROUGH, + VIR_DOMAIN_TPM_TYPE_EMULATOR, =20 VIR_DOMAIN_TPM_TYPE_LAST } virDomainTPMBackendType; @@ -1298,6 +1299,11 @@ struct _virDomainTPMDef { struct { virDomainChrSourceDef source; } passthrough; + struct { + virDomainChrSourceDef source; + char *storagepath; + char *logfile; + } emulator; } data; }; =20 @@ -2810,6 +2816,7 @@ int virDomainDeviceAddressIsValid(virDomainDeviceInfo= Ptr info, int type); virDomainDeviceInfoPtr virDomainDeviceGetInfo(virDomainDeviceDefPtr device= ); void virDomainTPMDefFree(virDomainTPMDefPtr def); +void virDomainTPMDelete(virDomainDefPtr def); =20 typedef int (*virDomainDeviceInfoCallback)(virDomainDefPtr def, virDomainDeviceDefPtr dev, diff --git a/src/libvirt_private.syms b/src/libvirt_private.syms index 03fe3b3..935ffcc 100644 --- a/src/libvirt_private.syms +++ b/src/libvirt_private.syms @@ -556,6 +556,7 @@ virDomainTimerTrackTypeToString; virDomainTPMBackendTypeFromString; virDomainTPMBackendTypeToString; virDomainTPMDefFree; +virDomainTPMDelete; virDomainTPMModelTypeFromString; virDomainTPMModelTypeToString; virDomainUSBDeviceDefForeach; @@ -1745,6 +1746,7 @@ saferead; safewrite; safezero; virBuildPathInternal; +virDirChownFiles; virDirClose; virDirCreate; virDirOpen; @@ -2971,6 +2973,11 @@ virTimeStringThenRaw; =20 # util/virtpm.h virTPMCreateCancelPath; +virTPMDeleteEmulatorStorage; +virTPMEmulatorBuildCommand; +virTPMEmulatorInitPaths; +virTPMEmulatorPrepareHost; +virTPMEmulatorStop; =20 =20 # util/virtypedparam.h diff --git a/src/qemu/Makefile.inc.am b/src/qemu/Makefile.inc.am index 8ef290a..6c8daf8 100644 --- a/src/qemu/Makefile.inc.am +++ b/src/qemu/Makefile.inc.am @@ -19,6 +19,8 @@ QEMU_DRIVER_SOURCES =3D \ qemu/qemu_domain_address.h \ qemu/qemu_cgroup.c \ qemu/qemu_cgroup.h \ + qemu/qemu_extdevice.c \ + qemu/qemu_extdevice.h \ qemu/qemu_hostdev.c \ qemu/qemu_hostdev.h \ qemu/qemu_hotplug.c \ diff --git a/src/qemu/libvirtd_qemu.aug b/src/qemu/libvirtd_qemu.aug index c19bf3a..cc5d657 100644 --- a/src/qemu/libvirtd_qemu.aug +++ b/src/qemu/libvirtd_qemu.aug @@ -118,6 +118,8 @@ module Libvirtd_qemu =3D let vxhs_entry =3D bool_entry "vxhs_tls" | str_entry "vxhs_tls_x509_cert_dir" =20 + let swtpm_entry =3D str_entry "swtpm_user" + (* Each entry in the config is one of the following ... *) let entry =3D default_tls_entry | vnc_entry @@ -137,6 +139,7 @@ module Libvirtd_qemu =3D | gluster_debug_level_entry | memory_entry | vxhs_entry + | swtpm_entry =20 let comment =3D [ label "#comment" . del /#[ \t]*/ "# " . store /([^ \= t\n][^\n]*)?/ . del /\n/ "\n" ] let empty =3D [ label "#empty" . eol ] diff --git a/src/qemu/qemu.conf b/src/qemu/qemu.conf index 43dd561..f64ae68 100644 --- a/src/qemu/qemu.conf +++ b/src/qemu/qemu.conf @@ -775,3 +775,10 @@ # This directory is used for memoryBacking source if configured as file. # NOTE: big files will be stored here #memory_backing_dir =3D "/var/lib/libvirt/qemu/ram" + +# User for the swtpm TPM Emulator +# +# Default is 'tss'; this is the same user that tcsd (TrouSerS) installs +# and uses; alternative is 'root' +# +#swtpm_user =3D "tss" diff --git a/src/qemu/qemu_capabilities.c b/src/qemu/qemu_capabilities.c index 0952663..ce4db62 100644 --- a/src/qemu/qemu_capabilities.c +++ b/src/qemu/qemu_capabilities.c @@ -467,6 +467,7 @@ VIR_ENUM_IMPL(virQEMUCaps, QEMU_CAPS_LAST, "virtio-mouse-ccw", "virtio-tablet-ccw", "tpm-crb", + "tpm-emulator", ); =20 =20 @@ -3098,6 +3099,10 @@ static const struct tpmTypeToCaps virQEMUCapsTPMType= sToCaps[] =3D { .type =3D VIR_DOMAIN_TPM_TYPE_PASSTHROUGH, .caps =3D QEMU_CAPS_DEVICE_TPM_PASSTHROUGH, }, + { + .type =3D VIR_DOMAIN_TPM_TYPE_EMULATOR, + .caps =3D QEMU_CAPS_DEVICE_TPM_EMULATOR, + }, }; =20 const struct tpmTypeToCaps virQEMUCapsTPMModelsToCaps[] =3D { diff --git a/src/qemu/qemu_capabilities.h b/src/qemu/qemu_capabilities.h index 604525a..0cc2882 100644 --- a/src/qemu/qemu_capabilities.h +++ b/src/qemu/qemu_capabilities.h @@ -451,6 +451,7 @@ typedef enum { QEMU_CAPS_DEVICE_VIRTIO_MOUSE_CCW, /* -device virtio-mouse-ccw */ QEMU_CAPS_DEVICE_VIRTIO_TABLET_CCW, /* -device virtio-tablet-ccw */ QEMU_CAPS_DEVICE_TPM_CRB, /* -device tpm-crb */ + QEMU_CAPS_DEVICE_TPM_EMULATOR, /* -tpmdev emulator */ =20 QEMU_CAPS_LAST /* this must always be the last item */ } virQEMUCapsFlags; diff --git a/src/qemu/qemu_cgroup.c b/src/qemu/qemu_cgroup.c index b604edb..bd4859c 100644 --- a/src/qemu/qemu_cgroup.c +++ b/src/qemu/qemu_cgroup.c @@ -238,6 +238,7 @@ qemuSetupTPMCgroup(virDomainObjPtr vm) case VIR_DOMAIN_TPM_TYPE_PASSTHROUGH: ret =3D qemuSetupChrSourceCgroup(vm, &dev->data.passthrough.source= ); break; + case VIR_DOMAIN_TPM_TYPE_EMULATOR: case VIR_DOMAIN_TPM_TYPE_LAST: break; } diff --git a/src/qemu/qemu_command.c b/src/qemu/qemu_command.c index 89fd08b..878a147 100644 --- a/src/qemu/qemu_command.c +++ b/src/qemu/qemu_command.c @@ -9614,21 +9614,33 @@ qemuBuildTPMDevStr(const virDomainDef *def, =20 =20 static char * -qemuBuildTPMBackendStr(const virDomainDef *def, +qemuBuildTPMBackendStr(virDomainDef *def, + virQEMUDriverPtr driver, virCommandPtr cmd, virQEMUCapsPtr qemuCaps, int *tpmfd, - int *cancelfd) + int *cancelfd, + char **chardev) { - const virDomainTPMDef *tpm =3D def->tpm; + virDomainTPMDef *tpm =3D def->tpm; virBuffer buf =3D VIR_BUFFER_INITIALIZER; - const char *type =3D virDomainTPMBackendTypeToString(tpm->type); + const char *type =3D NULL; char *cancel_path =3D NULL, *devset =3D NULL; const char *tpmdev; + virQEMUDriverConfigPtr cfg =3D virQEMUDriverGetConfig(driver); =20 *tpmfd =3D -1; *cancelfd =3D -1; =20 + switch (tpm->type) { + case VIR_DOMAIN_TPM_TYPE_PASSTHROUGH: + case VIR_DOMAIN_TPM_TYPE_EMULATOR: + type =3D virDomainTPMBackendTypeToString(tpm->type); + break; + case VIR_DOMAIN_TPM_TYPE_LAST: + goto error; + } + virBufferAsprintf(&buf, "%s,id=3Dtpm-%s", type, tpm->info.alias); =20 switch (tpm->type) { @@ -9679,6 +9691,17 @@ qemuBuildTPMBackendStr(const virDomainDef *def, VIR_FREE(cancel_path); =20 break; + case VIR_DOMAIN_TPM_TYPE_EMULATOR: + if (!virQEMUCapsGet(qemuCaps, QEMU_CAPS_DEVICE_TPM_EMULATOR)) + goto no_support; + + virBufferAddLit(&buf, ",chardev=3Dchrtpm"); + + if (virAsprintf(chardev, "socket,id=3Dchrtpm,path=3D%s", + tpm->data.emulator.source.data.nix.path) < 0) + goto error; + + break; case VIR_DOMAIN_TPM_TYPE_LAST: goto error; } @@ -9686,6 +9709,8 @@ qemuBuildTPMBackendStr(const virDomainDef *def, if (virBufferCheckError(&buf) < 0) goto error; =20 + virObjectUnref(cfg); + return virBufferContentAndReset(&buf); =20 no_support: @@ -9699,16 +9724,19 @@ qemuBuildTPMBackendStr(const virDomainDef *def, VIR_FREE(cancel_path); =20 virBufferFreeAndReset(&buf); + virObjectUnref(cfg); return NULL; } =20 =20 static int -qemuBuildTPMCommandLine(virCommandPtr cmd, - const virDomainDef *def, +qemuBuildTPMCommandLine(virQEMUDriverPtr driver, + virCommandPtr cmd, + virDomainDef *def, virQEMUCapsPtr qemuCaps) { char *optstr; + char *chardev =3D NULL; int tpmfd =3D -1; int cancelfd =3D -1; char *fdset; @@ -9716,13 +9744,19 @@ qemuBuildTPMCommandLine(virCommandPtr cmd, if (!def->tpm) return 0; =20 - if (!(optstr =3D qemuBuildTPMBackendStr(def, cmd, qemuCaps, - &tpmfd, &cancelfd))) + if (!(optstr =3D qemuBuildTPMBackendStr(def, driver, cmd, qemuCaps, + &tpmfd, &cancelfd, + &chardev))) return -1; =20 virCommandAddArgList(cmd, "-tpmdev", optstr, NULL); VIR_FREE(optstr); =20 + if (chardev) { + virCommandAddArgList(cmd, "-chardev", chardev, NULL); + VIR_FREE(chardev); + } + if (tpmfd >=3D 0) { fdset =3D qemuVirCommandGetFDSet(cmd, tpmfd); if (!fdset) @@ -10151,7 +10185,7 @@ qemuBuildCommandLine(virQEMUDriverPtr driver, chardevStdioLogd) < 0) goto error; =20 - if (qemuBuildTPMCommandLine(cmd, def, qemuCaps) < 0) + if (qemuBuildTPMCommandLine(driver, cmd, def, qemuCaps) < 0) goto error; =20 if (qemuBuildInputCommandLine(cmd, def, qemuCaps) < 0) diff --git a/src/qemu/qemu_conf.c b/src/qemu/qemu_conf.c index 36cf3a2..486b314 100644 --- a/src/qemu/qemu_conf.c +++ b/src/qemu/qemu_conf.c @@ -164,6 +164,10 @@ virQEMUDriverConfigPtr virQEMUDriverConfigNew(bool pri= vileged) "%s/log/libvirt/qemu", LOCALSTATEDIR) < 0) goto error; =20 + if (virAsprintf(&cfg->swtpmLogDir, + "%s/log/swtpm/libvirt/qemu", LOCALSTATEDIR) < 0) + goto error; + if (VIR_STRDUP(cfg->configBaseDir, SYSCONFDIR "/libvirt") < 0) goto error; =20 @@ -171,6 +175,10 @@ virQEMUDriverConfigPtr virQEMUDriverConfigNew(bool pri= vileged) "%s/run/libvirt/qemu", LOCALSTATEDIR) < 0) goto error; =20 + if (virAsprintf(&cfg->swtpmStateDir, + "%s/run/libvirt/qemu/swtpm", LOCALSTATEDIR) < 0) + goto error; + if (virAsprintf(&cfg->cacheDir, "%s/cache/libvirt/qemu", LOCALSTATEDIR) < 0) goto error; @@ -191,6 +199,9 @@ virQEMUDriverConfigPtr virQEMUDriverConfigNew(bool priv= ileged) goto error; if (virAsprintf(&cfg->memoryBackingDir, "%s/ram", cfg->libDir) < 0) goto error; + if (virAsprintf(&cfg->swtpmStorageDir, "%s/lib/libvirt/swtpm", + LOCALSTATEDIR) < 0) + goto error; } else { char *rundir; char *cachedir; @@ -204,6 +215,11 @@ virQEMUDriverConfigPtr virQEMUDriverConfigNew(bool pri= vileged) VIR_FREE(cachedir); goto error; } + if (virAsprintf(&cfg->swtpmLogDir, + "%s/qemu/log", cachedir) < 0) { + VIR_FREE(cachedir); + goto error; + } if (virAsprintf(&cfg->cacheDir, "%s/qemu/cache", cachedir) < 0) { VIR_FREE(cachedir); goto error; @@ -219,6 +235,9 @@ virQEMUDriverConfigPtr virQEMUDriverConfigNew(bool priv= ileged) } VIR_FREE(rundir); =20 + if (virAsprintf(&cfg->swtpmStateDir, "%s/qemu/run/swtpm", rundir) = < 0) + goto error; + if (!(cfg->configBaseDir =3D virGetUserConfigDirectory())) goto error; =20 @@ -238,6 +257,8 @@ virQEMUDriverConfigPtr virQEMUDriverConfigNew(bool priv= ileged) goto error; if (virAsprintf(&cfg->memoryBackingDir, "%s/qemu/ram", cfg->config= BaseDir) < 0) goto error; + if (virAsprintf(&cfg->swtpmStorageDir, "%s/qemu/swtpm", cfg->confi= gBaseDir) < 0) + goto error; } =20 if (virAsprintf(&cfg->configDir, "%s/qemu", cfg->configBaseDir) < 0) @@ -336,6 +357,9 @@ virQEMUDriverConfigPtr virQEMUDriverConfigNew(bool priv= ileged) &cfg->nfirmwares) < 0) goto error; =20 + if (virGetUserID("tss", &cfg->swtpm_user) < 0) + cfg->swtpm_user =3D 0; /* root */ + return cfg; =20 error: @@ -356,7 +380,9 @@ static void virQEMUDriverConfigDispose(void *obj) VIR_FREE(cfg->configDir); VIR_FREE(cfg->autostartDir); VIR_FREE(cfg->logDir); + VIR_FREE(cfg->swtpmLogDir); VIR_FREE(cfg->stateDir); + VIR_FREE(cfg->swtpmStateDir); =20 VIR_FREE(cfg->libDir); VIR_FREE(cfg->cacheDir); @@ -405,6 +431,7 @@ static void virQEMUDriverConfigDispose(void *obj) virFirmwareFreeList(cfg->firmwares, cfg->nfirmwares); =20 VIR_FREE(cfg->memoryBackingDir); + VIR_FREE(cfg->swtpmStorageDir); } =20 =20 @@ -475,7 +502,7 @@ int virQEMUDriverConfigLoadFile(virQEMUDriverConfigPtr = cfg, int rv; size_t i, j; char *stdioHandler =3D NULL; - char *user =3D NULL, *group =3D NULL; + char *user =3D NULL, *group =3D NULL, *swtpm_user =3D NULL; char **controllers =3D NULL; char **hugetlbfs =3D NULL; char **nvram =3D NULL; @@ -912,6 +939,11 @@ int virQEMUDriverConfigLoadFile(virQEMUDriverConfigPtr= cfg, if (virConfGetValueString(conf, "memory_backing_dir", &cfg->memoryBack= ingDir) < 0) goto cleanup; =20 + if (virConfGetValueString(conf, "swtpm_user", &swtpm_user) < 0) + goto cleanup; + if (swtpm_user && virGetUserID(swtpm_user, &cfg->swtpm_user) < 0) + goto cleanup; + ret =3D 0; =20 cleanup: @@ -922,6 +954,7 @@ int virQEMUDriverConfigLoadFile(virQEMUDriverConfigPtr = cfg, VIR_FREE(corestr); VIR_FREE(user); VIR_FREE(group); + VIR_FREE(swtpm_user); virConfFree(conf); return ret; } diff --git a/src/qemu/qemu_conf.h b/src/qemu/qemu_conf.h index e1ad546..93d3c65 100644 --- a/src/qemu/qemu_conf.h +++ b/src/qemu/qemu_conf.h @@ -102,7 +102,9 @@ struct _virQEMUDriverConfig { char *configDir; char *autostartDir; char *logDir; + char *swtpmLogDir; char *stateDir; + char *swtpmStateDir; /* These two directories are ones QEMU processes use (so must match * the QEMU user/group */ char *libDir; @@ -111,6 +113,7 @@ struct _virQEMUDriverConfig { char *snapshotDir; char *channelTargetDir; char *nvramDir; + char *swtpmStorageDir; =20 char *defaultTLSx509certdir; bool checkdefaultTLSx509certdir; @@ -206,6 +209,8 @@ struct _virQEMUDriverConfig { =20 bool vxhsTLS; char *vxhsTLSx509certdir; + + uid_t swtpm_user; }; =20 /* Main driver state */ diff --git a/src/qemu/qemu_domain.c b/src/qemu/qemu_domain.c index 580e0f8..542b67b 100644 --- a/src/qemu/qemu_domain.c +++ b/src/qemu/qemu_domain.c @@ -33,6 +33,7 @@ #include "qemu_capabilities.h" #include "qemu_migration.h" #include "qemu_security.h" +#include "qemu_extdevice.h" #include "viralloc.h" #include "virlog.h" #include "virerror.h" @@ -7088,6 +7089,8 @@ qemuDomainRemoveInactive(virQEMUDriverPtr driver, VIR_WARN("unable to remove snapshot directory %s", snapDir); VIR_FREE(snapDir); } + if (!qemuExtDevicesInitPaths(driver, vm->def)) + virDomainTPMDelete(vm->def); =20 virObjectRef(vm); =20 @@ -10280,6 +10283,7 @@ qemuDomainSetupTPM(virQEMUDriverConfigPtr cfg ATTRI= BUTE_UNUSED, return -1; break; =20 + case VIR_DOMAIN_TPM_TYPE_EMULATOR: case VIR_DOMAIN_TPM_TYPE_LAST: /* nada */ break; diff --git a/src/qemu/qemu_driver.c b/src/qemu/qemu_driver.c index 7bcc493..066aa4a 100644 --- a/src/qemu/qemu_driver.c +++ b/src/qemu/qemu_driver.c @@ -59,6 +59,7 @@ #include "qemu_migration.h" #include "qemu_blockjob.h" #include "qemu_security.h" +#include "qemu_extdevice.h" =20 #include "virerror.h" #include "virlog.h" @@ -7365,6 +7366,9 @@ qemuDomainCreateWithFlags(virDomainPtr dom, unsigned = int flags) goto endjob; } =20 + if (qemuExtDevicesInitPaths(driver, vm->def) < 0) + goto endjob; + if (qemuDomainObjStart(dom->conn, driver, vm, flags, QEMU_ASYNC_JOB_START) < 0) goto endjob; @@ -7510,6 +7514,9 @@ qemuDomainUndefineFlags(virDomainPtr dom, if (!(vm =3D qemuDomObjFromDomain(dom))) return -1; =20 + if (qemuExtDevicesInitPaths(driver, vm->def) < 0) + return -1; + cfg =3D virQEMUDriverGetConfig(driver); =20 if (virDomainUndefineFlagsEnsureACL(dom->conn, vm->def) < 0) diff --git a/src/qemu/qemu_extdevice.c b/src/qemu/qemu_extdevice.c new file mode 100644 index 0000000..be3df7c --- /dev/null +++ b/src/qemu/qemu_extdevice.c @@ -0,0 +1,264 @@ +/* + * qemu_extdevice.c: QEMU external devices support + * + * Copyright (C) 2014, 2018 IBM Corporation + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; either + * version 2.1 of the License, or (at your option) any later version. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with this library. If not, see + * . + * + * Author: Stefan Berger + */ + +#include + +#include "qemu_extdevice.h" +#include "qemu_domain.h" + +#include "viralloc.h" +#include "virlog.h" +#include "virstring.h" +#include "virtime.h" +#include "virtpm.h" + +#define VIR_FROM_THIS VIR_FROM_QEMU + +VIR_LOG_INIT("qemu.qemu_extdevice") + +static int +qemuExtDeviceLogCommand(qemuDomainLogContextPtr logCtxt, + virCommandPtr cmd, + const char *info) +{ + int ret =3D -1; + char *timestamp =3D NULL; + char *logline =3D NULL; + int logFD; + + logFD =3D qemuDomainLogContextGetWriteFD(logCtxt); + + if ((timestamp =3D virTimeStringNow()) =3D=3D NULL) + goto cleanup; + + if (virAsprintf(&logline, "%s: Starting external device: %s\n", + timestamp, info) < 0) + goto cleanup; + + if (safewrite(logFD, logline, strlen(logline)) < 0) + goto cleanup; + + virCommandWriteArgLog(cmd, logFD); + + ret =3D 0; + + cleanup: + VIR_FREE(timestamp); + VIR_FREE(logline); + + return ret; +} + +static int qemuExtTPMInitPaths(virQEMUDriverPtr driver, + virDomainDefPtr def) +{ + virQEMUDriverConfigPtr cfg =3D virQEMUDriverGetConfig(driver); + int ret =3D 0; + + switch (def->tpm->type) { + case VIR_DOMAIN_TPM_TYPE_EMULATOR: + ret =3D virTPMEmulatorInitPaths(def->tpm, cfg->swtpmStorageDir, de= f->name); + break; + case VIR_DOMAIN_TPM_TYPE_PASSTHROUGH: + case VIR_DOMAIN_TPM_TYPE_LAST: + break; + } + + return ret; +} + +static int qemuExtTPMPrepareHost(virQEMUDriverPtr driver, + virDomainDefPtr def) +{ + virQEMUDriverConfigPtr cfg =3D virQEMUDriverGetConfig(driver); + int ret =3D 0; + + switch (def->tpm->type) { + case VIR_DOMAIN_TPM_TYPE_EMULATOR: + ret =3D virTPMEmulatorPrepareHost(def->tpm, cfg->swtpmLogDir, + def->name, cfg->swtpm_user, + cfg->swtpmStateDir, cfg->user); + break; + case VIR_DOMAIN_TPM_TYPE_PASSTHROUGH: + case VIR_DOMAIN_TPM_TYPE_LAST: + break; + } + + return ret; +} + +/* + * qemuExtTPMStartEmulator: + * + * @driver: QEMU driver + * @def: domain definition + * @logCtxt: log context + * + * Start the external TPM Emulator: + * - have the command line built + * - start the external TPM Emulator and sync with it before QEMU start + */ +static int +qemuExtTPMStartEmulator(virQEMUDriverPtr driver, + virDomainDefPtr def, + qemuDomainLogContextPtr logCtxt) +{ + int ret =3D -1; + virCommandPtr cmd =3D NULL; + int exitstatus; + char *errbuf =3D NULL; + virQEMUDriverConfigPtr cfg =3D virQEMUDriverGetConfig(driver); + virDomainTPMDefPtr tpm =3D def->tpm; + + /* stop any left-over TPM emulator for this VM */ + virTPMEmulatorStop(cfg->swtpmStateDir, def->name); + + if (!(cmd =3D virTPMEmulatorBuildCommand(tpm, def->name, def->uuid, + cfg->swtpm_user))) + goto cleanup; + + if (qemuExtDeviceLogCommand(logCtxt, cmd, "TPM Emulator") < 0) + goto cleanup; + + virCommandSetErrorBuffer(cmd, &errbuf); + + if (virCommandRun(cmd, &exitstatus) < 0 || exitstatus !=3D 0) { + VIR_ERROR("Could not start 'swtpm'. exitstatus: %d\n" + "stderr: %s\n", exitstatus, errbuf); + virReportError(VIR_ERR_INTERNAL_ERROR, + _("Could not start 'swtpm'. exitstatus: %d, " + "error: %s"), exitstatus, errbuf); + goto error; + } + + ret =3D 0; + + cleanup: + VIR_FREE(errbuf); + virCommandFree(cmd); + + virObjectUnref(cfg); + + return ret; + + error: + virTPMEmulatorStop(cfg->swtpmStateDir, def->name); + VIR_FREE(tpm->data.emulator.source.data.nix.path); + + goto cleanup; +} + +static int +qemuExtTPMStart(virQEMUDriverPtr driver, + virDomainDefPtr def, + qemuDomainLogContextPtr logCtxt) +{ + int ret =3D 0; + virDomainTPMDefPtr tpm =3D def->tpm; + + switch (tpm->type) { + case VIR_DOMAIN_TPM_TYPE_EMULATOR: + ret =3D qemuExtTPMStartEmulator(driver, def, logCtxt); + break; + case VIR_DOMAIN_TPM_TYPE_PASSTHROUGH: + case VIR_DOMAIN_TPM_TYPE_LAST: + break; + } + + return ret; +} + +static void +qemuExtTPMStop(virQEMUDriverPtr driver, virDomainDefPtr def) +{ + virQEMUDriverConfigPtr cfg =3D virQEMUDriverGetConfig(driver); + + switch (def->tpm->type) { + case VIR_DOMAIN_TPM_TYPE_EMULATOR: + virTPMEmulatorStop(cfg->swtpmStateDir, def->name); + break; + case VIR_DOMAIN_TPM_TYPE_PASSTHROUGH: + case VIR_DOMAIN_TPM_TYPE_LAST: + break; + } +} + +/* + * qemuExtDevicesInitPaths: + * + * @driver: QEMU driver + * @def: domain definition + * + * Initialize paths of external devices so that it is known where state is + * stored and we can remove directories and files in case of domain XML + * changes. + */ +int qemuExtDevicesInitPaths(virQEMUDriverPtr driver, + virDomainDefPtr def) +{ + int ret =3D 0; + + if (def->tpm) + ret =3D qemuExtTPMInitPaths(driver, def); + + return ret; +} + +/* + * qemuExtDevicesPrepareHost: + * + * @driver: QEMU driver + * @def: domain definition + * + * Prepare host storage paths for external devices. + */ +int qemuExtDevicesPrepareHost(virQEMUDriverPtr driver, + virDomainDefPtr def) +{ + int ret =3D 0; + + if (def->tpm) + ret =3D qemuExtTPMPrepareHost(driver, def); + + return ret; +} + +int +qemuExtDevicesStart(virQEMUDriverPtr driver, + virDomainDefPtr def, + qemuDomainLogContextPtr logCtxt) +{ + int ret =3D 0; + + if (def->tpm) + ret =3D qemuExtTPMStart(driver, def, logCtxt); + + return ret; +} + +void +qemuExtDevicesStop(virQEMUDriverPtr driver, + virDomainDefPtr def) +{ + if (def->tpm) + qemuExtTPMStop(driver, def); +} diff --git a/src/qemu/qemu_extdevice.h b/src/qemu/qemu_extdevice.h new file mode 100644 index 0000000..0bc7735 --- /dev/null +++ b/src/qemu/qemu_extdevice.h @@ -0,0 +1,44 @@ +/* + * qemu_extdevice.h: QEMU external devices support + * + * Copyright (C) 2014, 2018 IBM Corporation + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; either + * version 2.1 of the License, or (at your option) any later version. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with this library. If not, see + * . + * + * Author: Stefan Berger + */ +#ifndef __QEMU_EXTDEVICE_H__ +# define __QEMU_EXTDEVICE_H__ + +# include "qemu_conf.h" +# include "qemu_domain.h" + +int qemuExtDevicesInitPaths(virQEMUDriverPtr driver, + virDomainDefPtr def) + ATTRIBUTE_RETURN_CHECK; + +int qemuExtDevicesPrepareHost(virQEMUDriverPtr driver, + virDomainDefPtr def) + ATTRIBUTE_RETURN_CHECK; + +int qemuExtDevicesStart(virQEMUDriverPtr driver, + virDomainDefPtr def, + qemuDomainLogContextPtr logCtxt) + ATTRIBUTE_RETURN_CHECK; + +void qemuExtDevicesStop(virQEMUDriverPtr driver, virDomainDefPtr def); + +#endif /* __QEMU_EXTDEVICE_H__ */ + diff --git a/src/qemu/qemu_process.c b/src/qemu/qemu_process.c index 1afb71f..7bf90a4 100644 --- a/src/qemu/qemu_process.c +++ b/src/qemu/qemu_process.c @@ -47,6 +47,7 @@ #include "qemu_migration.h" #include "qemu_interface.h" #include "qemu_security.h" +#include "qemu_extdevice.h" =20 #include "cpu/cpu.h" #include "datatypes.h" @@ -5869,6 +5870,10 @@ qemuProcessPrepareHost(virQEMUDriverPtr driver, if (qemuProcessPrepareHostStorage(driver, vm, flags) < 0) goto cleanup; =20 + VIR_DEBUG("Preparing external devices"); + if (qemuExtDevicesPrepareHost(driver, vm->def) < 0) + goto cleanup; + ret =3D 0; cleanup: virObjectUnref(cfg); @@ -5952,6 +5957,9 @@ qemuProcessLaunch(virConnectPtr conn, goto cleanup; logfile =3D qemuDomainLogContextGetWriteFD(logCtxt); =20 + if (qemuExtDevicesStart(driver, vm->def, logCtxt) < 0) + goto cleanup; + VIR_DEBUG("Building emulator command line"); if (!(cmd =3D qemuBuildCommandLine(driver, qemuDomainLogContextGetManager(logCtx= t), @@ -6191,6 +6199,8 @@ qemuProcessLaunch(virConnectPtr conn, ret =3D 0; =20 cleanup: + if (ret) + qemuExtDevicesStop(driver, vm->def); qemuDomainSecretDestroy(vm); virCommandFree(cmd); virObjectUnref(logCtxt); @@ -6557,6 +6567,8 @@ void qemuProcessStop(virQEMUDriverPtr driver, /* Clear network bandwidth */ virDomainClearNetBandwidth(vm); =20 + qemuExtDevicesStop(driver, vm->def); + virDomainConfVMNWFilterTeardown(vm); =20 if (cfg->macFilter) { diff --git a/src/qemu/test_libvirtd_qemu.aug.in b/src/qemu/test_libvirtd_qe= mu.aug.in index 688e5b9..03bef74 100644 --- a/src/qemu/test_libvirtd_qemu.aug.in +++ b/src/qemu/test_libvirtd_qemu.aug.in @@ -100,3 +100,4 @@ module Test_libvirtd_qemu =3D { "1" =3D "mount" } } { "memory_backing_dir" =3D "/var/lib/libvirt/qemu/ram" } +{ "swtpm_user" =3D "tss" } diff --git a/src/security/security_dac.c b/src/security/security_dac.c index 663c8c9..351f6f4 100644 --- a/src/security/security_dac.c +++ b/src/security/security_dac.c @@ -1372,6 +1372,11 @@ virSecurityDACSetTPMFileLabel(virSecurityManagerPtr = mgr, &tpm->data.passthrough.source, false); break; + case VIR_DOMAIN_TPM_TYPE_EMULATOR: + ret =3D virSecurityDACSetChardevLabel(mgr, def, + &tpm->data.emulator.source, + false); + break; case VIR_DOMAIN_TPM_TYPE_LAST: break; } @@ -1393,6 +1398,7 @@ virSecurityDACRestoreTPMFileLabel(virSecurityManagerP= tr mgr, &tpm->data.passthrough.sou= rce, false); break; + case VIR_DOMAIN_TPM_TYPE_EMULATOR: case VIR_DOMAIN_TPM_TYPE_LAST: break; } diff --git a/src/security/security_selinux.c b/src/security/security_selinu= x.c index c26cdac..17bc07a 100644 --- a/src/security/security_selinux.c +++ b/src/security/security_selinux.c @@ -1472,6 +1472,12 @@ virSecuritySELinuxSetTPMFileLabel(virSecurityManager= Ptr mgr, return -1; } break; + case VIR_DOMAIN_TPM_TYPE_EMULATOR: + tpmdev =3D tpm->data.emulator.source.data.nix.path; + rc =3D virSecuritySELinuxSetFilecon(mgr, tpmdev, seclabel->imagela= bel); + if (rc < 0) + return -1; + break; case VIR_DOMAIN_TPM_TYPE_LAST: break; } @@ -1505,6 +1511,7 @@ virSecuritySELinuxRestoreTPMFileLabelInt(virSecurityM= anagerPtr mgr, VIR_FREE(cancel_path); } break; + case VIR_DOMAIN_TPM_TYPE_EMULATOR: case VIR_DOMAIN_TPM_TYPE_LAST: break; } diff --git a/src/util/virfile.c b/src/util/virfile.c index 5e9bd20..aaedb7a 100644 --- a/src/util/virfile.c +++ b/src/util/virfile.c @@ -38,6 +38,7 @@ #include #include #include +#include #if defined HAVE_MNTENT_H && defined HAVE_GETMNTENT_R # include #endif @@ -2933,6 +2934,54 @@ void virDirClose(DIR **dirp) *dirp =3D NULL; } =20 +/* + * virDirChownFiles: + * @name: name of the directory + * @uid: uid + * @gid: gid + * + * Change ownership of all regular files in a directory. + * + * Returns -1 on error, with error already reported, 0 on success. + */ +int virDirChownFiles(const char *name, uid_t uid, gid_t gid) +{ + struct dirent *ent; + int ret; + DIR *dir; + char *path; + + if (virDirOpen(&dir, name) < 0) + return -1; + + while ((ret =3D virDirRead(dir, &ent, name)) > 0) { + if (ent->d_type !=3D DT_REG) + continue; + + if (virAsprintf(&path, "%s/%s", name, ent->d_name) < 0) { + ret =3D -1; + break; + } + if (chown(path, uid, gid) < 0) { + ret =3D -1; + virReportSystemError(errno, + _("cannot chown '%s' to (%u, %u)"), + ent->d_name, (unsigned int) uid, + (unsigned int) gid); + } + VIR_FREE(path); + if (ret < 0) + break; + } + + virDirClose(&dir); + + if (ret < 0) + return -1; + + return 0; +} + static int virFileMakePathHelper(char *path, mode_t mode) { @@ -3031,6 +3080,17 @@ virFileMakeParentPath(const char *path) return ret; } =20 +static int +_virFileDeletePathCB(const char *fpath, const struct stat *sb ATTRIBUTE_UN= USED, + int typeflag ATTRIBUTE_UNUSED, struct FTW *ftwbuf ATT= RIBUTE_UNUSED) +{ + return remove(fpath); +} + +int virFileDeletePath(const char *path) +{ + return nftw(path, _virFileDeletePathCB, 64, FTW_DEPTH | FTW_PHYS); +} =20 /* Build up a fully qualified path for a config file to be * associated with a persistent guest or network */ diff --git a/src/util/virfile.h b/src/util/virfile.h index cd2a386..5cc2299 100644 --- a/src/util/virfile.h +++ b/src/util/virfile.h @@ -253,11 +253,13 @@ int virDirRead(DIR *dirp, struct dirent **ent, const = char *dirname) void virDirClose(DIR **dirp) ATTRIBUTE_NONNULL(1); # define VIR_DIR_CLOSE(dir) virDirClose(&(dir)) +int virDirChownFiles(const char *name, uid_t uid, gid_t gid); =20 int virFileMakePath(const char *path) ATTRIBUTE_RETURN_CHECK; int virFileMakePathWithMode(const char *path, mode_t mode) ATTRIBUTE_RETURN_CHECK; int virFileMakeParentPath(const char *path) ATTRIBUTE_RETURN_CHECK; +int virFileDeletePath(const char *path) ATTRIBUTE_RETURN_CHECK; =20 char *virFileBuildPath(const char *dir, const char *name, diff --git a/src/util/virtpm.c b/src/util/virtpm.c index d5c10da..649153e 100644 --- a/src/util/virtpm.c +++ b/src/util/virtpm.c @@ -1,7 +1,7 @@ /* * virtpm.c: TPM support * - * Copyright (C) 2013 IBM Corporation + * Copyright (C) 2013,2018 IBM Corporation * * This library is free software; you can redistribute it and/or * modify it under the terms of the GNU Lesser General Public @@ -22,16 +22,36 @@ =20 #include =20 +#include #include +#include +#include +#include =20 +#include "conf/domain_conf.h" +#include "viralloc.h" +#include "vircommand.h" #include "virstring.h" #include "virerror.h" #include "viralloc.h" #include "virfile.h" +#include "virkmod.h" +#include "virlog.h" #include "virtpm.h" +#include "virutil.h" +#include "configmake.h" =20 #define VIR_FROM_THIS VIR_FROM_NONE =20 +VIR_LOG_INIT("util.tpm") + +/* + * executables for the swtpm; to be found on the host + */ +static char *swtpm_path; +static char *swtpm_setup; +static char *swtpm_ioctl; + /** * virTPMCreateCancelPath: * @devpath: Path to the TPM device @@ -74,3 +94,474 @@ virTPMCreateCancelPath(const char *devpath) cleanup: return path; } + +/* + * virTPMEmulatorInit + * + * Initialize the Emulator functions by searching for necessary + * executables that we will use to start and setup the swtpm + */ +static int +virTPMEmulatorInit(void) +{ + if (!swtpm_path) { + swtpm_path =3D virFindFileInPath("swtpm"); + if (!swtpm_path) { + virReportError(VIR_ERR_INTERNAL_ERROR, "%s", + _("Could not find swtpm 'swtpm' in PATH")); + return -1; + } + if (!virFileIsExecutable(swtpm_path)) { + virReportError(VIR_ERR_INTERNAL_ERROR, + _("TPM emulator %s is not an executable"), + swtpm_path); + VIR_FREE(swtpm_path); + return -1; + } + } + + if (!swtpm_setup) { + swtpm_setup =3D virFindFileInPath("swtpm_setup"); + if (!swtpm_setup) { + virReportError(VIR_ERR_INTERNAL_ERROR, "%s", + _("Could not find 'swtpm_setup' in PATH")); + return -1; + } + if (!virFileIsExecutable(swtpm_setup)) { + virReportError(VIR_ERR_INTERNAL_ERROR, + _("'%s' is not an executable"), + swtpm_setup); + VIR_FREE(swtpm_setup); + return -1; + } + } + + if (!swtpm_ioctl) { + swtpm_ioctl =3D virFindFileInPath("swtpm_ioctl"); + if (!swtpm_ioctl) { + virReportError(VIR_ERR_INTERNAL_ERROR, "%s", + _("Could not find swtpm_ioctl in PATH")); + return -1; + } + if (!virFileIsExecutable(swtpm_ioctl)) { + virReportError(VIR_ERR_INTERNAL_ERROR, + _("swtpm_ioctl program %s is not an executable"= ), + swtpm_ioctl); + VIR_FREE(swtpm_ioctl); + return -1; + } + } + + return 0; +} + +/* + * virTPMCreateEmulatorStoragePath + * + * @swtpmStorageDir: directory for swtpm persistent state + * @vmname: The name of the VM for which to create the storage + * + * Create the swtpm's storage path + */ +static char * +virTPMCreateEmulatorStoragePath(const char *swtpmStorageDir, + const char *vmname) +{ + char *path =3D NULL; + + ignore_value(virAsprintf(&path, "%s/%s/tpm1.2", swtpmStorageDir, vmnam= e)); + + return path; +} + +/* + * virtTPMGetTPMStorageDir: + * + * @storagepath: directory for swtpm's pesistent state + * + * Derive the 'TPMStorageDir' from the storagepath by searching + * for the last '/'. + */ +static char * +virTPMGetTPMStorageDir(const char *storagepath) +{ + const char *tail =3D strrchr(storagepath, '/'); + char *path =3D NULL; + + if (!tail) { + virReportError(VIR_ERR_INTERNAL_ERROR, + _("Could not get tail of storagedir %s"), + storagepath); + return NULL; + } + ignore_value(VIR_STRNDUP(path, storagepath, tail - storagepath)); + + return path; +} + +/* + * virTPMEmulatorInitStorage + * + * Initialize the TPM Emulator storage by creating its root directory, + * which is typically found in /var/lib/libvirt/tpm. + * + */ +static int +virTPMEmulatorInitStorage(const char *swtpmStorageDir) +{ + int rc =3D 0; + + /* allow others to cd into this dir */ + if (virFileMakePathWithMode(swtpmStorageDir, 0711) < 0) { + virReportSystemError(errno, + _("Could not create TPM directory %s"), + swtpmStorageDir); + rc =3D -1; + } + + return rc; +} + +/* + * virTPMCreateEmulatorStorage + * + * @storagepath: directory for swtpm's pesistent state + * @vmname: The name of the VM + * @created: a pointer to a bool that will be set to true if the + * storage was created because it did not exist yet + * @userid: The userid that needs to be able to access the directory + * + * Unless the storage path for the swtpm for the given VM + * already exists, create it and make it accessible for the given userid. + * Adapt ownership of the directory and all swtpm's state files there. + */ +static int +virTPMCreateEmulatorStorage(const char *storagepath, + bool *created, + uid_t swtpm_user) +{ + int ret =3D -1; + char *swtpmStorageDir =3D virTPMGetTPMStorageDir(storagepath); + + if (!swtpmStorageDir) + return -1; + + if (virTPMEmulatorInitStorage(swtpmStorageDir) < 0) + return -1; + + *created =3D false; + + if (!virFileExists(storagepath)) + *created =3D true; + + if (virDirCreate(storagepath, 0700, swtpm_user, swtpm_user, + VIR_DIR_CREATE_ALLOW_EXIST) < 0) { + virReportError(VIR_ERR_INTERNAL_ERROR, + _("Could not create directory %s as uid %u"), + storagepath, swtpm_user); + goto cleanup; + } + + if (virDirChownFiles(storagepath, swtpm_user, swtpm_user) < 0) + goto cleanup; + + ret =3D 0; + + cleanup: + VIR_FREE(swtpmStorageDir); + + return ret; +} + +void +virTPMDeleteEmulatorStorage(virDomainTPMDefPtr tpm) +{ + char *path =3D virTPMGetTPMStorageDir(tpm->data.emulator.storagepath); + if (path) { + ignore_value(virFileDeletePath(path)); + VIR_FREE(path); + } +} + +/* + * virTPMCreateEmulatorSocket: + * + * @swtpmStateDir: the directory where to create the socket in + * + * Create the vTPM device name from the given parameters + */ +static char * +virTPMCreateEmulatorSocket(const char *swtpmStateDir, const char *vmname) +{ + char *path =3D NULL; + + ignore_value(virAsprintf(&path, "%s/%s-swtpm.sock", swtpmStateDir, + vmname)); + + return path; +} + +/* + * virTPMEmulatorInitPaths: + * + * @tpm: TPM definition for an emulator type + * @swtpmStorageDir: the general swtpm storage dir which is used as a base + * directory for creating VM specific directories + * @vmname: the name of the VM + */ +int virTPMEmulatorInitPaths(virDomainTPMDefPtr tpm, + const char *swtpmStorageDir, + const char *vmname) +{ + if (!tpm->data.emulator.storagepath && + !(tpm->data.emulator.storagepath =3D + virTPMCreateEmulatorStoragePath(swtpmStorageDir, vmname))) + return -1; + + return 0; +} + +/* + * virTPMEmulatorPrepareHost: + * + * @tpm: tpm definition + * @logDir: directory where swtpm writes its logs into + * @vmname: name of the VM + * @swtpm_user: uid to run the swtpm with + * @swtpmStateDir: directory for swtpm's persistent state + * @qemu_user: uid that qemu will run with; we share the socket file with = it + * + * Prepare the log directory for the swtpm and adjust ownership of it and = the + * log file we will be using. Prepare the state directory where we will sh= are + * the socket between tss and qemu users. + */ +int virTPMEmulatorPrepareHost(virDomainTPMDefPtr tpm, + const char *logDir, const char *vmname, + uid_t swtpm_user, const char *swtpmStateDir, + uid_t qemu_user) +{ + int ret =3D -1; + + if (virTPMEmulatorInit() < 0) + return -1; + + /* create log dir ... */ + if (virFileMakePathWithMode(logDir, 0771) < 0) + goto cleanup; + + /* ... and adjust ownership */ + if (virDirCreate(logDir, 0771, swtpm_user, swtpm_user, + VIR_DIR_CREATE_ALLOW_EXIST) < 0) + goto cleanup; + + /* create logfile name ... */ + if (virAsprintf(&tpm->data.emulator.logfile, "%s/%s-swtpm.log", + logDir, vmname) < 0) + goto cleanup; + + /* ... and make sure it can be accessed by swtpm_user */ + if (virFileExists(tpm->data.emulator.logfile) && + chown(tpm->data.emulator.logfile, swtpm_user, swtpm_user) < 0) { + virReportSystemError(errno, + _("Could not chown on swtpm logfile %s"), + tpm->data.emulator.logfile); + goto cleanup; + } + + /* create our swtpm state dir ... */ + if (virDirCreate(swtpmStateDir, 0771, qemu_user, swtpm_user, + VIR_DIR_CREATE_ALLOW_EXIST) < 0) + goto cleanup; + + /* create the socket filename */ + if (!(tpm->data.emulator.source.data.nix.path =3D + virTPMCreateEmulatorSocket(swtpmStateDir, vmname))) + goto cleanup; + tpm->data.emulator.source.type =3D VIR_DOMAIN_CHR_TYPE_UNIX; + + ret =3D 0; + + cleanup: + if (ret) + VIR_FREE(tpm->data.emulator.logfile); + + return ret; +} + +/* + * virTPMEmulatorRunSetup + * + * @storagepath: path to the directory for TPM state + * @vmname: the name of the VM + * @vmuuid: the UUID of the VM + * @swtpm_user: The userid to switch to when setting up the TPM; + * typically this should be the uid of 'tss' or 'root' + * @logfile: The file to write the log into; it must be writable + * for the user given by userid or 'tss' + * + * Setup the external swtpm + */ +static int +virTPMEmulatorRunSetup(const char *storagepath, const char *vmname, + const unsigned char *vmuuid, + uid_t swtpm_user, const char *logfile) +{ + virCommandPtr cmd =3D NULL; + int exitstatus; + int rc =3D 0; + char uuid[VIR_UUID_STRING_BUFLEN]; + char *vmid =3D NULL; + + cmd =3D virCommandNew(swtpm_setup); + if (!cmd) { + rc =3D -1; + goto cleanup; + } + + virUUIDFormat(vmuuid, uuid); + if (virAsprintf(&vmid, "%s:%s", vmname, uuid) < 0) + goto cleanup; + + virCommandSetUID(cmd, swtpm_user); + virCommandSetGID(cmd, swtpm_user); + + virCommandAddArgList(cmd, + "--tpm-state", storagepath, + "--vmid", vmid, + "--logfile", logfile, + "--createek", + "--create-ek-cert", + "--create-platform-cert", + "--lock-nvram", + "--not-overwrite", + NULL); + + virCommandClearCaps(cmd); + + if (virCommandRun(cmd, &exitstatus) < 0 || exitstatus !=3D 0) { + char *buffer =3D NULL; + ignore_value(virFileReadAllQuiet(logfile, 10240, &buffer)); + + virReportError(VIR_ERR_INTERNAL_ERROR, + _("Could not run '%s'. exitstatus: %d;\n" + "%s"), + swtpm_setup, exitstatus, buffer); + VIR_FREE(buffer); + rc =3D -1; + } + + cleanup: + VIR_FREE(vmid); + virCommandFree(cmd); + + return rc; +} + +/* + * virTPMEmulatorBuildCommand: + * + * @tpm: TPM definition + * @vmname: The name of the VM + * @vmuuid: The UUID of the VM + * @swtpm_user: The uid for the swtpm to run as (drop privileges to from r= oot) + * + * Create the virCommand use for starting the emulator + * Do some initializations on the way, such as creation of storage + * and emulator setup. + */ +virCommandPtr +virTPMEmulatorBuildCommand(virDomainTPMDefPtr tpm, const char *vmname, + const unsigned char *vmuuid, uid_t swtpm_user) +{ + virCommandPtr cmd =3D NULL; + bool created =3D false; + + if (virTPMCreateEmulatorStorage(tpm->data.emulator.storagepath, + &created, swtpm_user) < 0) + return NULL; + + if (created && + virTPMEmulatorRunSetup(tpm->data.emulator.storagepath, vmname, vmu= uid, + swtpm_user, tpm->data.emulator.logfile) < 0) + goto error; + + unlink(tpm->data.emulator.source.data.nix.path); + + cmd =3D virCommandNew(swtpm_path); + if (!cmd) + goto error; + + virCommandClearCaps(cmd); + + virCommandAddArgList(cmd, "socket", "--daemon", "--ctrl", NULL); + virCommandAddArgFormat(cmd, "type=3Dunixio,path=3D%s,mode=3D0660", + tpm->data.emulator.source.data.nix.path); + + virCommandAddArg(cmd, "--tpmstate"); + virCommandAddArgFormat(cmd, "dir=3D%s,mode=3D0640", + tpm->data.emulator.storagepath); + + virCommandAddArg(cmd, "--log"); + virCommandAddArgFormat(cmd, "file=3D%s", tpm->data.emulator.logfile); + + virCommandSetUID(cmd, swtpm_user); + virCommandSetGID(cmd, swtpm_user); + + return cmd; + + error: + if (created) + virTPMDeleteEmulatorStorage(tpm); + + VIR_FREE(tpm->data.emulator.source.data.nix.path); + VIR_FREE(tpm->data.emulator.storagepath); + + virCommandFree(cmd); + + return NULL; +} + +/* + * virTPMEmulatorStop + * @swtpmStateDir: A directory where the socket is located + * @vmname: name of the VM + * + * Gracefully stop the swptm + */ +void +virTPMEmulatorStop(const char *swtpmStateDir, const char *vmname) +{ + virCommandPtr cmd; + char *pathname; + char *errbuf =3D NULL; + + if (virTPMEmulatorInit() < 0) + return; + + if (!(pathname =3D virTPMCreateEmulatorSocket(swtpmStateDir, vmname))) + return; + + if (!virFileExists(pathname)) + goto cleanup; + + cmd =3D virCommandNew(swtpm_ioctl); + if (!cmd) { + VIR_FREE(pathname); + return; + } + + virCommandAddArgList(cmd, "--unix", pathname, "-s", NULL); + + virCommandSetErrorBuffer(cmd, &errbuf); + + ignore_value(virCommandRun(cmd, NULL)); + + virCommandFree(cmd); + + /* clean up the socket */ + unlink(pathname); + + cleanup: + VIR_FREE(pathname); + VIR_FREE(errbuf); +} diff --git a/src/util/virtpm.h b/src/util/virtpm.h index b21fc05..8afd606 100644 --- a/src/util/virtpm.h +++ b/src/util/virtpm.h @@ -1,7 +1,7 @@ /* * virtpm.h: TPM support * - * Copyright (C) 2013 IBM Corporation + * Copyright (C) 2013,2018 IBM Corporation * * This library is free software; you can redistribute it and/or * modify it under the terms of the GNU Lesser General Public @@ -22,6 +22,29 @@ #ifndef __VIR_TPM_H__ # define __VIR_TPM_H__ =20 +# include "vircommand.h" + +typedef struct _virDomainTPMDef virDomainTPMDef; +typedef virDomainTPMDef *virDomainTPMDefPtr; + char *virTPMCreateCancelPath(const char *devpath) ATTRIBUTE_NOINLINE; =20 +int virTPMEmulatorInitPaths(virDomainTPMDefPtr tpm, + const char *swtpmStorageDir, + const char *vmname) + ATTRIBUTE_RETURN_CHECK; +int virTPMEmulatorPrepareHost(virDomainTPMDefPtr tpm, + const char *logDir, const char *vmname, + uid_t swtpm_user, const char *swtpmStateDir, + uid_t qemu_user) + ATTRIBUTE_RETURN_CHECK; +virCommandPtr virTPMEmulatorBuildCommand(virDomainTPMDefPtr tpm, + const char *vmname, + const unsigned char *vmuuid, + uid_t swtpm_user) + ATTRIBUTE_RETURN_CHECK; +void virTPMEmulatorStop(const char *swtpmStateDir, + const char *vmname); +void virTPMDeleteEmulatorStorage(virDomainTPMDefPtr tpm); + #endif /* __VIR_TPM_H__ */ --=20 2.5.5 -- libvir-list mailing list libvir-list@redhat.com https://www.redhat.com/mailman/listinfo/libvir-list From nobody Mon Apr 29 09:01:19 2024 Delivered-To: importer@patchew.org Received-SPF: pass (zoho.com: domain of redhat.com designates 209.132.183.28 as permitted sender) client-ip=209.132.183.28; envelope-from=libvir-list-bounces@redhat.com; helo=mx1.redhat.com; Authentication-Results: mx.zohomail.com; spf=pass (zoho.com: domain of redhat.com designates 209.132.183.28 as permitted sender) smtp.mailfrom=libvir-list-bounces@redhat.com Return-Path: Received: from mx1.redhat.com (mx1.redhat.com [209.132.183.28]) by mx.zohomail.com with SMTPS id 1523415030406437.41648298189625; Tue, 10 Apr 2018 19:50:30 -0700 (PDT) Received: from smtp.corp.redhat.com (int-mx03.intmail.prod.int.phx2.redhat.com [10.5.11.13]) (using TLSv1.2 with cipher AECDH-AES256-SHA (256/256 bits)) (No client certificate requested) by mx1.redhat.com (Postfix) with ESMTPS id 9DBA58553D; Wed, 11 Apr 2018 02:50:28 +0000 (UTC) Received: from colo-mx.corp.redhat.com (colo-mx01.intmail.prod.int.phx2.redhat.com [10.5.11.20]) by smtp.corp.redhat.com (Postfix) with ESMTPS id E7ED16609C; Wed, 11 Apr 2018 02:50:27 +0000 (UTC) Received: from lists01.pubmisc.prod.ext.phx2.redhat.com (lists01.pubmisc.prod.ext.phx2.redhat.com [10.5.19.33]) by colo-mx.corp.redhat.com (Postfix) with ESMTP id 94FA71800CA0; Wed, 11 Apr 2018 02:50:25 +0000 (UTC) Received: from smtp.corp.redhat.com (int-mx05.intmail.prod.int.phx2.redhat.com [10.5.11.15]) by lists01.pubmisc.prod.ext.phx2.redhat.com (8.13.8/8.13.8) with ESMTP id w3B2oNf3009922 for ; Tue, 10 Apr 2018 22:50:23 -0400 Received: by smtp.corp.redhat.com (Postfix) id 995C96C8D3; Wed, 11 Apr 2018 02:50:23 +0000 (UTC) Received: from mx1.redhat.com (ext-mx19.extmail.prod.ext.phx2.redhat.com [10.5.110.48]) by smtp.corp.redhat.com (Postfix) with ESMTPS id 919A66C8C2 for ; Wed, 11 Apr 2018 02:50:21 +0000 (UTC) Received: from mx0a-001b2d01.pphosted.com (mx0b-001b2d01.pphosted.com [148.163.158.5]) (using TLSv1.2 with cipher ECDHE-RSA-AES256-GCM-SHA384 (256/256 bits)) (No client certificate requested) by mx1.redhat.com (Postfix) with ESMTPS id 8A5F932D0C68 for ; Wed, 11 Apr 2018 02:50:20 +0000 (UTC) Received: from pps.filterd (m0098413.ppops.net [127.0.0.1]) by mx0b-001b2d01.pphosted.com (8.16.0.22/8.16.0.22) with SMTP id w3B2nbKL127006 for ; Tue, 10 Apr 2018 22:50:20 -0400 Received: from e36.co.us.ibm.com (e36.co.us.ibm.com [32.97.110.154]) by mx0b-001b2d01.pphosted.com with ESMTP id 2h97gjmsdj-1 (version=TLSv1.2 cipher=AES256-SHA256 bits=256 verify=NOT) for ; Tue, 10 Apr 2018 22:50:19 -0400 Received: from localhost by e36.co.us.ibm.com with IBM ESMTP SMTP Gateway: Authorized Use Only! Violators will be prosecuted for from ; Tue, 10 Apr 2018 20:50:18 -0600 Received: from b03cxnp08028.gho.boulder.ibm.com (9.17.130.20) by e36.co.us.ibm.com (192.168.1.136) with IBM ESMTP SMTP Gateway: Authorized Use Only! Violators will be prosecuted; Tue, 10 Apr 2018 20:50:17 -0600 Received: from b03ledav005.gho.boulder.ibm.com (b03ledav005.gho.boulder.ibm.com [9.17.130.236]) by b03cxnp08028.gho.boulder.ibm.com (8.14.9/8.14.9/NCO v10.0) with ESMTP id w3B2oH028520102; Tue, 10 Apr 2018 19:50:17 -0700 Received: from b03ledav005.gho.boulder.ibm.com (unknown [127.0.0.1]) by IMSVA (Postfix) with ESMTP id 5C909BE039; Tue, 10 Apr 2018 20:50:17 -0600 (MDT) Received: from sbct-3.watson.ibm.com (unknown [9.47.158.153]) by b03ledav005.gho.boulder.ibm.com (Postfix) with ESMTP id 1A75CBE047; Tue, 10 Apr 2018 20:50:17 -0600 (MDT) From: Stefan Berger To: libvir-list@redhat.com Date: Tue, 10 Apr 2018 22:50:02 -0400 In-Reply-To: <1523415005-30661-1-git-send-email-stefanb@linux.vnet.ibm.com> References: <1523415005-30661-1-git-send-email-stefanb@linux.vnet.ibm.com> X-TM-AS-GCONF: 00 x-cbid: 18041102-0020-0000-0000-00000DB8AB99 X-IBM-SpamModules-Scores: X-IBM-SpamModules-Versions: BY=3.00008834; HX=3.00000241; KW=3.00000007; PH=3.00000004; SC=3.00000256; SDB=6.01016139; UDB=6.00518173; IPR=6.00795386; MB=3.00020511; MTD=3.00000008; XFM=3.00000015; UTC=2018-04-11 02:50:18 X-IBM-AV-DETECTION: SAVI=unused REMOTE=unused XFE=unused x-cbparentid: 18041102-0021-0000-0000-000060DB7196 Message-Id: <1523415005-30661-4-git-send-email-stefanb@linux.vnet.ibm.com> X-Proofpoint-Virus-Version: vendor=fsecure engine=2.50.10434:, , definitions=2018-04-11_01:, , signatures=0 X-Proofpoint-Spam-Details: rule=outbound_notspam policy=outbound score=0 priorityscore=1501 malwarescore=0 suspectscore=1 phishscore=0 bulkscore=0 spamscore=0 clxscore=1015 lowpriorityscore=0 impostorscore=0 adultscore=0 classifier=spam adjust=0 reason=mlx scancount=1 engine=8.0.1-1709140000 definitions=main-1804110026 X-Greylist: Sender passed SPF test, Sender IP whitelisted by DNSRBL, ACL 207 matched, not delayed by milter-greylist-4.5.16 (mx1.redhat.com [10.5.110.48]); Wed, 11 Apr 2018 02:50:20 +0000 (UTC) X-Greylist: inspected by milter-greylist-4.5.16 (mx1.redhat.com [10.5.110.48]); Wed, 11 Apr 2018 02:50:20 +0000 (UTC) for IP:'148.163.158.5' DOMAIN:'mx0b-001b2d01.pphosted.com' HELO:'mx0a-001b2d01.pphosted.com' FROM:'stefanb@linux.vnet.ibm.com' RCPT:'' X-RedHat-Spam-Score: 1.738 * (DNS_FROM_AHBL_RHSBL, RCVD_IN_DNSWL_LOW) 148.163.158.5 mx0b-001b2d01.pphosted.com 148.163.158.5 mx0b-001b2d01.pphosted.com X-Scanned-By: MIMEDefang 2.84 on 10.5.110.48 X-Scanned-By: MIMEDefang 2.79 on 10.5.11.15 X-loop: libvir-list@redhat.com Subject: [libvirt] [PATCH v2 3/6] tpm: Add test cases for external swtpm TPM emulator X-BeenThere: libvir-list@redhat.com X-Mailman-Version: 2.1.12 Precedence: junk List-Id: Development discussions about the libvirt library & tools List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , MIME-Version: 1.0 Content-Transfer-Encoding: quoted-printable Sender: libvir-list-bounces@redhat.com Errors-To: libvir-list-bounces@redhat.com X-Scanned-By: MIMEDefang 2.79 on 10.5.11.13 X-Greylist: Sender IP whitelisted, not delayed by milter-greylist-4.5.16 (mx1.redhat.com [10.5.110.28]); Wed, 11 Apr 2018 02:50:29 +0000 (UTC) X-ZohoMail: RSF_0 Z_629925259 SPT_0 Content-Type: text/plain; charset="utf-8" This patch adds extensions to existing test cases and specific test cases for the tpm-emulator. Signed-off-by: Stefan Berger --- tests/qemucapabilitiesdata/caps_2.11.0.s390x.xml | 1 + tests/qemucapabilitiesdata/caps_2.12.0.aarch64.xml | 1 + tests/qemucapabilitiesdata/caps_2.12.0.ppc64.xml | 1 + tests/qemucapabilitiesdata/caps_2.12.0.s390x.xml | 1 + tests/qemucapabilitiesdata/caps_2.12.0.x86_64.xml | 1 + tests/qemuxml2argvdata/tpm-emulator.args | 24 +++++++++++++++ tests/qemuxml2argvdata/tpm-emulator.xml | 30 +++++++++++++++++++ tests/qemuxml2argvtest.c | 15 ++++++++++ tests/qemuxml2xmloutdata/tpm-emulator.xml | 34 ++++++++++++++++++= ++++ tests/qemuxml2xmltest.c | 1 + 10 files changed, 109 insertions(+) create mode 100644 tests/qemuxml2argvdata/tpm-emulator.args create mode 100644 tests/qemuxml2argvdata/tpm-emulator.xml create mode 100644 tests/qemuxml2xmloutdata/tpm-emulator.xml diff --git a/tests/qemucapabilitiesdata/caps_2.11.0.s390x.xml b/tests/qemuc= apabilitiesdata/caps_2.11.0.s390x.xml index 70a35ef..376f58a 100644 --- a/tests/qemucapabilitiesdata/caps_2.11.0.s390x.xml +++ b/tests/qemucapabilitiesdata/caps_2.11.0.s390x.xml @@ -150,6 +150,7 @@ + 2011000 0 342058 diff --git a/tests/qemucapabilitiesdata/caps_2.12.0.aarch64.xml b/tests/qem= ucapabilitiesdata/caps_2.12.0.aarch64.xml index ff48293..069e0ae 100644 --- a/tests/qemucapabilitiesdata/caps_2.12.0.aarch64.xml +++ b/tests/qemucapabilitiesdata/caps_2.12.0.aarch64.xml @@ -187,6 +187,7 @@ + 2011090 0 342346 diff --git a/tests/qemucapabilitiesdata/caps_2.12.0.ppc64.xml b/tests/qemuc= apabilitiesdata/caps_2.12.0.ppc64.xml index ee7fb9e..46d2463 100644 --- a/tests/qemucapabilitiesdata/caps_2.12.0.ppc64.xml +++ b/tests/qemucapabilitiesdata/caps_2.12.0.ppc64.xml @@ -185,6 +185,7 @@ + 2011090 0 419215 diff --git a/tests/qemucapabilitiesdata/caps_2.12.0.s390x.xml b/tests/qemuc= apabilitiesdata/caps_2.12.0.s390x.xml index b5b6b5b..36ffd75 100644 --- a/tests/qemucapabilitiesdata/caps_2.12.0.s390x.xml +++ b/tests/qemucapabilitiesdata/caps_2.12.0.s390x.xml @@ -150,6 +150,7 @@ + 2011090 0 0 diff --git a/tests/qemucapabilitiesdata/caps_2.12.0.x86_64.xml b/tests/qemu= capabilitiesdata/caps_2.12.0.x86_64.xml index 39ee4f4..b2f06b3 100644 --- a/tests/qemucapabilitiesdata/caps_2.12.0.x86_64.xml +++ b/tests/qemucapabilitiesdata/caps_2.12.0.x86_64.xml @@ -226,6 +226,7 @@ + 2011090 0 390060 diff --git a/tests/qemuxml2argvdata/tpm-emulator.args b/tests/qemuxml2argvd= ata/tpm-emulator.args new file mode 100644 index 0000000..9418c74 --- /dev/null +++ b/tests/qemuxml2argvdata/tpm-emulator.args @@ -0,0 +1,24 @@ +LC_ALL=3DC \ +PATH=3D/bin \ +HOME=3D/home/test \ +USER=3Dtest \ +LOGNAME=3Dtest \ +QEMU_AUDIO_DRV=3Dnone \ +/usr/bin/qemu-system-x86_64 \ +-name TPM-VM \ +-S \ +-M pc-0.12 \ +-m 2048 \ +-smp 1,sockets=3D1,cores=3D1,threads=3D1 \ +-uuid 11d7cd22-da89-3094-6212-079a48a309a1 \ +-nographic \ +-nodefaults \ +-chardev socket,id=3Dcharmonitor,path=3D/tmp/lib/domain--1-TPM-VM/monitor.= sock,\ +server,nowait \ +-mon chardev=3Dcharmonitor,id=3Dmonitor,mode=3Dreadline \ +-boot c \ +-usb \ +-tpmdev emulator,id=3Dtpm-tpm0,chardev=3Dchrtpm \ +-chardev socket,id=3Dchrtpm,path=3D/dev/test \ +-device tpm-tis,tpmdev=3Dtpm-tpm0,id=3Dtpm0 \ +-device virtio-balloon-pci,id=3Dballoon0,bus=3Dpci.0,addr=3D0x3 diff --git a/tests/qemuxml2argvdata/tpm-emulator.xml b/tests/qemuxml2argvda= ta/tpm-emulator.xml new file mode 100644 index 0000000..2f4e777 --- /dev/null +++ b/tests/qemuxml2argvdata/tpm-emulator.xml @@ -0,0 +1,30 @@ + + TPM-VM + 11d7cd22-da89-3094-6212-079a48a309a1 + 2097152 + 512288 + 1 + + hvm + + + + + + + + destroy + restart + destroy + + /usr/bin/qemu-system-x86_64 + + + + + + + + + + diff --git a/tests/qemuxml2argvtest.c b/tests/qemuxml2argvtest.c index 2992197..06dca97 100644 --- a/tests/qemuxml2argvtest.c +++ b/tests/qemuxml2argvtest.c @@ -497,6 +497,19 @@ testCompareXMLToArgv(const void *data) } } =20 + if (vm->def->tpm) { + switch (vm->def->tpm->type) { + case VIR_DOMAIN_TPM_TYPE_EMULATOR: + if (VIR_STRDUP(vm->def->tpm->data.emulator.source.data.file.pat= h, + "/dev/test") < 0) + goto cleanup; + break; + case VIR_DOMAIN_TPM_TYPE_PASSTHROUGH: + case VIR_DOMAIN_TPM_TYPE_LAST: + break; + } + } + if (!(cmd =3D qemuProcessCreatePretendCmd(&driver, vm, migrateURI, (flags & FLAG_FIPS), false, VIR_QEMU_PROCESS_START_COLD)))= { @@ -2139,6 +2152,8 @@ mymain(void) QEMU_CAPS_DEVICE_TPM_CRB); DO_TEST_PARSE_ERROR("tpm-no-backend-invalid", QEMU_CAPS_DEVICE_TPM_PASSTHROUGH, QEMU_CAPS_DEVICE= _TPM_TIS); + DO_TEST("tpm-emulator", + QEMU_CAPS_DEVICE_TPM_EMULATOR, QEMU_CAPS_DEVICE_TPM_TIS); =20 =20 DO_TEST_PARSE_ERROR("pci-domain-invalid", NONE); diff --git a/tests/qemuxml2xmloutdata/tpm-emulator.xml b/tests/qemuxml2xmlo= utdata/tpm-emulator.xml new file mode 100644 index 0000000..1f783bb --- /dev/null +++ b/tests/qemuxml2xmloutdata/tpm-emulator.xml @@ -0,0 +1,34 @@ + + TPM-VM + 11d7cd22-da89-3094-6212-079a48a309a1 + 2097152 + 512288 + 1 + + hvm + + + + + + + + destroy + restart + destroy + + /usr/bin/qemu-system-x86_64 + +
+ + + + + + + + +
+ + + diff --git a/tests/qemuxml2xmltest.c b/tests/qemuxml2xmltest.c index 0f56029..b3e7c8e 100644 --- a/tests/qemuxml2xmltest.c +++ b/tests/qemuxml2xmltest.c @@ -700,6 +700,7 @@ mymain(void) DO_TEST("usb-ich9-ehci-addr", NONE); DO_TEST("disk-copy_on_read", NONE); DO_TEST("tpm-passthrough", NONE); + DO_TEST("tpm-emulator", NONE); =20 DO_TEST("metadata", NONE); DO_TEST("metadata-duplicate", NONE); --=20 2.5.5 -- libvir-list mailing list libvir-list@redhat.com https://www.redhat.com/mailman/listinfo/libvir-list From nobody Mon Apr 29 09:01:19 2024 Delivered-To: importer@patchew.org Received-SPF: pass (zoho.com: domain of redhat.com designates 209.132.183.28 as permitted sender) client-ip=209.132.183.28; envelope-from=libvir-list-bounces@redhat.com; helo=mx1.redhat.com; Authentication-Results: mx.zohomail.com; spf=pass (zoho.com: domain of redhat.com designates 209.132.183.28 as permitted sender) smtp.mailfrom=libvir-list-bounces@redhat.com Return-Path: Received: from mx1.redhat.com (mx1.redhat.com [209.132.183.28]) by mx.zohomail.com with SMTPS id 1523415045300122.93324191582656; Tue, 10 Apr 2018 19:50:45 -0700 (PDT) Received: from smtp.corp.redhat.com (int-mx05.intmail.prod.int.phx2.redhat.com [10.5.11.15]) (using TLSv1.2 with cipher AECDH-AES256-SHA (256/256 bits)) (No client certificate requested) by mx1.redhat.com (Postfix) with ESMTPS id A6FB0A799; Wed, 11 Apr 2018 02:50:43 +0000 (UTC) Received: from colo-mx.corp.redhat.com (colo-mx01.intmail.prod.int.phx2.redhat.com [10.5.11.20]) by smtp.corp.redhat.com (Postfix) with ESMTPS id 7EEDF6C8E6; Wed, 11 Apr 2018 02:50:43 +0000 (UTC) Received: from lists01.pubmisc.prod.ext.phx2.redhat.com (lists01.pubmisc.prod.ext.phx2.redhat.com [10.5.19.33]) by colo-mx.corp.redhat.com (Postfix) with ESMTP id 3D05E18033EB; Wed, 11 Apr 2018 02:50:43 +0000 (UTC) Received: from smtp.corp.redhat.com (int-mx03.intmail.prod.int.phx2.redhat.com [10.5.11.13]) by lists01.pubmisc.prod.ext.phx2.redhat.com (8.13.8/8.13.8) with ESMTP id w3B2oNJH009927 for ; Tue, 10 Apr 2018 22:50:23 -0400 Received: by smtp.corp.redhat.com (Postfix) id AA3736607A; Wed, 11 Apr 2018 02:50:23 +0000 (UTC) Received: from mx1.redhat.com (ext-mx13.extmail.prod.ext.phx2.redhat.com [10.5.110.42]) by smtp.corp.redhat.com (Postfix) with ESMTPS id A3F1066064 for ; Wed, 11 Apr 2018 02:50:23 +0000 (UTC) Received: from mx0a-001b2d01.pphosted.com (mx0a-001b2d01.pphosted.com [148.163.156.1]) (using TLSv1.2 with cipher ECDHE-RSA-AES256-GCM-SHA384 (256/256 bits)) (No client certificate requested) by mx1.redhat.com (Postfix) with ESMTPS id C6C8A32D645E for ; Wed, 11 Apr 2018 02:50:22 +0000 (UTC) Received: from pps.filterd (m0098393.ppops.net [127.0.0.1]) by mx0a-001b2d01.pphosted.com (8.16.0.22/8.16.0.22) with SMTP id w3B2ncPi140919 for ; Tue, 10 Apr 2018 22:50:22 -0400 Received: from e31.co.us.ibm.com (e31.co.us.ibm.com [32.97.110.149]) by mx0a-001b2d01.pphosted.com with ESMTP id 2h97jt4tpc-1 (version=TLSv1.2 cipher=AES256-SHA256 bits=256 verify=NOT) for ; Tue, 10 Apr 2018 22:50:22 -0400 Received: from localhost by e31.co.us.ibm.com with IBM ESMTP SMTP Gateway: Authorized Use Only! Violators will be prosecuted for from ; Tue, 10 Apr 2018 20:50:21 -0600 Received: from b03cxnp07029.gho.boulder.ibm.com (9.17.130.16) by e31.co.us.ibm.com (192.168.1.131) with IBM ESMTP SMTP Gateway: Authorized Use Only! Violators will be prosecuted; Tue, 10 Apr 2018 20:50:19 -0600 Received: from b03ledav005.gho.boulder.ibm.com (b03ledav005.gho.boulder.ibm.com [9.17.130.236]) by b03cxnp07029.gho.boulder.ibm.com (8.14.9/8.14.9/NCO v10.0) with ESMTP id w3B2oHj06029816; Tue, 10 Apr 2018 19:50:18 -0700 Received: from b03ledav005.gho.boulder.ibm.com (unknown [127.0.0.1]) by IMSVA (Postfix) with ESMTP id AF36EBE04C; Tue, 10 Apr 2018 20:50:18 -0600 (MDT) Received: from sbct-3.watson.ibm.com (unknown [9.47.158.153]) by b03ledav005.gho.boulder.ibm.com (Postfix) with ESMTP id 6E560BE038; Tue, 10 Apr 2018 20:50:18 -0600 (MDT) From: Stefan Berger To: libvir-list@redhat.com Date: Tue, 10 Apr 2018 22:50:03 -0400 In-Reply-To: <1523415005-30661-1-git-send-email-stefanb@linux.vnet.ibm.com> References: <1523415005-30661-1-git-send-email-stefanb@linux.vnet.ibm.com> X-TM-AS-GCONF: 00 x-cbid: 18041102-8235-0000-0000-00000D4BA98D X-IBM-SpamModules-Scores: X-IBM-SpamModules-Versions: BY=3.00008834; HX=3.00000241; KW=3.00000007; PH=3.00000004; SC=3.00000256; SDB=6.01016139; UDB=6.00518174; IPR=6.00795386; MB=3.00020511; MTD=3.00000008; XFM=3.00000015; UTC=2018-04-11 02:50:20 X-IBM-AV-DETECTION: SAVI=unused REMOTE=unused XFE=unused x-cbparentid: 18041102-8236-0000-0000-0000406EB9CA Message-Id: <1523415005-30661-5-git-send-email-stefanb@linux.vnet.ibm.com> X-Proofpoint-Virus-Version: vendor=fsecure engine=2.50.10434:, , definitions=2018-04-11_01:, , signatures=0 X-Proofpoint-Spam-Details: rule=outbound_notspam policy=outbound score=0 priorityscore=1501 malwarescore=0 suspectscore=3 phishscore=0 bulkscore=0 spamscore=0 clxscore=1015 lowpriorityscore=0 impostorscore=0 adultscore=0 classifier=spam adjust=0 reason=mlx scancount=1 engine=8.0.1-1709140000 definitions=main-1804110026 X-Greylist: Sender passed SPF test, Sender IP whitelisted by DNSRBL, ACL 207 matched, not delayed by milter-greylist-4.5.16 (mx1.redhat.com [10.5.110.42]); Wed, 11 Apr 2018 02:50:22 +0000 (UTC) X-Greylist: inspected by milter-greylist-4.5.16 (mx1.redhat.com [10.5.110.42]); Wed, 11 Apr 2018 02:50:22 +0000 (UTC) for IP:'148.163.156.1' DOMAIN:'mx0a-001b2d01.pphosted.com' HELO:'mx0a-001b2d01.pphosted.com' FROM:'stefanb@linux.vnet.ibm.com' RCPT:'' X-RedHat-Spam-Score: 0.728 (DNS_FROM_AHBL_RHSBL, RCVD_IN_DNSWL_LOW, RCVD_IN_MSPIKE_H5, RCVD_IN_MSPIKE_WL) 148.163.156.1 mx0a-001b2d01.pphosted.com 148.163.156.1 mx0a-001b2d01.pphosted.com X-Scanned-By: MIMEDefang 2.84 on 10.5.110.42 X-Scanned-By: MIMEDefang 2.79 on 10.5.11.13 X-loop: libvir-list@redhat.com Subject: [libvirt] [PATCH v2 4/6] tpm: Label the external swtpm with SELinux labels X-BeenThere: libvir-list@redhat.com X-Mailman-Version: 2.1.12 Precedence: junk List-Id: Development discussions about the libvirt library & tools List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , MIME-Version: 1.0 Content-Transfer-Encoding: quoted-printable Sender: libvir-list-bounces@redhat.com Errors-To: libvir-list-bounces@redhat.com X-Scanned-By: MIMEDefang 2.79 on 10.5.11.15 X-Greylist: Sender IP whitelisted, not delayed by milter-greylist-4.5.16 (mx1.redhat.com [10.5.110.29]); Wed, 11 Apr 2018 02:50:44 +0000 (UTC) X-ZohoMail: RSF_0 Z_629925259 SPT_0 Content-Type: text/plain; charset="utf-8" In this patch we label the swtpm process with SELinux labels. We give it the same label as the QEMU process has. We label its state directory and files as well. The file and process labels now look as follows: Directory: /var/lib/libvirt/swtpm [root@localhost swtpm]# ls -lZ total 4 rwx------. 2 tss tss system_u:object_r:svirt_image_t:s0:c254,c932 4096 Ap= r 5 16:46 testvm [root@localhost testvm]# ls -lZ total 8 -rw-r--r--. 1 tss tss system_u:object_r:svirt_image_t:s0:c254,c932 3648 Apr= 5 16:46 tpm-00.permall The log in /var/log/swtpm/libvirt/qemu is labeled as follows: -rw-r--r--. 1 tss tss system_u:object_r:svirt_image_t:s0:c254,c932 2237 Apr= 5 16:46 vtpm.log [root@localhost 485d0004-a48f-436a-8457-8a3b73e28567]# ps auxZ | grep swtpm= | grep ctrl | grep -v grep system_u:system_r:svirt_t:s0:c254,c932 tss 25664 0.0 0.0 28172 3892 ? = Ss 16:57 0:00 /usr/bin/swtpm socket --daemon --ctrl type=3Dunixio,p= ath=3D/var/run/libvirt/qemu/swtpm/testvm-swtpm.sock,mode=3D0660 --tpmstate = dir=3D/var/lib/libvirt/swtpm/testvm/tpm1.2 --log file=3D/var/log/swtpm/libv= irt/qemu/testvm-swtpm.log [root@localhost 485d0004-a48f-436a-8457-8a3b73e28567]# ps auxZ | grep qemu = | grep tpm | grep -v grep system_u:system_r:svirt_t:s0:c254,c932 qemu 25669 99.0 0.0 3096704 48500 ?= Sl 16:57 3:28 /bin/qemu-system-x86_64 [..] Signed-off-by: Stefan Berger --- src/libvirt_private.syms | 1 + src/qemu/qemu_extdevice.c | 22 ++++++++++++- src/security/security_driver.h | 4 +++ src/security/security_manager.c | 18 +++++++++++ src/security/security_manager.h | 3 ++ src/security/security_selinux.c | 68 +++++++++++++++++++++++++++++++++++++= ++++ src/security/security_stack.c | 19 ++++++++++++ 7 files changed, 134 insertions(+), 1 deletion(-) diff --git a/src/libvirt_private.syms b/src/libvirt_private.syms index 935ffcc..af9163f 100644 --- a/src/libvirt_private.syms +++ b/src/libvirt_private.syms @@ -1334,6 +1334,7 @@ virSecurityManagerSetProcessLabel; virSecurityManagerSetSavedStateLabel; virSecurityManagerSetSocketLabel; virSecurityManagerSetTapFDLabel; +virSecurityManagerSetTPMLabels; virSecurityManagerStackAddNested; virSecurityManagerTransactionAbort; virSecurityManagerTransactionCommit; diff --git a/src/qemu/qemu_extdevice.c b/src/qemu/qemu_extdevice.c index be3df7c..ee327ca 100644 --- a/src/qemu/qemu_extdevice.c +++ b/src/qemu/qemu_extdevice.c @@ -141,12 +141,32 @@ qemuExtTPMStartEmulator(virQEMUDriverPtr driver, =20 virCommandSetErrorBuffer(cmd, &errbuf); =20 - if (virCommandRun(cmd, &exitstatus) < 0 || exitstatus !=3D 0) { + if (virSecurityManagerSetTPMLabels(driver->securityManager, + def) < 0) + goto error; + + if (virSecurityManagerSetChildProcessLabel(driver->securityManager, + def, cmd) < 0) + goto error; + + if (virSecurityManagerPreFork(driver->securityManager) < 0) + goto error; + + /* make sure we run this with the appropriate user */ + virCommandSetUID(cmd, cfg->swtpm_user); + virCommandSetGID(cmd, cfg->swtpm_user); + + ret =3D virCommandRun(cmd, &exitstatus); + + virSecurityManagerPostFork(driver->securityManager); + + if (ret < 0 || exitstatus !=3D 0) { VIR_ERROR("Could not start 'swtpm'. exitstatus: %d\n" "stderr: %s\n", exitstatus, errbuf); virReportError(VIR_ERR_INTERNAL_ERROR, _("Could not start 'swtpm'. exitstatus: %d, " "error: %s"), exitstatus, errbuf); + ret =3D -1; goto error; } =20 diff --git a/src/security/security_driver.h b/src/security/security_driver.h index 95e7c4d..4aa415f 100644 --- a/src/security/security_driver.h +++ b/src/security/security_driver.h @@ -149,6 +149,8 @@ typedef int (*virSecurityDomainRestoreChardevLabel) (vi= rSecurityManagerPtr mgr, virDomainDefPtr def, virDomainChrSourceDef= Ptr dev_source, bool chardevStdioLogd= ); +typedef int (*virSecurityDomainSetTPMLabels) (virSecurityManagerPtr mgr, + virDomainDefPtr def); =20 =20 struct _virSecurityDriver { @@ -213,6 +215,8 @@ struct _virSecurityDriver { =20 virSecurityDomainSetChardevLabel domainSetSecurityChardevLabel; virSecurityDomainRestoreChardevLabel domainRestoreSecurityChardevLabel; + + virSecurityDomainSetTPMLabels domainSetSecurityTPMLabels; }; =20 virSecurityDriverPtr virSecurityDriverLookup(const char *name, diff --git a/src/security/security_manager.c b/src/security/security_manage= r.c index fdeea4d..0547daa 100644 --- a/src/security/security_manager.c +++ b/src/security/security_manager.c @@ -1,3 +1,4 @@ + /* * security_manager.c: Internal security manager API * @@ -1207,3 +1208,20 @@ virSecurityManagerRestoreChardevLabel(virSecurityMan= agerPtr mgr, virReportUnsupportedError(); return -1; } + + +int virSecurityManagerSetTPMLabels(virSecurityManagerPtr mgr, + virDomainDefPtr vm) +{ + int ret; + + if (mgr->drv->domainSetSecurityTPMLabels) { + virObjectLock(mgr); + ret =3D mgr->drv->domainSetSecurityTPMLabels(mgr, vm); + virObjectUnlock(mgr); + + return ret; + } + + return 0; +} diff --git a/src/security/security_manager.h b/src/security/security_manage= r.h index c36a8b4..671f6a8 100644 --- a/src/security/security_manager.h +++ b/src/security/security_manager.h @@ -194,4 +194,7 @@ int virSecurityManagerRestoreChardevLabel(virSecurityMa= nagerPtr mgr, virDomainChrSourceDefPtr dev_sou= rce, bool chardevStdioLogd); =20 +int virSecurityManagerSetTPMLabels(virSecurityManagerPtr mgr, + virDomainDefPtr vm); + #endif /* VIR_SECURITY_MANAGER_H__ */ diff --git a/src/security/security_selinux.c b/src/security/security_selinu= x.c index 17bc07a..5d8b8cb 100644 --- a/src/security/security_selinux.c +++ b/src/security/security_selinux.c @@ -3047,6 +3047,72 @@ virSecuritySELinuxDomainSetPathLabel(virSecurityMana= gerPtr mgr, return virSecuritySELinuxSetFilecon(mgr, path, seclabel->imagelabel); } =20 +static int +_virSecuritySELinuxSetSecurityFileLabels(virSecurityManagerPtr mgr, + const char *path, + virSecurityLabelDefPtr seclabel) +{ + int ret =3D 0; + struct dirent *ent; + char *filename =3D NULL; + DIR *dir; + + if (virDirOpen(&dir, path) < 0) + return virSecuritySELinuxSetFilecon(mgr, path, seclabel->imagelabe= l); + + while ((ret =3D virDirRead(dir, &ent, path)) > 0) { + if (ent->d_type !=3D DT_REG) + continue; + + if (virAsprintf(&filename, "%s/%s", path, ent->d_name) < 0) { + ret =3D -1; + break; + } + ret =3D virSecuritySELinuxSetFilecon(mgr, filename, + seclabel->imagelabel); + VIR_FREE(filename); + if (ret) + break; + } + if (ret) + virReportSystemError(errno, _("Unable to label files under %s"), + path); + + virDirClose(&dir); + + return ret; +} + +static int +virSecuritySELinuxSetSecurityTPMLabels(virSecurityManagerPtr mgr, + virDomainDefPtr def) +{ + int ret =3D 0; + virSecurityLabelDefPtr seclabel; + + seclabel =3D virDomainDefGetSecurityLabelDef(def, SECURITY_SELINUX_NAM= E); + if (seclabel =3D=3D NULL) + return 0; + + switch (def->tpm->type) { + case VIR_DOMAIN_TPM_TYPE_PASSTHROUGH: + break; + case VIR_DOMAIN_TPM_TYPE_EMULATOR: + ret =3D _virSecuritySELinuxSetSecurityFileLabels( + mgr, def->tpm->data.emulator.storagepath, + seclabel); + if (ret =3D=3D 0 && def->tpm->data.emulator.logfile) + ret =3D _virSecuritySELinuxSetSecurityFileLabels( + mgr, def->tpm->data.emulator.logfile, + seclabel); + break; + case VIR_DOMAIN_TPM_TYPE_LAST: + break; + } + + return ret; +} + virSecurityDriver virSecurityDriverSELinux =3D { .privateDataLen =3D sizeof(virSecuritySELinuxData), .name =3D SECURITY_SELINUX_NAME, @@ -3106,4 +3172,6 @@ virSecurityDriver virSecurityDriverSELinux =3D { =20 .domainSetSecurityChardevLabel =3D virSecuritySELinuxSetChardevLa= bel, .domainRestoreSecurityChardevLabel =3D virSecuritySELinuxRestoreChard= evLabel, + + .domainSetSecurityTPMLabels =3D virSecuritySELinuxSetSecurityT= PMLabels, }; diff --git a/src/security/security_stack.c b/src/security/security_stack.c index 9615f9f..7f10ef0 100644 --- a/src/security/security_stack.c +++ b/src/security/security_stack.c @@ -760,6 +760,23 @@ virSecurityStackDomainRestoreChardevLabel(virSecurityM= anagerPtr mgr, return rc; } =20 +static int +virSecurityStackSetSecurityTPMLabels(virSecurityManagerPtr mgr, + virDomainDefPtr vm) +{ + virSecurityStackDataPtr priv =3D virSecurityManagerGetPrivateData(mgr); + virSecurityStackItemPtr item =3D priv->itemsHead; + int rc =3D 0; + + for (; item; item =3D item->next) { + if (virSecurityManagerSetTPMLabels(item->securityManager, + vm) < 0) + rc =3D -1; + } + + return rc; +} + virSecurityDriver virSecurityDriverStack =3D { .privateDataLen =3D sizeof(virSecurityStackData), .name =3D "stack", @@ -822,4 +839,6 @@ virSecurityDriver virSecurityDriverStack =3D { =20 .domainSetSecurityChardevLabel =3D virSecurityStackDomainSetChard= evLabel, .domainRestoreSecurityChardevLabel =3D virSecurityStackDomainRestoreC= hardevLabel, + + .domainSetSecurityTPMLabels =3D virSecurityStackSetSecurityTPM= Labels, }; --=20 2.5.5 -- libvir-list mailing list libvir-list@redhat.com https://www.redhat.com/mailman/listinfo/libvir-list From nobody Mon Apr 29 09:01:19 2024 Delivered-To: importer@patchew.org Received-SPF: pass (zoho.com: domain of redhat.com designates 209.132.183.28 as permitted sender) client-ip=209.132.183.28; envelope-from=libvir-list-bounces@redhat.com; helo=mx1.redhat.com; Authentication-Results: mx.zohomail.com; spf=pass (zoho.com: domain of redhat.com designates 209.132.183.28 as permitted sender) smtp.mailfrom=libvir-list-bounces@redhat.com Return-Path: Received: from mx1.redhat.com (mx1.redhat.com [209.132.183.28]) by mx.zohomail.com with SMTPS id 1523415033407131.5631421387999; Tue, 10 Apr 2018 19:50:33 -0700 (PDT) Received: from smtp.corp.redhat.com (int-mx05.intmail.prod.int.phx2.redhat.com [10.5.11.15]) (using TLSv1.2 with cipher AECDH-AES256-SHA (256/256 bits)) (No client certificate requested) by mx1.redhat.com (Postfix) with ESMTPS id B45A9C04B925; Wed, 11 Apr 2018 02:50:31 +0000 (UTC) Received: from colo-mx.corp.redhat.com (colo-mx02.intmail.prod.int.phx2.redhat.com [10.5.11.21]) by smtp.corp.redhat.com (Postfix) with ESMTPS id 7C2556C8D3; Wed, 11 Apr 2018 02:50:31 +0000 (UTC) Received: from lists01.pubmisc.prod.ext.phx2.redhat.com (lists01.pubmisc.prod.ext.phx2.redhat.com [10.5.19.33]) by colo-mx.corp.redhat.com (Postfix) with ESMTP id 3FCD34CA9D; Wed, 11 Apr 2018 02:50:31 +0000 (UTC) Received: from smtp.corp.redhat.com (int-mx01.intmail.prod.int.phx2.redhat.com [10.5.11.11]) by lists01.pubmisc.prod.ext.phx2.redhat.com (8.13.8/8.13.8) with ESMTP id w3B2oTL8009974 for ; Tue, 10 Apr 2018 22:50:29 -0400 Received: by smtp.corp.redhat.com (Postfix) id E9A97857B1; Wed, 11 Apr 2018 02:50:29 +0000 (UTC) Received: from mx1.redhat.com (ext-mx06.extmail.prod.ext.phx2.redhat.com [10.5.110.30]) by smtp.corp.redhat.com (Postfix) with ESMTPS id E2887857AD for ; Wed, 11 Apr 2018 02:50:27 +0000 (UTC) Received: from mx0a-001b2d01.pphosted.com (mx0a-001b2d01.pphosted.com [148.163.156.1]) (using TLSv1.2 with cipher ECDHE-RSA-AES256-GCM-SHA384 (256/256 bits)) (No client certificate requested) by mx1.redhat.com (Postfix) with ESMTPS id B42F7369BD for ; Wed, 11 Apr 2018 02:50:24 +0000 (UTC) Received: from pps.filterd (m0098409.ppops.net [127.0.0.1]) by mx0a-001b2d01.pphosted.com (8.16.0.22/8.16.0.22) with SMTP id w3B2ncDs133929 for ; Tue, 10 Apr 2018 22:50:24 -0400 Received: from e38.co.us.ibm.com (e38.co.us.ibm.com [32.97.110.159]) by mx0a-001b2d01.pphosted.com with ESMTP id 2h97n2vn9d-1 (version=TLSv1.2 cipher=AES256-SHA256 bits=256 verify=NOT) for ; Tue, 10 Apr 2018 22:50:24 -0400 Received: from localhost by e38.co.us.ibm.com with IBM ESMTP SMTP Gateway: Authorized Use Only! Violators will be prosecuted for from ; Tue, 10 Apr 2018 20:50:23 -0600 Received: from b03cxnp07029.gho.boulder.ibm.com (9.17.130.16) by e38.co.us.ibm.com (192.168.1.138) with IBM ESMTP SMTP Gateway: Authorized Use Only! Violators will be prosecuted; Tue, 10 Apr 2018 20:50:20 -0600 Received: from b03ledav005.gho.boulder.ibm.com (b03ledav005.gho.boulder.ibm.com [9.17.130.236]) by b03cxnp07029.gho.boulder.ibm.com (8.14.9/8.14.9/NCO v10.0) with ESMTP id w3B2oKtL10813718; Tue, 10 Apr 2018 19:50:20 -0700 Received: from b03ledav005.gho.boulder.ibm.com (unknown [127.0.0.1]) by IMSVA (Postfix) with ESMTP id 0E996BE039; Tue, 10 Apr 2018 20:50:20 -0600 (MDT) Received: from sbct-3.watson.ibm.com (unknown [9.47.158.153]) by b03ledav005.gho.boulder.ibm.com (Postfix) with ESMTP id C16D8BE038; Tue, 10 Apr 2018 20:50:19 -0600 (MDT) From: Stefan Berger To: libvir-list@redhat.com Date: Tue, 10 Apr 2018 22:50:04 -0400 In-Reply-To: <1523415005-30661-1-git-send-email-stefanb@linux.vnet.ibm.com> References: <1523415005-30661-1-git-send-email-stefanb@linux.vnet.ibm.com> X-TM-AS-GCONF: 00 x-cbid: 18041102-0028-0000-0000-0000096DBFE9 X-IBM-SpamModules-Scores: X-IBM-SpamModules-Versions: BY=3.00008834; HX=3.00000241; KW=3.00000007; PH=3.00000004; SC=3.00000256; SDB=6.01016139; UDB=6.00518174; IPR=6.00795386; MB=3.00020511; MTD=3.00000008; XFM=3.00000015; UTC=2018-04-11 02:50:21 X-IBM-AV-DETECTION: SAVI=unused REMOTE=unused XFE=unused x-cbparentid: 18041102-0029-0000-0000-00003A536983 Message-Id: <1523415005-30661-6-git-send-email-stefanb@linux.vnet.ibm.com> X-Proofpoint-Virus-Version: vendor=fsecure engine=2.50.10434:, , definitions=2018-04-11_01:, , signatures=0 X-Proofpoint-Spam-Details: rule=outbound_notspam policy=outbound score=0 priorityscore=1501 malwarescore=0 suspectscore=43 phishscore=0 bulkscore=0 spamscore=0 clxscore=1015 lowpriorityscore=0 impostorscore=0 adultscore=0 classifier=spam adjust=0 reason=mlx scancount=1 engine=8.0.1-1709140000 definitions=main-1804110026 X-Greylist: Sender passed SPF test, Sender IP whitelisted by DNSRBL, ACL 207 matched, not delayed by milter-greylist-4.5.16 (mx1.redhat.com [10.5.110.30]); Wed, 11 Apr 2018 02:50:24 +0000 (UTC) X-Greylist: inspected by milter-greylist-4.5.16 (mx1.redhat.com [10.5.110.30]); Wed, 11 Apr 2018 02:50:24 +0000 (UTC) for IP:'148.163.156.1' DOMAIN:'mx0a-001b2d01.pphosted.com' HELO:'mx0a-001b2d01.pphosted.com' FROM:'stefanb@linux.vnet.ibm.com' RCPT:'' X-RedHat-Spam-Score: -1.71 (RCVD_IN_DNSWL_LOW, RCVD_IN_MSPIKE_H5, RCVD_IN_MSPIKE_WL) 148.163.156.1 mx0a-001b2d01.pphosted.com 148.163.156.1 mx0a-001b2d01.pphosted.com X-Scanned-By: MIMEDefang 2.78 on 10.5.110.30 X-Scanned-By: MIMEDefang 2.79 on 10.5.11.11 X-loop: libvir-list@redhat.com Subject: [libvirt] [PATCH v2 5/6] tpm: Add support for choosing emulation of a TPM 2 X-BeenThere: libvir-list@redhat.com X-Mailman-Version: 2.1.12 Precedence: junk List-Id: Development discussions about the libvirt library & tools List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , MIME-Version: 1.0 Content-Transfer-Encoding: quoted-printable Sender: libvir-list-bounces@redhat.com Errors-To: libvir-list-bounces@redhat.com X-Scanned-By: MIMEDefang 2.79 on 10.5.11.15 X-Greylist: Sender IP whitelisted, not delayed by milter-greylist-4.5.16 (mx1.redhat.com [10.5.110.31]); Wed, 11 Apr 2018 02:50:32 +0000 (UTC) X-ZohoMail: RSF_0 Z_629925259 SPT_0 Content-Type: text/plain; charset="utf-8" This patch extends the TPM's device XML with TPM 2 support. This only works for the emulator type backend and looks as follows: Once the version of a TPM has been chosen it cannot be changed anymore unle= ss one removes the TPM device first and then reads it. However, one looses all the secrets stored inside or tied to the emulated TPM by doing this. Signed-off-by: Stefan Berger --- docs/formatdomain.html.in | 17 +++++- docs/schemas/domaincommon.rng | 13 ++++ src/conf/domain_conf.c | 20 +++++- src/conf/domain_conf.h | 6 ++ src/util/virtpm.c | 84 ++++++++++++++++++++++= +--- tests/qemuxml2argvdata/tpm-emulator-tpm2.args | 24 ++++++++ tests/qemuxml2argvdata/tpm-emulator-tpm2.xml | 30 +++++++++ tests/qemuxml2argvtest.c | 2 + tests/qemuxml2xmloutdata/tpm-emulator-tpm2.xml | 34 +++++++++++ 9 files changed, 221 insertions(+), 9 deletions(-) create mode 100644 tests/qemuxml2argvdata/tpm-emulator-tpm2.args create mode 100644 tests/qemuxml2argvdata/tpm-emulator-tpm2.xml create mode 100644 tests/qemuxml2xmloutdata/tpm-emulator-tpm2.xml diff --git a/docs/formatdomain.html.in b/docs/formatdomain.html.in index bd6fedc..e5463a0 100644 --- a/docs/formatdomain.html.in +++ b/docs/formatdomain.html.in @@ -7635,7 +7635,7 @@ qemu-kvm -net nic,model=3D? /dev/null ... <devices> <tpm model=3D'tpm-tis'> - <backend type=3D'emulator'> + <backend type=3D'emulator' tpmversion=3D'2'> </backend> </tpm> </devices> @@ -7684,6 +7684,21 @@ qemu-kvm -net nic,model=3D? /dev/null +
tpmversion
+
+

+ The tpmversion attribute indicates the version + of the TPM. By default a TPM 1.2 is created. This attribute + only works with the emulator backend. The following + versions are supported: +

+
    +
  • '1.2' : creates a TPM 1.2
  • +
  • '2.0' or '2' : creates a TPM 2
  • +
+ Note that once a certain version of a TPM has been created for + a guest, the version must not be changed anymore. +
=20

NVRAM device

diff --git a/docs/schemas/domaincommon.rng b/docs/schemas/domaincommon.rng index d628444..77328bd 100644 --- a/docs/schemas/domaincommon.rng +++ b/docs/schemas/domaincommon.rng @@ -4140,6 +4140,19 @@ + + + + + + 1.2 + 2 + 2.0 + + + + + =20 diff --git a/src/conf/domain_conf.c b/src/conf/domain_conf.c index b5f1c3f..0bbb547 100644 --- a/src/conf/domain_conf.c +++ b/src/conf/domain_conf.c @@ -12552,7 +12552,7 @@ virDomainSmartcardDefParseXML(virDomainXMLOptionPtr= xmlopt, * or like this: * * - * + * * */ static virDomainTPMDefPtr @@ -12565,6 +12565,7 @@ virDomainTPMDefParseXML(virDomainXMLOptionPtr xmlop= t, char *path =3D NULL; char *model =3D NULL; char *backend =3D NULL; + char *tpmversion =3D NULL; virDomainTPMDefPtr def; xmlNodePtr save =3D ctxt->node; xmlNodePtr *backends =3D NULL; @@ -12611,6 +12612,20 @@ virDomainTPMDefParseXML(virDomainXMLOptionPtr xmlo= pt, goto error; } =20 + tpmversion =3D virXMLPropString(backends[0], "tpmversion"); + if (!tpmversion || STREQ(tpmversion, "1.2")) { + def->tpmversion =3D VIR_DOMAIN_TPM_VERSION_1_2; + /* only TIS available for emulator */ + if (def->type =3D=3D VIR_DOMAIN_TPM_TYPE_EMULATOR) + def->model =3D VIR_DOMAIN_TPM_MODEL_TIS; + } else if (STREQ(tpmversion, "2.0") || STREQ(tpmversion, "2")) { + def->tpmversion =3D VIR_DOMAIN_TPM_VERSION_2; + } else { + virReportError(VIR_ERR_CONFIG_UNSUPPORTED, + _("Unsupported TPM version '%s'"), + tpmversion); + } + switch (def->type) { case VIR_DOMAIN_TPM_TYPE_PASSTHROUGH: path =3D virXPathString("string(./backend/device/@path)", ctxt); @@ -12635,6 +12650,7 @@ virDomainTPMDefParseXML(virDomainXMLOptionPtr xmlop= t, VIR_FREE(model); VIR_FREE(backend); VIR_FREE(backends); + VIR_FREE(tpmversion); ctxt->node =3D save; return def; =20 @@ -24798,6 +24814,8 @@ virDomainTPMDefFormat(virBufferPtr buf, virBufferAdjustIndent(buf, 2); virBufferAsprintf(buf, "type)); + if (def->tpmversion =3D=3D VIR_DOMAIN_TPM_VERSION_2) + virBufferAddLit(buf, " tpmversion=3D'2'"); virBufferAdjustIndent(buf, 2); =20 switch (def->type) { diff --git a/src/conf/domain_conf.h b/src/conf/domain_conf.h index f632184..80f599c 100644 --- a/src/conf/domain_conf.h +++ b/src/conf/domain_conf.h @@ -1289,12 +1289,18 @@ typedef enum { VIR_DOMAIN_TPM_TYPE_LAST } virDomainTPMBackendType; =20 +typedef enum { + VIR_DOMAIN_TPM_VERSION_1_2, + VIR_DOMAIN_TPM_VERSION_2, +} virDomainTPMVersion; + # define VIR_DOMAIN_TPM_DEFAULT_DEVICE "/dev/tpm0" =20 struct _virDomainTPMDef { virDomainTPMBackendType type; virDomainDeviceInfo info; virDomainTPMModel model; + virDomainTPMVersion tpmversion; union { struct { virDomainChrSourceDef source; diff --git a/src/util/virtpm.c b/src/util/virtpm.c index 649153e..3bb911e 100644 --- a/src/util/virtpm.c +++ b/src/util/virtpm.c @@ -52,6 +52,8 @@ static char *swtpm_path; static char *swtpm_setup; static char *swtpm_ioctl; =20 +static bool swtpm_supports_tpm2; + /** * virTPMCreateCancelPath: * @devpath: Path to the TPM device @@ -96,6 +98,38 @@ virTPMCreateCancelPath(const char *devpath) } =20 /* + * virTPMCheckForTPM2Support + * + * Check whether swtpm_setup supports TPM 2 + */ +static void +virTPMCheckForTPM2Support(void) +{ + virCommandPtr cmd; + char *help =3D NULL; + + if (!swtpm_setup) + return; + + cmd =3D virCommandNew(swtpm_setup); + if (!cmd) + return; + + virCommandAddArg(cmd, "--help"); + virCommandSetOutputBuffer(cmd, &help); + + if (virCommandRun(cmd, NULL) < 0) + goto cleanup; + + if (strstr(help, "--tpm2")) + swtpm_supports_tpm2 =3D true; + + cleanup: + virCommandFree(cmd); + VIR_FREE(help); +} + +/* * virTPMEmulatorInit * * Initialize the Emulator functions by searching for necessary @@ -134,6 +168,7 @@ virTPMEmulatorInit(void) VIR_FREE(swtpm_setup); return -1; } + virTPMCheckForTPM2Support(); } =20 if (!swtpm_ioctl) { @@ -160,16 +195,28 @@ virTPMEmulatorInit(void) * * @swtpmStorageDir: directory for swtpm persistent state * @vmname: The name of the VM for which to create the storage + * @tpmversion: version of the TPM * * Create the swtpm's storage path */ static char * virTPMCreateEmulatorStoragePath(const char *swtpmStorageDir, - const char *vmname) + const char *vmname, + virDomainTPMVersion tpmversion) { char *path =3D NULL; + const char *dir =3D ""; + + switch (tpmversion) { + case VIR_DOMAIN_TPM_VERSION_1_2: + dir =3D "tpm1.2"; + break; + case VIR_DOMAIN_TPM_VERSION_2: + dir =3D "tpm2"; + break; + } =20 - ignore_value(virAsprintf(&path, "%s/%s/tpm1.2", swtpmStorageDir, vmnam= e)); + ignore_value(virAsprintf(&path, "%s/%s/%s", swtpmStorageDir, vmname, d= ir)); =20 return path; } @@ -313,9 +360,10 @@ int virTPMEmulatorInitPaths(virDomainTPMDefPtr tpm, const char *swtpmStorageDir, const char *vmname) { - if (!tpm->data.emulator.storagepath && - !(tpm->data.emulator.storagepath =3D - virTPMCreateEmulatorStoragePath(swtpmStorageDir, vmname))) + VIR_FREE(tpm->data.emulator.storagepath); + if (!(tpm->data.emulator.storagepath =3D + virTPMCreateEmulatorStoragePath(swtpmStorageDir, vmname, + tpm->tpmversion))) return -1; =20 return 0; @@ -398,13 +446,15 @@ int virTPMEmulatorPrepareHost(virDomainTPMDefPtr tpm, * typically this should be the uid of 'tss' or 'root' * @logfile: The file to write the log into; it must be writable * for the user given by userid or 'tss' + * @tpmversion: The version of the TPM, either a TPM 1.2 or TPM 2 * * Setup the external swtpm */ static int virTPMEmulatorRunSetup(const char *storagepath, const char *vmname, const unsigned char *vmuuid, - uid_t swtpm_user, const char *logfile) + uid_t swtpm_user, const char *logfile, + const virDomainTPMVersion tpmversion) { virCommandPtr cmd =3D NULL; int exitstatus; @@ -425,6 +475,17 @@ virTPMEmulatorRunSetup(const char *storagepath, const = char *vmname, virCommandSetUID(cmd, swtpm_user); virCommandSetGID(cmd, swtpm_user); =20 + switch (tpmversion) { + case VIR_DOMAIN_TPM_VERSION_1_2: + break; + case VIR_DOMAIN_TPM_VERSION_2: + virCommandAddArgList(cmd, "--tpm2", NULL); + if (!swtpm_supports_tpm2) { + goto cleanup; + } + break; + } + virCommandAddArgList(cmd, "--tpm-state", storagepath, "--vmid", vmid, @@ -482,7 +543,8 @@ virTPMEmulatorBuildCommand(virDomainTPMDefPtr tpm, cons= t char *vmname, =20 if (created && virTPMEmulatorRunSetup(tpm->data.emulator.storagepath, vmname, vmu= uid, - swtpm_user, tpm->data.emulator.logfile) < 0) + swtpm_user, tpm->data.emulator.logfile, + tpm->tpmversion) < 0) goto error; =20 unlink(tpm->data.emulator.source.data.nix.path); @@ -507,6 +569,14 @@ virTPMEmulatorBuildCommand(virDomainTPMDefPtr tpm, con= st char *vmname, virCommandSetUID(cmd, swtpm_user); virCommandSetGID(cmd, swtpm_user); =20 + switch (tpm->tpmversion) { + case VIR_DOMAIN_TPM_VERSION_1_2: + break; + case VIR_DOMAIN_TPM_VERSION_2: + virCommandAddArg(cmd, "--tpm2"); + break; + } + return cmd; =20 error: diff --git a/tests/qemuxml2argvdata/tpm-emulator-tpm2.args b/tests/qemuxml2= argvdata/tpm-emulator-tpm2.args new file mode 100644 index 0000000..9418c74 --- /dev/null +++ b/tests/qemuxml2argvdata/tpm-emulator-tpm2.args @@ -0,0 +1,24 @@ +LC_ALL=3DC \ +PATH=3D/bin \ +HOME=3D/home/test \ +USER=3Dtest \ +LOGNAME=3Dtest \ +QEMU_AUDIO_DRV=3Dnone \ +/usr/bin/qemu-system-x86_64 \ +-name TPM-VM \ +-S \ +-M pc-0.12 \ +-m 2048 \ +-smp 1,sockets=3D1,cores=3D1,threads=3D1 \ +-uuid 11d7cd22-da89-3094-6212-079a48a309a1 \ +-nographic \ +-nodefaults \ +-chardev socket,id=3Dcharmonitor,path=3D/tmp/lib/domain--1-TPM-VM/monitor.= sock,\ +server,nowait \ +-mon chardev=3Dcharmonitor,id=3Dmonitor,mode=3Dreadline \ +-boot c \ +-usb \ +-tpmdev emulator,id=3Dtpm-tpm0,chardev=3Dchrtpm \ +-chardev socket,id=3Dchrtpm,path=3D/dev/test \ +-device tpm-tis,tpmdev=3Dtpm-tpm0,id=3Dtpm0 \ +-device virtio-balloon-pci,id=3Dballoon0,bus=3Dpci.0,addr=3D0x3 diff --git a/tests/qemuxml2argvdata/tpm-emulator-tpm2.xml b/tests/qemuxml2a= rgvdata/tpm-emulator-tpm2.xml new file mode 100644 index 0000000..070bedb --- /dev/null +++ b/tests/qemuxml2argvdata/tpm-emulator-tpm2.xml @@ -0,0 +1,30 @@ + + TPM-VM + 11d7cd22-da89-3094-6212-079a48a309a1 + 2097152 + 512288 + 1 + + hvm + + + + + + + + destroy + restart + destroy + + /usr/bin/qemu-system-x86_64 + + + + + + + + + + diff --git a/tests/qemuxml2argvtest.c b/tests/qemuxml2argvtest.c index 06dca97..ac80a64 100644 --- a/tests/qemuxml2argvtest.c +++ b/tests/qemuxml2argvtest.c @@ -2154,6 +2154,8 @@ mymain(void) QEMU_CAPS_DEVICE_TPM_PASSTHROUGH, QEMU_CAPS_DEVICE= _TPM_TIS); DO_TEST("tpm-emulator", QEMU_CAPS_DEVICE_TPM_EMULATOR, QEMU_CAPS_DEVICE_TPM_TIS); + DO_TEST("tpm-emulator-tpm2", + QEMU_CAPS_DEVICE_TPM_EMULATOR, QEMU_CAPS_DEVICE_TPM_TIS); =20 =20 DO_TEST_PARSE_ERROR("pci-domain-invalid", NONE); diff --git a/tests/qemuxml2xmloutdata/tpm-emulator-tpm2.xml b/tests/qemuxml= 2xmloutdata/tpm-emulator-tpm2.xml new file mode 100644 index 0000000..4a68bd8 --- /dev/null +++ b/tests/qemuxml2xmloutdata/tpm-emulator-tpm2.xml @@ -0,0 +1,34 @@ + + TPM-VM + 11d7cd22-da89-3094-6212-079a48a309a1 + 2097152 + 512288 + 1 + + hvm + + + + + + + + destroy + restart + destroy + + /usr/bin/qemu-system-x86_64 + +
+ + + + + + + + +
+ + + --=20 2.5.5 -- libvir-list mailing list libvir-list@redhat.com https://www.redhat.com/mailman/listinfo/libvir-list From nobody Mon Apr 29 09:01:19 2024 Delivered-To: importer@patchew.org Received-SPF: pass (zoho.com: domain of redhat.com designates 209.132.183.28 as permitted sender) client-ip=209.132.183.28; envelope-from=libvir-list-bounces@redhat.com; helo=mx1.redhat.com; Authentication-Results: mx.zohomail.com; spf=pass (zoho.com: domain of redhat.com designates 209.132.183.28 as permitted sender) smtp.mailfrom=libvir-list-bounces@redhat.com Return-Path: Received: from mx1.redhat.com (mx1.redhat.com [209.132.183.28]) by mx.zohomail.com with SMTPS id 1523415049902560.8932318074203; Tue, 10 Apr 2018 19:50:49 -0700 (PDT) Received: from smtp.corp.redhat.com (int-mx03.intmail.prod.int.phx2.redhat.com [10.5.11.13]) (using TLSv1.2 with cipher AECDH-AES256-SHA (256/256 bits)) (No client certificate requested) by mx1.redhat.com (Postfix) with ESMTPS id 7CB8D4902F; Wed, 11 Apr 2018 02:50:48 +0000 (UTC) Received: from colo-mx.corp.redhat.com (colo-mx01.intmail.prod.int.phx2.redhat.com [10.5.11.20]) by smtp.corp.redhat.com (Postfix) with ESMTPS id 4CBD56AFE0; Wed, 11 Apr 2018 02:50:48 +0000 (UTC) Received: from lists01.pubmisc.prod.ext.phx2.redhat.com (lists01.pubmisc.prod.ext.phx2.redhat.com [10.5.19.33]) by colo-mx.corp.redhat.com (Postfix) with ESMTP id 0954B180596E; Wed, 11 Apr 2018 02:50:48 +0000 (UTC) Received: from smtp.corp.redhat.com (int-mx02.intmail.prod.int.phx2.redhat.com [10.5.11.12]) by lists01.pubmisc.prod.ext.phx2.redhat.com (8.13.8/8.13.8) with ESMTP id w3B2oSFN009957 for ; Tue, 10 Apr 2018 22:50:28 -0400 Received: by smtp.corp.redhat.com (Postfix) id 684D2662CE; Wed, 11 Apr 2018 02:50:28 +0000 (UTC) Received: from mx1.redhat.com (ext-mx04.extmail.prod.ext.phx2.redhat.com [10.5.110.28]) by smtp.corp.redhat.com (Postfix) with ESMTPS id 61BAC60CD3 for ; Wed, 11 Apr 2018 02:50:28 +0000 (UTC) Received: from mx0a-001b2d01.pphosted.com (mx0a-001b2d01.pphosted.com [148.163.156.1]) (using TLSv1.2 with cipher ECDHE-RSA-AES256-GCM-SHA384 (256/256 bits)) (No client certificate requested) by mx1.redhat.com (Postfix) with ESMTPS id 42D2380469 for ; Wed, 11 Apr 2018 02:50:26 +0000 (UTC) Received: from pps.filterd (m0098399.ppops.net [127.0.0.1]) by mx0a-001b2d01.pphosted.com (8.16.0.22/8.16.0.22) with SMTP id w3B2nfbZ127203 for ; Tue, 10 Apr 2018 22:50:25 -0400 Received: from e37.co.us.ibm.com (e37.co.us.ibm.com [32.97.110.158]) by mx0a-001b2d01.pphosted.com with ESMTP id 2h98dak0ha-1 (version=TLSv1.2 cipher=AES256-SHA256 bits=256 verify=NOT) for ; Tue, 10 Apr 2018 22:50:25 -0400 Received: from localhost by e37.co.us.ibm.com with IBM ESMTP SMTP Gateway: Authorized Use Only! Violators will be prosecuted for from ; Tue, 10 Apr 2018 20:50:24 -0600 Received: from b03cxnp07028.gho.boulder.ibm.com (9.17.130.15) by e37.co.us.ibm.com (192.168.1.137) with IBM ESMTP SMTP Gateway: Authorized Use Only! Violators will be prosecuted; Tue, 10 Apr 2018 20:50:21 -0600 Received: from b03ledav005.gho.boulder.ibm.com (b03ledav005.gho.boulder.ibm.com [9.17.130.236]) by b03cxnp07028.gho.boulder.ibm.com (8.14.9/8.14.9/NCO v10.0) with ESMTP id w3B2oLqa14811644; Tue, 10 Apr 2018 19:50:21 -0700 Received: from b03ledav005.gho.boulder.ibm.com (unknown [127.0.0.1]) by IMSVA (Postfix) with ESMTP id 61D43BE039; Tue, 10 Apr 2018 20:50:21 -0600 (MDT) Received: from sbct-3.watson.ibm.com (unknown [9.47.158.153]) by b03ledav005.gho.boulder.ibm.com (Postfix) with ESMTP id 20E2ABE03E; Tue, 10 Apr 2018 20:50:21 -0600 (MDT) From: Stefan Berger To: libvir-list@redhat.com Date: Tue, 10 Apr 2018 22:50:05 -0400 In-Reply-To: <1523415005-30661-1-git-send-email-stefanb@linux.vnet.ibm.com> References: <1523415005-30661-1-git-send-email-stefanb@linux.vnet.ibm.com> X-TM-AS-GCONF: 00 x-cbid: 18041102-0024-0000-0000-000018357F6F X-IBM-SpamModules-Scores: X-IBM-SpamModules-Versions: BY=3.00008834; HX=3.00000241; KW=3.00000007; PH=3.00000004; SC=3.00000256; SDB=6.01016139; UDB=6.00518173; IPR=6.00795386; MB=3.00020511; MTD=3.00000008; XFM=3.00000015; UTC=2018-04-11 02:50:23 X-IBM-AV-DETECTION: SAVI=unused REMOTE=unused XFE=unused x-cbparentid: 18041102-0025-0000-0000-00004F78820B Message-Id: <1523415005-30661-7-git-send-email-stefanb@linux.vnet.ibm.com> X-Proofpoint-Virus-Version: vendor=fsecure engine=2.50.10434:, , definitions=2018-04-11_01:, , signatures=0 X-Proofpoint-Spam-Details: rule=outbound_notspam policy=outbound score=0 priorityscore=1501 malwarescore=0 suspectscore=3 phishscore=0 bulkscore=0 spamscore=0 clxscore=1015 lowpriorityscore=0 impostorscore=0 adultscore=0 classifier=spam adjust=0 reason=mlx scancount=1 engine=8.0.1-1709140000 definitions=main-1804110026 X-Greylist: Sender passed SPF test, Sender IP whitelisted by DNSRBL, ACL 207 matched, not delayed by milter-greylist-4.5.16 (mx1.redhat.com [10.5.110.28]); Wed, 11 Apr 2018 02:50:26 +0000 (UTC) X-Greylist: inspected by milter-greylist-4.5.16 (mx1.redhat.com [10.5.110.28]); Wed, 11 Apr 2018 02:50:26 +0000 (UTC) for IP:'148.163.156.1' DOMAIN:'mx0a-001b2d01.pphosted.com' HELO:'mx0a-001b2d01.pphosted.com' FROM:'stefanb@linux.vnet.ibm.com' RCPT:'' X-RedHat-Spam-Score: -1.71 (RCVD_IN_DNSWL_LOW, RCVD_IN_MSPIKE_H5, RCVD_IN_MSPIKE_WL) 148.163.156.1 mx0a-001b2d01.pphosted.com 148.163.156.1 mx0a-001b2d01.pphosted.com X-Scanned-By: MIMEDefang 2.78 on 10.5.110.28 X-Scanned-By: MIMEDefang 2.79 on 10.5.11.12 X-loop: libvir-list@redhat.com Subject: [libvirt] [PATCH v2 6/6] tpm: Add swtpm to emulator cgroup X-BeenThere: libvir-list@redhat.com X-Mailman-Version: 2.1.12 Precedence: junk List-Id: Development discussions about the libvirt library & tools List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , MIME-Version: 1.0 Content-Transfer-Encoding: quoted-printable Sender: libvir-list-bounces@redhat.com Errors-To: libvir-list-bounces@redhat.com X-Scanned-By: MIMEDefang 2.79 on 10.5.11.13 X-Greylist: Sender IP whitelisted, not delayed by milter-greylist-4.5.16 (mx1.redhat.com [10.5.110.38]); Wed, 11 Apr 2018 02:50:48 +0000 (UTC) X-ZohoMail: RSF_0 Z_629925259 SPT_0 Content-Type: text/plain; charset="utf-8" Add the external swtpm to the emulator cgroup so that upper limits of CPU usage can be enforced on the emulated TPM. To enable this we need to have the swtpm write its process id (pid) into a file. We then read it from the file to configure the emulator cgroup. The PID file is created in /var/run/libvirt/qemu/swtpm: [root@localhost swtpm]# ls -lZ /var/run/libvirt/qemu/swtpm/ total 4 -rw-r--r--. 1 tss tss system_u:object_r:qemu_var_run_t:s0 5 Apr = 10 12:26 testvm-swtpm.pid srw-rw----. 1 qemu qemu system_u:object_r:svirt_image_t:s0:c597,c632 0 Apr = 10 12:26 testvm-swtpm.sock The swtpm command line now looks as follows: root@localhost testvm]# ps auxZ | grep swtpm | grep socket | grep -v grep system_u:system_r:virtd_t:s0:c597,c632 tss 18697 0.0 0.0 28172 3892 ? = Ss 16:46 0:00 /usr/bin/swtpm socket --daemon --ctrl type=3Dunixio,pat= h=3D/var/run/libvirt/qemu/swtpm/testvm-swtpm.sock,mode=3D0660 --tpmstate di= r=3D/var/lib/libvirt/swtpm/testvm --log file=3D/var/log/swtpm/libvirt/qemu/= testvm-swtpm.log --pid file=3D/var/run/libvirt/qemu/swtpm/testvm-swtpm.pid Signed-off-by: Stefan Berger --- src/conf/domain_conf.c | 1 + src/conf/domain_conf.h | 1 + src/libvirt_private.syms | 1 + src/qemu/qemu_cgroup.c | 53 +++++++++++++++++++++++++++++++++++++++++++= ++++ src/qemu/qemu_cgroup.h | 1 + src/qemu/qemu_extdevice.c | 19 +++++++++++++++++ src/qemu/qemu_process.c | 4 ++++ src/util/vircgroup.c | 42 +++++++++++++++++++++++++++++++++++++ src/util/vircgroup.h | 1 + src/util/virtpm.c | 33 +++++++++++++++++++++++++++++ 10 files changed, 156 insertions(+) diff --git a/src/conf/domain_conf.c b/src/conf/domain_conf.c index 0bbb547..e19f7dc 100644 --- a/src/conf/domain_conf.c +++ b/src/conf/domain_conf.c @@ -2620,6 +2620,7 @@ void virDomainTPMDefFree(virDomainTPMDefPtr def) VIR_FREE(def->data.emulator.source.data.nix.path); VIR_FREE(def->data.emulator.storagepath); VIR_FREE(def->data.emulator.logfile); + VIR_FREE(def->data.emulator.pidfile); break; case VIR_DOMAIN_TPM_TYPE_LAST: break; diff --git a/src/conf/domain_conf.h b/src/conf/domain_conf.h index 80f599c..34bd4a2 100644 --- a/src/conf/domain_conf.h +++ b/src/conf/domain_conf.h @@ -1309,6 +1309,7 @@ struct _virDomainTPMDef { virDomainChrSourceDef source; char *storagepath; char *logfile; + char *pidfile; } emulator; } data; }; diff --git a/src/libvirt_private.syms b/src/libvirt_private.syms index af9163f..00cb294 100644 --- a/src/libvirt_private.syms +++ b/src/libvirt_private.syms @@ -1467,6 +1467,7 @@ virBufferVasprintf; =20 # util/vircgroup.h virCgroupAddMachineTask; +virCgroupAddProc; virCgroupAddTask; virCgroupAddTaskController; virCgroupAllowAllDevices; diff --git a/src/qemu/qemu_cgroup.c b/src/qemu/qemu_cgroup.c index bd4859c..859ed55 100644 --- a/src/qemu/qemu_cgroup.c +++ b/src/qemu/qemu_cgroup.c @@ -37,6 +37,7 @@ #include "virtypedparam.h" #include "virnuma.h" #include "virsystemd.h" +#include "virpidfile.h" =20 #define VIR_FROM_THIS VIR_FROM_QEMU =20 @@ -1106,6 +1107,58 @@ qemuSetupCgroupCpusetCpus(virCgroupPtr cgroup, =20 =20 int +qemuSetupCgroupForExtDevices(virDomainObjPtr vm) +{ + qemuDomainObjPrivatePtr priv =3D vm->privateData; + virDomainTPMDefPtr tpm =3D vm->def->tpm; + virCgroupPtr cgroup_temp =3D NULL; + pid_t pid; + int ret =3D -1; + + if (priv->cgroup =3D=3D NULL) + return 0; /* Not supported, so claim success */ + + /* + * If CPU cgroup controller is not initialized here, then we need + * neither period nor quota settings. And if CPUSET controller is + * not initialized either, then there's nothing to do anyway. + */ + if (!virCgroupHasController(priv->cgroup, VIR_CGROUP_CONTROLLER_CPU) && + !virCgroupHasController(priv->cgroup, VIR_CGROUP_CONTROLLER_CPUSET= )) + return 0; + + if (virCgroupNewThread(priv->cgroup, VIR_CGROUP_THREAD_EMULATOR, 0, + false, &cgroup_temp) < 0) + goto cleanup; + + if (tpm) { + switch (tpm->type) { + case VIR_DOMAIN_TPM_TYPE_EMULATOR: + if (virPidFileReadPath(tpm->data.emulator.pidfile, &pid) < 0) { + virReportError(VIR_ERR_INTERNAL_ERROR, + _("Could not read swtpm's pidfile %s"), + tpm->data.emulator.pidfile); + goto cleanup; + } + if (virCgroupAddProc(cgroup_temp, pid) < 0) + goto cleanup; + break; + case VIR_DOMAIN_TPM_TYPE_PASSTHROUGH: + case VIR_DOMAIN_TPM_TYPE_LAST: + break; + } + } + + ret =3D 0; + +cleanup: + virCgroupFree(&cgroup_temp); + + return ret; +} + + +int qemuSetupGlobalCpuCgroup(virDomainObjPtr vm) { qemuDomainObjPrivatePtr priv =3D vm->privateData; diff --git a/src/qemu/qemu_cgroup.h b/src/qemu/qemu_cgroup.h index 3b8ff60..478bf7e 100644 --- a/src/qemu/qemu_cgroup.h +++ b/src/qemu/qemu_cgroup.h @@ -69,6 +69,7 @@ int qemuSetupCgroupVcpuBW(virCgroupPtr cgroup, long long quota); int qemuSetupCgroupCpusetCpus(virCgroupPtr cgroup, virBitmapPtr cpumask); int qemuSetupGlobalCpuCgroup(virDomainObjPtr vm); +int qemuSetupCgroupForExtDevices(virDomainObjPtr vm); int qemuRemoveCgroup(virDomainObjPtr vm); =20 typedef struct _qemuCgroupEmulatorAllNodesData qemuCgroupEmulatorAllNodesD= ata; diff --git a/src/qemu/qemu_extdevice.c b/src/qemu/qemu_extdevice.c index ee327ca..23ec310 100644 --- a/src/qemu/qemu_extdevice.c +++ b/src/qemu/qemu_extdevice.c @@ -128,6 +128,9 @@ qemuExtTPMStartEmulator(virQEMUDriverPtr driver, char *errbuf =3D NULL; virQEMUDriverConfigPtr cfg =3D virQEMUDriverGetConfig(driver); virDomainTPMDefPtr tpm =3D def->tpm; + char *pidfiledata =3D NULL; + int timeout; + int len; =20 /* stop any left-over TPM emulator for this VM */ virTPMEmulatorStop(cfg->swtpmStateDir, def->name); @@ -170,6 +173,22 @@ qemuExtTPMStartEmulator(virQEMUDriverPtr driver, goto error; } =20 + /* check that the swtpm has written its pid into the file */ + timeout =3D 1000; /* ms */ + while ((len =3D virFileReadHeaderQuiet(tpm->data.emulator.pidfile, + 10, &pidfiledata)) <=3D 0) { + if (len =3D=3D 0 && timeout > 0) { + timeout -=3D 50; + usleep(50 * 1000); + continue; + } + virReportError(VIR_ERR_INTERNAL_ERROR, + _("swtpm did not write pidfile '%s'"), + tpm->data.emulator.pidfile); + goto error; + } + VIR_FREE(pidfiledata); + ret =3D 0; =20 cleanup: diff --git a/src/qemu/qemu_process.c b/src/qemu/qemu_process.c index 7bf90a4..4877c49 100644 --- a/src/qemu/qemu_process.c +++ b/src/qemu/qemu_process.c @@ -6072,6 +6072,10 @@ qemuProcessLaunch(virConnectPtr conn, if (qemuProcessSetupEmulator(vm) < 0) goto cleanup; =20 + VIR_DEBUG("Setting cgroup for external devices (if required)"); + if (qemuSetupCgroupForExtDevices(vm) < 0) + goto cleanup; + VIR_DEBUG("Setting up resctrl"); if (qemuProcessResctrlCreate(driver, vm) < 0) goto cleanup; diff --git a/src/util/vircgroup.c b/src/util/vircgroup.c index 0a31947..4809f12 100644 --- a/src/util/vircgroup.c +++ b/src/util/vircgroup.c @@ -1245,6 +1245,38 @@ virCgroupAddMachineTask(virCgroupPtr group, pid_t pi= d) return virCgroupAddTaskInternal(group, pid, true); } =20 +/** + * virCgroupAddProc: + * + * @group: The cgroup to add a process to + * @pid: The pid of the process to add + * + * Returns: 0 on success, -1 on error + */ +int +virCgroupAddProc(virCgroupPtr group, pid_t pid) +{ + int ret =3D -1; + size_t i; + + for (i =3D 0; i < VIR_CGROUP_CONTROLLER_LAST; i++) { + /* Skip over controllers not mounted */ + if (!group->controllers[i].mountPoint) + continue; + + /* We must never add tasks in systemd's hierarchy */ + if (i =3D=3D VIR_CGROUP_CONTROLLER_SYSTEMD) + continue; + + if (virCgroupSetValueU64(group, i, "cgroup.procs", pid) < 0) + goto cleanup; + } + + ret =3D 0; + cleanup: + return ret; +} + =20 /** * virCgroupAddTaskController: @@ -4298,6 +4330,16 @@ virCgroupAddMachineTask(virCgroupPtr group ATTRIBUTE= _UNUSED, =20 =20 int +virCgroupAddProc(virCgroupPtr group ATTRIBUTE_UNUSED, + pid_t pid ATTRIBUTE_UNUSED) +{ + virReportSystemError(ENXIO, "%s", + _("Control groups not supported on this platform"= )); + return -1; +} + + +int virCgroupAddTaskController(virCgroupPtr group ATTRIBUTE_UNUSED, pid_t pid ATTRIBUTE_UNUSED, int controller ATTRIBUTE_UNUSED) diff --git a/src/util/vircgroup.h b/src/util/vircgroup.h index d833927..82b3964 100644 --- a/src/util/vircgroup.h +++ b/src/util/vircgroup.h @@ -132,6 +132,7 @@ int virCgroupPathOfController(virCgroupPtr group, =20 int virCgroupAddTask(virCgroupPtr group, pid_t pid); int virCgroupAddMachineTask(virCgroupPtr group, pid_t pid); +int virCgroupAddProc(virCgroupPtr group, pid_t pid); =20 int virCgroupAddTaskController(virCgroupPtr group, pid_t pid, diff --git a/src/util/virtpm.c b/src/util/virtpm.c index 3bb911e..af2e1d2 100644 --- a/src/util/virtpm.c +++ b/src/util/virtpm.c @@ -39,6 +39,7 @@ #include "virlog.h" #include "virtpm.h" #include "virutil.h" +#include "virpidfile.h" #include "configmake.h" =20 #define VIR_FROM_THIS VIR_FROM_NONE @@ -370,6 +371,25 @@ int virTPMEmulatorInitPaths(virDomainTPMDefPtr tpm, } =20 /* + * virTPMCreatePidfileName + */ +static char *virTPMCreatePidfileName(const char *swtpmStateDir, + const char *vmname) +{ + char *pidfile =3D NULL; + char *devname =3D NULL; + + if (virAsprintf(&devname, "%s-swtpm", vmname) < 0) + return NULL; + + pidfile =3D virPidFileBuildPath(swtpmStateDir, devname); + + VIR_FREE(devname); + + return pidfile; +} + +/* * virTPMEmulatorPrepareHost: * * @tpm: tpm definition @@ -427,6 +447,10 @@ int virTPMEmulatorPrepareHost(virDomainTPMDefPtr tpm, goto cleanup; tpm->data.emulator.source.type =3D VIR_DOMAIN_CHR_TYPE_UNIX; =20 + if (!(tpm->data.emulator.pidfile =3D + virTPMCreatePidfileName(swtpmStateDir, vmname))) + goto cleanup; + ret =3D 0; =20 cleanup: @@ -577,6 +601,9 @@ virTPMEmulatorBuildCommand(virDomainTPMDefPtr tpm, cons= t char *vmname, break; } =20 + virCommandAddArg(cmd, "--pid"); + virCommandAddArgFormat(cmd, "file=3D%s", tpm->data.emulator.pidfile); + return cmd; =20 error: @@ -604,6 +631,7 @@ virTPMEmulatorStop(const char *swtpmStateDir, const cha= r *vmname) virCommandPtr cmd; char *pathname; char *errbuf =3D NULL; + char *pidfile; =20 if (virTPMEmulatorInit() < 0) return; @@ -632,6 +660,11 @@ virTPMEmulatorStop(const char *swtpmStateDir, const ch= ar *vmname) unlink(pathname); =20 cleanup: + /* clean up the PID file */ + if ((pidfile =3D virTPMCreatePidfileName(swtpmStateDir, vmname))) { + unlink(pidfile); + VIR_FREE(pidfile); + } VIR_FREE(pathname); VIR_FREE(errbuf); } --=20 2.5.5 -- libvir-list mailing list libvir-list@redhat.com https://www.redhat.com/mailman/listinfo/libvir-list