From nobody Tue Feb 10 07:41:09 2026 Delivered-To: importer@patchew.org Received-SPF: pass (zohomail.com: domain of redhat.com designates 170.10.133.124 as permitted sender) client-ip=170.10.133.124; envelope-from=libvir-list-bounces@redhat.com; helo=us-smtp-delivery-124.mimecast.com; Authentication-Results: mx.zohomail.com; dkim=pass; spf=pass (zohomail.com: domain of redhat.com designates 170.10.133.124 as permitted sender) smtp.mailfrom=libvir-list-bounces@redhat.com; dmarc=pass(p=none dis=none) header.from=redhat.com ARC-Seal: i=1; a=rsa-sha256; t=1627058472; cv=none; d=zohomail.com; s=zohoarc; b=IbIBvMf9JY7UybfleTJtJF2dhE9OejSKflKK0yxo63sByyBKlHC88XUEb2zbERKzRnvnDbm/Q7EVskPushSUDo8ULsqcfTMxU+KiSz3C8nlOuuKoE4X/7HohUsAVJXDzA+HfsHqzURWw8SE1V2fzK9CKRdLV0mqY2UF+Fa5PEDo= ARC-Message-Signature: i=1; a=rsa-sha256; c=relaxed/relaxed; d=zohomail.com; s=zohoarc; t=1627058472; h=Content-Type:Content-Transfer-Encoding:Date:From:In-Reply-To:List-Subscribe:List-Post:List-Id:List-Archive:List-Help:List-Unsubscribe:MIME-Version:Message-ID:References:Sender:Subject:To; bh=qPCLjBhyUBUCL79Rz3JNBP+/DN15TZmV7JnyIuEdeX8=; b=IicUQMcoEbSaftIJnXzRijQSeg2B6EBGObG8cyyxHFt+aDLjOnXm59h8iNeF34JQGNG+nUJiKMC/+Lar854/FDWcIReyaWu/l0EkftQ7+mjbZR+1w/VuwHRCh/MHXMUHbHw/UMEfbhyTXEL+AsRj56vTJ0NfSHEZJxSU6EKNRcc= ARC-Authentication-Results: i=1; mx.zohomail.com; dkim=pass; spf=pass (zohomail.com: domain of redhat.com designates 170.10.133.124 as permitted sender) smtp.mailfrom=libvir-list-bounces@redhat.com; dmarc=pass header.from= (p=none dis=none) Return-Path: Received: from us-smtp-delivery-124.mimecast.com (us-smtp-delivery-124.mimecast.com [170.10.133.124]) by mx.zohomail.com with SMTPS id 1627058472256902.5953784811292; Fri, 23 Jul 2021 09:41:12 -0700 (PDT) Received: from mimecast-mx01.redhat.com (mimecast-mx01.redhat.com [209.132.183.4]) (Using TLS) by relay.mimecast.com with ESMTP id us-mta-388-BlTyeR1oNESI4wdapsaE8Q-1; Fri, 23 Jul 2021 12:41:09 -0400 Received: from smtp.corp.redhat.com (int-mx04.intmail.prod.int.phx2.redhat.com [10.5.11.14]) (using TLSv1.2 with cipher AECDH-AES256-SHA (256/256 bits)) (No client certificate requested) by mimecast-mx01.redhat.com (Postfix) with ESMTPS id 42453107B788; Fri, 23 Jul 2021 16:41:04 +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 2090C5D9D5; Fri, 23 Jul 2021 16:41:04 +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 DCEA24A7C9; Fri, 23 Jul 2021 16:41:03 +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 16NGenIv001329 for ; Fri, 23 Jul 2021 12:40:49 -0400 Received: by smtp.corp.redhat.com (Postfix) id 0646A687D5; Fri, 23 Jul 2021 16:40:49 +0000 (UTC) Received: from himantopus.redhat.com (ovpn-114-96.phx2.redhat.com [10.3.114.96]) by smtp.corp.redhat.com (Postfix) with ESMTPS id 75BB56091B for ; Fri, 23 Jul 2021 16:40:48 +0000 (UTC) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=redhat.com; s=mimecast20190719; t=1627058471; h=from:from:sender:sender:reply-to:subject:subject:date:date: message-id:message-id:to:to:cc:mime-version:mime-version: content-type:content-type: content-transfer-encoding:content-transfer-encoding: in-reply-to:in-reply-to:references:references:list-id:list-help: list-unsubscribe:list-subscribe:list-post; bh=qPCLjBhyUBUCL79Rz3JNBP+/DN15TZmV7JnyIuEdeX8=; b=EENi9IvZ4RJ17Afc6ZG8Ed6wpj0fth33ao7vmtISEwbvPBSy9Rr7ZasGT9fX8a1k8XYDo3 h5jgnltz6jzBKR6SAiWJfiAFzGjRJOfHSrrvoXw6eZUgyZwbh9onnkvLYb4566nX6G8VZL /8fYKjW/fyqhUptkM+o/Xl/hRDHtIL0= X-MC-Unique: BlTyeR1oNESI4wdapsaE8Q-1 From: Jonathon Jongsma To: libvir-list@redhat.com Subject: [libvirt PATCH 4/7] nodedev: Add parser validation for node devices Date: Fri, 23 Jul 2021 11:40:39 -0500 Message-Id: <20210723164042.1334799-5-jjongsma@redhat.com> In-Reply-To: <20210723164042.1334799-1-jjongsma@redhat.com> References: <20210723164042.1334799-1-jjongsma@redhat.com> MIME-Version: 1.0 X-Scanned-By: MIMEDefang 2.79 on 10.5.11.13 X-loop: libvir-list@redhat.com 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: , Sender: libvir-list-bounces@redhat.com Errors-To: libvir-list-bounces@redhat.com X-Scanned-By: MIMEDefang 2.79 on 10.5.11.14 Authentication-Results: relay.mimecast.com; auth=pass smtp.auth=CUSA124A263 smtp.mailfrom=libvir-list-bounces@redhat.com X-Mimecast-Spam-Score: 0 X-Mimecast-Originator: redhat.com Content-Transfer-Encoding: quoted-printable X-ZohoMail-DKIM: pass (identity @redhat.com) X-ZM-MESSAGEID: 1627058474093100002 Content-Type: text/plain; charset="utf-8" At the moment, this is only for mediated devices. When a new mediated device is created or defined, the xml is expected specify the nodedev name of an existing device as its parent. We were not previously validating this and were simply accepting any string here. Signed-off-by: Jonathon Jongsma --- src/conf/node_device_conf.c | 30 +++++++++--- src/conf/node_device_conf.h | 20 +++++++- src/conf/virnodedeviceobj.h | 1 + src/hypervisor/domain_driver.c | 7 +-- src/node_device/node_device_driver.c | 68 +++++++++++++++++++++++++++- src/node_device/node_device_driver.h | 3 ++ src/node_device/node_device_udev.c | 2 + src/test/test_driver.c | 6 ++- tests/nodedevmdevctltest.c | 7 ++- tests/nodedevxml2xmltest.c | 3 +- 10 files changed, 129 insertions(+), 18 deletions(-) diff --git a/src/conf/node_device_conf.c b/src/conf/node_device_conf.c index 332b12f997..cd1c07092d 100644 --- a/src/conf/node_device_conf.c +++ b/src/conf/node_device_conf.c @@ -2174,10 +2174,12 @@ static virNodeDeviceDef * virNodeDeviceDefParse(const char *str, const char *filename, int create, - const char *virt_type) + const char *virt_type, + virNodeDeviceDefParserCallbacks *parserCallbacks, + void *opaque) { xmlDocPtr xml; - virNodeDeviceDef *def =3D NULL; + g_autoptr(virNodeDeviceDef) def =3D NULL; =20 if ((xml =3D virXMLParse(filename, str, _("(node_device_definition)"))= )) { def =3D virNodeDeviceDefParseNode(xml, xmlDocGetRootElement(xml), @@ -2185,25 +2187,39 @@ virNodeDeviceDefParse(const char *str, xmlFreeDoc(xml); } =20 - return def; + if (parserCallbacks) { + int ret =3D 0; + /* validate definition */ + if (parserCallbacks->validate) { + ret =3D parserCallbacks->validate(def, opaque); + if (ret < 0) + return NULL; + } + } + + return g_steal_pointer(&def); } =20 =20 virNodeDeviceDef * virNodeDeviceDefParseString(const char *str, int create, - const char *virt_type) + const char *virt_type, + virNodeDeviceDefParserCallbacks *parserCallbac= ks, + void *opaque) { - return virNodeDeviceDefParse(str, NULL, create, virt_type); + return virNodeDeviceDefParse(str, NULL, create, virt_type, parserCallb= acks, opaque); } =20 =20 virNodeDeviceDef * virNodeDeviceDefParseFile(const char *filename, int create, - const char *virt_type) + const char *virt_type, + virNodeDeviceDefParserCallbacks *parserCallbacks, + void *opaque) { - return virNodeDeviceDefParse(NULL, filename, create, virt_type); + return virNodeDeviceDefParse(NULL, filename, create, virt_type, parser= Callbacks, opaque); } =20 =20 diff --git a/src/conf/node_device_conf.h b/src/conf/node_device_conf.h index 556878b9a8..786de85060 100644 --- a/src/conf/node_device_conf.h +++ b/src/conf/node_device_conf.h @@ -349,15 +349,31 @@ struct _virNodeDeviceDef { char * virNodeDeviceDefFormat(const virNodeDeviceDef *def); =20 + +typedef int (*virNodeDeviceDefPostParseCallback)(virNodeDeviceDef *dev, + void *opaque); + +typedef int (*virNodeDeviceDefValidateCallback)(virNodeDeviceDef *dev, + void *opaque); + +typedef struct _virNodeDeviceDefParserCallbacks { + virNodeDeviceDefPostParseCallback postParse; + virNodeDeviceDefValidateCallback validate; +} virNodeDeviceDefParserCallbacks; + virNodeDeviceDef * virNodeDeviceDefParseString(const char *str, int create, - const char *virt_type); + const char *virt_type, + virNodeDeviceDefParserCallbacks *callbacks, + void *opaque); =20 virNodeDeviceDef * virNodeDeviceDefParseFile(const char *filename, int create, - const char *virt_type); + const char *virt_type, + virNodeDeviceDefParserCallbacks *callbacks, + void *opaque); =20 virNodeDeviceDef * virNodeDeviceDefParseNode(xmlDocPtr xml, diff --git a/src/conf/virnodedeviceobj.h b/src/conf/virnodedeviceobj.h index 0cb78748a4..1fdd4f65da 100644 --- a/src/conf/virnodedeviceobj.h +++ b/src/conf/virnodedeviceobj.h @@ -47,6 +47,7 @@ struct _virNodeDeviceDriverState { =20 /* Immutable pointer, self-locking APIs */ virObjectEventState *nodeDeviceEventState; + virNodeDeviceDefParserCallbacks parserCallbacks; }; =20 void diff --git a/src/hypervisor/domain_driver.c b/src/hypervisor/domain_driver.c index 29e11c0447..2969d55173 100644 --- a/src/hypervisor/domain_driver.c +++ b/src/hypervisor/domain_driver.c @@ -395,7 +395,8 @@ virDomainDriverNodeDeviceReset(virNodeDevicePtr dev, if (!xml) return -1; =20 - def =3D virNodeDeviceDefParseString(xml, EXISTING_DEVICE, NULL); + def =3D virNodeDeviceDefParseString(xml, EXISTING_DEVICE, NULL, + NULL, NULL); if (!def) return -1; =20 @@ -440,7 +441,7 @@ virDomainDriverNodeDeviceReAttach(virNodeDevicePtr dev, if (!xml) return -1; =20 - def =3D virNodeDeviceDefParseString(xml, EXISTING_DEVICE, NULL); + def =3D virNodeDeviceDefParseString(xml, EXISTING_DEVICE, NULL, NULL, = NULL); if (!def) return -1; =20 @@ -488,7 +489,7 @@ virDomainDriverNodeDeviceDetachFlags(virNodeDevicePtr d= ev, if (!xml) return -1; =20 - def =3D virNodeDeviceDefParseString(xml, EXISTING_DEVICE, NULL); + def =3D virNodeDeviceDefParseString(xml, EXISTING_DEVICE, NULL, NULL, = NULL); if (!def) return -1; =20 diff --git a/src/node_device/node_device_driver.c b/src/node_device/node_de= vice_driver.c index ad2ca2a614..8f39d79c68 100644 --- a/src/node_device/node_device_driver.c +++ b/src/node_device/node_device_driver.c @@ -896,7 +896,8 @@ nodeDeviceCreateXML(virConnectPtr conn, =20 virt_type =3D virConnectGetType(conn); =20 - if (!(def =3D virNodeDeviceDefParseString(xmlDesc, CREATE_DEVICE, virt= _type))) + if (!(def =3D virNodeDeviceDefParseString(xmlDesc, CREATE_DEVICE, virt= _type, + &driver->parserCallbacks, NULL= ))) return NULL; =20 if (virNodeDeviceCreateXMLEnsureACL(conn, def) < 0) @@ -1376,7 +1377,8 @@ nodeDeviceDefineXML(virConnect *conn, =20 virt_type =3D virConnectGetType(conn); =20 - if (!(def =3D virNodeDeviceDefParseString(xmlDesc, CREATE_DEVICE, virt= _type))) + if (!(def =3D virNodeDeviceDefParseString(xmlDesc, CREATE_DEVICE, virt= _type, + &driver->parserCallbacks, NULL= ))) return NULL; =20 if (virNodeDeviceDefineXMLEnsureACL(conn, def) < 0) @@ -1761,3 +1763,65 @@ nodeDeviceDefCopyFromMdevctl(virNodeDeviceDef *dst, =20 return ret; } + + +/* validate that parent exists */ +static int nodeDeviceDefValidateMdev(virNodeDeviceDef *def, + G_GNUC_UNUSED virNodeDevCapMdev *mdev, + G_GNUC_UNUSED void *opaque) +{ + virNodeDeviceObj *obj =3D NULL; + if (!def->parent) { + virReportError(VIR_ERR_CONFIG_UNSUPPORTED, "%s", + _("missing parent device")); + return -1; + } + obj =3D virNodeDeviceObjListFindByName(driver->devs, def->parent); + if (!obj) { + virReportError(VIR_ERR_CONFIG_UNSUPPORTED, + _("invalid parent device '%s'"), + def->parent); + return -1; + } + + virNodeDeviceObjEndAPI(&obj); + return 0; +} + +int nodeDeviceDefValidate(virNodeDeviceDef *def, + G_GNUC_UNUSED void *opaque) +{ + virNodeDevCapsDef *caps =3D NULL; + for (caps =3D def->caps; caps !=3D NULL; caps =3D caps->next) { + switch (caps->data.type) { + case VIR_NODE_DEV_CAP_MDEV: + if (nodeDeviceDefValidateMdev(def, &caps->data.mdev, opaqu= e) < 0) + return -1; + break; + + case VIR_NODE_DEV_CAP_SYSTEM: + case VIR_NODE_DEV_CAP_PCI_DEV: + case VIR_NODE_DEV_CAP_USB_DEV: + case VIR_NODE_DEV_CAP_USB_INTERFACE: + case VIR_NODE_DEV_CAP_NET: + case VIR_NODE_DEV_CAP_SCSI_HOST: + case VIR_NODE_DEV_CAP_SCSI_TARGET: + case VIR_NODE_DEV_CAP_SCSI: + case VIR_NODE_DEV_CAP_STORAGE: + case VIR_NODE_DEV_CAP_FC_HOST: + case VIR_NODE_DEV_CAP_VPORTS: + case VIR_NODE_DEV_CAP_SCSI_GENERIC: + case VIR_NODE_DEV_CAP_DRM: + case VIR_NODE_DEV_CAP_MDEV_TYPES: + case VIR_NODE_DEV_CAP_CCW_DEV: + case VIR_NODE_DEV_CAP_CSS_DEV: + case VIR_NODE_DEV_CAP_VDPA: + case VIR_NODE_DEV_CAP_AP_CARD: + case VIR_NODE_DEV_CAP_AP_QUEUE: + case VIR_NODE_DEV_CAP_AP_MATRIX: + case VIR_NODE_DEV_CAP_LAST: + break; + } + } + return 0; +} diff --git a/src/node_device/node_device_driver.h b/src/node_device/node_de= vice_driver.h index edd763f0e4..d9b9b7a961 100644 --- a/src/node_device/node_device_driver.h +++ b/src/node_device/node_device_driver.h @@ -171,3 +171,6 @@ bool nodeDeviceDefCopyFromMdevctl(virNodeDeviceDef *dst, int nodeDeviceCreate(virNodeDevice *dev, unsigned int flags); + +int nodeDeviceDefValidate(virNodeDeviceDef *def, + void *opaque); diff --git a/src/node_device/node_device_udev.c b/src/node_device/node_devi= ce_udev.c index e7db74b325..ccf94d8e7d 100644 --- a/src/node_device/node_device_udev.c +++ b/src/node_device/node_device_udev.c @@ -2243,6 +2243,8 @@ nodeStateInitialize(bool privileged, driver->privateData =3D priv; driver->nodeDeviceEventState =3D virObjectEventStateNew(); =20 + driver->parserCallbacks.validate =3D nodeDeviceDefValidate; + if (udevPCITranslateInit(privileged) < 0) goto unlock; =20 diff --git a/src/test/test_driver.c b/src/test/test_driver.c index 892dc978f2..c2d642ff6b 100644 --- a/src/test/test_driver.c +++ b/src/test/test_driver.c @@ -7481,7 +7481,8 @@ testNodeDeviceMockCreateVport(testDriver *driver, if (!xml) goto cleanup; =20 - if (!(def =3D virNodeDeviceDefParseString(xml, EXISTING_DEVICE, NULL))) + if (!(def =3D virNodeDeviceDefParseString(xml, EXISTING_DEVICE, NULL, = NULL, + NULL))) goto cleanup; =20 VIR_FREE(def->name); @@ -7543,7 +7544,8 @@ testNodeDeviceCreateXML(virConnectPtr conn, =20 virCheckFlags(0, NULL); =20 - if (!(def =3D virNodeDeviceDefParseString(xmlDesc, CREATE_DEVICE, NULL= ))) + if (!(def =3D virNodeDeviceDefParseString(xmlDesc, CREATE_DEVICE, NULL, + NULL, NULL))) goto cleanup; =20 /* We run this simply for validation - it essentially validates that diff --git a/tests/nodedevmdevctltest.c b/tests/nodedevmdevctltest.c index 7af89ab5f1..bf1d7b4984 100644 --- a/tests/nodedevmdevctltest.c +++ b/tests/nodedevmdevctltest.c @@ -12,6 +12,10 @@ =20 #define VIRT_TYPE "QEMU" =20 +static virNodeDeviceDefParserCallbacks parser_callbacks =3D { + .validate =3D nodeDeviceDefValidate +}; + struct TestInfo { const char *filename; virMdevctlCommand command; @@ -66,7 +70,8 @@ testMdevctlCmd(virMdevctlCommand cmd_type, return -1; } =20 - if (!(def =3D virNodeDeviceDefParseFile(mdevxml, create, VIRT_TYPE))) + if (!(def =3D virNodeDeviceDefParseFile(mdevxml, create, VIRT_TYPE, + &parser_callbacks, NULL))) return -1; =20 /* this function will set a stdin buffer containing the json configura= tion diff --git a/tests/nodedevxml2xmltest.c b/tests/nodedevxml2xmltest.c index e9716726d7..d8f81456ee 100644 --- a/tests/nodedevxml2xmltest.c +++ b/tests/nodedevxml2xmltest.c @@ -25,7 +25,8 @@ testCompareXMLToXMLFiles(const char *xml, const char *out= file) if (virTestLoadFile(xml, &xmlData) < 0) goto fail; =20 - if (!(dev =3D virNodeDeviceDefParseString(xmlData, EXISTING_DEVICE, NU= LL))) + if (!(dev =3D virNodeDeviceDefParseString(xmlData, EXISTING_DEVICE, NU= LL, + NULL, NULL))) goto fail; =20 /* Calculate some things that are not read in */ --=20 2.31.1