From nobody Mon Feb 2 07:31:22 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=1768405154; cv=none; d=zohomail.com; s=zohoarc; b=U7jsJkeUaq3AhcrrwnhPEMHLv4Xv/fLEtVJNLsGzDUjZKy8qH6C2oiYpdxFVljEX3vINO6aahHLMpMmT9A9aUmIT/pGq3+yxJ3tk0fw5nvZMh+oMsz3ZZ1mC1CowUNZswN4NgpMPi4qyiIoqbYh+G7z3YHCCDQbRu/uPrbi8DFk= ARC-Message-Signature: i=1; a=rsa-sha256; c=relaxed/relaxed; d=zohomail.com; s=zohoarc; t=1768405154; h=Content-Type:Content-Transfer-Encoding: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:Cc; bh=t+eKO6YatoGsRu2LG6wmND4r0AkWtYG0qOJZwWRpHHI=; b=AeO3hNLg/a3lNkj0fzrMBLyaEavZG7xUoCMRKr+wqul5Bm9qnLFcKxJsBEzJc9c4RhMhxP9c/PafqqCTzcXnrzRtE7SEAjjZkwqGQpmKHeNUGaWxET2UPQZfig+6rjbXB5MupLvMDneschj7IzMxjChWeaj8g8aUDZbOvornmfo= 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 1768405154944282.50039851877716; Wed, 14 Jan 2026 07:39:14 -0800 (PST) Received: by lists.libvirt.org (Postfix, from userid 993) id 0971C418A9; Wed, 14 Jan 2026 10:39:14 -0500 (EST) Received: from [172.19.199.83] (lists.libvirt.org [8.43.85.245]) by lists.libvirt.org (Postfix) with ESMTP id 65B6643E01; Wed, 14 Jan 2026 10:36:00 -0500 (EST) Received: by lists.libvirt.org (Postfix, from userid 993) id 2821C3F358; Wed, 14 Jan 2026 10:35:41 -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 8F2713F361 for ; Wed, 14 Jan 2026 10:35:40 -0500 (EST) Received: from mx-prod-mc-05.mail-002.prod.us-west-2.aws.redhat.com (ec2-54-186-198-63.us-west-2.compute.amazonaws.com [54.186.198.63]) by relay.mimecast.com with ESMTP with STARTTLS (version=TLSv1.3, cipher=TLS_AES_256_GCM_SHA384) id us-mta-145-34VocvsFMWyaKF4eUdy-TQ-1; Wed, 14 Jan 2026 10:35:37 -0500 Received: from mx-prod-int-01.mail-002.prod.us-west-2.aws.redhat.com (mx-prod-int-01.mail-002.prod.us-west-2.aws.redhat.com [10.30.177.4]) (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 mx-prod-mc-05.mail-002.prod.us-west-2.aws.redhat.com (Postfix) with ESMTPS id 2680619560B5 for ; Wed, 14 Jan 2026 15:35:37 +0000 (UTC) Received: from moe (unknown [10.43.3.236]) by mx-prod-int-01.mail-002.prod.us-west-2.aws.redhat.com (Postfix) with ESMTP id 81D3530002D8 for ; Wed, 14 Jan 2026 15:35:36 +0000 (UTC) X-Spam-Checker-Version: SpamAssassin 4.0.1 (2024-03-26) on lists.libvirt.org X-Spam-Level: X-Spam-Status: No, score=-3.4 required=5.0 tests=BAYES_00,DKIM_INVALID, DKIM_SIGNED,MAILING_LIST_MULTI,RCVD_IN_DNSWL_LOW, 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=1768404940; h=from:from: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; bh=t+eKO6YatoGsRu2LG6wmND4r0AkWtYG0qOJZwWRpHHI=; b=Wgx85mA+1NGno0GdDFIiLdy/o1R3gvEWz9H9sci5ygb4924VwNF/ei4vbSTaW+Yb5cLwVI OffVjv5gI4GXZt4PteDmpazUMni4HPqQ8i25t7hYN1KWDfF3+CgSkZD5d6tUCFR/NuRWbi UgMuZCvWFCPqtXKsgk+jPscwB+JwQ9w= X-MC-Unique: 34VocvsFMWyaKF4eUdy-TQ-1 X-Mimecast-MFC-AGG-ID: 34VocvsFMWyaKF4eUdy-TQ_1768404937 To: devel@lists.libvirt.org Subject: [PATCH 3/3] security_apparmor: Move profile loading into .domainLoadProfile callback Date: Wed, 14 Jan 2026 16:35:31 +0100 Message-ID: In-Reply-To: References: MIME-Version: 1.0 X-Scanned-By: MIMEDefang 3.4.1 on 10.30.177.4 X-Mimecast-Spam-Score: 0 X-Mimecast-MFC-PROC-ID: RErqYtX5tbqNoEN0jA6U4uJNuX5-T74tqgF4x84ci3U_1768404937 X-Mimecast-Originator: redhat.com Content-Transfer-Encoding: quoted-printable Message-ID-Hash: GQFKXMPBQHR746TM2HLRMYVIBHFC6QHL X-Message-ID-Hash: GQFKXMPBQHR746TM2HLRMYVIBHFC6QHL X-MailFrom: mprivozn@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 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: Michal Privoznik via Devel Reply-To: Michal Privoznik X-ZohoMail-DKIM: fail (Header signature does not verify) X-ZM-MESSAGEID: 1768405156148158500 Content-Type: text/plain; charset="utf-8"; x-default="true" From: Michal Privoznik Here's the problem. When starting a QEMU domain, the process is split into several phases. A simplified process looks like this: 1) qemuProcessPrepareDomain() 1a) qemuSecurityGenLabel() 1b) generate run time paths 1c) qemuSecurityManagerLoadProfile() 2) qemuProcessPrepareHost() 2a) qemuSecurityDomainSetPathLabel() /* transitively */ 3) qemuProcessLaunch() 3a) qemuSecuritySetAllLabel() NB, step 2a) also contains helper processes used to set up host, that we want to run in the security context of the domain (e.g. swtpm_setup). This works well for SELinux and DAC because their APIs basically match 1:1 to ours. But it's not that simple with AppArmor. It doesn't contain any profile upfront, so one is generated in step 1a) (among with seclabel). But at that point, the domain definition has no run time info. This can then lead to some paths being left out (for instance, disks which source wasn't translated from storage pool/vol spec into a path). After previous commits, there's this new step 1c) which can actually load the profile. Therefore, move profile loading into .domainLoadProfile callback. Resolves: https://gitlab.com/libvirt/libvirt/-/issues/135 Signed-off-by: Michal Privoznik --- src/security/security_apparmor.c | 31 +++++++++++++++++++++++-------- 1 file changed, 23 insertions(+), 8 deletions(-) diff --git a/src/security/security_apparmor.c b/src/security/security_appar= mor.c index 68ac39611f..98fad9034d 100644 --- a/src/security/security_apparmor.c +++ b/src/security/security_apparmor.c @@ -387,23 +387,36 @@ AppArmorGenSecurityLabel(virSecurityManager *mgr G_GN= UC_UNUSED, if (!secdef->model) secdef->model =3D g_strdup(SECURITY_APPARMOR_NAME); =20 - /* Now that we have a label, load the profile into the kernel. */ + return 0; +} + + +static int +AppArmorLoadProfile(virSecurityManager *mgr G_GNUC_UNUSED, + virDomainDef *def) +{ + virSecurityLabelDef *secdef =3D virDomainDefGetSecurityLabelDef(def, + SECURITY_APPARMOR_NAME); + + if (!secdef) + return 0; + + if ((secdef->type =3D=3D VIR_DOMAIN_SECLABEL_STATIC) || + (secdef->type =3D=3D VIR_DOMAIN_SECLABEL_NONE)) { + return 0; + } + if (load_profile(mgr, secdef->label, def, NULL, false) < 0) { virReportError(VIR_ERR_INTERNAL_ERROR, _("cannot load AppArmor profile \'%1$s\'"), secdef->label); - goto err; + return -1; } =20 return 0; - - err: - VIR_FREE(secdef->label); - VIR_FREE(secdef->imagelabel); - VIR_FREE(secdef->model); - return -1; } =20 + static int AppArmorSetSecurityAllLabel(virSecurityManager *mgr, char *const *sharedFilesystems G_GNUC_UNUSED, @@ -1157,6 +1170,8 @@ virSecurityDriver virAppArmorSecurityDriver =3D { .domainReserveSecurityLabel =3D AppArmorReserveSecurityLabel, .domainReleaseSecurityLabel =3D AppArmorReleaseSecurityLabel, =20 + .domainLoadProfile =3D AppArmorLoadProfile, + .domainGetSecurityProcessLabel =3D AppArmorGetSecurityProcessLabe= l, .domainSetSecurityProcessLabel =3D AppArmorSetSecurityProcessLabe= l, .domainSetSecurityChildProcessLabel =3D AppArmorSetSecurityChildProces= sLabel, --=20 2.52.0