From nobody Fri Nov 21 10:19:31 2025 Delivered-To: importer@patchew.org Received-SPF: pass (zohomail.com: domain of lists.libvirt.org designates 8.43.85.245 as permitted sender) client-ip=8.43.85.245; envelope-from=devel-bounces@lists.libvirt.org; helo=lists.libvirt.org; Authentication-Results: mx.zohomail.com; dkim=fail; spf=pass (zohomail.com: domain of lists.libvirt.org designates 8.43.85.245 as permitted sender) smtp.mailfrom=devel-bounces@lists.libvirt.org; dmarc=pass(p=reject dis=none) header.from=lists.libvirt.org ARC-Seal: i=1; a=rsa-sha256; t=1762515591; cv=none; d=zohomail.com; s=zohoarc; b=VMuGkcL3PczT5p/pvpEq2EWt2HoEnZQGto7IIRvWcqC3XyZO/bzDE+EM3uSeN+7ZVG43bpPtENTofQ2jQsnBMYzQ9IbJuB05wXHKQO06N9mK8ypYPhup2GgpxDJUp599EVJ9ijOJu+fCKnijb/HXrcW77HjY4LKPMPBCWo167OQ= ARC-Message-Signature: i=1; a=rsa-sha256; c=relaxed/relaxed; d=zohomail.com; s=zohoarc; t=1762515591; h=Content-Type:Content-Transfer-Encoding:Cc:Cc:Date:Date:From:From:In-Reply-To:List-Subscribe:List-Post:List-Owner:List-Id:List-Archive:List-Help:List-Unsubscribe:MIME-Version:Message-ID:Reply-To:Reply-To:References:Subject:Subject:To:To:Message-Id; bh=bn6EVZ3lIo6bccowcI1ikXcKOK37Jse1uEUf8Jdwmxk=; b=WF9m+fDQbHLtZ8U+Bu9BYNenKcBGLRVpm76J09EritbyzXjiZzepfYVxD2h21rAC6/eIu26JLWqdcvGeS1XJc4sVTBhj9ayZph4BoY29CKABEksqq8tEYxzQ/ufekL5QVxO6x1Cmknw+5hiG4nOAGnOYyM6oYJn8ySHVf2iVgZk= ARC-Authentication-Results: i=1; mx.zohomail.com; dkim=fail; spf=pass (zohomail.com: domain of lists.libvirt.org designates 8.43.85.245 as permitted sender) smtp.mailfrom=devel-bounces@lists.libvirt.org; dmarc=pass header.from= (p=reject dis=none) Return-Path: Received: from lists.libvirt.org (lists.libvirt.org [8.43.85.245]) by mx.zohomail.com with SMTPS id 1762515591348425.78734774201826; Fri, 7 Nov 2025 03:39:51 -0800 (PST) Received: by lists.libvirt.org (Postfix, from userid 993) id 414BE44561; Fri, 7 Nov 2025 06:39:33 -0500 (EST) Received: from [172.19.199.29] (lists.libvirt.org [8.43.85.245]) by lists.libvirt.org (Postfix) with ESMTP id 2D7BC44B0B; Fri, 7 Nov 2025 06:30:03 -0500 (EST) Received: by lists.libvirt.org (Postfix, from userid 993) id 01B4C44884; Fri, 7 Nov 2025 06:29:52 -0500 (EST) Received: from us-smtp-delivery-124.mimecast.com (us-smtp-delivery-124.mimecast.com [170.10.129.124]) (using TLSv1.3 with cipher TLS_AES_256_GCM_SHA384 (256/256 bits) key-exchange X25519 server-signature RSA-PSS (3072 bits) server-digest SHA256) (No client certificate requested) by lists.libvirt.org (Postfix) with ESMTPS id 9451241AAA for ; Fri, 7 Nov 2025 06:26:47 -0500 (EST) Received: from mail-wm1-f71.google.com (mail-wm1-f71.google.com [209.85.128.71]) by relay.mimecast.com with ESMTP with STARTTLS (version=TLSv1.3, cipher=TLS_AES_256_GCM_SHA384) id us-mta-163-0LVioufnNs-tiVn2cArbMA-1; Fri, 07 Nov 2025 06:26:46 -0500 Received: by mail-wm1-f71.google.com with SMTP id 5b1f17b1804b1-477171bbf51so4379935e9.3 for ; Fri, 07 Nov 2025 03:26:45 -0800 (PST) Received: from wheatley.localdomain ([85.93.96.130]) by smtp.gmail.com with ESMTPSA id 5b1f17b1804b1-47763dc2b8asm43154045e9.2.2025.11.07.03.26.43 (version=TLS1_3 cipher=TLS_AES_256_GCM_SHA384 bits=256/256); Fri, 07 Nov 2025 03:26:43 -0800 (PST) Received: from wheatley.pinto-pinecone.ts.net (wheatley.k8r.cz [127.0.0.1]) by wheatley.localdomain (Postfix) with ESMTP id 367B3E161B5B; Fri, 07 Nov 2025 12:26:42 +0100 (CET) X-Spam-Checker-Version: SpamAssassin 4.0.1 (2024-03-26) on lists.libvirt.org X-Spam-Level: X-Spam-Status: No, score=-5.0 required=5.0 tests=BAYES_00,DKIM_INVALID, DKIM_SIGNED,MAILING_LIST_MULTI,RCVD_IN_DNSWL_MED, RCVD_IN_VALIDITY_CERTIFIED_BLOCKED,RCVD_IN_VALIDITY_RPBL_BLOCKED, RCVD_IN_VALIDITY_SAFE_BLOCKED,SPF_PASS autolearn=unavailable autolearn_force=no version=4.0.1 DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=redhat.com; s=mimecast20190719; t=1762514807; h=from:from:reply-to:subject:subject:date:date:message-id:message-id: to:to:cc:cc:mime-version:mime-version:content-type:content-type: content-transfer-encoding:content-transfer-encoding: in-reply-to:in-reply-to:references:references; bh=bn6EVZ3lIo6bccowcI1ikXcKOK37Jse1uEUf8Jdwmxk=; b=VJ1wbPbv5d+SlstjCAzYlz/S7kwln0q9swke1d+uyQpv2KQ20RNKWyQ4brSIVym2WaLb/c ItlaD+DarUgGEIv2xDm3EHewYx1/BwnexqZQOabrHOSCUQiRZ5OdAGtI0SBHmWjf0ZbPzH nDi5EOgIp7SJVmga1nWsNvQxFbM/EeA= X-MC-Unique: 0LVioufnNs-tiVn2cArbMA-1 X-Mimecast-MFC-AGG-ID: 0LVioufnNs-tiVn2cArbMA_1762514805 X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20230601; t=1762514805; x=1763119605; h=content-transfer-encoding:mime-version:references:in-reply-to :message-id:date:subject:cc:to:from:x-gm-gg:x-gm-message-state:from :to:cc:subject:date:message-id:reply-to; bh=bn6EVZ3lIo6bccowcI1ikXcKOK37Jse1uEUf8Jdwmxk=; b=C4ebiFqIpSd/20dfp08IledRysRddE8s/Hi8gcFupHR3vkbQdtBFbFHjADP37+IpFT cn+zcA71qpM5qY/TgmzTuABURyhoxeChWlLJqiJi1ztDeoaK7ogbVzYiyE6O/z7AmyNs JHdkhZHUs0HEk5YAbE+p0sn6n9zGf+UxFKJ68rxRre9gQqwjVo70XKP6RmMJKVTIsc7h EqAvJwbDX5VpvBI3cMWEiCIMUOCJFoCFRSR7Iub//CDGbo0P3xUQTNXWmP5zAcDpGVRp 9QueeCqZ9xuf5H4g1BZL3PZD/79LThefFwWPcmMqjTbgzsSqsxtcIxysocwPmSRZLWVl cWgg== X-Gm-Message-State: AOJu0YyOSvHa/+2g212GJf+m4NYW+MOpnKM/JFXvtBF2abp+zGe/v/3h NfeLVwQ051WyrHt4RM2qwXD+NZCzekiljt50uOYIguC6gzp3eE5mrbaBUjVD7FgATU9KyAP4Jhj 4RgmZkH8N2WGp+6s+bBoQSuQrETMwVmcPVWxjTUZ9JnC+h1u7nRIc381vx8s= X-Gm-Gg: ASbGncuP5HvdXYJe3HXMVoKp8uiAwzJ9pRDTNRIBqakqy0pUGi78i+skfhaPlhI55FX Bl2DLT0KY8960qDL8i6Jd1tkW/GM/iRmEL19+jsDe5we50OLZ4zQDlbhsucgWtkG6pU37heIb40 RuiGr0ubKmZkEpagmbaCvGZqbbyxAYZMCChY6laqBZPD0GKsjQlT5CmvLhEV9r/0Vqq5oj2sSOr Hr1GfLgLxQAwrYupadGpOnw47lRRPH3h7VX9O471/vQaBxF1R7oQG3Z1cf9FLLLGpNmTlxzjFnh NXSDztJl40I55vUVvPjnpkCjRt7FSBQUbQm9rQhMDlzYB2DPVgEG94/sFrGP5M1RIa/bram495A 0t5d0o6CX X-Received: by 2002:a05:600c:8b5b:b0:477:10c4:b4e with SMTP id 5b1f17b1804b1-4776bcdb6eemr21914425e9.41.1762514804909; Fri, 07 Nov 2025 03:26:44 -0800 (PST) X-Google-Smtp-Source: AGHT+IGBkO5mVLNjCUPXUhXEzUxef7Rehh6IoVVw4rbhFsvI0qdFxvB6b6t5DHIsZ2hJ5U9DG+raxQ== X-Received: by 2002:a05:600c:8b5b:b0:477:10c4:b4e with SMTP id 5b1f17b1804b1-4776bcdb6eemr21914215e9.41.1762514804488; Fri, 07 Nov 2025 03:26:44 -0800 (PST) To: devel@lists.libvirt.org Subject: [PATCH 6/7] ch: Check ACLs before parsing the whole domain XML Date: Fri, 7 Nov 2025 12:26:34 +0100 Message-ID: X-Mailer: git-send-email 2.51.2 In-Reply-To: References: MIME-Version: 1.0 X-Mimecast-Spam-Score: 0 X-Mimecast-MFC-PROC-ID: G9rE5deTqQZVAi117GM8h1Tm6IV5tYWUmus7Id248pc_1762514805 X-Mimecast-Originator: redhat.com Content-Type: text/plain; charset="utf-8" Content-Transfer-Encoding: quoted-printable Message-ID-Hash: 3ZE3RXFIIKMSTEFCYIE6JVDUH6OY5SSP X-Message-ID-Hash: 3ZE3RXFIIKMSTEFCYIE6JVDUH6OY5SSP X-MailFrom: mkletzan@redhat.com X-Mailman-Rule-Misses: dmarc-mitigation; no-senders; approved; loop; banned-address; header-match-devel.lists.libvirt.org-0; emergency; member-moderation; nonmember-moderation; administrivia; implicit-dest; max-recipients; max-size; news-moderation; no-subject; digests; suspicious-header CC: =?UTF-8?q?=D0=A1=D0=B2=D1=8F=D1=82=D0=BE=D1=81=D0=BB=D0=B0=D0=B2=20=D0=A2=D0=B5=D1=80=D0=B5=D1=88=D0=B8=D0=BD?= X-Mailman-Version: 3.3.10 Precedence: list List-Id: Development discussions about the libvirt library & tools Archived-At: List-Archive: List-Help: List-Owner: List-Post: List-Subscribe: List-Unsubscribe: From: Martin Kletzander via Devel Reply-To: Martin Kletzander X-ZohoMail-DKIM: fail (Header signature does not verify) X-ZM-MESSAGEID: 1762515593350158500 From: Martin Kletzander Utilise the new virDomainDefIDsParseString() for that. This is one of the more complex ones since there is also a function that reads relevant metadata from a save image XML. In order not to extract the parsing out of the function (and make the function basically trivial and all callers more complex) add a callback to the function which will be used to check the ACLs. And since this function is called in APIs that perform ACL checks both with and without flags, add two of them for good measure. Fixes: CVE-2025-12748 Reported-by: =D0=A1=D0=B2=D1=8F=D1=82=D0=BE=D1=81=D0=BB=D0=B0=D0=B2 =D0=A2= =D0=B5=D1=80=D0=B5=D1=88=D0=B8=D0=BD Signed-off-by: Martin Kletzander --- src/ch/ch_driver.c | 76 ++++++++++++++++++++++++++++++++-------------- 1 file changed, 53 insertions(+), 23 deletions(-) diff --git a/src/ch/ch_driver.c b/src/ch/ch_driver.c index ad13306c4cfd..70653aeea7d3 100644 --- a/src/ch/ch_driver.c +++ b/src/ch/ch_driver.c @@ -216,14 +216,19 @@ chDomainCreateXML(virConnectPtr conn, if (flags & VIR_DOMAIN_START_VALIDATE) parse_flags |=3D VIR_DOMAIN_DEF_PARSE_VALIDATE_SCHEMA; =20 + /* Avoid parsing the whole domain definition for ACL checks */ + if (!(vmdef =3D virDomainDefIDsParseString(xml, driver->xmlopt, parse_= flags))) + return NULL; + + if (virDomainCreateXMLEnsureACL(conn, vmdef) < 0) + return NULL; + + g_clear_pointer(&vmdef, virObjectUnref); =20 if ((vmdef =3D virDomainDefParseString(xml, driver->xmlopt, NULL, parse_flags)) =3D=3D NULL) goto cleanup; =20 - if (virDomainCreateXMLEnsureACL(conn, vmdef) < 0) - goto cleanup; - if (!(vm =3D virDomainObjListAdd(driver->domains, &vmdef, driver->xmlopt, @@ -347,6 +352,15 @@ chDomainDefineXMLFlags(virConnectPtr conn, const char = *xml, unsigned int flags) if (flags & VIR_DOMAIN_START_VALIDATE) parse_flags |=3D VIR_DOMAIN_DEF_PARSE_VALIDATE_SCHEMA; =20 + /* Avoid parsing the whole domain definition for ACL checks */ + if (!(vmdef =3D virDomainDefIDsParseString(xml, driver->xmlopt, parse_= flags))) + return NULL; + + if (virDomainDefineXMLFlagsEnsureACL(conn, vmdef) < 0) + return NULL; + + g_clear_pointer(&vmdef, virObjectUnref); + if ((vmdef =3D virDomainDefParseString(xml, driver->xmlopt, NULL, parse_flags)) =3D=3D NULL) goto cleanup; @@ -354,9 +368,6 @@ chDomainDefineXMLFlags(virConnectPtr conn, const char *= xml, unsigned int flags) if (virXMLCheckIllegalChars("name", vmdef->name, "\n") < 0) goto cleanup; =20 - if (virDomainDefineXMLFlagsEnsureACL(conn, vmdef) < 0) - goto cleanup; - if (!(vm =3D virDomainObjListAdd(driver->domains, &vmdef, driver->xmlopt, 0, &oldDef))) @@ -920,16 +931,24 @@ chDomainSaveXMLRead(int fd) return g_steal_pointer(&xml); } =20 -static int chDomainSaveImageRead(virCHDriver *driver, +static int chDomainSaveImageRead(virConnectPtr conn, const char *path, - virDomainDef **ret_def) + virDomainDef **ret_def, + unsigned int flags, + int (*ensureACL)(virConnectPtr, virDomain= Def *), + int (*ensureACLWithFlags)(virConnectPtr, + virDomainDef *, + unsigned int)) { + virCHDriver *driver =3D conn->privateData; g_autoptr(virCHDriverConfig) cfg =3D virCHDriverGetConfig(driver); g_autoptr(virDomainDef) def =3D NULL; g_autofree char *from =3D NULL; g_autofree char *xml =3D NULL; VIR_AUTOCLOSE fd =3D -1; int ret =3D -1; + unsigned int parse_flags =3D VIR_DOMAIN_DEF_PARSE_INACTIVE | + VIR_DOMAIN_DEF_PARSE_SKIP_VALIDATE; =20 from =3D g_strdup_printf("%s/%s", path, CH_SAVE_XML); if ((fd =3D virFileOpenAs(from, O_RDONLY, 0, cfg->user, cfg->group, 0)= ) < 0) { @@ -942,9 +961,23 @@ static int chDomainSaveImageRead(virCHDriver *driver, if (!(xml =3D chDomainSaveXMLRead(fd))) goto end; =20 - if (!(def =3D virDomainDefParseString(xml, driver->xmlopt, NULL, - VIR_DOMAIN_DEF_PARSE_INACTIVE | - VIR_DOMAIN_DEF_PARSE_SKIP_VALIDATE= ))) + if (ensureACL || ensureACLWithFlags) { + /* Parse only the IDs for ACL checks */ + g_autoptr(virDomainDef) aclDef =3D virDomainDefIDsParseString(xml, + driver= ->xmlopt, + parse_= flags); + + if (!aclDef) + goto end; + + if (ensureACL && ensureACL(conn, aclDef) < 0) + goto end; + + if (ensureACLWithFlags && ensureACLWithFlags(conn, aclDef, flags) = < 0) + goto end; + } + + if (!(def =3D virDomainDefParseString(xml, driver->xmlopt, NULL, parse= _flags))) goto end; =20 *ret_def =3D g_steal_pointer(&def); @@ -965,10 +998,9 @@ chDomainSaveImageGetXMLDesc(virConnectPtr conn, =20 virCheckFlags(VIR_DOMAIN_SAVE_IMAGE_XML_SECURE, NULL); =20 - if (chDomainSaveImageRead(driver, path, &def) < 0) - goto cleanup; - - if (virDomainSaveImageGetXMLDescEnsureACL(conn, def) < 0) + if (chDomainSaveImageRead(conn, path, &def, flags, + virDomainSaveImageGetXMLDescEnsureACL, + NULL) < 0) goto cleanup; =20 ret =3D virDomainDefFormat(def, driver->xmlopt, @@ -1068,10 +1100,9 @@ chDomainManagedSaveGetXMLDesc(virDomainPtr dom, unsi= gned int flags) goto cleanup; =20 path =3D chDomainManagedSavePath(driver, vm); - if (chDomainSaveImageRead(driver, path, &def) < 0) - goto cleanup; - - if (virDomainManagedSaveGetXMLDescEnsureACL(dom->conn, def, flags) < 0) + if (chDomainSaveImageRead(dom->conn, path, &def, flags, + NULL, + virDomainManagedSaveGetXMLDescEnsureACL) < 0) goto cleanup; =20 ret =3D virDomainDefFormat(def, driver->xmlopt, @@ -1123,10 +1154,9 @@ chDomainRestoreFlags(virConnectPtr conn, return -1; } =20 - if (chDomainSaveImageRead(driver, from, &def) < 0) - goto cleanup; - - if (virDomainRestoreFlagsEnsureACL(conn, def) < 0) + if (chDomainSaveImageRead(conn, from, &def, flags, + virDomainRestoreFlagsEnsureACL, + NULL) < 0) goto cleanup; =20 if (chDomainSaveRestoreAdditionalValidation(driver, def) < 0) --=20 2.51.2