From mboxrd@z Thu Jan 1 00:00:00 1970 Received: from atuin.qyliss.net (localhost [IPv6:::1]) by atuin.qyliss.net (Postfix) with ESMTP id 75A1C1924D; Fri, 28 Nov 2025 21:30:30 +0000 (UTC) Received: by atuin.qyliss.net (Postfix, from userid 993) id 9F7C019243; Fri, 28 Nov 2025 21:30:28 +0000 (UTC) X-Spam-Checker-Version: SpamAssassin 4.0.1 (2024-03-26) on atuin.qyliss.net X-Spam-Level: X-Spam-Status: No, score=-0.8 required=3.0 tests=DKIM_SIGNED,DKIM_VALID, DKIM_VALID_AU,DMARC_MISSING,RCVD_IN_DNSWL_LOW,SPF_HELO_PASS autolearn=unavailable autolearn_force=no version=4.0.1 Received: from fout-b2-smtp.messagingengine.com (fout-b2-smtp.messagingengine.com [202.12.124.145]) by atuin.qyliss.net (Postfix) with ESMTPS id BEF0C192BF for ; Fri, 28 Nov 2025 21:30:27 +0000 (UTC) Received: from phl-compute-02.internal (phl-compute-02.internal [10.202.2.42]) by mailfout.stl.internal (Postfix) with ESMTP id 67CA11D00734; Fri, 28 Nov 2025 16:30:25 -0500 (EST) Received: from phl-mailfrontend-02 ([10.202.2.163]) by phl-compute-02.internal (MEProxy); Fri, 28 Nov 2025 16:30:25 -0500 DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=alyssa.is; h=cc :cc:content-type:content-type:date:date:from:from:in-reply-to :in-reply-to:message-id:mime-version:references:reply-to:subject :subject:to:to; s=fm3; t=1764365425; x=1764451825; bh=ZTVi2me3CC fbgVDVCDOzoKSX36FoG8/+T+MUiGrvWGw=; b=JuWhrtv/ou+x1Y4DELqKt83zn1 AwUNNHtgzavEW3gukMVYTfgD+pyXir4xT27KXptqr1WxVKA5Hn3A0+RaECj2VKyD wvYLts1euje1OWEZLtBRn3WaGUfOnD0HxWmljLPO9O4pdZ7mw2V56o+sPSQJozU+ rI8eMz04HCHhhl1agCxISvKUKwa6tzVkPv/497s3nNNbOMimH6PdfaqSVZYtt8TF 3MA8Np6hNvyfyWuI2ECrKZ7K7qrq70XCfYkVg6TY5HMtN+OLViCi8LQoL3pG7F93 wm/dIgmVpcYN08JaKfGLccatOX0MEdRU9kQ5GNnYeg+vG/zz3SGO3JVioSQw== DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d= messagingengine.com; h=cc:cc:content-type:content-type:date:date :feedback-id:feedback-id:from:from:in-reply-to:in-reply-to :message-id:mime-version:references:reply-to:subject:subject:to :to:x-me-proxy:x-me-sender:x-me-sender:x-sasl-enc; s=fm1; t= 1764365425; x=1764451825; bh=ZTVi2me3CCfbgVDVCDOzoKSX36FoG8/+T+M UiGrvWGw=; b=WwXSNsdtW9mT8r0qDqRCDKoFgY5VM+qh11N2CtHuR236t/JizAR L/+CemMA53zN1g7QTbA/BnbcMnFzUxY9dq6VN4S48TAbKnn+pFA5qfWu41G/Oqo6 4BUbtYEAH63PYX8spv2NXX1IFNPxJ1nRSdvsO7ITHeZRANbgCDijLPto6huFti97 zaJVELwQxlQACFToW5Km0qDIj2hFYx4T/TrRqh0VBk6WdntPo3z8sGUgQcYdgodj Bz2mRXqRbFZ6eb1KZ3KyCkaLzj1otOwezcCz8NCPehB5CpKF4HSDnzONKvvybUl5 sSBMeDvtHv3DM3Kb8nwTlIrPhmaVX+7Ethw== X-ME-Sender: X-ME-Received: X-ME-Proxy-Cause: gggruggvucftvghtrhhoucdtuddrgeeffedrtdeggddvhedtkeejucetufdoteggodetrf dotffvucfrrhhofhhilhgvmecuhfgrshhtofgrihhlpdfurfetoffkrfgpnffqhgenuceu rghilhhouhhtmecufedttdenucesvcftvggtihhpihgvnhhtshculddquddttddmnecujf gurhepfffhvfevuffkfhggtggujgesghdtsfertddtvdenucfhrhhomheptehlhihsshgr ucftohhsshcuoehhihesrghlhihsshgrrdhisheqnecuggftrfgrthhtvghrnheptdejue etkeehfeeuleeugfevieffkefhteefiedvfeehuefhjeegvdeiffeihfeinecuvehluhhs thgvrhfuihiivgeptdenucfrrghrrghmpehmrghilhhfrhhomhephhhisegrlhihshhsrg drihhspdhnsggprhgtphhtthhopedvpdhmohguvgepshhmthhpohhuthdprhgtphhtthho peguvghmihhosggvnhhouhhrsehgmhgrihhlrdgtohhmpdhrtghpthhtohepuggvvhgvlh esshhpvggtthhruhhmqdhoshdrohhrgh X-ME-Proxy: Feedback-ID: i12284293:Fastmail Received: by mail.messagingengine.com (Postfix) with ESMTPA; Fri, 28 Nov 2025 16:30:24 -0500 (EST) Received: by fw12.qyliss.net (Postfix, from userid 1000) id 7B0512DB351E; Fri, 28 Nov 2025 22:30:08 +0100 (CET) Date: Fri, 28 Nov 2025 22:30:08 +0100 From: Alyssa Ross To: Demi Marie Obenour Subject: Re: [PATCH v5 11/13] Support updates via systemd-sysupdate Message-ID: References: <20251126-updates-v5-0-fd746748febd@gmail.com> <20251126-updates-v5-11-fd746748febd@gmail.com> <87zf86nuay.fsf@alyssa.is> <87v7itopob.fsf@alyssa.is> <87pl91oof1.fsf@alyssa.is> MIME-Version: 1.0 Content-Type: multipart/signed; micalg=pgp-sha512; protocol="application/pgp-signature"; boundary="a4qbk7xbfjojbgat" Content-Disposition: inline In-Reply-To: Message-ID-Hash: ZE3GW4UFQ7O7VJY3MF4ZWZUXHX5MO4TC X-Message-ID-Hash: ZE3GW4UFQ7O7VJY3MF4ZWZUXHX5MO4TC X-MailFrom: hi@alyssa.is X-Mailman-Rule-Misses: dmarc-mitigation; no-senders; approved; emergency; loop; banned-address; member-moderation; header-match-devel.spectrum-os.org-0; header-match-devel.spectrum-os.org-1; header-match-devel.spectrum-os.org-2; header-match-devel.spectrum-os.org-3; header-match-devel.spectrum-os.org-4; nonmember-moderation; administrivia; implicit-dest; max-recipients; max-size; news-moderation; no-subject; digests; suspicious-header CC: Spectrum OS Development X-Mailman-Version: 3.3.9 Precedence: list List-Id: Patches and low-level development discussion Archived-At: List-Archive: List-Help: List-Owner: List-Post: List-Subscribe: List-Unsubscribe: --a4qbk7xbfjojbgat Content-Type: text/plain; protected-headers=v1; charset=us-ascii Content-Disposition: inline Subject: Re: [PATCH v5 11/13] Support updates via systemd-sysupdate MIME-Version: 1.0 On Fri, Nov 28, 2025 at 04:28:20PM -0500, Demi Marie Obenour wrote: > On 11/28/25 16:08, Alyssa Ross wrote: > > Demi Marie Obenour writes: > > > >> On 11/28/25 15:41, Alyssa Ross wrote: > >>> Demi Marie Obenour writes: > >>> > >>>> On 11/28/25 08:47, Alyssa Ross wrote: > >>>>> Demi Marie Obenour writes: > >>>>> > >>>>>> diff --git a/host/rootfs/image/usr/bin/spectrum-update b/host/rootfs/image/usr/bin/spectrum-update > >>>>>> new file mode 100755 > >>>>>> index 0000000000000000000000000000000000000000..613b43570d0538fce20296ccb1de2a6364e0df55 > >>>>>> --- /dev/null > >>>>>> +++ b/host/rootfs/image/usr/bin/spectrum-update > >>>>>> @@ -0,0 +1,92 @@ > >>>>>> +#!/bin/execlineb -WS1 > >>>>>> +# SPDX-License-Identifier: EUPL-1.2+ > >>>>>> +# SPDX-FileCopyrightText: 2025 Demi Marie Obenour > >>>>>> + > >>>>>> +if { mkdir -p -m 0700 /run/updater } > >>>>>> + > >>>>>> +# Take a global lock to avoid races. > >>>>>> +s6-setlock /run/update-lock > >>>>>> + > >>>>>> +foreground { redirfd -w 2 /dev/null rmdir -- $1 } > >>>>>> +if { umask 0077 mkdir -p -- $1 } > >>>>>> +cd $1 > >>>>>> +foreground { > >>>>>> + # If this exists already that is okay. > >>>>>> + foreground { redirfd -w 2 /dev/null btrfs subvolume create -- shared } > >>>>>> + > >>>>>> + # Delete any stale temporary files. Delete any existing signature > >>>>>> + # files. If the VM is still running (it should not be), the VM might > >>>>>> + # have write access to the directory. However, updates-dir-check is > >>>>>> + # safe against that. > >>>>>> + if { updates-dir-check cleanup shared } > >>>>>> + > >>>>>> + if { > >>>>>> + foreground { > >>>>>> + # TODO: suppress only "subvolume does not exist" errors. > >>>>>> + redirfd -w 2 /dev/null > >>>>>> + btrfs subvolume delete snapshot > >>>>>> + } > >>>>>> + rm -f snapshot > >>>>>> + } > >>>>>> + > >>>>>> + backtick -E update_vm_id { > >>>>>> + backtick -E id_path { readlink /run/vm/by-name/sys.appvm-systemd-sysupdate } > >>>>>> + basename -- $id_path > >>>>>> + } > >>>>>> + > >>>>>> + # $fsdir is read-only to the guest, but read-write to the host. > >>>>>> + # Directories bind-mounted into it are read-write to the guest. > >>>>>> + # See etc/s6-linux-init/run-image/service/vhost-user-fs/template/run > >>>>>> + # for details. > >>>>>> + > >>>>> > >>>>> This still refers to a non-existent variable. > >> > >> Whoops! > >> > >>>>>> + # Set up /etc with what the VM needs. The VM will overlay this > >>>>>> + # on its own /etc. > >>>>>> + # > >>>>>> + # In the future, this should use a bind mount instead of copying > >>>>>> + # into a tmpfs. However, this would significantly complicate the > >>>>>> + # cleanup code. Deleting fs/etc would require undoing the bind > >>>>>> + # mounts instead of rm -rf. Once this code is in a separate mount > >>>>>> + # namespace, the copies should be replaced by bind mounts. > >>>>>> + if { > >>>>>> + if { rm -rf -- /run/vm/by-id/${update_vm_id}/fs/etc } > >>>>>> + umask 022 > >>>>>> + if { mkdir -p -- /run/vm/by-id/${update_vm_id}/fs/updates /run/vm/by-id/${update_vm_id}/fs/etc/systemd } > >>>>>> + if { cp -R -- /etc/vm-sysupdate.d /etc/update-url /run/vm/by-id/${update_vm_id}/fs/etc } > >>>>>> + cp -- /etc/systemd/import-pubring.gpg /run/vm/by-id/${update_vm_id}/fs/etc/systemd > >>>>>> + } > >>>>>> + > >>>>>> + # If the directory is already mounted, unmount it. This prevents a > >>>>>> + # confusing error from mount. > >>>>>> + foreground { redirfd -w 2 /dev/null umount -- /run/vm/by-id/${update_vm_id}/fs/updates } > >>>>>> + > >>>>>> + # Share the update directory with the VM. > >>>>>> + if { mount --bind -- shared /run/vm/by-id/${update_vm_id}/fs/updates } > >>>>>> + > >>>>>> + # Start the update VM. > >>>>>> + if { vm-start $update_vm_id } > >>>>>> + > >>>>>> + # Wait for the VM to exit. > >>>>>> + # TODO: This is racy. If the update finishes before this code runs, > >>>>>> + # the s6-svwait call will fail. > >>>>>> + if { s6-svwait -D /run/service/vmm/instance/${update_vm_id} } > >>>>>> + > >>>>>> + # Remove the bind mount. > >>>>>> + if { umount -- /run/vm/by-id/${update_vm_id}/fs/updates } > >>>>>> + > >>>>>> + # Ensure that the VM cannot change the directory > >>>>>> + # while systemd-sysupdate is using it. > >>>>>> + if { btrfs subvolume snapshot -- shared snapshot } > >>>>>> + > >>>>>> + # Validate the update directory. Delete any stale temporary files. > >>>>>> + # Check that a signature file was downloaded. > >>>>>> + if { updates-dir-check check snapshot } > >>>>>> + > >>>>>> + unshare --mount > >>>>>> + if { mount --bind -o ro -- snapshot /run/updater } > >>>>>> + > >>>>>> + /usr/lib/systemd/systemd-sysupdate update > >>>>> > >>>>> Why not just make a readonly snapshot? > >>>>> (btrfs subvolume snapshot -r) > >>>> > >>>> The checker will delete any temporary files it comes across, so it > >>>> needs write access. A snapshot is much heavier than a bind mount > >>>> and isn't automatically cleaned up. > >>> > >>> Okay, but why do we need to block systemd-sysupdate from writing to this > >>> directory, but not to anywhere else on the system? > >> > >> We don't. I'm fine with a writable mount. Either should work. > > > > Then let's keep things simple and drop the unshare and mount. We can > > deprivilege it properly in the future. > > The mount is absolutely necessary: it ensures that the update is > available where the .transfer file says it will be. It just doesn't > need to be read-only. > > The unshare is there to allow trivial cleanup by the kernel once > systemd-sysupdate exits. Ah, then I was misreading. If the mount has to be there, it might as well be read-only. With the outdated comment removed: Reviewed-by: Alyssa Ross --a4qbk7xbfjojbgat Content-Type: application/pgp-signature; name="signature.asc" -----BEGIN PGP SIGNATURE----- iHUEABYKAB0WIQQGoGac7QfI+H5ZtFCZddwkt31pFQUCaSoUXwAKCRCZddwkt31p Fbv9AQCVOa/gEx+gcN94j8S1xZc29ikXHjDf2O3xVrrtKSujogEA4c0HCQIr7FIq EF92RBMj64K3lCckGSXGrhF1uL2B6AU= =9QDU -----END PGP SIGNATURE----- --a4qbk7xbfjojbgat--