From nobody Mon Feb 2 09:27:43 2026 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; 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=1767645979; cv=none; d=zohomail.com; s=zohoarc; b=GVpwv6sLWY/Rz5qenLNg/ALNU6D60MB4iAlCkprRQajD3EyGgRf7iHajH6IuKsOQ1Hb+umgvh0yiYlmpliq03lM6NWVZsa38L/aLMHrfah/oDutXUd8TZ0oCsqcDz13bEwnp+Sz/9aQ4knqNc3hXJ8TY9lLhPUFyIC/X7DST0So= ARC-Message-Signature: i=1; a=rsa-sha256; c=relaxed/relaxed; d=zohomail.com; s=zohoarc; t=1767645979; 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=qd2feiETYGSmELbxNS0ZwB2ccSr1fDwct/4WrLDuphQ=; b=Ty6I1qcnQZ39typS48IISiMcoEhr4GMsqx/kitUHD2KPwAtot/VOgVk22S44LjmxefRQqcvbJYPTia9xbTm87K0M1MV6Sp+RozfLnbgl2pWtfa6/tq4NHMGwR2u7g/y0rtoEoQbMcMpF6Yg4IhhPevuUQo0zPkJVcBSNaBf7KRc= 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 176764597980862.76732230127686; Mon, 5 Jan 2026 12:46:19 -0800 (PST) Received: by lists.libvirt.org (Postfix, from userid 993) id E13883F390; Mon, 5 Jan 2026 15:46:18 -0500 (EST) Received: from [172.19.199.83] (lists.libvirt.org [8.43.85.245]) by lists.libvirt.org (Postfix) with ESMTP id 7BE0641B53; Mon, 5 Jan 2026 15:44:13 -0500 (EST) Received: by lists.libvirt.org (Postfix, from userid 993) id 753E041933; Mon, 5 Jan 2026 15:35:03 -0500 (EST) Received: from smtp-relay-internal-1.canonical.com (smtp-relay-internal-1.canonical.com [185.125.188.123]) (using TLSv1.3 with cipher TLS_AES_256_GCM_SHA384 (256/256 bits) key-exchange X25519 server-signature RSA-PSS (3072 bits)) (No client certificate requested) by lists.libvirt.org (Postfix) with ESMTPS id 3F5ED4192F for ; Mon, 5 Jan 2026 15:34:58 -0500 (EST) Received: from mail-yx1-f71.google.com (mail-yx1-f71.google.com [74.125.224.71]) (using TLSv1.3 with cipher TLS_AES_256_GCM_SHA384 (256/256 bits) key-exchange X25519 server-signature RSA-PSS (2048 bits) server-digest SHA256) (No client certificate requested) by smtp-relay-internal-1.canonical.com (Postfix) with ESMTPS id 541603F856 for ; Mon, 5 Jan 2026 20:28:45 +0000 (UTC) Received: by mail-yx1-f71.google.com with SMTP id 956f58d0204a3-6447a801fbaso456636d50.2 for ; Mon, 05 Jan 2026 12:28:45 -0800 (PST) Received: from r.lxd ([147.219.77.79]) by smtp.gmail.com with ESMTPSA id 00721157ae682-790aa57deacsm65117b3.20.2026.01.05.12.28.43 (version=TLS1_3 cipher=TLS_AES_256_GCM_SHA384 bits=256/256); Mon, 05 Jan 2026 12:28:43 -0800 (PST) X-Spam-Checker-Version: SpamAssassin 4.0.1 (2024-03-26) on lists.libvirt.org X-Spam-Level: X-Spam-Status: No, score=-3.7 required=5.0 tests=BAYES_00,DKIM_INVALID, DKIM_SIGNED,MAILING_LIST_MULTI,RCVD_IN_BL_SPAMCOP_NET, 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=canonical.com; s=20251003; t=1767644925; bh=qd2feiETYGSmELbxNS0ZwB2ccSr1fDwct/4WrLDuphQ=; h=From:Date:Subject:MIME-Version:Content-Type:Message-Id:References: In-Reply-To:To:Cc; b=tRZ+Ube+wTWviGpCnI6U0ydBqKyQMuKx92UTukDptxubtiy3gVuxyifcIQU45AI0O BV6yeEs/1BwHwwTFkdfbCUHGavmKtbSkqpeuMFWS2V9ZwMBAgoB/C/fT7UuILbP6P6 IsokHxwrh2DTcXNQJGWVO2dBgEvg5ReDewuMWBFrFyQJ6bk40UC8yFLf9N2qwimhxs Y6QWT82jYHLRlvHFUnOPqwKWPwiQD+uTQv61NVQqgYxxOzlS6usZJk4rcTc40jJ1AX uEXQo0nK0gTZ3oCXl+mUQqkno7F0dXMa5+gBxrBpxcTehUNpS9PlT5VmSxQMCeUhx3 CQgLtGgL9KDBCN3R81tYNAk0CCEAvOF3zCg+qRKcf8cs8txamvT1abPYudhvEFoa3B j5M2an8+0XRkXPYnwpxp84HcvBEZfde4CczxEGJRKM6nlVHequNJSdJ9hhXWk8rkDY blw7myu7ZzXa8mWu80rq7m7iyA8mRdqqTuBOFeuS6QdjdHLbxIGcE8pu35FIgEgTF/ RpOQls2nacxvhX5IT13wtTeqEhHG3aL+3MIwIJlwss4pWnqJ3kF0k0D9eVx6h1QWfK nDto6HkLd0fQzK6AKCJlWHP9U2DRrVx90lHdp6OfbyRPy+Akyii+rbD0ODv+n0A4zr 16jD4Hq5VO55ItMxi2Phpack= X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20230601; t=1767644924; x=1768249724; h=cc:to:in-reply-to:references:message-id:content-transfer-encoding :mime-version:subject:date:from:x-gm-gg:x-gm-message-state:from:to :cc:subject:date:message-id:reply-to; bh=qd2feiETYGSmELbxNS0ZwB2ccSr1fDwct/4WrLDuphQ=; b=IrMJZI+BN+ah0ixSyk7ebVMwgFDM3yufifbS5ik1qcXUImgCrAiM7ZWb2mBzNdu5Wa ZdVunbnEZH5LpnY7EuJSrv06W2E4Fk8CGzPZ85HShbEjVnF7sc+/9xK949yCwMhvNBco itWEU2uVh1+1UCeTH1cT2JF+4Ab57+XkPD/XaF9brq3FDjOrEfDLyHcXPaFlXLg9pd9O mJRDb/dZzeA22rj9Ga0rv2mQ2fCzptu+y+0fz7mZHoXr1BqQVneVB4vDEP3nkfIuhUi+ zMzYg/MfxXmuLAOifsJtXyHN/QX/2wJE1THN4RwBl8w/ry/TRhcrN1nRB7O+Ej/Lm6ZE sCiw== X-Gm-Message-State: AOJu0YxvRFISPf7d7/zGHz/1Ux8BgsyMveBd6L2uztJy4amnRw058bMv Iyd/YM4hg0GyY+bsTNNVy5pmks1bqS8YPaYCNSy/UX4yk8mAh8wCef/L8Sb0pukKoCMAA7Oskj4 wbl1317noWhkx4Ax9NsyL9xyLoQP5nM5AoWvCBdiL70XU7VlaqWRY7Jd7ox4TpdWMolKLaHivvb A= X-Gm-Gg: AY/fxX6vhlCxTBP6bi6IpM01GMUHPg5EZfeMpdTl+8d+8ZaVmtY4XmQO9bI3T2eB6oc HDDrB/MyfzZ2X/+z6/jGNMeZTqZn/nqbhUrXuWwzFrOlh9WdBHi1DM5DWSSAqS4C8o9uIY+0YbP VSRLU2TIEWxx8NPOpXCFdpcWpsmE1mb7eRDQbjIwxFtlyRJPmYFum7hOweXoE+sBAeRnYmtU+W6 IT6URGtVL5KeFjFfFnlrR8XBlZytr0K8t0wavcXosBvWPAIDkMyOM0o/79lolIn7djIXYlLCmzn fFg6s/MjKqX8Cn3I4smvUqXzpckHKlj2hJt+o6SbDpqqnEK4p+9q9/7etkuL/DWy597ef5PUYV5 mT5EHYXyb7mwQDgRU X-Received: by 2002:a05:690e:1503:b0:646:90aa:bc3d with SMTP id 956f58d0204a3-6470c868276mr689627d50.31.1767644924273; Mon, 05 Jan 2026 12:28:44 -0800 (PST) X-Google-Smtp-Source: AGHT+IHAg3qsWd4SugAvseUChZF8nDOlEveqgBUR7vt4Zw1g1eoUwgYCqvyL63tIf/qvGI53S5Eahg== X-Received: by 2002:a05:690e:1503:b0:646:90aa:bc3d with SMTP id 956f58d0204a3-6470c868276mr689605d50.31.1767644923856; Mon, 05 Jan 2026 12:28:43 -0800 (PST) Date: Mon, 05 Jan 2026 14:27:23 -0600 Subject: [PATCH 3/3] qemu: Store blockcommit permissions in domstatus XML MIME-Version: 1.0 Content-Type: text/plain; charset="utf-8" Content-Transfer-Encoding: quoted-printable Message-Id: <20260105-apparmor-races-v1-3-932cf0e990b7@canonical.com> References: <20260105-apparmor-races-v1-0-932cf0e990b7@canonical.com> In-Reply-To: <20260105-apparmor-races-v1-0-932cf0e990b7@canonical.com> To: devel@lists.libvirt.org X-Mailer: b4 0.14.3 X-Developer-Signature: v=1; a=openpgp-sha256; l=8267; i=wesley.hershberger@canonical.com; h=from:subject:message-id; bh=ear3/rli5we/eENa9L1JP2NzXJd696GBj5T+KPUTBSI=; b=owEB7QES/pANAwAKAfkogKziOh25AcsmYgBpXB73qAvWWV8/BUjF7y8pCZbvGN2XKWQMdoxMm qb/nW7t6t2JAbMEAAEKAB0WIQQsIHxFLwpehxEbQ8r5KICs4joduQUCaVwe9wAKCRD5KICs4jod uT0dC/44Zycmp+BlDPlc5TF/ENni1EXu4aB75SA0CUZlhcjDmLXJAA2ExChcVc2RC1BazpBAmqw zZosvo3H+17rdmZNOQgkRq4BBFRyQqaYfkyZMPH0HCLon+R/P8M4mngPc/ke2ulEA9200l0vuqs B92Zjt1sUnJmHX5+mVFtpfKi2SPqSFCTS/NcLLBlpmuA54FpTM9jAdhPMFM7U0gcIe98RzWQfAh WJiGakFHRccea4g3Q258orAGtnaJgzmV0Q6Muk2WksejkXvVPy+p92sHZZ9vZ5NDupFzG2D1ilR J3Gn34P7y0UwvTfL8PTqj/ajmCRe1QbyH2M0SOKAo1BhxpHBQVp8AWc87LgzllegVjPN8kCJRHt p0sGuWmfnaRTN4+JOE18evUTijVcIyU8TCFz3624ov0//oafdwH4V4hmBtpiQ+8M+3hBIBS2FSX Db4klL1jV8Tsyx4Z7GsQr6SiZB97ZZXPxDCVDT/hLFLXN/w4vkSkhjGg+rhu2wadx6Bwg= X-Developer-Key: i=wesley.hershberger@canonical.com; a=openpgp; fpr=2C207C452F0A5E87111B43CAF92880ACE23A1DB9 Message-ID-Hash: XZJLPDAFBV62FKNBMA2SCTRTXKP5LTQ6 X-Message-ID-Hash: XZJLPDAFBV62FKNBMA2SCTRTXKP5LTQ6 X-MailFrom: wesley.hershberger@canonical.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: wesley.hershberger@canonical.com, georgia.garcia@canonical.com, hector.cao@canonical.com 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: Wesley Hershberger via Devel Reply-To: Wesley Hershberger X-ZohoMail-DKIM: fail (Header signature does not verify) X-ZM-MESSAGEID: 1767645981782158500 Adds a read-only attribute allowWrite to a disk's backingStore source element for the duration of a block commit operation, which records that write access is needed for that backingStore. This is used by the AppArmor security driver when re-generating profiles. Partial-Resolves: #692 Bug-Ubuntu: https://bugs.launchpad.net/bugs/2126574 Signed-off-by: Wesley Hershberger --- src/conf/domain_conf.c | 7 +++++++ src/conf/storage_source_conf.c | 2 ++ src/conf/storage_source_conf.h | 3 +++ src/qemu/qemu_block.c | 26 ++++++++++++++++++++++++++ src/qemu/qemu_blockjob.c | 8 ++++++++ src/qemu/qemu_security.c | 7 +++++++ src/security/virt-aa-helper.c | 7 ++----- 7 files changed, 55 insertions(+), 5 deletions(-) diff --git a/src/conf/domain_conf.c b/src/conf/domain_conf.c index bfeed3dc96..02ff45626e 100644 --- a/src/conf/domain_conf.c +++ b/src/conf/domain_conf.c @@ -7842,6 +7842,10 @@ virDomainStorageSourceParse(xmlNodePtr node, return -1; } =20 + if (!(flags & VIR_DOMAIN_DEF_PARSE_INACTIVE) && + g_strcmp0(virXMLPropString(node, "allowWrite"), "yes") =3D=3D 0) + src->secAllowWrite =3D true; + if ((tmp =3D virXPathNode("./auth", ctxt)) && !(src->auth =3D virStorageAuthDefParse(tmp, ctxt))) return -1; @@ -23753,6 +23757,9 @@ virDomainDiskSourceFormat(virBuffer *buf, if (attrIndex && src->id !=3D 0) virBufferAsprintf(&attrBuf, " index=3D'%u'", src->id); =20 + if ((flags & VIR_DOMAIN_DEF_FORMAT_STATUS) && src->secAllowWrite) + virBufferAddLit(&attrBuf, " allowWrite=3D'yes'"); + if (virDomainDiskDataStoreFormat(&childBuf, src, xmlopt, flags) < 0) return -1; =20 diff --git a/src/conf/storage_source_conf.c b/src/conf/storage_source_conf.c index 087de1eaf2..4550a25500 100644 --- a/src/conf/storage_source_conf.c +++ b/src/conf/storage_source_conf.c @@ -911,6 +911,8 @@ virStorageSourceCopy(const virStorageSource *src, def->nfs_uid =3D src->nfs_uid; def->nfs_gid =3D src->nfs_gid; =20 + def->secAllowWrite =3D src->secAllowWrite; + /* 'ioerror_timestamp' and 'ioerror_message' are deliberately not copi= ed */ =20 return g_steal_pointer(&def); diff --git a/src/conf/storage_source_conf.h b/src/conf/storage_source_conf.h index fc868b31af..0a54ff8c9c 100644 --- a/src/conf/storage_source_conf.h +++ b/src/conf/storage_source_conf.h @@ -449,6 +449,9 @@ struct _virStorageSource { * to do this decision. */ bool seclabelSkipRemember; + /* Temporary write access to this source is required (currently only f= or + * QEMU blockcommit) */ + bool secAllowWrite; =20 /* Last instance of hypervisor originated I/O error message and timest= amp. * The error stored here is not designed to be stable. The message diff --git a/src/qemu/qemu_block.c b/src/qemu/qemu_block.c index a7062d3e96..3aed5d5a7f 100644 --- a/src/qemu/qemu_block.c +++ b/src/qemu/qemu_block.c @@ -3763,6 +3763,20 @@ qemuBlockCommit(virDomainObj *vm, * operation succeeds, but doing that requires tracking the * operation in XML across libvirtd restarts. */ clean_access =3D true; + + /* Ensure needed perms are present in domstatus XML; this prevents rac= es + * in the AppArmor secdriver */ + baseSource->secAllowWrite =3D true; + if (baseSource->dataFileStore) + baseSource->dataFileStore->secAllowWrite =3D true; + if (top_parent && top_parent !=3D disk->src) { + top_parent->secAllowWrite =3D true; + if (top_parent->dataFileStore) + top_parent->dataFileStore->secAllowWrite =3D true; + } + + qemuDomainSaveStatus(vm); + if (qemuDomainStorageSourceAccessAllow(driver, vm, baseSource, false, false, false) < 0) goto cleanup; @@ -3838,6 +3852,18 @@ qemuBlockCommit(virDomainObj *vm, virErrorPtr orig_err; virErrorPreserveLast(&orig_err); =20 + /* Revert changes to domstatus XML */ + baseSource->secAllowWrite =3D false; + if (baseSource->dataFileStore) + baseSource->dataFileStore->secAllowWrite =3D false; + if (top_parent && top_parent !=3D disk->src) { + top_parent->secAllowWrite =3D false; + if (top_parent->dataFileStore) + top_parent->dataFileStore->secAllowWrite =3D false; + } + + qemuDomainSaveStatus(vm); + /* Revert access to read-only, if possible. */ if (baseSource->dataFileStore) { qemuDomainStorageSourceAccessAllow(driver, vm, baseSource->dat= aFileStore, diff --git a/src/qemu/qemu_blockjob.c b/src/qemu/qemu_blockjob.c index b54a5b3811..97a6afe7e3 100644 --- a/src/qemu/qemu_blockjob.c +++ b/src/qemu/qemu_blockjob.c @@ -1065,20 +1065,24 @@ qemuBlockJobProcessEventCompletedCommit(virQEMUDriv= er *driver, =20 /* revert access to images */ if (job->data.commit.base->dataFileStore) { + job->data.commit.base->dataFileStore->secAllowWrite =3D false; qemuDomainStorageSourceAccessAllow(driver, vm, job->data.commit.ba= se->dataFileStore, true, false, false); qemuBlockReopenReadOnly(vm, job->data.commit.base->dataFileStore, = asyncJob); } + job->data.commit.base->secAllowWrite =3D false; qemuDomainStorageSourceAccessAllow(driver, vm, job->data.commit.base, true, false, false); =20 if (job->data.commit.topparent !=3D job->disk->src) { if (job->data.commit.topparent->dataFileStore) { + job->data.commit.topparent->dataFileStore->secAllowWrite =3D f= alse; qemuDomainStorageSourceAccessAllow(driver, vm, job->data.commi= t.topparent->dataFileStore, true, false, false); =20 qemuBlockReopenReadWrite(vm, job->data.commit.topparent->dataF= ileStore, asyncJob); } + job->data.commit.topparent->secAllowWrite =3D false; qemuDomainStorageSourceAccessAllow(driver, vm, job->data.commit.to= pparent, true, false, true); } @@ -1177,6 +1181,10 @@ qemuBlockJobProcessEventCompletedActiveCommit(virQEM= UDriver *driver, baseparent->backingStore =3D NULL; job->disk->src =3D job->data.commit.base; job->disk->src->readonly =3D job->data.commit.top->readonly; + job->disk->src->secAllowWrite =3D false; + if (job->disk->src->dataFileStore) { + job->disk->src->dataFileStore->secAllowWrite =3D false; + } =20 if (qemuBlockJobProcessEventCompletedCommitBitmaps(vm, job, asyncJob) = < 0) return; diff --git a/src/qemu/qemu_security.c b/src/qemu/qemu_security.c index 6bb0f9170d..603feba87e 100644 --- a/src/qemu/qemu_security.c +++ b/src/qemu/qemu_security.c @@ -201,6 +201,13 @@ qemuSecurityMoveImageMetadata(virQEMUDriver *driver, if (qemuDomainNamespaceEnabled(vm, QEMU_DOMAIN_NS_MOUNT)) pid =3D vm->pid; =20 + if (dst) { + dst->secAllowWrite =3D src->secAllowWrite; + if (dst->backingStore && src->backingStore) { + dst->backingStore->secAllowWrite =3D src->backingStore->secAll= owWrite; + } + } + return virSecurityManagerMoveImageMetadata(driver->securityManager, cfg->sharedFilesystems, pid, src, dst); diff --git a/src/security/virt-aa-helper.c b/src/security/virt-aa-helper.c index 7920162cdc..fc2d4d9d41 100644 --- a/src/security/virt-aa-helper.c +++ b/src/security/virt-aa-helper.c @@ -833,11 +833,8 @@ add_file_path(virStorageSource *src, if (!src->path || !virStorageSourceIsLocalStorage(src)) return 0; =20 - if (depth =3D=3D 0) { - if (src->readonly) - ret =3D vah_add_file(buf, src->path, "Rk"); - else - ret =3D vah_add_file(buf, src->path, "rwk"); + if ((depth =3D=3D 0 && !src->readonly) || src->secAllowWrite) { + ret =3D vah_add_file(buf, src->path, "rwk"); } else { ret =3D vah_add_file(buf, src->path, "Rk"); } --=20 2.51.0