From mboxrd@z Thu Jan 1 00:00:00 1970 X-Spam-Checker-Version: SpamAssassin 3.4.6 (2021-04-09) on atuin.qyliss.net X-Spam-Level: X-Spam-Status: No, score=-1.8 required=5.0 tests=DKIM_SIGNED,DKIM_VALID, DKIM_VALID_AU,MAILING_LIST_MULTI,RCVD_IN_DNSWL_LOW,RCVD_IN_MSPIKE_H3, RCVD_IN_MSPIKE_WL,SPF_HELO_PASS autolearn=unavailable autolearn_force=no version=3.4.6 Received: from atuin.qyliss.net (localhost [IPv6:::1]) by atuin.qyliss.net (Postfix) with ESMTP id 6A68990409; Mon, 10 Oct 2022 23:32:45 +0000 (UTC) Received: by atuin.qyliss.net (Postfix, from userid 496) id 545A2901A5; Mon, 10 Oct 2022 23:32:28 +0000 (UTC) Received: from out4-smtp.messagingengine.com (out4-smtp.messagingengine.com [66.111.4.28]) by atuin.qyliss.net (Postfix) with ESMTPS id 5E718900CD for ; Mon, 10 Oct 2022 23:32:13 +0000 (UTC) Received: from compute4.internal (compute4.nyi.internal [10.202.2.44]) by mailout.nyi.internal (Postfix) with ESMTP id 206265C01B2 for ; Mon, 10 Oct 2022 19:32:10 -0400 (EDT) Received: from mailfrontend1 ([10.202.2.162]) by compute4.internal (MEProxy); Mon, 10 Oct 2022 19:32:10 -0400 DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=alyssa.is; h=cc :content-transfer-encoding:date:date:from:from:in-reply-to :in-reply-to:message-id:mime-version:references:reply-to:sender :subject:subject:to:to; s=fm2; t=1665444730; x=1665531130; bh=ND 6mMXOkbmOa6q9O8jMWhwgc56knSTffNeWatmie2gY=; b=2QRmQKh5iayw6Ysn/F 0RnFcgDjHaVWx7RCOP3FqiA8f8fCbAC6vmhKFAxwd9nsvgYmyWYuncK8FinUmKxS g+orqVzudYWMstMIh/GtpbeLVQdGjBWvvfGFn5Qk8fylqgJGQB0xBwAqlUVzCf+r cVVPGpV3zErnNpn0pmrY4LbMhRAFZX+LsbQlQ+i8UYj3gUfpyplsVYu9hRhxULNB qMFxfp13Ur9MIEDPFIS5ekqlrmEUGlAh3nmwxrKJe1RMk3pssiuGrHsn2UL8Cx/i DzVPUMg9N8eQM0I4T+GoIXhTfxbNRKWLutAy4ATpJK/Xf3KUNTP81oEFqicqw/Du oS0A== DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d= messagingengine.com; h=cc:content-transfer-encoding:date:date :feedback-id:feedback-id:from:from:in-reply-to:in-reply-to :message-id:mime-version:references:reply-to:sender:subject :subject:to:to:x-me-proxy:x-me-proxy:x-me-sender:x-me-sender :x-sasl-enc; s=fm3; t=1665444730; x=1665531130; bh=ND6mMXOkbmOa6 q9O8jMWhwgc56knSTffNeWatmie2gY=; b=QS5pDsklYGiKvnuKVulDrZq0+ZWXO 4QR6BaZOMtZzNRTksZvKS40CXuXUzfzc+BqRJjLAfHUw59s9u05XwtJV/aD0AlVt 3gv4PMhBLJdsFB1xVXbHFEpPpQONEcNIY56k+ioCD7PyiEuoGZbIeywvhLlTna9b weaHQHAZfe+euNR8uIOGJnD+GuXGE8apqCYhtjNMBuEajgBZMhyT3UZmr6gi6LHp RPQTI6dmWQ8eaksxrNVl9M/xn4AkJFsn/WvQULFXcDZAGav1inoaWKftZxXi+PDm SUyXXZWAGY17n2yZcz81S3VbCR4HsNrUoLf7PhREI1b+1HgdvvwUfdhvw== X-ME-Sender: X-ME-Received: X-ME-Proxy-Cause: gggruggvucftvghtrhhoucdtuddrgedvfedrfeejhedgvdduucetufdoteggodetrfdotf fvucfrrhhofhhilhgvmecuhfgrshhtofgrihhlpdfqfgfvpdfurfetoffkrfgpnffqhgen uceurghilhhouhhtmecufedttdenucenucfjughrpefhvffufffkofgjfhgggfestdekre dtredttdenucfhrhhomheptehlhihsshgrucftohhsshcuoehhihesrghlhihsshgrrdhi sheqnecuggftrfgrthhtvghrnhepgfefudekvdelieelledufeevheeglefggedvudejvd dtffeuueevffehleejkedvnecuvehluhhsthgvrhfuihiivgeptdenucfrrghrrghmpehm rghilhhfrhhomhepqhihlhhishhsseigvddvtddrqhihlhhishhsrdhnvght X-ME-Proxy: Feedback-ID: i12284293:Fastmail Received: by mail.messagingengine.com (Postfix) with ESMTPA for ; Mon, 10 Oct 2022 19:32:09 -0400 (EDT) Received: by x220.qyliss.net (Postfix, from userid 1000) id CCC10BC0; Mon, 10 Oct 2022 23:32:06 +0000 (UTC) From: Alyssa Ross To: devel@spectrum-os.org Subject: [PATCH 16/22] host/rootfs: resolve VM symlinks with /ext root Date: Mon, 10 Oct 2022 23:28:56 +0000 Message-Id: <20221010232909.1953738-17-hi@alyssa.is> X-Mailer: git-send-email 2.37.1 In-Reply-To: <20221010232909.1953738-1-hi@alyssa.is> References: <20221010232909.1953738-1-hi@alyssa.is> MIME-Version: 1.0 Content-Transfer-Encoding: 8bit Message-ID-Hash: DRHIN6UXKIL4P2WEWPGH5UVFX4LQHZLW X-Message-ID-Hash: DRHIN6UXKIL4P2WEWPGH5UVFX4LQHZLW X-MailFrom: qyliss@x220.qyliss.net X-Mailman-Rule-Misses: dmarc-mitigation; no-senders; approved; emergency; loop; banned-address; member-moderation; header-match-config-1; header-match-devel.spectrum-os.org-0; header-match-devel.spectrum-os.org-1; header-match-devel.spectrum-os.org-2; nonmember-moderation; administrivia; implicit-dest; max-recipients; max-size; news-moderation; no-subject; digests; suspicious-header X-Mailman-Version: 3.3.5 Precedence: list List-Id: Patches and low-level development discussion Archived-At: List-Archive: List-Help: List-Owner: List-Post: List-Subscribe: List-Unsubscribe: A goal here was to minimize the amount of C that needed to be written, so I designed resolve_in_root as the smallest possible program that could usefully expose RESOLVE_IN_ROOT functionality to scripts in a generic way. Rather than a program that does the resolution and then prints the absolute path, I also considered a program that would chdir() to the resulting directory and then exec a new argv. This was an even simpler implementation, since it didn't require any string handling at all, but it was a bit awkward to use and only worked for directories. resolve_in_root lives in the new tools/ directory rather than in host/, because it will also be useful in guests that need to interact with these Nix profiles. Signed-off-by: Alyssa Ross --- host/rootfs/default.nix | 8 ++- host/rootfs/etc/s6-rc/ext-rc-init/up | 8 ++- tools/resolve_in_root/default.nix | 23 ++++++++ tools/resolve_in_root/meson.build | 10 ++++ tools/resolve_in_root/resolve_in_root.c | 76 +++++++++++++++++++++++++ tools/resolve_in_root/test.sh | 11 ++++ 6 files changed, 131 insertions(+), 5 deletions(-) create mode 100644 tools/resolve_in_root/default.nix create mode 100644 tools/resolve_in_root/meson.build create mode 100644 tools/resolve_in_root/resolve_in_root.c create mode 100755 tools/resolve_in_root/test.sh diff --git a/host/rootfs/default.nix b/host/rootfs/default.nix index 0b08603..f5c8bcf 100644 --- a/host/rootfs/default.nix +++ b/host/rootfs/default.nix @@ -14,6 +14,10 @@ let inherit (lib) cleanSource cleanSourceWith concatMapStringsSep hasSuffix; inherit (nixosAllHardware.config.hardware) firmware; + resolve_in_root = import ../../tools/resolve_in_root { + config = config // { pkgs = pkgs.pkgsStatic; }; + }; + start-vm = import ../start-vm { config = config // { pkgs = pkgs.pkgsStatic; }; }; @@ -44,8 +48,8 @@ let foot = pkgsGui.foot.override { allowPgo = false; }; packages = [ - cloud-hypervisor e2fsprogs execline jq kmod mdevd s6 s6-linux-init s6-rc - socat start-vm virtiofsd + cloud-hypervisor e2fsprogs execline jq kmod mdevd resolve_in_root s6 + s6-linux-init s6-rc socat start-vm virtiofsd (cryptsetup.override { programs = { diff --git a/host/rootfs/etc/s6-rc/ext-rc-init/up b/host/rootfs/etc/s6-rc/ext-rc-init/up index 53ab127..4808f28 100644 --- a/host/rootfs/etc/s6-rc/ext-rc-init/up +++ b/host/rootfs/etc/s6-rc/ext-rc-init/up @@ -5,9 +5,11 @@ if { mkdir -p /run/s6-rc.ext.src } if { - elglob -0 dirs /ext/svc/data/*/ - forx -E dir { $dirs } - backtick -E name { basename -- $dir } + cd /ext + elglob -0 glob svc/data/* + forx -E reldir { $glob } + backtick -E name { basename -- $reldir } + backtick -E dir { resolve_in_root . $reldir } cd /run/s6-rc.ext.src diff --git a/tools/resolve_in_root/default.nix b/tools/resolve_in_root/default.nix new file mode 100644 index 0000000..f3ed081 --- /dev/null +++ b/tools/resolve_in_root/default.nix @@ -0,0 +1,23 @@ +# SPDX-License-Identifier: MIT +# SPDX-FileCopyrightText: 2022 Alyssa Ross + +{ config ? import ../../nix/eval-config.nix {} }: config.pkgs.callPackage ( +{ lib, stdenv, meson, ninja }: + +let + inherit (lib) cleanSource cleanSourceWith hasSuffix; +in + +stdenv.mkDerivation { + name = "resolve_in_root"; + + src = cleanSourceWith { + filter = name: _type: !(hasSuffix ".nix" name); + src = cleanSource ./.; + }; + + nativeBuildInputs = [ meson ninja ]; + + doCheck = true; +} +) { } diff --git a/tools/resolve_in_root/meson.build b/tools/resolve_in_root/meson.build new file mode 100644 index 0000000..a549ea6 --- /dev/null +++ b/tools/resolve_in_root/meson.build @@ -0,0 +1,10 @@ +# SPDX-License-Identifier: EUPL-1.2+ +# SPDX-FileCopyrightText: 2022 Alyssa Ross + +project('resolve_in_root', 'c') + +add_project_arguments('-D_GNU_SOURCE', language : 'c') + +prog = executable('resolve_in_root', 'resolve_in_root.c', install : true) + +test('test', find_program('test.sh'), args : prog) diff --git a/tools/resolve_in_root/resolve_in_root.c b/tools/resolve_in_root/resolve_in_root.c new file mode 100644 index 0000000..ab33c91 --- /dev/null +++ b/tools/resolve_in_root/resolve_in_root.c @@ -0,0 +1,76 @@ +// SPDX-License-Identifier: EUPL-1.2+ +// SPDX-FileCopyrightText: 2022 Alyssa Ross + +#include +#include +#include +#include +#include +#include +#include +#include + +#include + +#include + +#define STRINGIZE(x) STRINGIZE2(x) +#define STRINGIZE2(x) #x + +[[gnu::malloc]] [[gnu::nonnull]] char *areadlink(const char *pathname) +{ + char *target = NULL; + size_t link_size, target_size = 4096; + + for (;;) { + free(target); + if (!(target = malloc(target_size))) + return NULL; + if ((link_size = readlink(pathname, target, target_size)) == -1) + return NULL; + if (link_size < target_size) + break; + if (target_size > (((size_t)-1) >> 1)) { + errno = ENOMEM; + return NULL; + } + target_size <<= 1; + } + target[link_size] = '\0'; + + return target; +} + +int main(int argc, char **argv) +{ + // -1 because both paths include a null terminator. + char fdpath[sizeof "/proc/self/fd/" + sizeof(STRINGIZE(INT_MAX)) - 1]; + + char *target; + int rootfd, targetfd; + struct open_how how = { .flags = O_PATH }; + + // Ensure INT_MAX is actually defined, because otherwise + // sizeof("INT_MAX") will silently be used instead in fdpath's + // size. + (void) INT_MAX; + + if (argc != 3) { + fprintf(stderr, "Usage: %s root dir\n", argc ? argv[0] : "resolve_in_root"); + return 1; + } + + if ((rootfd = syscall(SYS_openat2, AT_FDCWD, argv[1], &how, sizeof how)) == -1) + err(EXIT_FAILURE, "opening %s", argv[1]); + + how.resolve = RESOLVE_IN_ROOT | RESOLVE_NO_MAGICLINKS | RESOLVE_NO_XDEV; + if ((targetfd = syscall(SYS_openat2, rootfd, argv[2], &how, sizeof how)) == -1) + err(EXIT_FAILURE, "opening %s with %s:/", argv[2], argv[1]); + + assert(snprintf(fdpath, sizeof fdpath, "/proc/self/fd/%d", targetfd) < sizeof fdpath); + + target = areadlink(fdpath); + if (!target) + err(EXIT_FAILURE, "reading %s", fdpath); + puts(target); +} diff --git a/tools/resolve_in_root/test.sh b/tools/resolve_in_root/test.sh new file mode 100755 index 0000000..c4afe3d --- /dev/null +++ b/tools/resolve_in_root/test.sh @@ -0,0 +1,11 @@ +#!/bin/sh -ue +# SPDX-License-Identifier: EUPL-1.2+ +# SPDX-FileCopyrightText: 2022 Alyssa Ross + +dir="$(mktemp -d)" +trap 'rm -rf "$dir"' EXIT + +touch "$dir/file" +ln -s /file "$dir/link" + +test "$("$1" "$dir" link)" = "$dir/file" -- 2.37.1