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 430B618F94; Fri, 28 Nov 2025 21:09:10 +0000 (UTC) Received: by atuin.qyliss.net (Postfix, from userid 993) id 6F2E118F90; Fri, 28 Nov 2025 21:09:08 +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 fhigh-b2-smtp.messagingengine.com (fhigh-b2-smtp.messagingengine.com [202.12.124.153]) by atuin.qyliss.net (Postfix) with ESMTPS id 647E318F8F for ; Fri, 28 Nov 2025 21:09:07 +0000 (UTC) Received: from phl-compute-02.internal (phl-compute-02.internal [10.202.2.42]) by mailfhigh.stl.internal (Postfix) with ESMTP id C991B7A07FE; Fri, 28 Nov 2025 16:09:04 -0500 (EST) Received: from phl-mailfrontend-02 ([10.202.2.163]) by phl-compute-02.internal (MEProxy); Fri, 28 Nov 2025 16:09:04 -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=1764364144; x=1764450544; bh=v0aeUgZWLI Z2IK8ElUU1Ah2yCYKM7XNgbaFkREO2AiU=; b=IU87d8LTmJQAffpQ7M+PjdvZjV omYr723c4xB+AaDUJMWQ036qlRpoO0gP5AMpdfQvYODHi2RuiXl213KdAZfelMVk OzqUrTYdzMW7U6W8GV4sXZXPTIEyI161CEVL16s2d41H51CfgGmAKycBzFruJ7yi 8aResCoG+65A7HnXN+rkSy5A6BZD2DTqEyv1zmv5kajju0twaKVnKB5QvBa/79ot /iD8G3qBKusTV6/n3Fos0ED/e+y76G/KcDnZB2oadcw7AX4dNfPbW2tMNnLQkuV2 S9UAbhClAiGy8rrw4cxiZomHwSR/1F3wZx1PrXhP5t3S07opTpStQRYDinwQ== 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= 1764364144; x=1764450544; bh=v0aeUgZWLIZ2IK8ElUU1Ah2yCYKM7XNgbaF kREO2AiU=; b=fxTCvRGF4VlD60UNQPBomkxvPhsyqge5d7V8LmbmdGn7gCbYFCy +1oF8SsEUMkj6QznmpF8j8TlL3v2RuTmdxlfI6SAGDR1cQ49GoeufrKQwtB0yTxs W+DNShVzZeBa18ifjgLtbCP0/32aEtKqooPmx15hJCV945ChEavHp5L7BoeTAuMp hmY0F3Xd2oIlrCJN+0T+cka+ONkOOfi1GYMqyUGsnREB5CxnJXIpxNHjtOBm1vGl HDZZULgnZ8qVqpi1gtyntY6sw3F8Re+oA5X+roRJT6fyL79a6QQmgZkIYyY/kV8v ZOmXsPGpfChxJWDjR689A7WZuZn74jumWDg== X-ME-Sender: X-ME-Received: X-ME-Proxy-Cause: gggruggvucftvghtrhhoucdtuddrgeeffedrtdeggddvhedtkeegucetufdoteggodetrf dotffvucfrrhhofhhilhgvmecuhfgrshhtofgrihhlpdfurfetoffkrfgpnffqhgenuceu rghilhhouhhtmecufedttdenucesvcftvggtihhpihgvnhhtshculddquddttddmnecujf gurhephffvvefujghffffkgggtsehgtderredttddtnecuhfhrohhmpeetlhihshhsrgcu tfhoshhsuceohhhisegrlhihshhsrgdrihhsqeenucggtffrrghtthgvrhhnpeeiudffue eilefgtefgtddttdekkeehkefgheekudefveetgeefiefftedvteeuveenucevlhhushht vghrufhiiigvpedtnecurfgrrhgrmhepmhgrihhlfhhrohhmpehhihesrghlhihsshgrrd hishdpnhgspghrtghpthhtohepvddpmhhouggvpehsmhhtphhouhhtpdhrtghpthhtohep uggvmhhiohgsvghnohhurhesghhmrghilhdrtghomhdprhgtphhtthhopeguvghvvghlse hsphgvtghtrhhumhdqohhsrdhorhhg X-ME-Proxy: Feedback-ID: i12284293:Fastmail Received: by mail.messagingengine.com (Postfix) with ESMTPA; Fri, 28 Nov 2025 16:09:03 -0500 (EST) Received: by fw12.qyliss.net (Postfix, from userid 1000) id AD2782DB32AA; Fri, 28 Nov 2025 22:08:52 +0100 (CET) From: Alyssa Ross To: Demi Marie Obenour Subject: Re: [PATCH v5 11/13] Support updates via systemd-sysupdate In-Reply-To: References: <20251126-updates-v5-0-fd746748febd@gmail.com> <20251126-updates-v5-11-fd746748febd@gmail.com> <87zf86nuay.fsf@alyssa.is> <87v7itopob.fsf@alyssa.is> Date: Fri, 28 Nov 2025 22:08:50 +0100 Message-ID: <87pl91oof1.fsf@alyssa.is> MIME-Version: 1.0 Content-Type: multipart/signed; boundary="=-=-="; micalg=pgp-sha512; protocol="application/pgp-signature" Message-ID-Hash: MBV7VAFA743XKKPUR4CESKYN3XHP7SYA X-Message-ID-Hash: MBV7VAFA743XKKPUR4CESKYN3XHP7SYA 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: --=-=-= Content-Type: text/plain Content-Transfer-Encoding: quoted-printable Demi Marie Obenour writes: > On 11/28/25 15:41, Alyssa Ross wrote: >> Demi Marie Obenour writes: >>=20 >>> 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..613b43570d0538fce2029= 6ccb1de2a6364e0df55 >>>>> --- /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 -- shar= ed } >>>>> + >>>>> + # Delete any stale temporary files. Delete any existing signature >>>>> + # files. If the VM is still running (it should not be), the VM mi= ght >>>>> + # 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/r= un >>>>> + # 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/v= m/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/${upda= te_vm_id}/fs/updates } >>>>> + >>>>> + # Share the update directory with the VM. >>>>> + if { mount --bind -- shared /run/vm/by-id/${update_vm_id}/fs/updat= es } >>>>> + >>>>> + # 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 run= s, >>>>> + # 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. >>=20 >> 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. --=-=-= Content-Type: application/pgp-signature; name="signature.asc" -----BEGIN PGP SIGNATURE----- iHUEARYKAB0WIQQGoGac7QfI+H5ZtFCZddwkt31pFQUCaSoPYgAKCRCZddwkt31p FaM9AP9nzD4z8U8Jkm4dAPS4Mr0Hv6sMiMO3dvSaTJGJZhcfBAEA6fXc2TPfUb/M 8mLntxddaxapIhXX7Y+Kv2FE3vXaLAM= =R0Bv -----END PGP SIGNATURE----- --=-=-=--