guix: add patches to fix guix#73919
This commit is contained in:
parent
661f01bea8
commit
0da66f6c64
4 changed files with 234 additions and 0 deletions
|
|
@ -0,0 +1,54 @@
|
||||||
|
From 532996c5908fb14cc8d102865280fb203c075c9c Mon Sep 17 00:00:00 2001
|
||||||
|
From: Reepca Russelstein <reepca@russelstein.xyz>
|
||||||
|
Date: Sun, 20 Oct 2024 17:32:23 -0500
|
||||||
|
Subject: [PATCH] etc: news: add news entry for build user takeover
|
||||||
|
vulnerability fix.
|
||||||
|
|
||||||
|
* etc/news.scm: add entry about build user takeover vulnerability.
|
||||||
|
---
|
||||||
|
etc/news.scm | 32 ++++++++++++++++++++++++++++++++
|
||||||
|
1 file changed, 32 insertions(+)
|
||||||
|
|
||||||
|
diff --git a/etc/news.scm b/etc/news.scm
|
||||||
|
index a64572df..63d2b7f9 100644
|
||||||
|
--- a/etc/news.scm
|
||||||
|
+++ b/etc/news.scm
|
||||||
|
@@ -26,6 +26,38 @@
|
||||||
|
(channel-news
|
||||||
|
(version 0)
|
||||||
|
|
||||||
|
+ (entry (commit "5966e0fdc78771c562e0f484a22f381a77908be0")
|
||||||
|
+ (title
|
||||||
|
+ (en "Daemon vulnerability allowing takeover of build users fixed"))
|
||||||
|
+ (body
|
||||||
|
+ (en "A vulnerability allowing a local user to execute arbitrary code
|
||||||
|
+as any of the build users has been identified and fixed. Most notably, this
|
||||||
|
+allows any local user to alter the result of any local build, even if it
|
||||||
|
+happens inside a container. The only requirements to exploit this
|
||||||
|
+vulnerability are the ability to start a derivation build and the ability to
|
||||||
|
+run arbitrary code with access to the store in the root PID namespace on the
|
||||||
|
+machine that build occurs on. This largely limits the vulnerability to
|
||||||
|
+multi-user systems.
|
||||||
|
+
|
||||||
|
+This vulnerability is caused by the fact that @command{guix-daemon} does not
|
||||||
|
+change ownership and permissions on the outputs of failed builds when it moves
|
||||||
|
+them to the store, and is also caused by there being a window of time between
|
||||||
|
+when it moves outputs of successful builds to the store and when it changes
|
||||||
|
+their ownership and permissions. Because of this, a build can create a binary
|
||||||
|
+with both setuid and setgid bits set and have it become visible to the outside
|
||||||
|
+world once the build ends. At that point any process that can access the
|
||||||
|
+store can execute it and gain the build user's privileges. From there any
|
||||||
|
+process owned by that build user can be manipulated via procfs and signals at
|
||||||
|
+will, allowing the attacker to control the output of its builds.
|
||||||
|
+
|
||||||
|
+You are advised to upgrade @command{guix-daemon}. Run @command{info \"(guix)
|
||||||
|
+Upgrading Guix\"}, for info on how to do that. Additionally, if there is any
|
||||||
|
+risk that a builder may have already created these setuid binaries (for
|
||||||
|
+example on accident), run @command{guix gc} to remove all failed build
|
||||||
|
+outputs.
|
||||||
|
+
|
||||||
|
+See @uref{https://issues.guix.gnu.org/73919} for more information on this
|
||||||
|
+vulnerability.")))
|
||||||
|
(entry (commit "788602b37ff42f730d4b7b569b0fb51465f147da")
|
||||||
|
(title
|
||||||
|
(en "New @option{--symlink} option for @command{guix shell}")
|
||||||
|
|
@ -0,0 +1,83 @@
|
||||||
|
From e936861263d9bafdfbe395c12526f2dc48ac17d7 Mon Sep 17 00:00:00 2001
|
||||||
|
Message-ID: <e936861263d9bafdfbe395c12526f2dc48ac17d7.1729457080.git.reepca@russelstein.xyz>
|
||||||
|
From: Reepca Russelstein <reepca@russelstein.xyz>
|
||||||
|
Date: Sun, 20 Oct 2024 15:36:06 -0500
|
||||||
|
Subject: [PATCH 1/2] nix: build: sanitize failed build outputs prior to
|
||||||
|
exposing them.
|
||||||
|
|
||||||
|
The only thing keeping a rogue builder and a local user from collaborating to
|
||||||
|
usurp control over the builder's user during the build is the fact that
|
||||||
|
whatever files the builder may produce are not accessible to any other users
|
||||||
|
yet. If we're going to make them accessible, we should probably do some
|
||||||
|
sanity checking to ensure that sort of collaborating can't happen.
|
||||||
|
|
||||||
|
Currently this isn't happening when failed build outputs are moved from the
|
||||||
|
chroot as an aid to debugging.
|
||||||
|
|
||||||
|
* nix/libstore/build.cc (secureFilePerms): new function.
|
||||||
|
(DerivationGoal::buildDone): use it.
|
||||||
|
|
||||||
|
Change-Id: I9dce1e3d8813b31cabd87a0e3219bf9830d8be96
|
||||||
|
---
|
||||||
|
nix/libstore/build.cc | 36 +++++++++++++++++++++++++++++++++++-
|
||||||
|
1 file changed, 35 insertions(+), 1 deletion(-)
|
||||||
|
|
||||||
|
diff --git a/nix/libstore/build.cc b/nix/libstore/build.cc
|
||||||
|
index d23c0944a4..67ebfe2f14 100644
|
||||||
|
--- a/nix/libstore/build.cc
|
||||||
|
+++ b/nix/libstore/build.cc
|
||||||
|
@@ -1301,6 +1301,34 @@ void replaceValidPath(const Path & storePath, const Path tmpPath)
|
||||||
|
MakeError(NotDeterministic, BuildError)
|
||||||
|
|
||||||
|
|
||||||
|
+/* Recursively make the file permissions of a path safe for exposure to
|
||||||
|
+ arbitrary users, but without canonicalising its permissions, timestamp, and
|
||||||
|
+ user. Throw an exception if a file type that isn't explicitly known to be
|
||||||
|
+ safe is found. */
|
||||||
|
+static void secureFilePerms(Path path)
|
||||||
|
+{
|
||||||
|
+ struct stat st;
|
||||||
|
+ if (lstat(path.c_str(), &st)) return;
|
||||||
|
+
|
||||||
|
+ switch(st.st_mode & S_IFMT) {
|
||||||
|
+ case S_IFLNK:
|
||||||
|
+ return;
|
||||||
|
+
|
||||||
|
+ case S_IFDIR:
|
||||||
|
+ for (auto & i : readDirectory(path)) {
|
||||||
|
+ secureFilePerms(path + "/" + i.name);
|
||||||
|
+ }
|
||||||
|
+ /* FALLTHROUGH */
|
||||||
|
+
|
||||||
|
+ case S_IFREG:
|
||||||
|
+ chmod(path.c_str(), (st.st_mode & ~S_IFMT) & ~(S_ISUID | S_ISGID | S_IWOTH));
|
||||||
|
+ break;
|
||||||
|
+
|
||||||
|
+ default:
|
||||||
|
+ throw Error(format("file `%1%' has an unsupported type") % path);
|
||||||
|
+ }
|
||||||
|
+}
|
||||||
|
+
|
||||||
|
void DerivationGoal::buildDone()
|
||||||
|
{
|
||||||
|
trace("build done");
|
||||||
|
@@ -1372,9 +1400,15 @@ void DerivationGoal::buildDone()
|
||||||
|
build failures. */
|
||||||
|
if (useChroot && buildMode == bmNormal)
|
||||||
|
foreach (PathSet::iterator, i, missingPaths)
|
||||||
|
- if (pathExists(chrootRootDir + *i))
|
||||||
|
+ if (pathExists(chrootRootDir + *i)) {
|
||||||
|
+ try {
|
||||||
|
+ secureFilePerms(chrootRootDir + *i);
|
||||||
|
rename((chrootRootDir + *i).c_str(), i->c_str());
|
||||||
|
+ } catch(Error & e) {
|
||||||
|
+ printMsg(lvlError, e.msg());
|
||||||
|
+ }
|
||||||
|
+ }
|
||||||
|
|
||||||
|
if (diskFull)
|
||||||
|
printMsg(lvlError, "note: build failure may have been caused by lack of free disk space");
|
||||||
|
|
||||||
|
--
|
||||||
|
2.45.2
|
||||||
|
|
||||||
|
|
@ -0,0 +1,64 @@
|
||||||
|
From d096d653cc69118e05f49247ab312d0096b16656 Mon Sep 17 00:00:00 2001
|
||||||
|
Message-ID: <d096d653cc69118e05f49247ab312d0096b16656.1729457080.git.reepca@russelstein.xyz>
|
||||||
|
In-Reply-To: <e936861263d9bafdfbe395c12526f2dc48ac17d7.1729457080.git.reepca@russelstein.xyz>
|
||||||
|
References: <e936861263d9bafdfbe395c12526f2dc48ac17d7.1729457080.git.reepca@russelstein.xyz>
|
||||||
|
From: Reepca Russelstein <reepca@russelstein.xyz>
|
||||||
|
Date: Sun, 20 Oct 2024 15:39:02 -0500
|
||||||
|
Subject: [PATCH 2/2] nix: build: sanitize successful build outputs prior to
|
||||||
|
exposing them.
|
||||||
|
|
||||||
|
There is currently a window of time between when the build outputs are exposed
|
||||||
|
and when their metadata is canonicalized.
|
||||||
|
|
||||||
|
* nix/libstore/build.cc (DerivationGoal::registerOutputs): wait until after
|
||||||
|
metadata canonicalization to move successful build outputs to the store.
|
||||||
|
|
||||||
|
Change-Id: Ia995136f3f965eaf7b0e1d92af964b816f3fb276
|
||||||
|
---
|
||||||
|
nix/libstore/build.cc | 23 ++++++++++++++---------
|
||||||
|
1 file changed, 14 insertions(+), 9 deletions(-)
|
||||||
|
|
||||||
|
diff --git a/nix/libstore/build.cc b/nix/libstore/build.cc
|
||||||
|
index 67ebfe2f14..43a8a37184 100644
|
||||||
|
--- a/nix/libstore/build.cc
|
||||||
|
+++ b/nix/libstore/build.cc
|
||||||
|
@@ -2369,15 +2369,6 @@ void DerivationGoal::registerOutputs()
|
||||||
|
Path actualPath = path;
|
||||||
|
if (useChroot) {
|
||||||
|
actualPath = chrootRootDir + path;
|
||||||
|
- if (pathExists(actualPath)) {
|
||||||
|
- /* Move output paths from the chroot to the store. */
|
||||||
|
- if (buildMode == bmRepair)
|
||||||
|
- replaceValidPath(path, actualPath);
|
||||||
|
- else
|
||||||
|
- if (buildMode != bmCheck && rename(actualPath.c_str(), path.c_str()) == -1)
|
||||||
|
- throw SysError(format("moving build output `%1%' from the chroot to the store") % path);
|
||||||
|
- }
|
||||||
|
- if (buildMode != bmCheck) actualPath = path;
|
||||||
|
} else {
|
||||||
|
Path redirected = redirectedOutputs[path];
|
||||||
|
if (buildMode == bmRepair
|
||||||
|
@@ -2463,6 +2454,20 @@ void DerivationGoal::registerOutputs()
|
||||||
|
canonicalisePathMetaData(actualPath,
|
||||||
|
buildUser.enabled() && !rewritten ? buildUser.getUID() : -1, inodesSeen);
|
||||||
|
|
||||||
|
+ if (useChroot) {
|
||||||
|
+ if (pathExists(actualPath)) {
|
||||||
|
+ /* Now that output paths have been canonicalized (in particular
|
||||||
|
+ there are no setuid files left), move them outside of the
|
||||||
|
+ chroot and to the store. */
|
||||||
|
+ if (buildMode == bmRepair)
|
||||||
|
+ replaceValidPath(path, actualPath);
|
||||||
|
+ else
|
||||||
|
+ if (buildMode != bmCheck && rename(actualPath.c_str(), path.c_str()) == -1)
|
||||||
|
+ throw SysError(format("moving build output `%1%' from the chroot to the store") % path);
|
||||||
|
+ }
|
||||||
|
+ if (buildMode != bmCheck) actualPath = path;
|
||||||
|
+ }
|
||||||
|
+
|
||||||
|
/* For this output path, find the references to other paths
|
||||||
|
contained in it. Compute the SHA-256 NAR hash at the same
|
||||||
|
time. The hash is stored in the database so that we can
|
||||||
|
--
|
||||||
|
2.45.2
|
||||||
|
|
||||||
33
helpers/make-guix
Normal file
33
helpers/make-guix
Normal file
|
|
@ -0,0 +1,33 @@
|
||||||
|
#!/bin/sh
|
||||||
|
#
|
||||||
|
# Copyright (C) 2024 Luis Guzmán <ark@switnet.org>
|
||||||
|
#
|
||||||
|
# This program is free software; you can redistribute it and/or modify
|
||||||
|
# it under the terms of the GNU General Public License as published by
|
||||||
|
# the Free Software Foundation; either version 2 of the License, or
|
||||||
|
# (at your option) any later version.
|
||||||
|
#
|
||||||
|
# This program is distributed in the hope that it will be useful,
|
||||||
|
# but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||||
|
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||||
|
# GNU General Public License for more details.
|
||||||
|
#
|
||||||
|
# You should have received a copy of the GNU General Public License
|
||||||
|
# along with this program; if not, write to the Free Software
|
||||||
|
# Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
|
||||||
|
#
|
||||||
|
|
||||||
|
VERSION=1
|
||||||
|
SECURITY=true
|
||||||
|
. ./config
|
||||||
|
|
||||||
|
# Apply missing CVEs upstream:
|
||||||
|
## 1. https://issues.guix.gnu.org/73919
|
||||||
|
for patch in $(ls -v ${DATA}/cve/*.patch)
|
||||||
|
do
|
||||||
|
patch_p1 $patch
|
||||||
|
done
|
||||||
|
|
||||||
|
changelog "Apply latest fix for #73919 on Ecne"
|
||||||
|
|
||||||
|
package
|
||||||
Loading…
Add table
Add a link
Reference in a new issue