Received: (at 75810) by debbugs.gnu.org; 22 Mar 2025 15:58:03 +0000 From debbugs-submit-bounces <at> debbugs.gnu.org Sat Mar 22 11:58:03 2025 Received: from localhost ([127.0.0.1]:44829 helo=debbugs.gnu.org) by debbugs.gnu.org with esmtp (Exim 4.84_2) (envelope-from <debbugs-submit-bounces <at> debbugs.gnu.org>) id 1tw1EY-0000Mb-NQ for submit <at> debbugs.gnu.org; Sat, 22 Mar 2025 11:58:03 -0400 Received: from hera.aquilenet.fr ([185.233.100.1]:49184) by debbugs.gnu.org with esmtps (TLS1.2:ECDHE_RSA_AES_256_GCM_SHA384:256) (Exim 4.84_2) (envelope-from <ludo@HIDDEN>) id 1tw1ER-0000Lv-OJ for 75810 <at> debbugs.gnu.org; Sat, 22 Mar 2025 11:58:00 -0400 Received: from localhost (localhost [127.0.0.1]) by hera.aquilenet.fr (Postfix) with ESMTP id 0BB74D5D; Sat, 22 Mar 2025 16:57:48 +0100 (CET) Authentication-Results: hera.aquilenet.fr; none X-Virus-Scanned: Debian amavis at hera.aquilenet.fr Received: from hera.aquilenet.fr ([127.0.0.1]) by localhost (hera.aquilenet.fr [127.0.0.1]) (amavis, port 10024) with ESMTP id WdJmg-tfMJ3f; Sat, 22 Mar 2025 16:57:47 +0100 (CET) Received: from ribbon (91-160-117-201.subs.proxad.net [91.160.117.201]) by hera.aquilenet.fr (Postfix) with ESMTPSA id A4C4A7E7; Sat, 22 Mar 2025 16:57:45 +0100 (CET) From: =?utf-8?Q?Ludovic_Court=C3=A8s?= <ludo@HIDDEN> To: Reepca Russelstein <reepca@HIDDEN> Subject: Re: [bug#75810] [PATCH v6 00/16] Rootless guix-daemon In-Reply-To: <87iko2gpgd.fsf@HIDDEN> (Reepca Russelstein's message of "Fri, 21 Mar 2025 14:21:06 -0500") References: <cover.1742230219.git.ludo@HIDDEN> <875xk7594u.fsf@HIDDEN> <87v7s6h21b.fsf@HIDDEN> <871puu53mf.fsf@HIDDEN> <87tt7na08n.fsf@HIDDEN> <87iko2gpgd.fsf@HIDDEN> Date: Sat, 22 Mar 2025 16:57:45 +0100 Message-ID: <87sen55a86.fsf@HIDDEN> User-Agent: Gnus/5.13 (Gnus v5.13) MIME-Version: 1.0 Content-Type: multipart/mixed; boundary="=-=-=" X-Rspamd-Queue-Id: 0BB74D5D X-Spamd-Result: default: False [4.90 / 15.00]; SPAM_FLAG(5.00)[]; BAYES_HAM(-3.00)[100.00%]; NEURAL_SPAM(3.00)[1.000]; MIME_GOOD(-0.10)[multipart/mixed,text/plain,text/x-patch]; RCVD_COUNT_TWO(0.00)[2]; FROM_EQ_ENVFROM(0.00)[]; MIME_TRACE(0.00)[0:+,1:+,2:+,3:+]; RCPT_COUNT_TWO(0.00)[2]; ARC_NA(0.00)[]; TO_MATCH_ENVRCPT_ALL(0.00)[]; RCVD_VIA_SMTP_AUTH(0.00)[]; RCVD_TLS_ALL(0.00)[]; FROM_HAS_DN(0.00)[]; TO_DN_SOME(0.00)[]; MID_RHS_MATCH_FROM(0.00)[] X-Spam-Level: **** X-Rspamd-Action: no action X-Spamd-Bar: ++++ X-Rspamd-Server: hera X-Spam-Score: 2.4 (++) X-Spam-Report: Spam detection software, running on the system "debbugs.gnu.org", has NOT identified this incoming email as spam. The original message has been attached to this so you can view it or label similar future email. If you have any questions, see the administrator of that system for details. Content preview: Hi Reepca, Reepca Russelstein <reepca@HIDDEN> skribis: > Ludovic Courtès <ludo@HIDDEN> writes: > >>> While ensuring that what actually gets execve'd is in the store suffices >>> to eliminate the vulnerability, it may be "conceptually purer" to >>> requi [...] Content analysis details: (2.4 points, 10.0 required) pts rule name description ---- ---------------------- -------------------------------------------------- 0.0 RCVD_IN_VALIDITY_SAFE_BLOCKED RBL: ADMINISTRATOR NOTICE: The query to Validity was blocked. See https://knowledge.validity.com/hc/en-us/articles/20961730681243 for more information. [185.233.100.1 listed in sa-accredit.habeas.com] 0.0 RCVD_IN_VALIDITY_RPBL_BLOCKED RBL: ADMINISTRATOR NOTICE: The query to Validity was blocked. See https://knowledge.validity.com/hc/en-us/articles/20961730681243 for more information. [185.233.100.1 listed in bl.score.senderscore.com] 1.0 SPF_SOFTFAIL SPF: sender does not match SPF record (softfail) -0.0 SPF_HELO_PASS SPF: HELO matches SPF record 1.5 PDS_OTHER_BAD_TLD Untrustworthy TLDs [URI: russelstein.xyz (xyz)] X-Debbugs-Envelope-To: 75810 Cc: 75810 <at> debbugs.gnu.org X-BeenThere: debbugs-submit <at> debbugs.gnu.org X-Mailman-Version: 2.1.18 Precedence: list List-Id: <debbugs-submit.debbugs.gnu.org> List-Unsubscribe: <https://debbugs.gnu.org/cgi-bin/mailman/options/debbugs-submit>, <mailto:debbugs-submit-request <at> debbugs.gnu.org?subject=unsubscribe> List-Archive: <https://debbugs.gnu.org/cgi-bin/mailman/private/debbugs-submit/> List-Post: <mailto:debbugs-submit <at> debbugs.gnu.org> List-Help: <mailto:debbugs-submit-request <at> debbugs.gnu.org?subject=help> List-Subscribe: <https://debbugs.gnu.org/cgi-bin/mailman/listinfo/debbugs-submit>, <mailto:debbugs-submit-request <at> debbugs.gnu.org?subject=subscribe> Errors-To: debbugs-submit-bounces <at> debbugs.gnu.org Sender: "Debbugs-submit" <debbugs-submit-bounces <at> debbugs.gnu.org> X-Spam-Score: 1.4 (+) X-Spam-Report: Spam detection software, running on the system "debbugs.gnu.org", has NOT identified this incoming email as spam. The original message has been attached to this so you can view it or label similar future email. If you have any questions, see the administrator of that system for details. Content preview: Hi Reepca, Reepca Russelstein <reepca@HIDDEN> skribis: > Ludovic Courtès <ludo@HIDDEN> writes: > >>> While ensuring that what actually gets execve'd is in the store suffices >>> to eliminate the vulnerability, it may be "conceptually purer" to >>> requi [...] Content analysis details: (1.4 points, 10.0 required) pts rule name description ---- ---------------------- -------------------------------------------------- 0.0 RCVD_IN_VALIDITY_SAFE_BLOCKED RBL: ADMINISTRATOR NOTICE: The query to Validity was blocked. See https://knowledge.validity.com/hc/en-us/articles/20961730681243 for more information. [185.233.100.1 listed in sa-trusted.bondedsender.org] 0.0 RCVD_IN_VALIDITY_RPBL_BLOCKED RBL: ADMINISTRATOR NOTICE: The query to Validity was blocked. See https://knowledge.validity.com/hc/en-us/articles/20961730681243 for more information. [185.233.100.1 listed in bl.score.senderscore.com] 1.0 SPF_SOFTFAIL SPF: sender does not match SPF record (softfail) -0.0 SPF_HELO_PASS SPF: HELO matches SPF record 1.5 PDS_OTHER_BAD_TLD Untrustworthy TLDs [URI: russelstein.xyz (xyz)] -1.0 MAILING_LIST_MULTI Multiple indicators imply a widely-seen list manager --=-=-= Content-Type: text/plain; charset=utf-8 Content-Transfer-Encoding: quoted-printable Hi Reepca, Reepca Russelstein <reepca@HIDDEN> skribis: > Ludovic Court=C3=A8s <ludo@HIDDEN> writes: > >>> While ensuring that what actually gets execve'd is in the store suffices >>> to eliminate the vulnerability, it may be "conceptually purer" to >>> require that the links pointing to it are all in the store as well. For >>> example, while a builder that is a symlink pointing to /proc/self/exe >>> wouldn't be able to modify the daemon binary, it's still a piece of >>> basically "undefined behavior" as far as the build environment is >>> concerned, which could be closed up. But that can come later just as >>> well. >> >> Yes. But in practice, =E2=80=9Cnormal=E2=80=9D symlinks (i.e., not /pro= c/self/exe) will >> lead =E2=80=98canonPath=E2=80=99 to throw if one component is outside th= e store, since >> =E2=80=98canonPath=E2=80=99 operates within the chroot. > > Unless the component actually exists and is outside of the store. If we > just rely on canonPath throwing an exception to be safe, then if there > ever arose a situation where a non-symlink executable existed outside of > the store, it would still be possible to convince the daemon to execute > it. [...] > I mention this because I see that patch 07/16 of v7 has left out the > isInStore check, and I think it should remain. Hmm right (I was very much assuming that /proc/self/exe was the only non-store executable, but better be safe than sorry). Re-adding this: --=-=-= Content-Type: text/x-patch Content-Disposition: inline diff --git a/nix/libstore/build.cc b/nix/libstore/build.cc index 1733322316..d0fcc99854 100644 --- a/nix/libstore/build.cc +++ b/nix/libstore/build.cc @@ -2390,6 +2390,9 @@ void DerivationGoal::runChild() within the chroot. */ builderBasename = baseNameOf(drv.builder); drv.builder = canonPath(drv.builder, true); + + if (!isInStore(drv.builder)) + throw Error(format("derivation builder '%1%' is outside the store") % drv.builder); } /* Fill in the arguments. */ --=-=-= Content-Type: text/plain; charset=utf-8 Content-Transfer-Encoding: quoted-printable > While researching container escape vulnerabilities, I recently came > across CAP_DAC_READ_SEARCH and open_by_handle_at, which is a system call > so insanely powerful it is outright banned in all but the root user > namespace. Or at least, it was. 10 months ago, in commit > 620c266f394932e5decc4b34683a75dfc59dc2f4 of > https://github.com/torvalds/linux, the requirements were relaxed so > that, in certain cases, processes in non-root user namespaces could use > open_by_handle_at. The way =E2=80=98open_by_handle_at=E2=80=99 is documented (=E2=80=9Chalf=E2= =80=9D of =E2=80=98openat=E2=80=99) does not make it immediately obvious to me what makes it =E2=80=9Cpowerful=E2=80=9D.= I see the risk of a confused deputy problem though because of the =E2=80=98mount_id= =E2=80=99 argument in addition to =E2=80=98handle=E2=80=99. Is that what you have in= mind? > The consequences of this for same-user containers are not clear to me > yet, as I haven't studied the kernel source enough to know what exactly > that commit message means by "privileges over the filesystem" or > "privileges over a subtree". I also haven't been able to test this > behavior yet, because my kernel is actually too old (I do my rebases and > upgrades rather less regularly than is recommended). I'll try to look > into this more once I update my system (and man-pages!), but figured I > should mention it, because aside from that, and the aforementioned > isInStore check, I can't think of any remaining concerns. Alright. I=E2=80=99ll send v8 with the change above. Thanks again! Ludo=E2=80=99. --=-=-=--
guix-patches@HIDDEN
:bug#75810
; Package guix-patches
.
Full text available.Received: (at 75810) by debbugs.gnu.org; 21 Mar 2025 20:06:29 +0000 From debbugs-submit-bounces <at> debbugs.gnu.org Fri Mar 21 16:06:29 2025 Received: from localhost ([127.0.0.1]:39672 helo=debbugs.gnu.org) by debbugs.gnu.org with esmtp (Exim 4.84_2) (envelope-from <debbugs-submit-bounces <at> debbugs.gnu.org>) id 1tvidR-000128-2V for submit <at> debbugs.gnu.org; Fri, 21 Mar 2025 16:06:29 -0400 Received: from mailout.russelstein.xyz ([2605:6400:20:11e::1]:55762) by debbugs.gnu.org with esmtps (TLS1.2:ECDHE_RSA_AES_256_GCM_SHA384:256) (Exim 4.84_2) (envelope-from <reepca@HIDDEN>) id 1tvidN-00011t-9X for 75810 <at> debbugs.gnu.org; Fri, 21 Mar 2025 16:06:26 -0400 DKIM-Signature: v=1; a=ed25519-sha256; q=dns/txt; c=relaxed/relaxed; d=russelstein.xyz; s=ed25519; h=Content-Type:MIME-Version:Message-ID:Date: References:In-Reply-To:Subject:Cc:To:From:Sender:Reply-To: Content-Transfer-Encoding:Content-ID:Content-Description:Resent-Date: Resent-From:Resent-Sender:Resent-To:Resent-Cc:Resent-Message-ID:List-Id: List-Help:List-Unsubscribe:List-Subscribe:List-Post:List-Owner:List-Archive; bh=URzbx0sup6gNrdi49Xm9KUmjQNDCCV/yRL1C4+qchU4=; b=xo7wIYcDaSSceEJmhIwtiaKd1F wWG4GthaLj5OPE10vLRX6wQ40m0KpdZN6yyxi4oFc90zVV4Dp9kxrg4lR8CA==; DKIM-Signature: v=1; a=rsa-sha256; q=dns/txt; c=relaxed/relaxed; d=russelstein.xyz; s=rsa; h=Content-Type:MIME-Version:Message-ID:Date: References:In-Reply-To:Subject:Cc:To:From:Sender:Reply-To: Content-Transfer-Encoding:Content-ID:Content-Description:Resent-Date: Resent-From:Resent-Sender:Resent-To:Resent-Cc:Resent-Message-ID:List-Id: List-Help:List-Unsubscribe:List-Subscribe:List-Post:List-Owner:List-Archive; bh=URzbx0sup6gNrdi49Xm9KUmjQNDCCV/yRL1C4+qchU4=; b=RTJZRMXHCQb3zInK2zgwMrXt2Y tzBC5KuCkJO7BuOlbDHv3+H6hoCRHQyrtc9z8Bf7q99zS3gMKBUy5p3M9AgdFSoA2pzRJRkRPNaha rYFBGmp4+LiLtZ+6WKZrp90RPrBy1xwM1gEIr8vo24GEbFjGnnnWQ4awHwi/lsibBobqV8jgFmSO6 Fa1YncNIh2RcS16JIk+lVKPPGFbpEGCx57TpKed6OUekb5KtHs99W05tpCNpiyBDnjJmKt1/znDgW 7PdwwWrEqoRgiEShMDmGAeRE40Wl76dL829y9+xGjcrfSl5UzBvPiud7IlcwsZddNcrY7HXAmvldj Ls6K3pryaewJKgvd8NZoA9jWbROktStxxF+/zhbDetHBrFCC8nLTscNJ4ykVMGbGMdgtigR5hmbza oWmqZT+ilROmZc3XcXM/X5l3RWEbCf7qZz/bkbzYbeaKLcFmxNIenGwfbdPX6lsvnXjtNJE4Ay+To yXIsS8ZQ2oGIg4YRYAzXciG4giX7BxRT1CyHvYQArscmYdAqnkQ5TyBAPZT4QUcNo5ijeMIEyfsTh FSJu2zd8QQNPzsgvDuNIGLZ4rdA5g37jWghPNgZIXoIWAB02ToJgCGsk+9NDSLB8c+thSVDaShtlV pg3glo2OZK2Iy0Ob9CfSuAql47h4K92RedsBNyZYg=; Received: by russelstein.xyz with esmtpsa (TLS1.3:ECDHE_SECP256R1__RSA_PSS_RSAE_SHA256__AES_256_GCM:256) (Exim 4.98) (envelope-from <reepca@HIDDEN>) id 1tvhw6-000000003n5-3y4m; Fri, 21 Mar 2025 14:21:43 -0500 From: Reepca Russelstein <reepca@HIDDEN> To: Ludovic =?utf-8?Q?Court=C3=A8s?= <ludo@HIDDEN> Subject: Re: [bug#75810] [PATCH v6 00/16] Rootless guix-daemon In-Reply-To: <87tt7na08n.fsf@HIDDEN> ("Ludovic =?utf-8?Q?Court=C3=A8s=22'?= =?utf-8?Q?s?= message of "Thu, 20 Mar 2025 21:57:44 +0100") References: <cover.1742230219.git.ludo@HIDDEN> <875xk7594u.fsf@HIDDEN> <87v7s6h21b.fsf@HIDDEN> <871puu53mf.fsf@HIDDEN> <87tt7na08n.fsf@HIDDEN> User-Agent: Gnus/5.13 (Gnus v5.13) Date: Fri, 21 Mar 2025 14:21:06 -0500 Message-ID: <87iko2gpgd.fsf@HIDDEN> MIME-Version: 1.0 Content-Type: multipart/signed; boundary="=-=-="; micalg=pgp-sha256; protocol="application/pgp-signature" X-Spam-Score: 0.5 X-Spam-Bar: / X-Spam-Score-Int: 5 X-Spam-Report: Spam detection software, running on the system "Sanctum", has NOT identified this incoming email as spam. The original message has been attached to this so you can view it or label similar future email. If you have any questions, see the administrator of that system for details. Content preview: Ludovic Courtès <ludo@HIDDEN> writes: >> While ensuring that what actually gets execve'd is in the store suffices >> to eliminate the vulnerability, it may be "conceptually purer" to >> require that the links pointing to it are all in the [...] Content analysis details: (0.5 points, 5.0 required) pts rule name description ---- ---------------------- -------------------------------------------------- -0.0 NO_RELAYS Informational: message was not relayed via SMTP 0.5 FROM_SUSPICIOUS_NTLD From abused NTLD X-Spam-Score: 2.0 (++) X-Spam-Report: Spam detection software, running on the system "debbugs.gnu.org", has NOT identified this incoming email as spam. The original message has been attached to this so you can view it or label similar future email. If you have any questions, see the administrator of that system for details. Content preview: Ludovic Courtès <ludo@HIDDEN> writes: >> While ensuring that what actually gets execve'd is in the store suffices >> to eliminate the vulnerability, it may be "conceptually purer" to >> require that the links pointing to it are all in the [...] Content analysis details: (2.0 points, 10.0 required) pts rule name description ---- ---------------------- -------------------------------------------------- 1.5 PDS_OTHER_BAD_TLD Untrustworthy TLDs [URI: russelstein.xyz (xyz)] 0.0 SPF_HELO_NONE SPF: HELO does not publish an SPF Record -0.0 SPF_PASS SPF: sender matches SPF record 0.5 FROM_SUSPICIOUS_NTLD From abused NTLD X-Debbugs-Envelope-To: 75810 Cc: 75810 <at> debbugs.gnu.org X-BeenThere: debbugs-submit <at> debbugs.gnu.org X-Mailman-Version: 2.1.18 Precedence: list List-Id: <debbugs-submit.debbugs.gnu.org> List-Unsubscribe: <https://debbugs.gnu.org/cgi-bin/mailman/options/debbugs-submit>, <mailto:debbugs-submit-request <at> debbugs.gnu.org?subject=unsubscribe> List-Archive: <https://debbugs.gnu.org/cgi-bin/mailman/private/debbugs-submit/> List-Post: <mailto:debbugs-submit <at> debbugs.gnu.org> List-Help: <mailto:debbugs-submit-request <at> debbugs.gnu.org?subject=help> List-Subscribe: <https://debbugs.gnu.org/cgi-bin/mailman/listinfo/debbugs-submit>, <mailto:debbugs-submit-request <at> debbugs.gnu.org?subject=subscribe> Errors-To: debbugs-submit-bounces <at> debbugs.gnu.org Sender: "Debbugs-submit" <debbugs-submit-bounces <at> debbugs.gnu.org> X-Spam-Score: 2.0 (++) X-Spam-Report: Spam detection software, running on the system "debbugs.gnu.org", has NOT identified this incoming email as spam. The original message has been attached to this so you can view it or label similar future email. If you have any questions, see the administrator of that system for details. Content preview: Ludovic Courtès <ludo@HIDDEN> writes: >> While ensuring that what actually gets execve'd is in the store suffices >> to eliminate the vulnerability, it may be "conceptually purer" to >> require that the links pointing to it are all in the [...] Content analysis details: (2.0 points, 10.0 required) pts rule name description ---- ---------------------- -------------------------------------------------- 1.5 PDS_OTHER_BAD_TLD Untrustworthy TLDs [URI: russelstein.xyz (xyz)] 0.0 SPF_HELO_NONE SPF: HELO does not publish an SPF Record -0.0 SPF_PASS SPF: sender matches SPF record 0.5 FROM_SUSPICIOUS_NTLD From abused NTLD 1.0 BULK_RE_SUSP_NTLD Precedence bulk and RE: from a suspicious TLD -1.0 MAILING_LIST_MULTI Multiple indicators imply a widely-seen list manager --=-=-= Content-Type: text/plain; charset=utf-8 Content-Transfer-Encoding: quoted-printable Ludovic Court=C3=A8s <ludo@HIDDEN> writes: >> While ensuring that what actually gets execve'd is in the store suffices >> to eliminate the vulnerability, it may be "conceptually purer" to >> require that the links pointing to it are all in the store as well. For >> example, while a builder that is a symlink pointing to /proc/self/exe >> wouldn't be able to modify the daemon binary, it's still a piece of >> basically "undefined behavior" as far as the build environment is >> concerned, which could be closed up. But that can come later just as >> well. > > Yes. But in practice, =E2=80=9Cnormal=E2=80=9D symlinks (i.e., not /proc= /self/exe) will > lead =E2=80=98canonPath=E2=80=99 to throw if one component is outside the= store, since > =E2=80=98canonPath=E2=80=99 operates within the chroot. Unless the component actually exists and is outside of the store. If we just rely on canonPath throwing an exception to be safe, then if there ever arose a situation where a non-symlink executable existed outside of the store, it would still be possible to convince the daemon to execute it. For example, suppose Linus Torvalds wakes up one day and decides "you know what, it really is wrong that we're lying about /proc/self/exe being a symlink" and changes it so that lstat reports a regular file (or a special file, really anything other than a symlink) that happens to be a valid argument to readlink. Or suppose in the interest of backwards-compatibility he instead adds /proc/self/exe-hardlink. canonPath won't throw if a symlink points to these hypothetical files, and the daemon would execute them. A similar situation could also happen if an executable showed up in /dev somehow. I mention this because I see that patch 07/16 of v7 has left out the isInStore check, and I think it should remain. > Since we don=E2=80=99t have =E2=80=98Group=3D=E2=80=99 in the .service fi= le, the daemon runs as > the group of =E2=80=98guix-daemon=E2=80=99, also called =E2=80=98guix-dae= mon=E2=80=99 (created by > =E2=80=98guix-install.sh=E2=80=99). > > I confirmed in a VM that the process is indeed running as > guix-daemon:guix-daemon. Great. While researching container escape vulnerabilities, I recently came across CAP_DAC_READ_SEARCH and open_by_handle_at, which is a system call so insanely powerful it is outright banned in all but the root user namespace. Or at least, it was. 10 months ago, in commit 620c266f394932e5decc4b34683a75dfc59dc2f4 of https://github.com/torvalds/linux, the requirements were relaxed so that, in certain cases, processes in non-root user namespaces could use open_by_handle_at. The consequences of this for same-user containers are not clear to me yet, as I haven't studied the kernel source enough to know what exactly that commit message means by "privileges over the filesystem" or "privileges over a subtree". I also haven't been able to test this behavior yet, because my kernel is actually too old (I do my rebases and upgrades rather less regularly than is recommended). I'll try to look into this more once I update my system (and man-pages!), but figured I should mention it, because aside from that, and the aforementioned isInStore check, I can't think of any remaining concerns. =2D reepca --=-=-= Content-Type: application/pgp-signature; name="signature.asc" -----BEGIN PGP SIGNATURE----- iQFLBAEBCAA1FiEEdNapMPRLm4SepVYGwWaqSV9/GJwFAmfdvCIXHHJlZXBjYUBy dXNzZWxzdGVpbi54eXoACgkQwWaqSV9/GJw9cgf/YBq+fhpaQcMA0BV+svZuMRFI wfhWb4wDZMU44bFBjLiJx+2A8xS0IUqKIvjXgYvgE7gNLjOnUFoFBqFMuMQu/Sh6 OTwoJLTtFbTBWClh8Abdy414hsCleeQEa3MGRVQ84y4SYhJu2G7c98z4M3UwBLeG 7LM/zEErb/yZ9QraQroEb7LaoyclIe/wtO7BAv+VI5mawDzYnP89oJsMTDJj2PWm XCi5F/v/WaS4KjWlON7ouweKlmiovF/S8BjLcFTOhZjwFWt8msGv6C7Wd4+ivEfx V7ce3xMiOsSgtxwjky//ve6oKSEV500pB7sEKbCbdBGKWADemcM0P5+YCbjERg== =nOjg -----END PGP SIGNATURE----- --=-=-=--
guix-patches@HIDDEN
:bug#75810
; Package guix-patches
.
Full text available.Received: (at 75810) by debbugs.gnu.org; 20 Mar 2025 20:58:26 +0000 From debbugs-submit-bounces <at> debbugs.gnu.org Thu Mar 20 16:58:26 2025 Received: from localhost ([127.0.0.1]:59228 helo=debbugs.gnu.org) by debbugs.gnu.org with esmtp (Exim 4.84_2) (envelope-from <debbugs-submit-bounces <at> debbugs.gnu.org>) id 1tvMyA-0006jN-7n for submit <at> debbugs.gnu.org; Thu, 20 Mar 2025 16:58:26 -0400 Received: from hera.aquilenet.fr ([185.233.100.1]:48212) by debbugs.gnu.org with esmtps (TLS1.2:ECDHE_RSA_AES_256_GCM_SHA384:256) (Exim 4.84_2) (envelope-from <ludo@HIDDEN>) id 1tvMxd-0006db-6w for 75810 <at> debbugs.gnu.org; Thu, 20 Mar 2025 16:57:57 -0400 Received: from localhost (localhost [127.0.0.1]) by hera.aquilenet.fr (Postfix) with ESMTP id 6FB5883F; Thu, 20 Mar 2025 21:57:46 +0100 (CET) Authentication-Results: hera.aquilenet.fr; none X-Virus-Scanned: Debian amavis at hera.aquilenet.fr Received: from hera.aquilenet.fr ([127.0.0.1]) by localhost (hera.aquilenet.fr [127.0.0.1]) (amavis, port 10024) with ESMTP id ouPCQ2c0wPiZ; Thu, 20 Mar 2025 21:57:45 +0100 (CET) Received: from ribbon (91-160-117-201.subs.proxad.net [91.160.117.201]) by hera.aquilenet.fr (Postfix) with ESMTPSA id 1C5BE212; Thu, 20 Mar 2025 21:57:45 +0100 (CET) From: =?utf-8?Q?Ludovic_Court=C3=A8s?= <ludo@HIDDEN> To: Reepca Russelstein <reepca@HIDDEN> Subject: Re: [bug#75810] [PATCH v6 00/16] Rootless guix-daemon In-Reply-To: <871puu53mf.fsf@HIDDEN> (Reepca Russelstein's message of "Tue, 18 Mar 2025 18:19:04 -0500") References: <cover.1742230219.git.ludo@HIDDEN> <875xk7594u.fsf@HIDDEN> <87v7s6h21b.fsf@HIDDEN> <871puu53mf.fsf@HIDDEN> Date: Thu, 20 Mar 2025 21:57:44 +0100 Message-ID: <87tt7na08n.fsf@HIDDEN> User-Agent: Gnus/5.13 (Gnus v5.13) MIME-Version: 1.0 Content-Type: text/plain; charset=utf-8 Content-Transfer-Encoding: quoted-printable X-Rspamd-Queue-Id: 6FB5883F X-Spamd-Result: default: False [4.90 / 15.00]; SPAM_FLAG(5.00)[]; BAYES_HAM(-3.00)[100.00%]; NEURAL_SPAM(3.00)[1.000]; MIME_GOOD(-0.10)[text/plain]; RCVD_COUNT_TWO(0.00)[2]; FROM_EQ_ENVFROM(0.00)[]; MIME_TRACE(0.00)[0:+]; RCPT_COUNT_TWO(0.00)[2]; ARC_NA(0.00)[]; TO_MATCH_ENVRCPT_ALL(0.00)[]; RCVD_VIA_SMTP_AUTH(0.00)[]; RCVD_TLS_ALL(0.00)[]; FROM_HAS_DN(0.00)[]; TO_DN_SOME(0.00)[]; MID_RHS_MATCH_FROM(0.00)[] X-Spam-Level: **** X-Rspamd-Action: no action X-Spamd-Bar: ++++ X-Rspamd-Server: hera X-Spam-Score: 2.4 (++) X-Spam-Report: Spam detection software, running on the system "debbugs.gnu.org", has NOT identified this incoming email as spam. The original message has been attached to this so you can view it or label similar future email. If you have any questions, see the administrator of that system for details. Content preview: Hi, Reepca Russelstein <reepca@HIDDEN> skribis: >> The visible changes in the build environment are unfortunate; I’m hoping >> they won’t have any practical impact, not any more than the other >> parameters that may change currently (build UID, [...] Content analysis details: (2.4 points, 10.0 required) pts rule name description ---- ---------------------- -------------------------------------------------- 0.0 RCVD_IN_VALIDITY_SAFE_BLOCKED RBL: ADMINISTRATOR NOTICE: The query to Validity was blocked. See https://knowledge.validity.com/hc/en-us/articles/20961730681243 for more information. [185.233.100.1 listed in sa-accredit.habeas.com] 1.0 SPF_SOFTFAIL SPF: sender does not match SPF record (softfail) -0.0 SPF_HELO_PASS SPF: HELO matches SPF record 1.5 PDS_OTHER_BAD_TLD Untrustworthy TLDs [URI: russelstein.xyz (xyz)] 0.0 RCVD_IN_VALIDITY_RPBL_BLOCKED RBL: ADMINISTRATOR NOTICE: The query to Validity was blocked. See https://knowledge.validity.com/hc/en-us/articles/20961730681243 for more information. [185.233.100.1 listed in bl.score.senderscore.com] X-Debbugs-Envelope-To: 75810 Cc: 75810 <at> debbugs.gnu.org X-BeenThere: debbugs-submit <at> debbugs.gnu.org X-Mailman-Version: 2.1.18 Precedence: list List-Id: <debbugs-submit.debbugs.gnu.org> List-Unsubscribe: <https://debbugs.gnu.org/cgi-bin/mailman/options/debbugs-submit>, <mailto:debbugs-submit-request <at> debbugs.gnu.org?subject=unsubscribe> List-Archive: <https://debbugs.gnu.org/cgi-bin/mailman/private/debbugs-submit/> List-Post: <mailto:debbugs-submit <at> debbugs.gnu.org> List-Help: <mailto:debbugs-submit-request <at> debbugs.gnu.org?subject=help> List-Subscribe: <https://debbugs.gnu.org/cgi-bin/mailman/listinfo/debbugs-submit>, <mailto:debbugs-submit-request <at> debbugs.gnu.org?subject=subscribe> Errors-To: debbugs-submit-bounces <at> debbugs.gnu.org Sender: "Debbugs-submit" <debbugs-submit-bounces <at> debbugs.gnu.org> X-Spam-Score: 1.4 (+) X-Spam-Report: Spam detection software, running on the system "debbugs.gnu.org", has NOT identified this incoming email as spam. The original message has been attached to this so you can view it or label similar future email. If you have any questions, see the administrator of that system for details. Content preview: Hi, Reepca Russelstein <reepca@HIDDEN> skribis: >> The visible changes in the build environment are unfortunate; I’m hoping >> they won’t have any practical impact, not any more than the other >> parameters that may change currently (build UID, [...] Content analysis details: (1.4 points, 10.0 required) pts rule name description ---- ---------------------- -------------------------------------------------- 1.0 SPF_SOFTFAIL SPF: sender does not match SPF record (softfail) -0.0 SPF_HELO_PASS SPF: HELO matches SPF record 1.5 PDS_OTHER_BAD_TLD Untrustworthy TLDs [URI: russelstein.xyz (xyz)] 0.0 RCVD_IN_VALIDITY_SAFE_BLOCKED RBL: ADMINISTRATOR NOTICE: The query to Validity was blocked. See https://knowledge.validity.com/hc/en-us/articles/20961730681243 for more information. [185.233.100.1 listed in sa-trusted.bondedsender.org] 0.0 RCVD_IN_VALIDITY_RPBL_BLOCKED RBL: ADMINISTRATOR NOTICE: The query to Validity was blocked. See https://knowledge.validity.com/hc/en-us/articles/20961730681243 for more information. [185.233.100.1 listed in bl.score.senderscore.com] -1.0 MAILING_LIST_MULTI Multiple indicators imply a widely-seen list manager Hi, Reepca Russelstein <reepca@HIDDEN> skribis: >> The visible changes in the build environment are unfortunate; I=E2=80=99= m hoping >> they won=E2=80=99t have any practical impact, not any more than the other >> parameters that may change currently (build UID, binfmt_misc, file >> system, etc.) We could test this hypothesis by rebuilding at least the >> entire set of packages up to =E2=80=98hello=E2=80=99. (I tried doing it= just now in a >> Debian VM but failed since the main partition cannot easily be extended; >> it=E2=80=99ll be easier to do with Guix System.) >> > > For what it's worth, the visible changes could be avoided with > subordinate ids, as I wrote in > https://debbugs.gnu.org/cgi/bugreport.cgi?bug=3D75810#86. Yes. The newuidmap/newgidmap mechanism looks like a hack to me so I=E2=80= =99m reluctant, but if we have to, we could take that route. > We could try it as-is and see how it goes, and if there are problems > with reproducibility add on using subordinate ids. I would expect it to > be a much smaller change than the root->rootless transition. Yes. >> 1. If /proc/self/exe points to (say) /usr/bin/guix-daemon, outside the >> store, execve fails with ENOENT because that file is not mounted in >> the chroot. > > No, like I wrote, /proc/self/exe, despite being reported as a symlink by > stat, does not follow the usual symlink semantics. This is much like > how the files in /proc/self/fd work, e.g.: Oh right; apologies, and thanks for taking the time to (re)explain and to come up with a reproducer. > From 'man 2 execve': > > ENOENT The file pathname or a script *or ELF interpreter* does not= exist. > > (emphasis mine). The dynamic linker registered in guix-daemon's binary > is not likely to exist in the container in this test, but an attacker > could easily make it so as long as it's in the store. Yes. And it wouldn=E2=80=99t be so hard when one is running guix-daemon fr= om the store (from the =E2=80=98guix=E2=80=99 package or from =E2=80=98guix pu= ll=E2=80=99). >> + drv.builder =3D canonPath(drv.builder, true); >> + printMsg(lvlError, format("builder is `%1%'") % drv.builder); >> + if (!isInStore(drv.builder)) >> + throw Error(format("derivation builder '%1%' is outside the store") %= drv.builder); >> } >>=20=20 >> /* Fill in the arguments. */ > > Note that we should still supply the original name or basename as > argv[0]. Right, noted! > While ensuring that what actually gets execve'd is in the store suffices > to eliminate the vulnerability, it may be "conceptually purer" to > require that the links pointing to it are all in the store as well. For > example, while a builder that is a symlink pointing to /proc/self/exe > wouldn't be able to modify the daemon binary, it's still a piece of > basically "undefined behavior" as far as the build environment is > concerned, which could be closed up. But that can come later just as > well. Yes. But in practice, =E2=80=9Cnormal=E2=80=9D symlinks (i.e., not /proc/s= elf/exe) will lead =E2=80=98canonPath=E2=80=99 to throw if one component is outside the s= tore, since =E2=80=98canonPath=E2=80=99 operates within the chroot. > One more consideration I noticed when looking at v6's patch 14/16 (the > guix-daemon.service one): we don't do anything to set the gid. I know > on guix system we usually use both dedicated privilege separation users > and groups for services. Should we use a dedicated group for > guix-daemon as well? Note that currently the chroot directories have > 0750 permissions, so it's very important that their group not be > accessible to others. Quoth <https://www.freedesktop.org/software/systemd/man/latest/systemd.exec.html#= User=3D>: User=3D, Group=3D Set the UNIX user or group that the processes are executed as, respectively. [=E2=80=A6] If no group is set, the default group of the = user is used. Since we don=E2=80=99t have =E2=80=98Group=3D=E2=80=99 in the .service file= , the daemon runs as the group of =E2=80=98guix-daemon=E2=80=99, also called =E2=80=98guix-daemo= n=E2=80=99 (created by =E2=80=98guix-install.sh=E2=80=99). I confirmed in a VM that the process is indeed running as guix-daemon:guix-daemon. I=E2=80=99ve just sent v7 with the =E2=80=98canonPath=E2=80=99 change discu= ssed above. Thank you! Ludo=E2=80=99.
guix-patches@HIDDEN
:bug#75810
; Package guix-patches
.
Full text available.Received: (at 75810) by debbugs.gnu.org; 20 Mar 2025 20:57:38 +0000 From debbugs-submit-bounces <at> debbugs.gnu.org Thu Mar 20 16:57:38 2025 Received: from localhost ([127.0.0.1]:59211 helo=debbugs.gnu.org) by debbugs.gnu.org with esmtp (Exim 4.84_2) (envelope-from <debbugs-submit-bounces <at> debbugs.gnu.org>) id 1tvMxN-0006d7-DI for submit <at> debbugs.gnu.org; Thu, 20 Mar 2025 16:57:37 -0400 Received: from eggs.gnu.org ([2001:470:142:3::10]:43324) by debbugs.gnu.org with esmtps (TLS1.2:ECDHE_RSA_AES_256_GCM_SHA384:256) (Exim 4.84_2) (envelope-from <ludo@HIDDEN>) id 1tvMwK-0006TT-Vt for 75810 <at> debbugs.gnu.org; Thu, 20 Mar 2025 16:56:33 -0400 Received: from fencepost.gnu.org ([2001:470:142:3::e]) by eggs.gnu.org with esmtps (TLS1.2:ECDHE_RSA_AES_256_GCM_SHA384:256) (Exim 4.90_1) (envelope-from <ludo@HIDDEN>) id 1tvMwF-0001J7-Lk; Thu, 20 Mar 2025 16:56:27 -0400 DKIM-Signature: v=1; a=rsa-sha256; q=dns/txt; c=relaxed/relaxed; d=gnu.org; s=fencepost-gnu-org; h=MIME-Version:References:In-Reply-To:Date:Subject:To: From; bh=X0/tFNKBOJDt5zziEmv0iW9Ld3YPlqHLdNS+SKnSB7U=; b=cevL2Gf/CYTyg4yvzuB1 xwXI0lAbdVF790ZYrZBQhgBR/RaX/rrBb1/l4g1liuJGDRY7Go1gxHfjwiusIn265vPZYAMIYqMmW JaaeFBWP/azHs8L/QE5HyezgpUwAo/d+lPS6K3qTF02DJ2S+uyXPEU7EYD85RYDV7ls5XGH+mUFGx E3JzA/L7Ym4RRfz7B3Sv1mMOM0mSHQiCQrh6C91sO/8VBBun3P+94kwy8rfwSkDn7v1og7b3NXAam VZX6gxDgoct69KqYThbSYtzItUBpxhnIpCl7x9jyaW2FCBRhlJztXd7D4JM2Cd7+yeY4o7Oxwu8IH 1deVr7oKUffbjA==; From: =?UTF-8?q?Ludovic=20Court=C3=A8s?= <ludo@HIDDEN> To: 75810 <at> debbugs.gnu.org Subject: [PATCH v7 16/16] DRAFT gnu: guix: Update to f447941. Date: Thu, 20 Mar 2025 21:54:49 +0100 Message-ID: <2cc77c23147a687c75b2f300c7570b805e518944.1742503591.git.ludo@HIDDEN> X-Mailer: git-send-email 2.48.1 In-Reply-To: <cover.1742503590.git.ludo@HIDDEN> References: <cover.1742503590.git.ludo@HIDDEN> MIME-Version: 1.0 Content-Transfer-Encoding: 8bit X-Spam-Score: -2.3 (--) X-Debbugs-Envelope-To: 75810 Cc: =?UTF-8?q?Ludovic=20Court=C3=A8s?= <ludo@HIDDEN> X-BeenThere: debbugs-submit <at> debbugs.gnu.org X-Mailman-Version: 2.1.18 Precedence: list List-Id: <debbugs-submit.debbugs.gnu.org> List-Unsubscribe: <https://debbugs.gnu.org/cgi-bin/mailman/options/debbugs-submit>, <mailto:debbugs-submit-request <at> debbugs.gnu.org?subject=unsubscribe> List-Archive: <https://debbugs.gnu.org/cgi-bin/mailman/private/debbugs-submit/> List-Post: <mailto:debbugs-submit <at> debbugs.gnu.org> List-Help: <mailto:debbugs-submit-request <at> debbugs.gnu.org?subject=help> List-Subscribe: <https://debbugs.gnu.org/cgi-bin/mailman/listinfo/debbugs-submit>, <mailto:debbugs-submit-request <at> debbugs.gnu.org?subject=subscribe> Errors-To: debbugs-submit-bounces <at> debbugs.gnu.org Sender: "Debbugs-submit" <debbugs-submit-bounces <at> debbugs.gnu.org> X-Spam-Score: -3.3 (---) DRAFT: Temporary commit. * gnu/packages/package-management.scm (guix): Update to f447941. Change-Id: I16b10e721b98e8721bf206c3b3824407147d9649 --- gnu/packages/package-management.scm | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/gnu/packages/package-management.scm b/gnu/packages/package-management.scm index a4a96878f7..a5d5083993 100644 --- a/gnu/packages/package-management.scm +++ b/gnu/packages/package-management.scm @@ -179,8 +179,8 @@ (define-public guix ;; Note: the 'update-guix-package.scm' script expects this definition to ;; start precisely like this. (let ((version "1.4.0") - (commit "5058b40aba825ab6e7b9e518dd1147d1e35fd7de") - (revision 34)) + (commit "f447941a9c03769bfd17d3193a5aaad32342da53") + (revision 35)) (package (name "guix") @@ -196,7 +196,7 @@ (define-public guix (commit commit))) (sha256 (base32 - "04vk4lslcd6h22yj5pxvb1pdyyxd8421gjfyvyb1bl3xn7c77246")) + "10id738y2cpg74jjfz8i2k8phw5lgbz91zx0nl0109z0ag0har34")) (file-name (string-append "guix-" version "-checkout")))) (build-system gnu-build-system) (arguments -- 2.48.1
guix-patches@HIDDEN
:bug#75810
; Package guix-patches
.
Full text available.Received: (at 75810) by debbugs.gnu.org; 20 Mar 2025 20:57:37 +0000 From debbugs-submit-bounces <at> debbugs.gnu.org Thu Mar 20 16:57:37 2025 Received: from localhost ([127.0.0.1]:59209 helo=debbugs.gnu.org) by debbugs.gnu.org with esmtp (Exim 4.84_2) (envelope-from <debbugs-submit-bounces <at> debbugs.gnu.org>) id 1tvMxM-0006cx-8l for submit <at> debbugs.gnu.org; Thu, 20 Mar 2025 16:57:37 -0400 Received: from eggs.gnu.org ([2001:470:142:3::10]:43310) by debbugs.gnu.org with esmtps (TLS1.2:ECDHE_RSA_AES_256_GCM_SHA384:256) (Exim 4.84_2) (envelope-from <ludo@HIDDEN>) id 1tvMwK-0006TQ-MQ for 75810 <at> debbugs.gnu.org; Thu, 20 Mar 2025 16:56:33 -0400 Received: from fencepost.gnu.org ([2001:470:142:3::e]) by eggs.gnu.org with esmtps (TLS1.2:ECDHE_RSA_AES_256_GCM_SHA384:256) (Exim 4.90_1) (envelope-from <ludo@HIDDEN>) id 1tvMwE-0001Is-N2; Thu, 20 Mar 2025 16:56:26 -0400 DKIM-Signature: v=1; a=rsa-sha256; q=dns/txt; c=relaxed/relaxed; d=gnu.org; s=fencepost-gnu-org; h=MIME-Version:References:In-Reply-To:Date:Subject:To: From; bh=U9fQ0OTjBRU5j/IE3K+dWpDNxDzyNub8ZawVN/rMOKM=; b=ai2NwQ1KD8h7mDBYNmCQ fsseLN2VRnHwjgKZ3HxDBamvT9Kif2iSf1QwZikI2ECwVgB482gQWbZtwLeF4PGlpXKqGyZy1HxaT swE6+wRxpFnHC02QOnNRcYRAJVrMuD7QcV6ig3tVj80gI7xQegUB0SbNMHAkvQ6KU5xwN68XmfFgy UV0Hd693IhphjKnFr5bIk/HiQO2vZa1SiLsP2HS6kXrt4eoXtBQt1CGSaMEfvUKjHuR63y8prYLYr jKAnOiLDnTr+hRhx4kEJJ+WprPUmLd8RyZQBvEcVp+aC81tH4pD9SQ+XcyEydnB/3W4szFAkZxmiq 8E2OCTALPhWZCA==; From: =?UTF-8?q?Ludovic=20Court=C3=A8s?= <ludo@HIDDEN> To: 75810 <at> debbugs.gnu.org Subject: [PATCH v7 15/16] guix-install.sh: Support the unprivileged daemon where possible. Date: Thu, 20 Mar 2025 21:54:48 +0100 Message-ID: <f447941a9c03769bfd17d3193a5aaad32342da53.1742503591.git.ludo@HIDDEN> X-Mailer: git-send-email 2.48.1 In-Reply-To: <cover.1742503590.git.ludo@HIDDEN> References: <cover.1742503590.git.ludo@HIDDEN> MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit X-Spam-Score: -2.3 (--) X-Debbugs-Envelope-To: 75810 Cc: =?UTF-8?q?Ludovic=20Court=C3=A8s?= <ludo@HIDDEN> X-BeenThere: debbugs-submit <at> debbugs.gnu.org X-Mailman-Version: 2.1.18 Precedence: list List-Id: <debbugs-submit.debbugs.gnu.org> List-Unsubscribe: <https://debbugs.gnu.org/cgi-bin/mailman/options/debbugs-submit>, <mailto:debbugs-submit-request <at> debbugs.gnu.org?subject=unsubscribe> List-Archive: <https://debbugs.gnu.org/cgi-bin/mailman/private/debbugs-submit/> List-Post: <mailto:debbugs-submit <at> debbugs.gnu.org> List-Help: <mailto:debbugs-submit-request <at> debbugs.gnu.org?subject=help> List-Subscribe: <https://debbugs.gnu.org/cgi-bin/mailman/listinfo/debbugs-submit>, <mailto:debbugs-submit-request <at> debbugs.gnu.org?subject=subscribe> Errors-To: debbugs-submit-bounces <at> debbugs.gnu.org Sender: "Debbugs-submit" <debbugs-submit-bounces <at> debbugs.gnu.org> X-Spam-Score: -3.3 (---) * etc/guix-install.sh (create_account): New function. (sys_create_build_user): Use it. When ‘guix-daemon.service’ contains “User=guix-daemon” only create the ‘guix-daemon’ user and group. (sys_delete_build_user): Delete the ‘guix-daemon’ user and group. (can_install_unprivileged_daemon): New function. (sys_create_store): When installing the unprivileged daemon, change ownership of /gnu and /var/guix, and create /var/log/guix. (sys_authorize_build_farms): When the ‘guix-daemon’ account exists, change ownership of /etc/guix. Change-Id: I73e573f1cc5c0cb3794aaaa6b576616b66e0c5e9 --- etc/guix-install.sh | 124 +++++++++++++++++++++++++++++++++++--------- 1 file changed, 99 insertions(+), 25 deletions(-) diff --git a/etc/guix-install.sh b/etc/guix-install.sh index 8887204df4..b5d833cd64 100755 --- a/etc/guix-install.sh +++ b/etc/guix-install.sh @@ -414,6 +414,11 @@ sys_create_store() cd "$tmp_path" _msg_info "Installing /var/guix and /gnu..." # Strip (skip) the leading ‘.’ component, which fails on read-only ‘/’. + # + # TODO: Eventually extract with ‘--owner=guix-daemon’ when installing + # and unprivileged guix-daemon service; for now, this script may install + # from both an old release that does not support unprivileged guix-daemon + # and a new release that does, so ‘chown -R’ later if needed. tar --extract --strip-components=1 --file "$pkg" -C / _msg_info "Linking the root user's profile" @@ -441,38 +446,95 @@ sys_delete_store() rm -rf ~root/.config/guix } +create_account() +{ + local user="$1" + local group="$2" + local supplementary_groups="$3" + local comment="$4" + + if id "$user" &>/dev/null; then + _msg_info "user '$user' is already in the system, reset" + usermod -g "$group" -G "$supplementary_groups" \ + -d /var/empty -s "$(which nologin)" \ + -c "$comment" "$user" + else + useradd -g "$group" -G "$supplementary_groups" \ + -d /var/empty -s "$(which nologin)" \ + -c "$comment" --system "$user" + _msg_pass "user added <$user>" + fi +} + +install_unprivileged_daemon() +{ # Return true when installing guix-daemon running without privileges. + [ "$INIT_SYS" = systemd ] && \ + grep -q "User=guix-daemon" \ + ~root/.config/guix/current/lib/systemd/system/guix-daemon.service +} + sys_create_build_user() { # Create the group and user accounts for build users. _debug "--- [ ${FUNCNAME[0]} ] ---" - if getent group guixbuild > /dev/null; then - _msg_info "group guixbuild exists" - else - groupadd --system guixbuild - _msg_pass "group <guixbuild> created" - fi - if getent group kvm > /dev/null; then _msg_info "group kvm exists and build users will be added to it" local KVMGROUP=,kvm fi - for i in $(seq -w 1 10); do - if id "guixbuilder${i}" &>/dev/null; then - _msg_info "user is already in the system, reset" - usermod -g guixbuild -G guixbuild"$KVMGROUP" \ - -d /var/empty -s "$(which nologin)" \ - -c "Guix build user $i" \ - "guixbuilder${i}"; - else - useradd -g guixbuild -G guixbuild"$KVMGROUP" \ - -d /var/empty -s "$(which nologin)" \ - -c "Guix build user $i" --system \ - "guixbuilder${i}"; - _msg_pass "user added <guixbuilder${i}>" - fi - done + if install_unprivileged_daemon + then + _msg_info "installing guix-daemon to run as an unprivileged user" + + # Installing guix-daemon to run as a non-root user requires + # unprivileged user namespaces. + if [ -f /proc/sys/kernel/unprivileged_userns_clone ] \ + && [ "$(cat /proc/sys/kernel/unprivileged_userns_clone)" -ne 1 ] + then + echo 1 > /proc/sys/kernel/unprivileged_userns_clone || \ + _err "failed to enable unprivileged user namespaces" + + _msg_warn "Unprivileged user namespaces were disabled and have been enabled now." + _msg_warn "This Linux feature is required by guix-daemon. To enable it permanently, run:" + _msg_warn ' echo 1 > /proc/sys/kernel/unprivileged_userns_clone' + _msg_warn "from the relevant startup script." + fi + + + if getent group guix-daemon > /dev/null; then + _msg_info "group guix-daemon exists" + else + groupadd --system guix-daemon + _msg_pass "group guix-daemon created" + fi + + create_account guix-daemon guix-daemon \ + guix-daemon$KVMGROUP \ + "Unprivileged Guix Daemon User" + + # ‘tar xf’ creates root:root files. Change that. + chown -R guix-daemon:guix-daemon /gnu /var/guix + chown -R root:root /var/guix/profiles/per-user/root + + # The unprivileged daemon cannot create the log directory by itself. + mkdir -p /var/log/guix + chown guix-daemon:guix-daemon /var/log/guix + chmod 755 /var/log/guix + else + if getent group guixbuild > /dev/null; then + _msg_info "group guixbuild exists" + else + groupadd --system guixbuild + _msg_pass "group <guixbuild> created" + fi + + for i in $(seq -w 1 10); do + create_account "guixbuilder${i}" "guixbuild" \ + "guixbuild${KVMGROUP}" \ + "Guix build user $i" + done + fi } sys_delete_build_user() @@ -487,6 +549,14 @@ sys_delete_build_user() if getent group guixbuild &>/dev/null; then groupdel -f guixbuild fi + + _msg_info "remove guix-daemon user" + if id guix-daemon &>/dev/null; then + userdel -f guix-daemon + fi + if getent group guix-daemon &>/dev/null; then + groupdel -f guix-daemon + fi } sys_enable_guix_daemon() @@ -529,11 +599,11 @@ sys_enable_guix_daemon() # Install after guix-daemon.service to avoid a harmless warning. # systemd .mount units must be named after the target directory. - # Here we assume a hard-coded name of /gnu/store. - install_unit gnu-store.mount + install_unit gnu-store.mount systemctl daemon-reload && - systemctl start guix-daemon; } && + systemctl start guix-daemon && + systemctl start gnu-store.mount; } && _msg_pass "enabled Guix daemon via systemd" ;; sysv-init) @@ -654,6 +724,10 @@ project's build farms?"; then && guix archive --authorize < "$key" \ && _msg_pass "Authorized public key for $host" done + if id guix-daemon &>/dev/null; then + # /etc/guix/acl must be readable by the unprivileged guix-daemon. + chown -R guix-daemon:guix-daemon /etc/guix + fi else _msg_info "Skipped authorizing build farm public keys" fi -- 2.48.1
guix-patches@HIDDEN
:bug#75810
; Package guix-patches
.
Full text available.Received: (at 75810) by debbugs.gnu.org; 20 Mar 2025 20:57:36 +0000 From debbugs-submit-bounces <at> debbugs.gnu.org Thu Mar 20 16:57:36 2025 Received: from localhost ([127.0.0.1]:59207 helo=debbugs.gnu.org) by debbugs.gnu.org with esmtp (Exim 4.84_2) (envelope-from <debbugs-submit-bounces <at> debbugs.gnu.org>) id 1tvMxH-0006cG-Ja for submit <at> debbugs.gnu.org; Thu, 20 Mar 2025 16:57:36 -0400 Received: from eggs.gnu.org ([2001:470:142:3::10]:43294) by debbugs.gnu.org with esmtps (TLS1.2:ECDHE_RSA_AES_256_GCM_SHA384:256) (Exim 4.84_2) (envelope-from <ludo@HIDDEN>) id 1tvMwH-0006Sw-Uy for 75810 <at> debbugs.gnu.org; Thu, 20 Mar 2025 16:56:32 -0400 Received: from fencepost.gnu.org ([2001:470:142:3::e]) by eggs.gnu.org with esmtps (TLS1.2:ECDHE_RSA_AES_256_GCM_SHA384:256) (Exim 4.90_1) (envelope-from <ludo@HIDDEN>) id 1tvMwC-0001IW-Gi; Thu, 20 Mar 2025 16:56:24 -0400 DKIM-Signature: v=1; a=rsa-sha256; q=dns/txt; c=relaxed/relaxed; d=gnu.org; s=fencepost-gnu-org; h=MIME-Version:References:In-Reply-To:Date:Subject:To: From; bh=46sXtSC4BF2MFB1vCWkw8ErjEqxl/gPSRof2zzVtuu0=; b=aKUt1IwJzaNnU1l2dpCo PkGwFNCfZMx7OOaf+NZ5vf5okykq+PxpiL9IcjwOFg5pNHd/KVuOZohQdjSp4WRXg4+ALzGMxXO5q 08b6mlLHCV94vvE5pzdQ7SWAwU45qmkAnMoYo322xx3CQE/pymaQ0q/qG7s80N4HgeJJDkoMEMkri 0GbtDD09nr5b5CjorinxDqdMxP/IiARFAqW9tfuFFaaQU1anRRpL+lQsdc5XA2r+Eu+Tiu1LD2GNy wu2tkiMotuvyubZqcTDXNoXu1q6Bf62baCxT42PnSvCU1JhpXoZpQ3BDvTQo/SgtV6jZd2mUhriQ6 W03k1s9Y5KA0lw==; From: =?UTF-8?q?Ludovic=20Court=C3=A8s?= <ludo@HIDDEN> To: 75810 <at> debbugs.gnu.org Subject: [PATCH v7 13/16] tests: Run in a chroot and unprivileged user namespaces. Date: Thu, 20 Mar 2025 21:54:46 +0100 Message-ID: <335f3ea4e1f909e6ba8d7c95edbe78b56ea475da.1742503591.git.ludo@HIDDEN> X-Mailer: git-send-email 2.48.1 In-Reply-To: <cover.1742503590.git.ludo@HIDDEN> References: <cover.1742503590.git.ludo@HIDDEN> MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit X-Spam-Score: -2.3 (--) X-Debbugs-Envelope-To: 75810 Cc: =?UTF-8?q?Ludovic=20Court=C3=A8s?= <ludo@HIDDEN> X-BeenThere: debbugs-submit <at> debbugs.gnu.org X-Mailman-Version: 2.1.18 Precedence: list List-Id: <debbugs-submit.debbugs.gnu.org> List-Unsubscribe: <https://debbugs.gnu.org/cgi-bin/mailman/options/debbugs-submit>, <mailto:debbugs-submit-request <at> debbugs.gnu.org?subject=unsubscribe> List-Archive: <https://debbugs.gnu.org/cgi-bin/mailman/private/debbugs-submit/> List-Post: <mailto:debbugs-submit <at> debbugs.gnu.org> List-Help: <mailto:debbugs-submit-request <at> debbugs.gnu.org?subject=help> List-Subscribe: <https://debbugs.gnu.org/cgi-bin/mailman/listinfo/debbugs-submit>, <mailto:debbugs-submit-request <at> debbugs.gnu.org?subject=subscribe> Errors-To: debbugs-submit-bounces <at> debbugs.gnu.org Sender: "Debbugs-submit" <debbugs-submit-bounces <at> debbugs.gnu.org> X-Spam-Score: -3.3 (---) * build-aux/test-env.in: Pass ‘--disable-chroot’ only when unprivileged user namespace support is lacking and warn in that case. * tests/store.scm ("build-things, check mode"): Use ‘gettimeofday’ rather than a shared file as a source of entropy. ("symlink is symlink") ("isolated environment", "inputs are read-only") ("inputs cannot be remounted read-write") ("build root cannot be made world-readable") ("/tmp, store, and /dev/{null,full} are writable") ("network is unreachable"): New tests. * tests/processes.scm ("client + lock"): Skip when ‘unprivileged-user-namespace-supported?’ returns true. Change-Id: I3b3c3ebdf6db5fd36ee70251d07b893c17ca1b84 --- build-aux/test-env.in | 18 ++- tests/processes.scm | 9 +- tests/store.scm | 247 ++++++++++++++++++++++++++++++++++++------ 3 files changed, 236 insertions(+), 38 deletions(-) diff --git a/build-aux/test-env.in b/build-aux/test-env.in index 9caa29da58..86c2e585d7 100644 --- a/build-aux/test-env.in +++ b/build-aux/test-env.in @@ -1,7 +1,7 @@ #!/bin/sh # GNU Guix --- Functional package management for GNU -# Copyright © 2012, 2013, 2014, 2015, 2016, 2017, 2018, 2019, 2021 Ludovic Courtès <ludo@HIDDEN> +# Copyright © 2012-2019, 2021, 2025 Ludovic Courtès <ludo@HIDDEN> # # This file is part of GNU Guix. # @@ -102,10 +102,24 @@ then rm -rf "$GUIX_STATE_DIRECTORY/daemon-socket" mkdir -m 0700 "$GUIX_STATE_DIRECTORY/daemon-socket" + # If unprivileged user namespaces are not supported, pass + # '--disable-chroot'. + if [ -f /proc/self/ns/user ] \ + && { [ ! -f /proc/sys/kernel/unprivileged_userns_clone ] \ + || [ "$(cat /proc/sys/kernel/unprivileged_userns_clone)" -eq 1 ]; } + then + extra_options="" + else + extra_options="--disable-chroot" + echo "unprivileged user namespaces not supported; \ +running 'guix-daemon $extra_options'" >&2 + fi + # Launch the daemon without chroot support because is may be # unavailable, for instance if we're not running as root. "@abs_top_builddir@/pre-inst-env" \ - "@abs_top_builddir@/guix-daemon" --disable-chroot \ + "@abs_top_builddir@/guix-daemon" \ + $extra_options \ --substitute-urls="$GUIX_BINARY_SUBSTITUTE_URL" & daemon_pid=$! diff --git a/tests/processes.scm b/tests/processes.scm index ba518f2d9e..a72ba16f58 100644 --- a/tests/processes.scm +++ b/tests/processes.scm @@ -1,5 +1,5 @@ ;;; GNU Guix --- Functional package management for GNU -;;; Copyright © 2018 Ludovic Courtès <ludo@HIDDEN> +;;; Copyright © 2018, 2025 Ludovic Courtès <ludo@HIDDEN> ;;; Copyright © 2019 Mathieu Othacehe <m.othacehe@HIDDEN> ;;; ;;; This file is part of GNU Guix. @@ -25,6 +25,8 @@ (define-module (test-processes) #:use-module (guix gexp) #:use-module ((guix utils) #:select (call-with-temporary-directory)) #:use-module (gnu packages bootstrap) + #:use-module ((gnu build linux-container) + #:select (unprivileged-user-namespace-supported?)) #:use-module (guix tests) #:use-module (srfi srfi-1) #:use-module (srfi srfi-64) @@ -84,6 +86,11 @@ (define-syntax-rule (test-assert* description exp) (and (kill (process-id daemon) 0) (string-suffix? "guix-daemon" (first (process-command daemon))))))) +(when (unprivileged-user-namespace-supported?) + ;; The test below assumes the build process can communicate with the outside + ;; world via the TOKEN1 and TOKEN2 files, which is impossible when + ;; guix-daemon is set up to build in separate namespaces. + (test-skip 1)) (test-assert* "client + lock" (with-store store (call-with-temporary-directory diff --git a/tests/store.scm b/tests/store.scm index 45948f4f43..b1ddff2082 100644 --- a/tests/store.scm +++ b/tests/store.scm @@ -1,5 +1,5 @@ ;;; GNU Guix --- Functional package management for GNU -;;; Copyright © 2012-2021, 2023 Ludovic Courtès <ludo@HIDDEN> +;;; Copyright © 2012-2021, 2023, 2025 Ludovic Courtès <ludo@HIDDEN> ;;; ;;; This file is part of GNU Guix. ;;; @@ -28,8 +28,12 @@ (define-module (test-store) #:use-module (guix base32) #:use-module (guix packages) #:use-module (guix derivations) + #:use-module ((guix modules) + #:select (source-module-closure)) #:use-module (guix serialization) #:use-module (guix build utils) + #:use-module ((gnu build linux-container) + #:select (unprivileged-user-namespace-supported?)) #:use-module (guix gexp) #:use-module (gnu packages) #:use-module (gnu packages bootstrap) @@ -391,6 +395,188 @@ (define %shell (equal? (valid-derivers %store o) (list (derivation-file-name d)))))) +(test-assert "symlink is symlink" + (let* ((a (add-text-to-store %store "hello.txt" (random-text))) + (b (build-expression->derivation + %store "symlink" + '(symlink (assoc-ref %build-inputs "a") %output) + #:inputs `(("a" ,a)))) + (c (build-expression->derivation + %store "symlink-reference" + `(call-with-output-file %output + (lambda (port) + ;; Check that B is indeed visible as a symlink. This should + ;; always be the case, both in the '--disable-chroot' and in + ;; the user namespace setups. + (pk 'stat (lstat (assoc-ref %build-inputs "b"))) + (display (readlink (assoc-ref %build-inputs "b")) + port))) + #:inputs `(("b" ,b))))) + (and (build-derivations %store (list c)) + (string=? (call-with-input-file (derivation->output-path c) + get-string-all) + a)))) + +(unless (unprivileged-user-namespace-supported?) + (test-skip 1)) +(test-equal "isolated environment" + (string-join (append + '("PID: 1" "UID: 30001") + (delete-duplicates + (sort (list "/dev" "/tmp" "/proc" "/etc" + (match (string-tokenize (%store-prefix) + (char-set-complement + (char-set #\/))) + ((top _ ...) (string-append "/" top)))) + string<?)) + '("/etc/group" "/etc/hosts" "/etc/passwd"))) + (let* ((b (add-text-to-store %store "build.sh" + "echo -n PID: $$ UID: $UID /* /etc/* > $out")) + (s (add-to-store %store "bash" #t "sha256" + (search-bootstrap-binary "bash" + (%current-system)))) + (d (derivation %store "the-thing" + s `("-e" ,b) + #:env-vars `(("foo" . ,(random-text))) + #:sources (list b s))) + (o (derivation->output-path d))) + (and (build-derivations %store (list d)) + (call-with-input-file o get-string-all)))) + +(unless (unprivileged-user-namespace-supported?) + (test-skip 1)) +(test-equal "inputs are read-only" + "All good!" + (let* ((input (plain-file (string-append "might-be-tampered-with-" + (number->string + (car (gettimeofday)) + 16)) + "All good!")) + (drv + (run-with-store %store + (gexp->derivation + "attempt-to-write-to-input" + (with-imported-modules (source-module-closure + '((guix build syscalls))) + #~(begin + (use-modules (guix build syscalls)) + + (let ((input #$input)) + (chmod input #o666) + (call-with-output-file input + (lambda (port) + (display "BAD!" port))) + (mkdir #$output)))))))) + (and (guard (c ((store-protocol-error? c) #t)) + (build-derivations %store (list drv))) + (call-with-input-file (run-with-store %store + (lower-object input)) + get-string-all)))) + +(unless (unprivileged-user-namespace-supported?) + (test-skip 1)) +(test-assert "inputs cannot be remounted read-write" + (let ((drv + (run-with-store %store + (gexp->derivation + "attempt-to-remount-input-read-write" + (with-imported-modules (source-module-closure + '((guix build syscalls))) + #~(begin + (use-modules (guix build syscalls)) + + (let ((input #$(plain-file "input-that-might-be-tampered-with" + "All good!"))) + (mount "none" input "none" (logior MS_BIND MS_REMOUNT)) + (call-with-output-file input + (lambda (port) + (display "BAD!" port))) + (mkdir #$output)))))))) + (guard (c ((store-protocol-error? c) #t)) + (build-derivations %store (list drv)) + #f))) + +(unless (unprivileged-user-namespace-supported?) + (test-skip 1)) +(test-assert "build root cannot be made world-readable" + (let ((drv + (run-with-store %store + (gexp->derivation + "attempt-to-make-root-world-readable" + (with-imported-modules (source-module-closure + '((guix build syscalls))) + #~(begin + (use-modules (guix build syscalls)) + + (catch 'system-error + (lambda () + (chmod "/" #o777)) + (lambda args + (format #t "failed to make root writable: ~a~%" + (strerror (system-error-errno args))) + (format #t "attempting read-write remount~%") + (mount "none" "/" "/" (logior MS_BIND MS_REMOUNT)) + (chmod "/" #o777))) + + ;; At this point, the build process could create a + ;; world-readable setuid binary under its root (so in the + ;; store) that would remain visible until the build + ;; completes. + (mkdir #$output))))))) + (guard (c ((store-protocol-error? c) #t)) + (build-derivations %store (list drv)) + #f))) + +(unless (unprivileged-user-namespace-supported?) + (test-skip 1)) +(test-assert "/tmp, store, and /dev/{null,full} are writable" + ;; All of /tmp and all of the store must be writable (the store is writable + ;; so that derivation outputs can be written to it, but in practice it's + ;; always been wide open). Things like /dev/null must be writable too. + (let ((drv (run-with-store %store + (gexp->derivation + "check-tmp-and-store-are-writable" + #~(begin + (mkdir "/tmp/something") + (mkdir (in-vicinity (getenv "NIX_STORE") + "some-other-thing")) + (call-with-output-file "/dev/null" + (lambda (port) + (display "Welcome to the void." port))) + (catch 'system-error + (lambda () + (call-with-output-file "/dev/full" + (lambda (port) + (display "No space left!" port))) + (error "Should have thrown!")) + (lambda args + (unless (= ENOSPC (system-error-errno args)) + (apply throw args)))) + (mkdir #$output)))))) + (build-derivations %store (list drv)))) + +(unless (unprivileged-user-namespace-supported?) + (test-skip 1)) +(test-assert "network is unreachable" + (let ((drv (run-with-store %store + (gexp->derivation + "check-network-unreachable" + #~(let ((check-connection-failure + (lambda (address expected-code) + (let ((s (socket AF_INET SOCK_STREAM 0))) + (catch 'system-error + (lambda () + (connect s AF_INET (inet-pton AF_INET address) 80)) + (lambda args + (let ((errno (system-error-errno args))) + (unless (= expected-code errno) + (error "wrong error code" + errno (strerror errno)))))))))) + (check-connection-failure "127.0.0.1" ECONNREFUSED) + (check-connection-failure "9.9.9.9" ENETUNREACH) + (mkdir #$output)))))) + (build-derivations %store (list drv)))) + (test-equal "with-build-handler" 'success (let* ((b (add-text-to-store %store "build" "echo $foo > $out" '())) @@ -1333,40 +1519,31 @@ (define %shell (test-assert "build-things, check mode" (with-store store - (call-with-temporary-output-file - (lambda (entropy entropy-port) - (write (random-text) entropy-port) - (force-output entropy-port) - (let* ((drv (build-expression->derivation - store "non-deterministic" - `(begin - (use-modules (rnrs io ports)) - (let ((out (assoc-ref %outputs "out"))) - (call-with-output-file out - (lambda (port) - ;; Rely on the fact that tests do not use the - ;; chroot, and thus ENTROPY is readable. - (display (call-with-input-file ,entropy - get-string-all) - port))) - #t)) - #:guile-for-build - (package-derivation store %bootstrap-guile (%current-system)))) - (file (derivation->output-path drv))) - (and (build-things store (list (derivation-file-name drv))) - (begin - (write (random-text) entropy-port) - (force-output entropy-port) - (guard (c ((store-protocol-error? c) - (pk 'determinism-exception c) - (and (not (zero? (store-protocol-error-status c))) - (string-contains (store-protocol-error-message c) - "deterministic")))) - ;; This one will produce a different result. Since we're in - ;; 'check' mode, this must fail. - (build-things store (list (derivation-file-name drv)) - (build-mode check)) - #f)))))))) + (let* ((drv (build-expression->derivation + store "non-deterministic" + `(begin + (use-modules (rnrs io ports)) + (let ((out (assoc-ref %outputs "out"))) + (call-with-output-file out + (lambda (port) + (let ((now (gettimeofday))) + (display (+ (car now) (cdr now)) port)))) + #t)) + #:guile-for-build + (package-derivation store %bootstrap-guile (%current-system)))) + (file (derivation->output-path drv))) + (and (build-things store (list (derivation-file-name drv))) + (begin + (guard (c ((store-protocol-error? c) + (pk 'determinism-exception c) + (and (not (zero? (store-protocol-error-status c))) + (string-contains (store-protocol-error-message c) + "deterministic")))) + ;; This one will produce a different result. Since we're in + ;; 'check' mode, this must fail. + (build-things store (list (derivation-file-name drv)) + (build-mode check)) + #f)))))) (test-assert "build-succeeded trace in check mode" (string-contains -- 2.48.1
guix-patches@HIDDEN
:bug#75810
; Package guix-patches
.
Full text available.Received: (at 75810) by debbugs.gnu.org; 20 Mar 2025 20:57:32 +0000 From debbugs-submit-bounces <at> debbugs.gnu.org Thu Mar 20 16:57:31 2025 Received: from localhost ([127.0.0.1]:59205 helo=debbugs.gnu.org) by debbugs.gnu.org with esmtp (Exim 4.84_2) (envelope-from <debbugs-submit-bounces <at> debbugs.gnu.org>) id 1tvMxF-0006bn-P3 for submit <at> debbugs.gnu.org; Thu, 20 Mar 2025 16:57:31 -0400 Received: from eggs.gnu.org ([2001:470:142:3::10]:43258) by debbugs.gnu.org with esmtps (TLS1.2:ECDHE_RSA_AES_256_GCM_SHA384:256) (Exim 4.84_2) (envelope-from <ludo@HIDDEN>) id 1tvMwE-0006SE-Pr for 75810 <at> debbugs.gnu.org; Thu, 20 Mar 2025 16:56:29 -0400 Received: from fencepost.gnu.org ([2001:470:142:3::e]) by eggs.gnu.org with esmtps (TLS1.2:ECDHE_RSA_AES_256_GCM_SHA384:256) (Exim 4.90_1) (envelope-from <ludo@HIDDEN>) id 1tvMw9-0001HX-0I; Thu, 20 Mar 2025 16:56:21 -0400 DKIM-Signature: v=1; a=rsa-sha256; q=dns/txt; c=relaxed/relaxed; d=gnu.org; s=fencepost-gnu-org; h=MIME-Version:References:In-Reply-To:Date:Subject:To: From; bh=s48JGBS7+1eAYxbQMZkgTk7NEwh17Swmtw6Ux+K/rLQ=; b=jofrqaIlcnE0qa/Wdx9w Pk5rZFUUnlnv7jh759fKfrteiU8+/3PW5taUW4+QmwimtAaDQrWHFuuk5ry8XgCiBnXN8YJG183DT WYQx8d9VM4cWKHXRSokrXfECVQJMqHGZBK7B1tGrC9ulSy95CFrLnPiBjWgM5EvzF+J/8hTRQ2oUC kpDJRuY0rjn5LVKVp+B4RXU+UmUs0uUaFiY4JDkbRMyP00o8oZLhBA9iQoHOLbbcjcEXvslVPuJj/ +Oav9uClWkDcPzhZZ6AAt/lAWxzudcxt5eem5JU7B0bpn8D6E8I6SV6AxTQWXSS2gI3HPP3X01qb1 eNuFW0Kjc76rjQ==; From: =?UTF-8?q?Ludovic=20Court=C3=A8s?= <ludo@HIDDEN> To: 75810 <at> debbugs.gnu.org Subject: [PATCH v7 10/16] daemon: Move comments where they belong. Date: Thu, 20 Mar 2025 21:54:43 +0100 Message-ID: <f414a5fe952d94ad1bf12bd683530c1fa293ccdc.1742503591.git.ludo@HIDDEN> X-Mailer: git-send-email 2.48.1 In-Reply-To: <cover.1742503590.git.ludo@HIDDEN> References: <cover.1742503590.git.ludo@HIDDEN> MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit X-Spam-Score: -2.3 (--) X-Debbugs-Envelope-To: 75810 Cc: =?UTF-8?q?Ludovic=20Court=C3=A8s?= <ludo@HIDDEN> X-BeenThere: debbugs-submit <at> debbugs.gnu.org X-Mailman-Version: 2.1.18 Precedence: list List-Id: <debbugs-submit.debbugs.gnu.org> List-Unsubscribe: <https://debbugs.gnu.org/cgi-bin/mailman/options/debbugs-submit>, <mailto:debbugs-submit-request <at> debbugs.gnu.org?subject=unsubscribe> List-Archive: <https://debbugs.gnu.org/cgi-bin/mailman/private/debbugs-submit/> List-Post: <mailto:debbugs-submit <at> debbugs.gnu.org> List-Help: <mailto:debbugs-submit-request <at> debbugs.gnu.org?subject=help> List-Subscribe: <https://debbugs.gnu.org/cgi-bin/mailman/listinfo/debbugs-submit>, <mailto:debbugs-submit-request <at> debbugs.gnu.org?subject=subscribe> Errors-To: debbugs-submit-bounces <at> debbugs.gnu.org Sender: "Debbugs-submit" <debbugs-submit-bounces <at> debbugs.gnu.org> X-Spam-Score: -3.3 (---) * nix/libstore/build.cc (DerivationGoal::startBuilder): Shuffle comments for clarity. Change-Id: I6557c103ade4a3ab046354548ea193c68f8c9c05 --- nix/libstore/build.cc | 13 +++++++------ 1 file changed, 7 insertions(+), 6 deletions(-) diff --git a/nix/libstore/build.cc b/nix/libstore/build.cc index fa0f293aac..1733322316 100644 --- a/nix/libstore/build.cc +++ b/nix/libstore/build.cc @@ -1870,18 +1870,19 @@ void DerivationGoal::startBuilder() } dirsInChroot[tmpDirInSandbox] = tmpDir; - /* Make the closure of the inputs available in the chroot, - rather than the whole store. This prevents any access - to undeclared dependencies. !!! As an extra security - precaution, make the fake store only writable by the - build user. */ + /* Create the fake store. */ Path chrootStoreDir = chrootRootDir + settings.nixStore; createDirs(chrootStoreDir); chmod_(chrootStoreDir, 01775); if (buildUser.enabled() && chown(chrootStoreDir.c_str(), 0, buildUser.getGID()) == -1) - throw SysError(format("cannot change ownership of ‘%1%’") % chrootStoreDir); + /* As an extra security precaution, make the fake store only + writable by the build user. */ + throw SysError(format("cannot change ownership of ‘%1%’") % chrootStoreDir); + /* Make the closure of the inputs available in the chroot, rather than + the whole store. This prevents any access to undeclared + dependencies. */ foreach (PathSet::iterator, i, inputPaths) { struct stat st; if (lstat(i->c_str(), &st)) -- 2.48.1
guix-patches@HIDDEN
:bug#75810
; Package guix-patches
.
Full text available.Received: (at 75810) by debbugs.gnu.org; 20 Mar 2025 20:57:30 +0000 From debbugs-submit-bounces <at> debbugs.gnu.org Thu Mar 20 16:57:29 2025 Received: from localhost ([127.0.0.1]:59203 helo=debbugs.gnu.org) by debbugs.gnu.org with esmtp (Exim 4.84_2) (envelope-from <debbugs-submit-bounces <at> debbugs.gnu.org>) id 1tvMxE-0006bY-KI for submit <at> debbugs.gnu.org; Thu, 20 Mar 2025 16:57:29 -0400 Received: from eggs.gnu.org ([2001:470:142:3::10]:43246) by debbugs.gnu.org with esmtps (TLS1.2:ECDHE_RSA_AES_256_GCM_SHA384:256) (Exim 4.84_2) (envelope-from <ludo@HIDDEN>) id 1tvMwE-0006S5-AM for 75810 <at> debbugs.gnu.org; Thu, 20 Mar 2025 16:56:27 -0400 Received: from fencepost.gnu.org ([2001:470:142:3::e]) by eggs.gnu.org with esmtps (TLS1.2:ECDHE_RSA_AES_256_GCM_SHA384:256) (Exim 4.90_1) (envelope-from <ludo@HIDDEN>) id 1tvMw4-0001Gq-Ti; Thu, 20 Mar 2025 16:56:20 -0400 DKIM-Signature: v=1; a=rsa-sha256; q=dns/txt; c=relaxed/relaxed; d=gnu.org; s=fencepost-gnu-org; h=MIME-Version:References:In-Reply-To:Date:Subject:To: From; bh=wZDaJpSBiec4HWURn73Fvz7bhdz1AmvaDkV9vu9Mxas=; b=d5vsrWNB3mXIzROjoTEK rnb9lRejIfyOhi/N1PzaOSMsDvnOXIrlAhjgfR2qINZDNvCE6HcsBtgSpK/y/ApscQIdnvsPopugj 5vz8vbGOUTruf0+uBOLzJ60EJEpqybWdHaJ2b2ygwIXIp0UXM0mgoHQeGxq6PR7UVd9vdw0Yw9KvR 6nKSZHAk9A9WOUUGam7Je48UMtg51CMEXlGl7eoRb/dgdPdPEBQ86wlnZ9+/Hw8chVdKFvjELaI8O ggiIG35/Gxat/ZnLntXkVz8EuzQk/3ej7HWjO0NQ5riQea+b8yWD0skQzrj12DxXLgVszhWBXG2kJ UsmPvDlkGdjsIg==; From: =?UTF-8?q?Ludovic=20Court=C3=A8s?= <ludo@HIDDEN> To: 75810 <at> debbugs.gnu.org Subject: [PATCH v7 08/16] daemon: Create /var/guix/profiles/per-user unconditionally. Date: Thu, 20 Mar 2025 21:54:41 +0100 Message-ID: <9267d0a9de0def5e4dd30fb3c2e420b116ddb5af.1742503591.git.ludo@HIDDEN> X-Mailer: git-send-email 2.48.1 In-Reply-To: <cover.1742503590.git.ludo@HIDDEN> References: <cover.1742503590.git.ludo@HIDDEN> MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit X-Spam-Score: -2.3 (--) X-Debbugs-Envelope-To: 75810 Cc: =?UTF-8?q?Ludovic=20Court=C3=A8s?= <ludo@HIDDEN> X-BeenThere: debbugs-submit <at> debbugs.gnu.org X-Mailman-Version: 2.1.18 Precedence: list List-Id: <debbugs-submit.debbugs.gnu.org> List-Unsubscribe: <https://debbugs.gnu.org/cgi-bin/mailman/options/debbugs-submit>, <mailto:debbugs-submit-request <at> debbugs.gnu.org?subject=unsubscribe> List-Archive: <https://debbugs.gnu.org/cgi-bin/mailman/private/debbugs-submit/> List-Post: <mailto:debbugs-submit <at> debbugs.gnu.org> List-Help: <mailto:debbugs-submit-request <at> debbugs.gnu.org?subject=help> List-Subscribe: <https://debbugs.gnu.org/cgi-bin/mailman/listinfo/debbugs-submit>, <mailto:debbugs-submit-request <at> debbugs.gnu.org?subject=subscribe> Errors-To: debbugs-submit-bounces <at> debbugs.gnu.org Sender: "Debbugs-submit" <debbugs-submit-bounces <at> debbugs.gnu.org> X-Spam-Score: -3.3 (---) * nix/libstore/local-store.cc (LocalStore::LocalStore): Create ‘perUserDir’ unconditionally. Change-Id: I5188320f9630a81d16f79212d0fffabd55d94abe --- nix/libstore/local-store.cc | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/nix/libstore/local-store.cc b/nix/libstore/local-store.cc index 83e6c3e16e..f6540c2117 100644 --- a/nix/libstore/local-store.cc +++ b/nix/libstore/local-store.cc @@ -79,12 +79,12 @@ LocalStore::LocalStore(bool reserveSpace) createSymlink(profilesDir, gcRootsDir + "/profiles"); } - /* Optionally, create directories and set permissions for a - multi-user install. */ + Path perUserDir = profilesDir + "/per-user"; + createDirs(perUserDir); + + /* Optionally, set permissions for a multi-user install. */ if (getuid() == 0 && settings.buildUsersGroup != "") { - Path perUserDir = profilesDir + "/per-user"; - createDirs(perUserDir); if (chmod(perUserDir.c_str(), 0755) == -1) throw SysError(format("could not set permissions on '%1%' to 755") % perUserDir); -- 2.48.1
guix-patches@HIDDEN
:bug#75810
; Package guix-patches
.
Full text available.Received: (at 75810) by debbugs.gnu.org; 20 Mar 2025 20:57:29 +0000 From debbugs-submit-bounces <at> debbugs.gnu.org Thu Mar 20 16:57:28 2025 Received: from localhost ([127.0.0.1]:59201 helo=debbugs.gnu.org) by debbugs.gnu.org with esmtp (Exim 4.84_2) (envelope-from <debbugs-submit-bounces <at> debbugs.gnu.org>) id 1tvMxA-0006b4-W8 for submit <at> debbugs.gnu.org; Thu, 20 Mar 2025 16:57:28 -0400 Received: from eggs.gnu.org ([2001:470:142:3::10]:43264) by debbugs.gnu.org with esmtps (TLS1.2:ECDHE_RSA_AES_256_GCM_SHA384:256) (Exim 4.84_2) (envelope-from <ludo@HIDDEN>) id 1tvMwF-0006SL-0A for 75810 <at> debbugs.gnu.org; Thu, 20 Mar 2025 16:56:32 -0400 Received: from fencepost.gnu.org ([2001:470:142:3::e]) by eggs.gnu.org with esmtps (TLS1.2:ECDHE_RSA_AES_256_GCM_SHA384:256) (Exim 4.90_1) (envelope-from <ludo@HIDDEN>) id 1tvMw2-0001GU-Fm; Thu, 20 Mar 2025 16:56:14 -0400 DKIM-Signature: v=1; a=rsa-sha256; q=dns/txt; c=relaxed/relaxed; d=gnu.org; s=fencepost-gnu-org; h=MIME-Version:References:In-Reply-To:Date:Subject:To: From; bh=YoCVmhHTeo9VRQVHqR2FhxsLwN9CxAbYohnVIH94Xfs=; b=TIlWowZ6pThFHOND5fDr 5KQFktNS7xNGAoD1+s0r0FgtPKAta80VXYApAyiqV+O86gzSonKDlZKjUg1vPbki01mbu9EYL79ps DFjkKoGHKGCyxKx+cXJ8hEtF3k6m+DGSM1rgCRNmukUlZNzXdaKCq+2pjPhbqqcq0JglFsENoN9YK tDbHnHP3aXJID+eJI2wj2QOMArPsfVa1nQRoX0nC8BClohnz8pnVdyfFkA+xxU24Sd7Zv/BH9amiu G8Ea3/czjU6KwbM8AXzzCgZtL/p+10C0jfnxiVClL6nuBEzqp2o9aKJ+5PqOTgOqRTqMsig73Joef f+mcaiZqStS+FQ==; From: =?UTF-8?q?Ludovic=20Court=C3=A8s?= <ludo@HIDDEN> To: 75810 <at> debbugs.gnu.org Subject: [PATCH v7 07/16] daemon: Allow running as non-root with unprivileged user namespaces. Date: Thu, 20 Mar 2025 21:54:40 +0100 Message-ID: <bc290bad704192a56391e451ecab7a138fb86778.1742503591.git.ludo@HIDDEN> X-Mailer: git-send-email 2.48.1 In-Reply-To: <cover.1742503590.git.ludo@HIDDEN> References: <cover.1742503590.git.ludo@HIDDEN> MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 X-Debbugs-Cc: Christopher Baines <guix@HIDDEN>, Josselin Poiret <dev@HIDDEN>, Ludovic Courtès <ludo@HIDDEN>, Mathieu Othacehe <othacehe@HIDDEN>, Maxim Cournoyer <maxim.cournoyer@HIDDEN>, Simon Tournier <zimon.toutoune@HIDDEN>, Tobias Geerinckx-Rice <me@HIDDEN> Content-Transfer-Encoding: 8bit X-Spam-Score: -0.8 (/) X-Debbugs-Envelope-To: 75810 Cc: =?UTF-8?q?Ludovic=20Court=C3=A8s?= <ludovic.courtes@HIDDEN>, Reepca Russelstein <reepca@HIDDEN> X-BeenThere: debbugs-submit <at> debbugs.gnu.org X-Mailman-Version: 2.1.18 Precedence: list List-Id: <debbugs-submit.debbugs.gnu.org> List-Unsubscribe: <https://debbugs.gnu.org/cgi-bin/mailman/options/debbugs-submit>, <mailto:debbugs-submit-request <at> debbugs.gnu.org?subject=unsubscribe> List-Archive: <https://debbugs.gnu.org/cgi-bin/mailman/private/debbugs-submit/> List-Post: <mailto:debbugs-submit <at> debbugs.gnu.org> List-Help: <mailto:debbugs-submit-request <at> debbugs.gnu.org?subject=help> List-Subscribe: <https://debbugs.gnu.org/cgi-bin/mailman/listinfo/debbugs-submit>, <mailto:debbugs-submit-request <at> debbugs.gnu.org?subject=subscribe> Errors-To: debbugs-submit-bounces <at> debbugs.gnu.org Sender: "Debbugs-submit" <debbugs-submit-bounces <at> debbugs.gnu.org> X-Spam-Score: -1.8 (-) From: Ludovic Courtès <ludovic.courtes@HIDDEN> Many thanks to Reepca Russelstein for their review and guidance on these changes. * nix/libstore/build.cc (guestUID, guestGID): New variables. (DerivationGoal)[readiness]: New field. (initializeUserNamespace): New function. (DerivationGoal::runChild): When ‘readiness.readSide’ is positive, read from it. (DerivationGoal::startBuilder): Call ‘chown’ only when ‘buildUser.enabled()’ is true. Pass CLONE_NEWUSER to ‘clone’ when ‘buildUser.enabled()’ is false or not running as root. Retry ‘clone’ without CLONE_NEWUSER upon EPERM. (DerivationGoal::registerOutputs): Make ‘actualPath’ writable before ‘rename’. (DerivationGoal::deleteTmpDir): Catch ‘SysError’ around ‘_chown’ call. * nix/libstore/local-store.cc (LocalStore::createUser): Do nothing if ‘dirs’ already exists. Warn instead of failing when failing to chown ‘dir’. * guix/substitutes.scm (%narinfo-cache-directory): Check for ‘_NIX_OPTIONS’ rather than getuid() == 0 to determine the cache location. * doc/guix.texi (Build Environment Setup): Reorganize a bit. Add section headings “Daemon Running as Root” and “The Isolated Build Environment”. Add “Daemon Running Without Privileges” subsection. Remove paragraph about ‘--disable-chroot’. (Invoking guix-daemon): Warn against ‘--disable-chroot’ and explain why. * tests/derivations.scm ("builder is outside the store"): New test. Reviewed-by: Reepca Russelstein <reepca@HIDDEN> --- doc/guix.texi | 102 +++++++++++++++----- guix/substitutes.scm | 2 +- nix/libstore/build.cc | 180 +++++++++++++++++++++++++++++++----- nix/libstore/local-store.cc | 18 +++- tests/derivations.scm | 10 ++ 5 files changed, 257 insertions(+), 55 deletions(-) diff --git a/doc/guix.texi b/doc/guix.texi index fe43ed2504..ab9e21e42e 100644 --- a/doc/guix.texi +++ b/doc/guix.texi @@ -877,6 +877,7 @@ Setting Up the Daemon @section Setting Up the Daemon @cindex daemon +@cindex build daemon During installation, the @dfn{build daemon} that must be running to use Guix has already been set up and you can run @command{guix} commands in your terminal program, @pxref{Getting Started}: @@ -921,20 +922,38 @@ Build Environment Setup @cindex build environment In a standard multi-user setup, Guix and its daemon---the @command{guix-daemon} program---are installed by the system -administrator; @file{/gnu/store} is owned by @code{root} and -@command{guix-daemon} runs as @code{root}. Unprivileged users may use -Guix tools to build packages or otherwise access the store, and the -daemon will do it on their behalf, ensuring that the store is kept in a -consistent state, and allowing built packages to be shared among users. +administrator. Unprivileged users may use Guix tools to build packages +or otherwise access the store, and the daemon will do it on their +behalf, ensuring that the store is kept in a consistent state, and +allowing built packages to be shared among users. + +There are currently two ways to set up and run the build daemon: + +@enumerate +@item +running @command{guix-daemon} as ``root'', letting it run build +processes as unprivileged users taken from a pool of build users---this +is the historical approach; + +@item +running @command{guix-daemon} as a separate unprivileged user, relying +on Linux's @dfn{unprivileged user namespace} functionality to set up +isolated environments---this is the option chosen when installing Guix +on a systemd-based distribution with the installation script +(@pxref{Binary Installation}). +@end enumerate + +The sections below describe each of these two configurations in more +detail and summarize the kind of build isolation they provide. + +@unnumberedsubsubsec Daemon Running as Root @cindex build users When @command{guix-daemon} runs as @code{root}, you may not want package build processes themselves to run as @code{root} too, for obvious security reasons. To avoid that, a special pool of @dfn{build users} should be created for use by build processes started by the daemon. -These build users need not have a shell and a home directory: they will -just be used when the daemon drops @code{root} privileges in build -processes. Having several such users allows the daemon to launch +Having several such users allows the daemon to launch distinct build processes under separate UIDs, which guarantees that they do not interfere with each other---an essential feature since builds are regarded as pure functions (@pxref{Introduction}). @@ -977,11 +996,45 @@ Build Environment Setup # guix-daemon --build-users-group=guixbuild @end example +In this setup, @file{/gnu/store} is owned by @code{root}. + +@unnumberedsubsubsec Daemon Running Without Privileges + +@cindex rootless build daemon +@cindex unprivileged build daemon +@cindex build daemon, unprivileged +The second and preferred option is to run @command{guix-daemon} +@emph{as an unprivileged user}. It has the advantage of reducing the +harm that can be done should a build process manage to exploit a +vulnerability in the daemon. This option requires the use of Linux's +unprivileged user namespace mechanism; today it is available and enabled +by most GNU/Linux distributions but can still be disabled. The +installation script automatically determines whether this option is +available on your system (@pxref{Binary Installation}). + +When using this option, you only need to create one user account, and +@command{guix-daemon} will run with the authority of that account: + +@example +# groupadd --system guix-daemon +# useradd -g guix-daemon -G guix-daemon \ + -d /var/empty -s $(which nologin) \ + -c "Guix daemon privilege separation user" \ + --system guix-daemon +@end example + +In this configuration, @file{/gnu/store} is owned by the +@code{guix-daemon} user. + +@unnumberedsubsubsec The Isolated Build Environment + @cindex chroot -@noindent -This way, the daemon starts build processes in a chroot, under one of -the @code{guixbuilder} users. On GNU/Linux, by default, the chroot -environment contains nothing but: +@cindex build environment isolation +@cindex isolated build environment +@cindex hermetic build environment +In both cases, the daemon starts build processes without privileges in +an @emph{isolated} or @emph{hermetic} build environment---a ``chroot''. +On GNU/Linux, by default, the build environment contains nothing but: @c Keep this list in sync with libstore/build.cc! ----------------------- @itemize @@ -1015,7 +1068,7 @@ Build Environment Setup @file{/homeless-shelter}. This helps to highlight inappropriate uses of @env{HOME} in the build scripts of packages. -All this usually enough to ensure details of the environment do not +All this is usually enough to ensure details of the environment do not influence build processes. In some exceptional cases where more control is needed---typically over the date, kernel, or CPU---you can resort to a virtual build machine (@pxref{build-vm, virtual build machines}). @@ -1035,14 +1088,6 @@ Build Environment Setup for fixed-output derivations (@pxref{Derivations}) or for substitutes (@pxref{Substitutes}). -If you are installing Guix as an unprivileged user, it is still possible -to run @command{guix-daemon} provided you pass @option{--disable-chroot}. -However, build processes will not be isolated from one another, and not -from the rest of the system. Thus, build processes may interfere with -each other, and may access programs, libraries, and other files -available on the system---making it much harder to view them as -@emph{pure} functions. - @node Daemon Offload Setup @subsection Using the Offload Facility @@ -1567,10 +1612,17 @@ Invoking guix-daemon @item --disable-chroot Disable chroot builds. -Using this option is not recommended since, again, it would allow build -processes to gain access to undeclared dependencies. It is necessary, -though, when @command{guix-daemon} is running under an unprivileged user -account. +@quotation Warning +Using this option is not recommended since it allows build processes to +gain access to undeclared dependencies, to interfere with one another, +and more generally to do anything that can be done with the authority of +build users or that of the daemon---which includes at least the ability +to tamper with any file in the store! + +You may find it necessary, though, when support for Linux unprivileged +user namespaces is missing (@pxref{Build Environment Setup}). Use at +your own risk! +@end quotation @item --log-compression=@var{type} Compress build logs according to @var{type}, one of @code{gzip}, diff --git a/guix/substitutes.scm b/guix/substitutes.scm index 7ca55788d5..86b9f5472a 100644 --- a/guix/substitutes.scm +++ b/guix/substitutes.scm @@ -79,7 +79,7 @@ (define %narinfo-cache-directory ;; time, 'guix substitute' is called by guix-daemon as root and stores its ;; cached data in /var/guix/…. However, when invoked from 'guix challenge' ;; as a user, it stores its cache in ~/.cache. - (if (zero? (getuid)) + (if (getenv "_NIX_OPTIONS") ;invoked by guix-daemon (or (and=> (getenv "XDG_CACHE_HOME") (cut string-append <> "/guix/substitute")) (string-append %state-directory "/substitute/cache")) diff --git a/nix/libstore/build.cc b/nix/libstore/build.cc index c8b778362a..e6cd45aba4 100644 --- a/nix/libstore/build.cc +++ b/nix/libstore/build.cc @@ -744,6 +744,10 @@ private: friend int childEntry(void *); + /* Pipe to notify readiness to the child process when using unprivileged + user namespaces. */ + Pipe readiness; + /* Check that the derivation outputs all exist and register them as valid. */ void registerOutputs(); @@ -1619,6 +1623,24 @@ int childEntry(void * arg) } +/* UID and GID of the build user inside its own user namespace. */ +static const uid_t guestUID = 30001; +static const gid_t guestGID = 30000; + +/* Initialize the user namespace of CHILD. */ +static void initializeUserNamespace(pid_t child, + uid_t hostUID = getuid(), + gid_t hostGID = getgid()) +{ + writeFile("/proc/" + std::to_string(child) + "/uid_map", + (format("%d %d 1") % guestUID % hostUID).str()); + + writeFile("/proc/" + std::to_string(child) + "/setgroups", "deny"); + + writeFile("/proc/" + std::to_string(child) + "/gid_map", + (format("%d %d 1") % guestGID % hostGID).str()); +} + void DerivationGoal::startBuilder() { auto f = format( @@ -1682,7 +1704,7 @@ void DerivationGoal::startBuilder() then an attacker could create in it a hardlink to a root-owned file such as /etc/shadow. If 'keepFailed' is true, the daemon would then chown that hardlink to the user, giving them write access to - that file. */ + that file. See CVE-2021-27851. */ tmpDir += "/top"; if (mkdir(tmpDir.c_str(), 0700) == 1) throw SysError("creating top-level build directory"); @@ -1799,7 +1821,7 @@ void DerivationGoal::startBuilder() if (mkdir(chrootRootDir.c_str(), 0750) == -1) throw SysError(format("cannot create ‘%1%’") % chrootRootDir); - if (chown(chrootRootDir.c_str(), 0, buildUser.getGID()) == -1) + if (buildUser.enabled() && chown(chrootRootDir.c_str(), 0, buildUser.getGID()) == -1) throw SysError(format("cannot change ownership of ‘%1%’") % chrootRootDir); /* Create a writable /tmp in the chroot. Many builders need @@ -1818,8 +1840,8 @@ void DerivationGoal::startBuilder() (format( "nixbld:x:%1%:%2%:Nix build user:/:/noshell\n" "nobody:x:65534:65534:Nobody:/:/noshell\n") - % (buildUser.enabled() ? buildUser.getUID() : getuid()) - % (buildUser.enabled() ? buildUser.getGID() : getgid())).str()); + % (buildUser.enabled() ? buildUser.getUID() : guestUID) + % (buildUser.enabled() ? buildUser.getGID() : guestGID)).str()); /* Declare the build user's group so that programs get a consistent view of the system (e.g., "id -gn"). */ @@ -1854,7 +1876,7 @@ void DerivationGoal::startBuilder() createDirs(chrootStoreDir); chmod_(chrootStoreDir, 01775); - if (chown(chrootStoreDir.c_str(), 0, buildUser.getGID()) == -1) + if (buildUser.enabled() && chown(chrootStoreDir.c_str(), 0, buildUser.getGID()) == -1) throw SysError(format("cannot change ownership of ‘%1%’") % chrootStoreDir); foreach (PathSet::iterator, i, inputPaths) { @@ -1960,14 +1982,36 @@ void DerivationGoal::startBuilder() if (useChroot) { char stack[32 * 1024]; int flags = CLONE_NEWPID | CLONE_NEWNS | CLONE_NEWIPC | CLONE_NEWUTS | SIGCHLD; - if (!fixedOutput) flags |= CLONE_NEWNET; + if (!fixedOutput) { + flags |= CLONE_NEWNET; + } + if (!buildUser.enabled() || getuid() != 0) { + flags |= CLONE_NEWUSER; + readiness.create(); + } + /* Ensure proper alignment on the stack. On aarch64, it has to be 16 bytes. */ - pid = clone(childEntry, + pid = clone(childEntry, (char *)(((uintptr_t)stack + sizeof(stack) - 8) & ~(uintptr_t)0xf), flags, this); - if (pid == -1) - throw SysError("cloning builder process"); + if (pid == -1) { + if ((flags & CLONE_NEWUSER) != 0 && getuid() != 0) + /* 'clone' fails with EPERM on distros where unprivileged user + namespaces are disabled. Error out instead of giving up on + isolation. */ + throw SysError("cannot create process in unprivileged user namespace"); + else + throw SysError("cloning builder process"); + } + + readiness.readSide.close(); + if ((flags & CLONE_NEWUSER) != 0) { + /* Initialize the UID/GID mapping of the child process. */ + initializeUserNamespace(pid); + writeFull(readiness.writeSide, (unsigned char*)"go\n", 3); + } + readiness.writeSide.close(); } else #endif { @@ -2013,23 +2057,37 @@ void DerivationGoal::runChild() _writeToStderr = 0; + if (readiness.writeSide >= 0) readiness.writeSide.close(); + + if (readiness.readSide >= 0) { + /* Wait for the parent process to initialize the UID/GID mapping + of our user namespace. */ + char str[20] = { '\0' }; + readFull(readiness.readSide, (unsigned char*)str, 3); + readiness.readSide.close(); + if (strcmp(str, "go\n") != 0) + throw Error("failed to initialize process in unprivileged user namespace"); + } + restoreAffinity(); commonChildInit(builderOut); #if CHROOT_ENABLED if (useChroot) { - /* Initialise the loopback interface. */ - AutoCloseFD fd(socket(PF_INET, SOCK_DGRAM, IPPROTO_IP)); - if (fd == -1) throw SysError("cannot open IP socket"); + if (!fixedOutput) { + /* Initialise the loopback interface. */ + AutoCloseFD fd(socket(PF_INET, SOCK_DGRAM, IPPROTO_IP)); + if (fd == -1) throw SysError("cannot open IP socket"); - struct ifreq ifr; - strcpy(ifr.ifr_name, "lo"); - ifr.ifr_flags = IFF_UP | IFF_LOOPBACK | IFF_RUNNING; - if (ioctl(fd, SIOCSIFFLAGS, &ifr) == -1) - throw SysError("cannot set loopback interface flags"); + struct ifreq ifr; + strcpy(ifr.ifr_name, "lo"); + ifr.ifr_flags = IFF_UP | IFF_LOOPBACK | IFF_RUNNING; + if (ioctl(fd, SIOCSIFFLAGS, &ifr) == -1) + throw SysError("cannot set loopback interface flags"); - fd.close(); + fd.close(); + } /* Set the hostname etc. to fixed values. */ char hostname[] = "localhost"; @@ -2180,6 +2238,27 @@ void DerivationGoal::runChild() /* Remount root as read-only. */ if (mount("/", "/", 0, MS_BIND | MS_REMOUNT | MS_RDONLY, 0) == -1) throw SysError(format("read-only remount of build root '%1%' failed") % chrootRootDir); + + if (getuid() != 0) { + /* Create a new mount namespace to "lock" previous mounts. + See mount_namespaces(7). */ + auto uid = getuid(); + auto gid = getgid(); + + if (unshare(CLONE_NEWNS | CLONE_NEWUSER) == -1) + throw SysError(format("creating new user and mount namespaces")); + + initializeUserNamespace(getpid(), uid, gid); + + /* Check that mounts within the build environment are "locked" + together and cannot be separated from within the build + environment namespace. Since + umount(2) is documented to fail with EINVAL when attempting + to unmount one of the mounts that are locked together, + check that this is what we get. */ + int ret = umount(tmpDirInSandbox.c_str()); + assert(ret == -1 && errno == EINVAL); + } } #endif @@ -2262,6 +2341,7 @@ void DerivationGoal::runChild() writeFull(STDERR_FILENO, "\n"); /* Execute the program. This should not return. */ + string builderBasename; if (isBuiltin(drv)) { try { logType = ltFlat; @@ -2285,11 +2365,25 @@ void DerivationGoal::runChild() writeFull(STDERR_FILENO, "error: " + string(e.what()) + "\n"); _exit(1); } - } + } else { + /* Ensure that the builder is within the store. This prevents + users from using /proc/self/exe (or a symlink to it) as their + builder, which could allow them to overwrite the guix-daemon + binary (CVE-2019-5736). + + This attack is possible even if the target of /proc/self/exe is + outside the chroot (it's as if it were a hard link), though it + requires that its ELF interpreter and dependencies be in the + chroot. + + Note: 'canonPath' throws if 'drv.builder' cannot be resolved + within the chroot. */ + builderBasename = baseNameOf(drv.builder); + drv.builder = canonPath(drv.builder, true); + } /* Fill in the arguments. */ Strings args; - string builderBasename = baseNameOf(drv.builder); args.push_back(builderBasename); foreach (Strings::iterator, i, drv.args) args.push_back(rewriteHashes(*i, rewritesToTmp)); @@ -2476,8 +2570,16 @@ void DerivationGoal::registerOutputs() 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) { + if (S_ISDIR(st.st_mode)) + /* Change mode on the directory to allow for + rename(2). */ + chmod(actualPath.c_str(), st.st_mode | 0700); + if (rename(actualPath.c_str(), path.c_str()) == -1) + throw SysError(format("moving build output `%1%' from the chroot to the store") % path); + if (S_ISDIR(st.st_mode) && chmod(path.c_str(), st.st_mode) == -1) + throw SysError(format("restoring permissions on directory `%1%'") % actualPath); + } } if (buildMode != bmCheck) actualPath = path; } @@ -2736,16 +2838,46 @@ void DerivationGoal::deleteTmpDir(bool force) // Change the ownership if clientUid is set. Never change the // ownership or the group to "root" for security reasons. if (settings.clientUid != (uid_t) -1 && settings.clientUid != 0) { - _chown(tmpDir, settings.clientUid, - settings.clientGid != 0 ? settings.clientGid : -1); + uid_t uid = settings.clientUid; + gid_t gid = settings.clientGid != 0 ? settings.clientGid : -1; + bool reown = false; + + /* First remove setuid/setgid bits. */ + secureFilePerms(tmpDir); + + try { + _chown(tmpDir, uid, gid); + + if (getuid() != 0) { + /* If, without being root, the '_chown' call above + succeeded, then it means we have CAP_CHOWN. Retake + ownership of tmpDir itself so it can be renamed + below. */ + reown = true; + } + + } catch (SysError & e) { + /* When running as an unprivileged user and without + CAP_CHOWN, we cannot chown the build tree. Print a + message and keep going. */ + printMsg(lvlInfo, format("cannot change ownership of build directory '%1%': %2%") + % tmpDir % strerror(e.errNo)); + } if (top != tmpDir) { + if (reown) chown(tmpDir.c_str(), getuid(), getgid()); + // Rename tmpDir to its parent, with an intermediate step. string pivot = top + ".pivot"; if (rename(top.c_str(), pivot.c_str()) == -1) throw SysError("pivoting failed build tree"); if (rename((pivot + "/top").c_str(), top.c_str()) == -1) throw SysError("renaming failed build tree"); + + if (reown) + /* Running unprivileged but with CAP_CHOWN. */ + chown(top.c_str(), uid, gid); + rmdir(pivot.c_str()); } } diff --git a/nix/libstore/local-store.cc b/nix/libstore/local-store.cc index 0883a4bbce..83e6c3e16e 100644 --- a/nix/libstore/local-store.cc +++ b/nix/libstore/local-store.cc @@ -1614,11 +1614,19 @@ void LocalStore::createUser(const std::string & userName, uid_t userId) { auto dir = settings.nixStateDir + "/profiles/per-user/" + userName; - createDirs(dir); - if (chmod(dir.c_str(), 0755) == -1) - throw SysError(format("changing permissions of directory '%s'") % dir); - if (chown(dir.c_str(), userId, -1) == -1) - throw SysError(format("changing owner of directory '%s'") % dir); + auto created = createDirs(dir); + if (!created.empty()) { + if (chmod(dir.c_str(), 0755) == -1) + throw SysError(format("changing permissions of directory '%s'") % dir); + + /* The following operation requires CAP_CHOWN or can be handled + manually by a user with CAP_CHOWN. */ + if (chown(dir.c_str(), userId, -1) == -1) { + rmdir(dir.c_str()); + string message = strerror(errno); + printMsg(lvlInfo, format("failed to change owner of directory '%1%' to %2%: %3%") % dir % userId % message); + } + } } diff --git a/tests/derivations.scm b/tests/derivations.scm index 72ea9aa9cc..9ea8b4a300 100644 --- a/tests/derivations.scm +++ b/tests/derivations.scm @@ -858,6 +858,16 @@ (define* (directory-contents dir #:optional (slurp get-bytevector-all)) (call-with-input-file (derivation->output-path drv) get-string-all)))) +(test-assert "builder is outside the store" + (let* ((builder (add-file-tree-to-store %store + `("builder" symlink "/proc/self/exe"))) + (drv (derivation %store "attempt-to-run-guix-daemon" builder '() + #:env-vars + '(("LD_PRELOAD" . "attacker-controlled.so"))))) + (guard (c ((store-protocol-error? c) c)) + (build-derivations %store (list drv)) + #f))) + (define %coreutils (false-if-exception -- 2.48.1
guix@HIDDEN, dev@HIDDEN, ludo@HIDDEN, othacehe@HIDDEN, maxim.cournoyer@HIDDEN, zimon.toutoune@HIDDEN, me@HIDDEN, guix-patches@HIDDEN
:bug#75810
; Package guix-patches
.
Full text available.Received: (at 75810) by debbugs.gnu.org; 20 Mar 2025 20:57:25 +0000 From debbugs-submit-bounces <at> debbugs.gnu.org Thu Mar 20 16:57:25 2025 Received: from localhost ([127.0.0.1]:59199 helo=debbugs.gnu.org) by debbugs.gnu.org with esmtp (Exim 4.84_2) (envelope-from <debbugs-submit-bounces <at> debbugs.gnu.org>) id 1tvMxA-0006az-H2 for submit <at> debbugs.gnu.org; Thu, 20 Mar 2025 16:57:24 -0400 Received: from eggs.gnu.org ([2001:470:142:3::10]:43306) by debbugs.gnu.org with esmtps (TLS1.2:ECDHE_RSA_AES_256_GCM_SHA384:256) (Exim 4.84_2) (envelope-from <ludo@HIDDEN>) id 1tvMwI-0006T3-UP for 75810 <at> debbugs.gnu.org; Thu, 20 Mar 2025 16:56:32 -0400 Received: from fencepost.gnu.org ([2001:470:142:3::e]) by eggs.gnu.org with esmtps (TLS1.2:ECDHE_RSA_AES_256_GCM_SHA384:256) (Exim 4.90_1) (envelope-from <ludo@HIDDEN>) id 1tvMwD-0001Ih-Jk; Thu, 20 Mar 2025 16:56:25 -0400 DKIM-Signature: v=1; a=rsa-sha256; q=dns/txt; c=relaxed/relaxed; d=gnu.org; s=fencepost-gnu-org; h=MIME-Version:References:In-Reply-To:Date:Subject:To: From; bh=Ngm8ANKAcfFhwlcmZn793WD7YKtaQddq8o8d6i84570=; b=qLarU0dj+QJphzNxQq1I 8XZfdZLpvm4KYSeRlgM4hkR4eTrGjVQ7eY3sZFExyAlsDYF8S+o84jbbpiSdR5Kz+PlKBbdwRmSUY robLVz8T16NDutJYCP7epsmfGiscIneTWDWuWgfVIVg/iJxy1CYHv4Lt7kSN5kcnxe0rxkjwNX66E hPTKk5uF0f7eqFGnr8x3AiBcsNK6ZeySJo5NitQTuSTHf/I/AxCtt+GcPTCCOTnib4rgzM5iOYU6J jkfa8ipc/JcumGjYOR8tsA+fV21wFEpnDGUnrKbELwrmCbvrSNvQn5YnM5BpSxOz0eAYApYE6GPRF 7RU/rXAAS0I+2w==; From: =?UTF-8?q?Ludovic=20Court=C3=A8s?= <ludo@HIDDEN> To: 75810 <at> debbugs.gnu.org Subject: [PATCH v7 14/16] =?UTF-8?q?etc:=20systemd=20services:=20Run=20?= =?UTF-8?q?=E2=80=98guix-daemon=E2=80=99=20as=20an=20unprivileged=20user.?= Date: Thu, 20 Mar 2025 21:54:47 +0100 Message-ID: <ef2307612d5f50df2e3be8767eb901257bfa599c.1742503591.git.ludo@HIDDEN> X-Mailer: git-send-email 2.48.1 In-Reply-To: <cover.1742503590.git.ludo@HIDDEN> References: <cover.1742503590.git.ludo@HIDDEN> MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit X-Spam-Score: -2.3 (--) X-Debbugs-Envelope-To: 75810 Cc: =?UTF-8?q?Ludovic=20Court=C3=A8s?= <ludo@HIDDEN> X-BeenThere: debbugs-submit <at> debbugs.gnu.org X-Mailman-Version: 2.1.18 Precedence: list List-Id: <debbugs-submit.debbugs.gnu.org> List-Unsubscribe: <https://debbugs.gnu.org/cgi-bin/mailman/options/debbugs-submit>, <mailto:debbugs-submit-request <at> debbugs.gnu.org?subject=unsubscribe> List-Archive: <https://debbugs.gnu.org/cgi-bin/mailman/private/debbugs-submit/> List-Post: <mailto:debbugs-submit <at> debbugs.gnu.org> List-Help: <mailto:debbugs-submit-request <at> debbugs.gnu.org?subject=help> List-Subscribe: <https://debbugs.gnu.org/cgi-bin/mailman/listinfo/debbugs-submit>, <mailto:debbugs-submit-request <at> debbugs.gnu.org?subject=subscribe> Errors-To: debbugs-submit-bounces <at> debbugs.gnu.org Sender: "Debbugs-submit" <debbugs-submit-bounces <at> debbugs.gnu.org> X-Spam-Score: -3.3 (---) * etc/guix-daemon.service.in (ExecStart): Remove ‘--build-users-group’. (Environment): Add ‘GUIX_STATE_DIRECTORY’. (Before, User, AmbientCapabilities, PrivateMounts, BindPaths): New fields. * etc/gnu-store.mount.in (Before): Remove. (WantedBy): Change to ‘multi-user.target’. Change-Id: Id826b8ab535844b6024d777f6bd15fd49db6d65e --- etc/gnu-store.mount.in | 3 +-- etc/guix-daemon.service.in | 22 ++++++++++++++++++++-- 2 files changed, 21 insertions(+), 4 deletions(-) diff --git a/etc/gnu-store.mount.in b/etc/gnu-store.mount.in index c94f2db72b..f9918c9e52 100644 --- a/etc/gnu-store.mount.in +++ b/etc/gnu-store.mount.in @@ -2,10 +2,9 @@ Description=Read-only @storedir@ for GNU Guix DefaultDependencies=no ConditionPathExists=@storedir@ -Before=guix-daemon.service [Install] -WantedBy=guix-daemon.service +WantedBy=multi-user.target [Mount] What=@storedir@ diff --git a/etc/guix-daemon.service.in b/etc/guix-daemon.service.in index 5c43d9b7f1..6a5ef97f9b 100644 --- a/etc/guix-daemon.service.in +++ b/etc/guix-daemon.service.in @@ -5,11 +5,29 @@ [Unit] Description=Build daemon for GNU Guix +# Start before 'gnu-store.mount' to get a writable view of the store. +Before=gnu-store.mount + [Service] ExecStart=@localstatedir@/guix/profiles/per-user/root/current-guix/bin/guix-daemon \ - --build-users-group=guixbuild --discover=no \ + --discover=no \ --substitute-urls='@GUIX_SUBSTITUTE_URLS@' -Environment='GUIX_LOCPATH=@localstatedir@/guix/profiles/per-user/root/guix-profile/lib/locale' LC_ALL=en_US.utf8 +Environment='GUIX_STATE_DIRECTORY=@localstatedir@/guix' 'GUIX_LOCPATH=@localstatedir@/guix/profiles/per-user/root/guix-profile/lib/locale' LC_ALL=en_US.utf8 + +# Run under a dedicated unprivileged user account. +User=guix-daemon + +# Bind-mount the store read-write in a private namespace, to counter the +# effect of 'gnu-store.mount'. +PrivateMounts=true +BindPaths=@storedir@ + +# Provide the CAP_CHOWN capability so that guix-daemon can create and chown +# /var/guix/profiles/per-user/$USER and also chown failed build directories +# when using '--keep-failed'. Note that guix-daemon explicitly drops ambient +# capabilities before executing build processes so they don't inherit them. +AmbientCapabilities=CAP_CHOWN + StandardOutput=journal StandardError=journal -- 2.48.1
guix-patches@HIDDEN
:bug#75810
; Package guix-patches
.
Full text available.Received: (at 75810) by debbugs.gnu.org; 20 Mar 2025 20:57:24 +0000 From debbugs-submit-bounces <at> debbugs.gnu.org Thu Mar 20 16:57:24 2025 Received: from localhost ([127.0.0.1]:59197 helo=debbugs.gnu.org) by debbugs.gnu.org with esmtp (Exim 4.84_2) (envelope-from <debbugs-submit-bounces <at> debbugs.gnu.org>) id 1tvMx6-0006aR-Ip for submit <at> debbugs.gnu.org; Thu, 20 Mar 2025 16:57:24 -0400 Received: from eggs.gnu.org ([2001:470:142:3::10]:43276) by debbugs.gnu.org with esmtps (TLS1.2:ECDHE_RSA_AES_256_GCM_SHA384:256) (Exim 4.84_2) (envelope-from <ludo@HIDDEN>) id 1tvMwF-0006SU-Qh for 75810 <at> debbugs.gnu.org; Thu, 20 Mar 2025 16:56:31 -0400 Received: from fencepost.gnu.org ([2001:470:142:3::e]) by eggs.gnu.org with esmtps (TLS1.2:ECDHE_RSA_AES_256_GCM_SHA384:256) (Exim 4.90_1) (envelope-from <ludo@HIDDEN>) id 1tvMwA-0001Hu-6I; Thu, 20 Mar 2025 16:56:22 -0400 DKIM-Signature: v=1; a=rsa-sha256; q=dns/txt; c=relaxed/relaxed; d=gnu.org; s=fencepost-gnu-org; h=MIME-Version:References:In-Reply-To:Date:Subject:To: From; bh=VxUd1aOcvzD/pYxOxBWjge8/c0+rM0LNoWab4Huyg4s=; b=sOIW8HgIG9yji1FC69p9 fcpPRcY+R3yPMeO+3jLKZZ9uxsNTZA70jxiZisQwpR95+Ea8a6+z6Ei2t6Vf7DlRICecSr4H1wUTf ez4BNrDPJhQlqjy3aoxfLbg6qg89fQW0OrEACoCDgYirBdTDFTr/3k4ef6T5c7AsP9DaUGy5/hih6 okC0t+c5HTXOpoVa0lgLhQSZf4owf0f6Tj0ku9itw0gexL3T/PsEex6PDl4pFAk5hZgXjUSdCFlPc p02MLyETwosDnDOJDy6HNzU5WOErh1ZwCM50pWFE01l3GcFTe+cXOv/otAmxPTa8wzbM+7Jv/gLqP FWyY351rylHxGw==; From: =?UTF-8?q?Ludovic=20Court=C3=A8s?= <ludo@HIDDEN> To: 75810 <at> debbugs.gnu.org Subject: [PATCH v7 11/16] =?UTF-8?q?linux-container:=20=E2=80=98unprivileg?= =?UTF-8?q?ed-user-namespace-supported=3F=E2=80=99=20returns=20#f=20on=20n?= =?UTF-8?q?on-Linux.?= Date: Thu, 20 Mar 2025 21:54:44 +0100 Message-ID: <83d801db84571a21ca93b2d177fca07888b99644.1742503591.git.ludo@HIDDEN> X-Mailer: git-send-email 2.48.1 In-Reply-To: <cover.1742503590.git.ludo@HIDDEN> References: <cover.1742503590.git.ludo@HIDDEN> MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit X-Spam-Score: -0.8 (/) X-Debbugs-Envelope-To: 75810 Cc: =?UTF-8?q?Ludovic=20Court=C3=A8s?= <ludo@HIDDEN>, Reepca Russelstein <reepca@HIDDEN> X-BeenThere: debbugs-submit <at> debbugs.gnu.org X-Mailman-Version: 2.1.18 Precedence: list List-Id: <debbugs-submit.debbugs.gnu.org> List-Unsubscribe: <https://debbugs.gnu.org/cgi-bin/mailman/options/debbugs-submit>, <mailto:debbugs-submit-request <at> debbugs.gnu.org?subject=unsubscribe> List-Archive: <https://debbugs.gnu.org/cgi-bin/mailman/private/debbugs-submit/> List-Post: <mailto:debbugs-submit <at> debbugs.gnu.org> List-Help: <mailto:debbugs-submit-request <at> debbugs.gnu.org?subject=help> List-Subscribe: <https://debbugs.gnu.org/cgi-bin/mailman/listinfo/debbugs-submit>, <mailto:debbugs-submit-request <at> debbugs.gnu.org?subject=subscribe> Errors-To: debbugs-submit-bounces <at> debbugs.gnu.org Sender: "Debbugs-submit" <debbugs-submit-bounces <at> debbugs.gnu.org> X-Spam-Score: -1.8 (-) Previously this procedure would return #t on non-Linux systems. * gnu/build/linux-container.scm (unprivileged-user-namespace-supported?): When USERNS-FILE doesn’t exist, return (user-namespace-supported?). Reported-by: Reepca Russelstein <reepca@HIDDEN> Change-Id: I92050338b8b68bc3bd87100317eba69fcdf14a0a --- gnu/build/linux-container.scm | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/gnu/build/linux-container.scm b/gnu/build/linux-container.scm index 5c303da8c8..a5c5d8962e 100644 --- a/gnu/build/linux-container.scm +++ b/gnu/build/linux-container.scm @@ -1,6 +1,6 @@ ;;; GNU Guix --- Functional package management for GNU ;;; Copyright © 2015 David Thompson <davet@HIDDEN> -;;; Copyright © 2017-2019, 2022, 2023 Ludovic Courtès <ludo@HIDDEN> +;;; Copyright © 2017-2019, 2022-2023, 2025 Ludovic Courtès <ludo@HIDDEN> ;;; ;;; This file is part of GNU Guix. ;;; @@ -44,7 +44,7 @@ (define (unprivileged-user-namespace-supported?) (let ((userns-file "/proc/sys/kernel/unprivileged_userns_clone")) (if (file-exists? userns-file) (eqv? #\1 (call-with-input-file userns-file read-char)) - #t))) + (user-namespace-supported?)))) (define (setgroups-supported?) "Return #t if the setgroups proc file, introduced in Linux-libre 3.19, -- 2.48.1
guix-patches@HIDDEN
:bug#75810
; Package guix-patches
.
Full text available.Received: (at 75810) by debbugs.gnu.org; 20 Mar 2025 20:57:21 +0000 From debbugs-submit-bounces <at> debbugs.gnu.org Thu Mar 20 16:57:20 2025 Received: from localhost ([127.0.0.1]:59195 helo=debbugs.gnu.org) by debbugs.gnu.org with esmtp (Exim 4.84_2) (envelope-from <debbugs-submit-bounces <at> debbugs.gnu.org>) id 1tvMx4-0006Zx-Do for submit <at> debbugs.gnu.org; Thu, 20 Mar 2025 16:57:20 -0400 Received: from eggs.gnu.org ([2001:470:142:3::10]:43278) by debbugs.gnu.org with esmtps (TLS1.2:ECDHE_RSA_AES_256_GCM_SHA384:256) (Exim 4.84_2) (envelope-from <ludo@HIDDEN>) id 1tvMwH-0006Sh-00 for 75810 <at> debbugs.gnu.org; Thu, 20 Mar 2025 16:56:31 -0400 Received: from fencepost.gnu.org ([2001:470:142:3::e]) by eggs.gnu.org with esmtps (TLS1.2:ECDHE_RSA_AES_256_GCM_SHA384:256) (Exim 4.90_1) (envelope-from <ludo@HIDDEN>) id 1tvMwB-0001I9-Fv; Thu, 20 Mar 2025 16:56:23 -0400 DKIM-Signature: v=1; a=rsa-sha256; q=dns/txt; c=relaxed/relaxed; d=gnu.org; s=fencepost-gnu-org; h=MIME-Version:References:In-Reply-To:Date:Subject:To: From; bh=h7pyHW14Ad8JD4BI17aR8N2pOM+R05MYeaIc86GwjoI=; b=nUzjFVSiVMGh9BsBMpwN CLB7hAlstMwvK3iEiocpmPyZ/71z3RCRmjBz0ANi4WbkLsOMg1SsAtLQ9nRuNIRQrjz5d3WGWaZc8 HTsjCz+SFSztQQ49NicpIVX2vZAcFkFh4pyCJoRi31TTRfBU8E2LD2wJ+AtEHLs0zBPhrkVBuqIDo tRQ2OHtw5plA0D6KDKSZUkwG8BBhaf0CBdFqlc+2K2Sy8HTYUlakVAXRsL+etLFi9RSV11/bjPecu F0xYj46zCjKx/9duCt3oOzFc7f0EA/hPEJl8pGe3GlJU0BMrQrSMtpJKwJaHyFksKY34fVw7Aylau L+AEmitaOrgflw==; From: =?UTF-8?q?Ludovic=20Court=C3=A8s?= <ludo@HIDDEN> To: 75810 <at> debbugs.gnu.org Subject: [PATCH v7 12/16] tests: Add missing derivation inputs. Date: Thu, 20 Mar 2025 21:54:45 +0100 Message-ID: <c295084210b8765cd27d8e10efb93179f2fa31b9.1742503591.git.ludo@HIDDEN> X-Mailer: git-send-email 2.48.1 In-Reply-To: <cover.1742503590.git.ludo@HIDDEN> References: <cover.1742503590.git.ludo@HIDDEN> MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit X-Spam-Score: -2.3 (--) X-Debbugs-Envelope-To: 75810 Cc: =?UTF-8?q?Ludovic=20Court=C3=A8s?= <ludo@HIDDEN> X-BeenThere: debbugs-submit <at> debbugs.gnu.org X-Mailman-Version: 2.1.18 Precedence: list List-Id: <debbugs-submit.debbugs.gnu.org> List-Unsubscribe: <https://debbugs.gnu.org/cgi-bin/mailman/options/debbugs-submit>, <mailto:debbugs-submit-request <at> debbugs.gnu.org?subject=unsubscribe> List-Archive: <https://debbugs.gnu.org/cgi-bin/mailman/private/debbugs-submit/> List-Post: <mailto:debbugs-submit <at> debbugs.gnu.org> List-Help: <mailto:debbugs-submit-request <at> debbugs.gnu.org?subject=help> List-Subscribe: <https://debbugs.gnu.org/cgi-bin/mailman/listinfo/debbugs-submit>, <mailto:debbugs-submit-request <at> debbugs.gnu.org?subject=subscribe> Errors-To: debbugs-submit-bounces <at> debbugs.gnu.org Sender: "Debbugs-submit" <debbugs-submit-bounces <at> debbugs.gnu.org> X-Spam-Score: -3.3 (---) These missing inputs go unnoticed when running ‘guix-daemon --disable-chroot’ but are immediately visible otherwise. * tests/derivations.scm ("fixed-output derivation"): Add %BASH to #:sources. ("fixed-output derivation: output paths are equal"): ("fixed-output derivation, recursive"): ("derivation with a fixed-output input"): ("derivation with duplicate fixed-output inputs"): ("derivation with equivalent fixed-output inputs"): ("build derivation with coreutils"): Likewise. * tests/packages.scm (bootstrap-binary): New procedure. ("package-source-derivation, origin, sha512"): Use it instead of ‘search-bootstrap-binary’ and add BASH to #:sources. ("package-source-derivation, origin, sha3-512"): Likewise. Change-Id: I4c9087df23c47729a3aff15e9e1435b7266e36e2 --- tests/derivations.scm | 24 +++++++++++++++--------- tests/packages.scm | 13 +++++++++---- 2 files changed, 24 insertions(+), 13 deletions(-) diff --git a/tests/derivations.scm b/tests/derivations.scm index 9ea8b4a300..b364110de0 100644 --- a/tests/derivations.scm +++ b/tests/derivations.scm @@ -1,5 +1,5 @@ ;;; GNU Guix --- Functional package management for GNU -;;; Copyright © 2012-2024 Ludovic Courtès <ludo@HIDDEN> +;;; Copyright © 2012-2025 Ludovic Courtès <ludo@HIDDEN> ;;; ;;; This file is part of GNU Guix. ;;; @@ -443,7 +443,7 @@ (define* (directory-contents dir #:optional (slurp get-bytevector-all)) (string-append "fixed-" (symbol->string hash-algorithm)) %bash `(,builder) - #:sources `(,builder) ;optional + #:sources (list %bash builder) #:hash hash #:hash-algo hash-algorithm))) (build-derivations %store (list drv)) @@ -462,9 +462,11 @@ (define* (directory-contents dir #:optional (slurp get-bytevector-all)) (hash (gcrypt:sha256 (string->utf8 "hello"))) (drv1 (derivation %store "fixed" %bash `(,builder1) + #:sources (list %bash builder1) #:hash hash #:hash-algo 'sha256)) (drv2 (derivation %store "fixed" %bash `(,builder2) + #:sources (list %bash builder2) #:hash hash #:hash-algo 'sha256)) (succeeded? (build-derivations %store (list drv1 drv2)))) (and succeeded? @@ -477,7 +479,7 @@ (define* (directory-contents dir #:optional (slurp get-bytevector-all)) (hash (gcrypt:sha256 (string->utf8 "hello"))) (drv (derivation %store "fixed-rec" %bash `(,builder) - #:sources (list builder) + #:sources (list %bash builder) #:hash (base32 "0sg9f58l1jj88w6pdrfdpj5x9b1zrwszk84j81zvby36q9whhhqa") #:hash-algo 'sha256 #:recursive? #t)) @@ -511,9 +513,11 @@ (define* (directory-contents dir #:optional (slurp get-bytevector-all)) (hash (gcrypt:sha256 (string->utf8 "hello"))) (fixed1 (derivation %store "fixed" %bash `(,builder1) + #:sources (list %bash builder1) #:hash hash #:hash-algo 'sha256)) (fixed2 (derivation %store "fixed" %bash `(,builder2) + #:sources (list %bash builder2) #:hash hash #:hash-algo 'sha256)) (fixed-out (derivation->output-path fixed1)) (builder3 (add-text-to-store @@ -548,9 +552,11 @@ (define* (directory-contents dir #:optional (slurp get-bytevector-all)) (hash (gcrypt:sha256 (string->utf8 "hello"))) (fixed1 (derivation %store "fixed" %bash `(,builder1) + #:sources (list %bash builder1) #:hash hash #:hash-algo 'sha256)) (fixed2 (derivation %store "fixed" %bash `(,builder2) + #:sources (list %bash builder2) #:hash hash #:hash-algo 'sha256)) (builder3 (add-text-to-store %store "builder.sh" "echo fake builder")) @@ -580,21 +586,21 @@ (define* (directory-contents dir #:optional (slurp get-bytevector-all)) '())) (hash (gcrypt:sha256 (string->utf8 "hello"))) (drv1 (derivation %store "fixed" %bash (list builder1) - #:sources (list builder1) + #:sources (list %bash builder1) #:hash hash #:hash-algo 'sha256)) (drv2 (derivation %store "fixed" %bash (list builder2) - #:sources (list builder2) + #:sources (list %bash builder2) #:hash hash #:hash-algo 'sha256)) (drv3a (derivation %store "fixed-user" %bash (list builder3) #:outputs '("one" "two") - #:sources (list builder3) + #:sources (list %bash builder3) #:inputs (list (derivation-input drv1)))) (drv3b (derivation %store "fixed-user" %bash (list builder3) #:outputs '("one" "two") - #:sources (list builder3) + #:sources (list %bash builder3) #:inputs (list (derivation-input drv2)))) (drv4 (derivation %store "fixed-user-user" %bash (list builder1) - #:sources (list builder1) + #:sources (list %bash builder1) #:inputs (list (derivation-input drv3a '("one")) (derivation-input drv3b '("two")))))) (match (derivation-inputs drv4) @@ -888,7 +894,7 @@ (define %coreutils ,(string-append (derivation->output-path %coreutils) "/bin"))) - #:sources (list builder) + #:sources (list %bash builder) #:inputs (list (derivation-input %coreutils)))) (succeeded? (build-derivations %store (list drv)))) diff --git a/tests/packages.scm b/tests/packages.scm index 50c1cab915..f56c63128d 100644 --- a/tests/packages.scm +++ b/tests/packages.scm @@ -80,6 +80,11 @@ (define %store ;; When grafting, do not add dependency on 'glibc-utf8-locales'. (%graft-with-utf8-locale? #f) +(define (bootstrap-binary name) + (let ((bin (search-bootstrap-binary name (%current-system)))) + (and %store + (add-to-store %store name #t "sha256" bin)))) + (test-begin "packages") @@ -609,14 +614,14 @@ (define %store (test-equal "package-source-derivation, origin, sha512" "hello" - (let* ((bash (search-bootstrap-binary "bash" (%current-system))) + (let* ((bash (bootstrap-binary "bash")) (builder (add-text-to-store %store "my-fixed-builder.sh" "echo -n hello > $out" '())) (method (lambda* (url hash-algo hash #:optional name #:rest rest) (and (eq? hash-algo 'sha512) (raw-derivation name bash (list builder) - #:sources (list builder) + #:sources (list bash builder) #:hash hash #:hash-algo hash-algo)))) (source (origin @@ -635,14 +640,14 @@ (define %store (test-equal "package-source-derivation, origin, sha3-512" "hello, sha3" - (let* ((bash (search-bootstrap-binary "bash" (%current-system))) + (let* ((bash (bootstrap-binary "bash")) (builder (add-text-to-store %store "my-fixed-builder.sh" "echo -n hello, sha3 > $out" '())) (method (lambda* (url hash-algo hash #:optional name #:rest rest) (and (eq? hash-algo 'sha3-512) (raw-derivation name bash (list builder) - #:sources (list builder) + #:sources (list bash builder) #:hash hash #:hash-algo hash-algo)))) (source (origin -- 2.48.1
guix-patches@HIDDEN
:bug#75810
; Package guix-patches
.
Full text available.Received: (at 75810) by debbugs.gnu.org; 20 Mar 2025 20:57:18 +0000 From debbugs-submit-bounces <at> debbugs.gnu.org Thu Mar 20 16:57:18 2025 Received: from localhost ([127.0.0.1]:59193 helo=debbugs.gnu.org) by debbugs.gnu.org with esmtp (Exim 4.84_2) (envelope-from <debbugs-submit-bounces <at> debbugs.gnu.org>) id 1tvMx3-0006Zp-82 for submit <at> debbugs.gnu.org; Thu, 20 Mar 2025 16:57:18 -0400 Received: from eggs.gnu.org ([2001:470:142:3::10]:43252) by debbugs.gnu.org with esmtps (TLS1.2:ECDHE_RSA_AES_256_GCM_SHA384:256) (Exim 4.84_2) (envelope-from <ludo@HIDDEN>) id 1tvMwE-0006S8-G0 for 75810 <at> debbugs.gnu.org; Thu, 20 Mar 2025 16:56:29 -0400 Received: from fencepost.gnu.org ([2001:470:142:3::e]) by eggs.gnu.org with esmtps (TLS1.2:ECDHE_RSA_AES_256_GCM_SHA384:256) (Exim 4.90_1) (envelope-from <ludo@HIDDEN>) id 1tvMw5-0001H7-Pe; Thu, 20 Mar 2025 16:56:20 -0400 DKIM-Signature: v=1; a=rsa-sha256; q=dns/txt; c=relaxed/relaxed; d=gnu.org; s=fencepost-gnu-org; h=MIME-Version:References:In-Reply-To:Date:Subject:To: From; bh=vFG6iPVFQp7C1RpVfJcQhN1IdM6ZNKaKsQYqPVGNrlk=; b=abyaoCi1w5HjKpcRFl+e HxYOoClTP3qRNWcnDX1/mN/zJzSNy/Lowy1GtbA5IvVS77jzrUS+aD91LRFJWWZLKnUz+qTBMUj9G j9frhXhtCcJSz0FonHP5nxLxF9BD5+NQowXIJUtJvJ7csdMRjgY3IlOcgayFVbtbi+D+jjLt47pxW LQKiCzbIhUibNohHNJIFFZAypIrPY7aOxJaiuRNTMraG4ev9cWyzfbq8lvQqk3QGgLLiKImDU2t+A 5Po7QhBUDzAa9ZX1cmaS//PnAu07wx5w04v09LRxoDXJxcHYmQfkIoOKHVtz3M3qr54il/aA40i56 DvuoX+e6HNVcdQ==; From: =?UTF-8?q?Ludovic=20Court=C3=A8s?= <ludo@HIDDEN> To: 75810 <at> debbugs.gnu.org Subject: [PATCH v7 09/16] daemon: Drop Linux ambient capabilities before executing builder. Date: Thu, 20 Mar 2025 21:54:42 +0100 Message-ID: <50bb8842d557522b6929215bbd5a721b1fa4c69b.1742503591.git.ludo@HIDDEN> X-Mailer: git-send-email 2.48.1 In-Reply-To: <cover.1742503590.git.ludo@HIDDEN> References: <cover.1742503590.git.ludo@HIDDEN> MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit X-Spam-Score: -2.3 (--) X-Debbugs-Envelope-To: 75810 Cc: =?UTF-8?q?Ludovic=20Court=C3=A8s?= <ludo@HIDDEN> X-BeenThere: debbugs-submit <at> debbugs.gnu.org X-Mailman-Version: 2.1.18 Precedence: list List-Id: <debbugs-submit.debbugs.gnu.org> List-Unsubscribe: <https://debbugs.gnu.org/cgi-bin/mailman/options/debbugs-submit>, <mailto:debbugs-submit-request <at> debbugs.gnu.org?subject=unsubscribe> List-Archive: <https://debbugs.gnu.org/cgi-bin/mailman/private/debbugs-submit/> List-Post: <mailto:debbugs-submit <at> debbugs.gnu.org> List-Help: <mailto:debbugs-submit-request <at> debbugs.gnu.org?subject=help> List-Subscribe: <https://debbugs.gnu.org/cgi-bin/mailman/listinfo/debbugs-submit>, <mailto:debbugs-submit-request <at> debbugs.gnu.org?subject=subscribe> Errors-To: debbugs-submit-bounces <at> debbugs.gnu.org Sender: "Debbugs-submit" <debbugs-submit-bounces <at> debbugs.gnu.org> X-Spam-Score: -3.3 (---) * config-daemon.ac: Check for <sys/prctl.h>. * nix/libstore/build.cc (DerivationGoal::runChild): When ‘useChroot’ is true, call ‘prctl’ to drop all ambient capabilities. Change-Id: If34637fc508e5fb6d278167f5df7802fc595284f --- config-daemon.ac | 2 +- nix/libstore/build.cc | 9 +++++++++ 2 files changed, 10 insertions(+), 1 deletion(-) diff --git a/config-daemon.ac b/config-daemon.ac index 4e949bc88a..35d9c8cd56 100644 --- a/config-daemon.ac +++ b/config-daemon.ac @@ -79,7 +79,7 @@ if test "x$guix_build_daemon" = "xyes"; then dnl Chroot support. AC_CHECK_FUNCS([chroot unshare]) AC_CHECK_HEADERS([sched.h sys/param.h sys/mount.h sys/syscall.h \ - linux/close_range.h]) + linux/close_range.h sys/prctl.h]) if test "x$ac_cv_func_chroot" != "xyes"; then AC_MSG_ERROR(['chroot' function missing, bailing out]) diff --git a/nix/libstore/build.cc b/nix/libstore/build.cc index e6cd45aba4..fa0f293aac 100644 --- a/nix/libstore/build.cc +++ b/nix/libstore/build.cc @@ -50,6 +50,9 @@ #if HAVE_SCHED_H #include <sched.h> #endif +#if HAVE_SYS_PRCTL_H +#include <sys/prctl.h> +#endif #define CHROOT_ENABLED HAVE_CHROOT && HAVE_SYS_MOUNT_H && defined(MS_BIND) && defined(MS_PRIVATE) @@ -2075,6 +2078,12 @@ void DerivationGoal::runChild() #if CHROOT_ENABLED if (useChroot) { +# if HAVE_SYS_PRCTL_H + /* Drop ambient capabilities such as CAP_CHOWN that might have + been granted when starting guix-daemon. */ + prctl(PR_CAP_AMBIENT, PR_CAP_AMBIENT_CLEAR_ALL, 0, 0, 0); +# endif + if (!fixedOutput) { /* Initialise the loopback interface. */ AutoCloseFD fd(socket(PF_INET, SOCK_DGRAM, IPPROTO_IP)); -- 2.48.1
guix-patches@HIDDEN
:bug#75810
; Package guix-patches
.
Full text available.Received: (at 75810) by debbugs.gnu.org; 20 Mar 2025 20:56:54 +0000 From debbugs-submit-bounces <at> debbugs.gnu.org Thu Mar 20 16:56:54 2025 Received: from localhost ([127.0.0.1]:59184 helo=debbugs.gnu.org) by debbugs.gnu.org with esmtp (Exim 4.84_2) (envelope-from <debbugs-submit-bounces <at> debbugs.gnu.org>) id 1tvMwc-0006WN-EM for submit <at> debbugs.gnu.org; Thu, 20 Mar 2025 16:56:54 -0400 Received: from eggs.gnu.org ([2001:470:142:3::10]:41202) by debbugs.gnu.org with esmtps (TLS1.2:ECDHE_RSA_AES_256_GCM_SHA384:256) (Exim 4.84_2) (envelope-from <ludo@HIDDEN>) id 1tvMwB-0006RR-ES for 75810 <at> debbugs.gnu.org; Thu, 20 Mar 2025 16:56:27 -0400 Received: from fencepost.gnu.org ([2001:470:142:3::e]) by eggs.gnu.org with esmtps (TLS1.2:ECDHE_RSA_AES_256_GCM_SHA384:256) (Exim 4.90_1) (envelope-from <ludo@HIDDEN>) id 1tvMw0-0001G6-27; Thu, 20 Mar 2025 16:56:12 -0400 DKIM-Signature: v=1; a=rsa-sha256; q=dns/txt; c=relaxed/relaxed; d=gnu.org; s=fencepost-gnu-org; h=MIME-Version:References:In-Reply-To:Date:Subject:To: From; bh=ozQM+lYqSSPDiTg6Dp/w4oPIGKDs4CrGaOeKp99rZWg=; b=i3BqnwDkbZHnTgOm4lNc OynN/H5vzCzwpGBMK5jFpl/WytGJZ/mtPVtOel6Zd7Uiwa/j7PrrEPzfQ4u85aab/zkyrBib7+oAZ My5nqM0Qa/n4AgmS0U78BRDqAGSCZILTz2/Os47XciYu2QUiTnWZYhORxe85pzQDHoEZyE4K1d6fC P6yAU6fit2DYDgOUuDlJWXwQAU+LnOs/v7LjGSPEiO5uyTjETFmayvDKcQSIdwNbp+7CssV0jqPyE /9m+aGWWljc3c5bLGqkpnIL63lhF1qNaPqTDzhsTVLYM0TWv9RBoku6y+2zsXSp5lglmhbyoGzwoC znjR/bWPZemOEA==; From: =?UTF-8?q?Ludovic=20Court=C3=A8s?= <ludo@HIDDEN> To: 75810 <at> debbugs.gnu.org Subject: [PATCH v7 05/16] daemon: Remount inputs as read-only. Date: Thu, 20 Mar 2025 21:54:38 +0100 Message-ID: <fc6bce54b185e36b01ad7dac102514d9a4ab9b9a.1742503591.git.ludo@HIDDEN> X-Mailer: git-send-email 2.48.1 In-Reply-To: <cover.1742503590.git.ludo@HIDDEN> References: <cover.1742503590.git.ludo@HIDDEN> MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit X-Spam-Score: -0.8 (/) X-Debbugs-Envelope-To: 75810 Cc: =?UTF-8?q?Ludovic=20Court=C3=A8s?= <ludo@HIDDEN>, Reepca Russelstein <reepca@HIDDEN> X-BeenThere: debbugs-submit <at> debbugs.gnu.org X-Mailman-Version: 2.1.18 Precedence: list List-Id: <debbugs-submit.debbugs.gnu.org> List-Unsubscribe: <https://debbugs.gnu.org/cgi-bin/mailman/options/debbugs-submit>, <mailto:debbugs-submit-request <at> debbugs.gnu.org?subject=unsubscribe> List-Archive: <https://debbugs.gnu.org/cgi-bin/mailman/private/debbugs-submit/> List-Post: <mailto:debbugs-submit <at> debbugs.gnu.org> List-Help: <mailto:debbugs-submit-request <at> debbugs.gnu.org?subject=help> List-Subscribe: <https://debbugs.gnu.org/cgi-bin/mailman/listinfo/debbugs-submit>, <mailto:debbugs-submit-request <at> debbugs.gnu.org?subject=subscribe> Errors-To: debbugs-submit-bounces <at> debbugs.gnu.org Sender: "Debbugs-submit" <debbugs-submit-bounces <at> debbugs.gnu.org> X-Spam-Score: -1.8 (-) * nix/libstore/build.cc (DerivationGoal::runChild): Remount ‘target’ as read-only. Reported-by: Reepca Russelstein <reepca@HIDDEN> Change-Id: Ib7201bcf4363be566f205d23d17fe2f55d3ad666 --- nix/libstore/build.cc | 7 +++++++ 1 file changed, 7 insertions(+) diff --git a/nix/libstore/build.cc b/nix/libstore/build.cc index 193b279b88..3861a1ffd9 100644 --- a/nix/libstore/build.cc +++ b/nix/libstore/build.cc @@ -2107,8 +2107,15 @@ void DerivationGoal::runChild() createDirs(dirOf(target)); writeFile(target, ""); } + + /* Extra flags passed with MS_BIND are ignored, hence the + extra MS_REMOUNT. */ if (mount(source.c_str(), target.c_str(), "", MS_BIND, 0) == -1) throw SysError(format("bind mount from `%1%' to `%2%' failed") % source % target); + if (source.compare(0, settings.nixStore.length(), settings.nixStore) == 0) { + if (mount(source.c_str(), target.c_str(), "", MS_BIND | MS_REMOUNT | MS_RDONLY, 0) == -1) + throw SysError(format("read-only remount of `%1%' failed") % target); + } } /* Bind a new instance of procfs on /proc to reflect our -- 2.48.1
guix-patches@HIDDEN
:bug#75810
; Package guix-patches
.
Full text available.Received: (at 75810) by debbugs.gnu.org; 20 Mar 2025 20:56:50 +0000 From debbugs-submit-bounces <at> debbugs.gnu.org Thu Mar 20 16:56:50 2025 Received: from localhost ([127.0.0.1]:59182 helo=debbugs.gnu.org) by debbugs.gnu.org with esmtp (Exim 4.84_2) (envelope-from <debbugs-submit-bounces <at> debbugs.gnu.org>) id 1tvMwY-0006Vx-Lh for submit <at> debbugs.gnu.org; Thu, 20 Mar 2025 16:56:50 -0400 Received: from eggs.gnu.org ([2001:470:142:3::10]:41200) by debbugs.gnu.org with esmtps (TLS1.2:ECDHE_RSA_AES_256_GCM_SHA384:256) (Exim 4.84_2) (envelope-from <ludo@HIDDEN>) id 1tvMwA-0006RD-F6 for 75810 <at> debbugs.gnu.org; Thu, 20 Mar 2025 16:56:26 -0400 Received: from fencepost.gnu.org ([2001:470:142:3::e]) by eggs.gnu.org with esmtps (TLS1.2:ECDHE_RSA_AES_256_GCM_SHA384:256) (Exim 4.90_1) (envelope-from <ludo@HIDDEN>) id 1tvMvz-0001G0-2l; Thu, 20 Mar 2025 16:56:11 -0400 DKIM-Signature: v=1; a=rsa-sha256; q=dns/txt; c=relaxed/relaxed; d=gnu.org; s=fencepost-gnu-org; h=MIME-Version:References:In-Reply-To:Date:Subject:To: From; bh=OHeVSHlKl++yMNnhWaubdTXXSn3UUkG8AbIkWMisgq8=; b=jzC8XOA1Bh9UaxNI+7zM DODwbwlhVkJ4OLC+9Ui0zevvwGbZW8ncawcqAqsxrck4ZzGc2ZR/wjOTmyi5uhV9N6c06oByt4pDY wSCuxvT1O4aPTD4CKZXve8zCHh85ms46Br1Ehk1IXcEng16iQApIvTretyTc4dtvDcmQZbhu/SRQg 0E6NIXI433bHM3OjJYZnNb13Yzl51oyYwT2qBqVdyLP866CbOB5he6gmFOxfYFgmHGU3YRskyao7W mur+N1CDP9z3tKdHYe7o8vP9uPtplll/qljjauYIp8QO/Zp7fPQs+aAPZibauz6tNmfik1AGEiA+B k0+OYcLWZLPJqw==; From: =?UTF-8?q?Ludovic=20Court=C3=A8s?= <ludo@HIDDEN> To: 75810 <at> debbugs.gnu.org Subject: [PATCH v7 04/16] daemon: Bind-mount all the inputs, not just directories. Date: Thu, 20 Mar 2025 21:54:37 +0100 Message-ID: <ce3f4c99d45c4e99e0c698fc9279d9b4c60ee30a.1742503591.git.ludo@HIDDEN> X-Mailer: git-send-email 2.48.1 In-Reply-To: <cover.1742503590.git.ludo@HIDDEN> References: <cover.1742503590.git.ludo@HIDDEN> MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit X-Spam-Score: -0.8 (/) X-Debbugs-Envelope-To: 75810 Cc: =?UTF-8?q?Ludovic=20Court=C3=A8s?= <ludo@HIDDEN>, Reepca Russelstein <reepca@HIDDEN> X-BeenThere: debbugs-submit <at> debbugs.gnu.org X-Mailman-Version: 2.1.18 Precedence: list List-Id: <debbugs-submit.debbugs.gnu.org> List-Unsubscribe: <https://debbugs.gnu.org/cgi-bin/mailman/options/debbugs-submit>, <mailto:debbugs-submit-request <at> debbugs.gnu.org?subject=unsubscribe> List-Archive: <https://debbugs.gnu.org/cgi-bin/mailman/private/debbugs-submit/> List-Post: <mailto:debbugs-submit <at> debbugs.gnu.org> List-Help: <mailto:debbugs-submit-request <at> debbugs.gnu.org?subject=help> List-Subscribe: <https://debbugs.gnu.org/cgi-bin/mailman/listinfo/debbugs-submit>, <mailto:debbugs-submit-request <at> debbugs.gnu.org?subject=subscribe> Errors-To: debbugs-submit-bounces <at> debbugs.gnu.org Sender: "Debbugs-submit" <debbugs-submit-bounces <at> debbugs.gnu.org> X-Spam-Score: -1.8 (-) * nix/libstore/build.cc (DerivationGoal::startBuilder): Add all of ‘inputPaths’ to ‘dirsInChroot’ instead of hard-linking regular files. Special-case symlinks. (DerivationGoal)[regularInputPaths]: Remove. Reported-by: Reepca Russelstein <reepca@HIDDEN> Change-Id: I070987f92d73f187f7826a975bee9ee309d67f56 --- nix/libstore/build.cc | 39 ++++++++++++++------------------------- 1 file changed, 14 insertions(+), 25 deletions(-) diff --git a/nix/libstore/build.cc b/nix/libstore/build.cc index 8ca5e5b732..193b279b88 100644 --- a/nix/libstore/build.cc +++ b/nix/libstore/build.cc @@ -659,9 +659,6 @@ private: /* RAII object to delete the chroot directory. */ std::shared_ptr<AutoDelete> autoDelChroot; - /* All inputs that are regular files. */ - PathSet regularInputPaths; - /* Whether this is a fixed-output derivation. */ bool fixedOutput; @@ -1850,9 +1847,7 @@ void DerivationGoal::startBuilder() /* Make the closure of the inputs available in the chroot, rather than the whole store. This prevents any access - to undeclared dependencies. Directories are bind-mounted, - while other inputs are hard-linked (since only directories - can be bind-mounted). !!! As an extra security + to undeclared dependencies. !!! As an extra security precaution, make the fake store only writable by the build user. */ Path chrootStoreDir = chrootRootDir + settings.nixStore; @@ -1863,28 +1858,22 @@ void DerivationGoal::startBuilder() throw SysError(format("cannot change ownership of ‘%1%’") % chrootStoreDir); foreach (PathSet::iterator, i, inputPaths) { - struct stat st; + struct stat st; if (lstat(i->c_str(), &st)) throw SysError(format("getting attributes of path `%1%'") % *i); - if (S_ISDIR(st.st_mode)) - dirsInChroot[*i] = *i; - else { - Path p = chrootRootDir + *i; - if (link(i->c_str(), p.c_str()) == -1) { - /* Hard-linking fails if we exceed the maximum - link count on a file (e.g. 32000 of ext3), - which is quite possible after a `nix-store - --optimise'. */ - if (errno != EMLINK) - throw SysError(format("linking `%1%' to `%2%'") % p % *i); - StringSink sink; - dumpPath(*i, sink); - StringSource source(sink.s); - restorePath(p, source); - } - regularInputPaths.insert(*i); - } + if (S_ISLNK(st.st_mode)) { + /* Since bind-mounts follow symlinks, thus representing their + target and not the symlink itself, special-case + symlinks. XXX: When running unprivileged, TARGET can be + deleted by the build process. Use 'open_tree' & co. when + it's more widely available. */ + Path target = chrootRootDir + *i; + if (symlink(readLink(*i).c_str(), target.c_str()) == -1) + throw SysError(format("failed to create symlink '%1%' to '%2%'") % target % readLink(*i)); + } + else + dirsInChroot[*i] = *i; } /* If we're repairing, checking or rebuilding part of a -- 2.48.1
guix-patches@HIDDEN
:bug#75810
; Package guix-patches
.
Full text available.Received: (at 75810) by debbugs.gnu.org; 20 Mar 2025 20:56:46 +0000 From debbugs-submit-bounces <at> debbugs.gnu.org Thu Mar 20 16:56:46 2025 Received: from localhost ([127.0.0.1]:59180 helo=debbugs.gnu.org) by debbugs.gnu.org with esmtp (Exim 4.84_2) (envelope-from <debbugs-submit-bounces <at> debbugs.gnu.org>) id 1tvMwU-0006Vb-PZ for submit <at> debbugs.gnu.org; Thu, 20 Mar 2025 16:56:46 -0400 Received: from eggs.gnu.org ([2001:470:142:3::10]:41198) by debbugs.gnu.org with esmtps (TLS1.2:ECDHE_RSA_AES_256_GCM_SHA384:256) (Exim 4.84_2) (envelope-from <ludo@HIDDEN>) id 1tvMw8-0006R1-6D for 75810 <at> debbugs.gnu.org; Thu, 20 Mar 2025 16:56:24 -0400 Received: from fencepost.gnu.org ([2001:470:142:3::e]) by eggs.gnu.org with esmtps (TLS1.2:ECDHE_RSA_AES_256_GCM_SHA384:256) (Exim 4.90_1) (envelope-from <ludo@HIDDEN>) id 1tvMvw-0001Fi-Ow; Thu, 20 Mar 2025 16:56:08 -0400 DKIM-Signature: v=1; a=rsa-sha256; q=dns/txt; c=relaxed/relaxed; d=gnu.org; s=fencepost-gnu-org; h=MIME-Version:References:In-Reply-To:Date:Subject:To: From; bh=fUCaHHG/eO75rZDRlbk9XFL7p37y9SICE8zVkSS6pAE=; b=XrWbV6giYPefhWhQYU4Y P6QWwFyqa5wg550QX5PzyQ48dVcVFy81VtGPI6PHBCNpdJWrAQVTP6wY0P1dh4qBkn0X0chwsxE0S TDCPtVMQ89PeFRb3QoUZQRIL3JbhJQwZtOw2q5OM1XIc9qkY85JCQQA6yZnQrzvtJlj77mmgqrYV6 NAW8slx9BqjdP1UQSFvEV09PqCZe2q0ez1MOu2h29e60BAYR6JZocR8CsWZWDcuusjDwZOgniIRoA Ubez7VghHqVA7x0POktfr1Vn9Ye+psrZ0V/CvPnwnIZcPm1UTOEb/IVYyp/jbpoEoRSGKMhzKhIqk 5QkYcTRCPhQUyw==; From: =?UTF-8?q?Ludovic=20Court=C3=A8s?= <ludo@HIDDEN> To: 75810 <at> debbugs.gnu.org Subject: [PATCH v7 02/16] daemon: Close the read end of the logging pipe. Date: Thu, 20 Mar 2025 21:54:35 +0100 Message-ID: <e4db1c0ad956a8ab383c5c688f32a97a9cb56b95.1742503591.git.ludo@HIDDEN> X-Mailer: git-send-email 2.48.1 In-Reply-To: <cover.1742503590.git.ludo@HIDDEN> References: <cover.1742503590.git.ludo@HIDDEN> MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit X-Spam-Score: -0.8 (/) X-Debbugs-Envelope-To: 75810 Cc: =?UTF-8?q?Ludovic=20Court=C3=A8s?= <ludo@HIDDEN>, Reepca Russelstein <reepca@HIDDEN> X-BeenThere: debbugs-submit <at> debbugs.gnu.org X-Mailman-Version: 2.1.18 Precedence: list List-Id: <debbugs-submit.debbugs.gnu.org> List-Unsubscribe: <https://debbugs.gnu.org/cgi-bin/mailman/options/debbugs-submit>, <mailto:debbugs-submit-request <at> debbugs.gnu.org?subject=unsubscribe> List-Archive: <https://debbugs.gnu.org/cgi-bin/mailman/private/debbugs-submit/> List-Post: <mailto:debbugs-submit <at> debbugs.gnu.org> List-Help: <mailto:debbugs-submit-request <at> debbugs.gnu.org?subject=help> List-Subscribe: <https://debbugs.gnu.org/cgi-bin/mailman/listinfo/debbugs-submit>, <mailto:debbugs-submit-request <at> debbugs.gnu.org?subject=subscribe> Errors-To: debbugs-submit-bounces <at> debbugs.gnu.org Sender: "Debbugs-submit" <debbugs-submit-bounces <at> debbugs.gnu.org> X-Spam-Score: -1.8 (-) * nix/libutil/util.cc (commonChildInit): Close ‘logPipe.readSide’. Reported-by: Reepca Russelstein <reepca@HIDDEN> Change-Id: Ia9e48d1afb85d7af52770e016f2b6832792044dd --- nix/libutil/util.cc | 3 +++ 1 file changed, 3 insertions(+) diff --git a/nix/libutil/util.cc b/nix/libutil/util.cc index eb2d16e1cc..56f116046c 100644 --- a/nix/libutil/util.cc +++ b/nix/libutil/util.cc @@ -1279,6 +1279,9 @@ void commonChildInit(Pipe & logPipe) if (setsid() == -1) throw SysError(format("creating a new session")); + /* Close the read end so only the parent holds a reference to it. */ + logPipe.readSide.close(); + /* Dup the write side of the logger pipe into stderr. */ if (dup2(logPipe.writeSide, STDERR_FILENO) == -1) throw SysError("cannot pipe standard error into log file"); -- 2.48.1
guix-patches@HIDDEN
:bug#75810
; Package guix-patches
.
Full text available.Received: (at 75810) by debbugs.gnu.org; 20 Mar 2025 20:56:43 +0000 From debbugs-submit-bounces <at> debbugs.gnu.org Thu Mar 20 16:56:42 2025 Received: from localhost ([127.0.0.1]:59178 helo=debbugs.gnu.org) by debbugs.gnu.org with esmtp (Exim 4.84_2) (envelope-from <debbugs-submit-bounces <at> debbugs.gnu.org>) id 1tvMwT-0006VR-R7 for submit <at> debbugs.gnu.org; Thu, 20 Mar 2025 16:56:42 -0400 Received: from eggs.gnu.org ([2001:470:142:3::10]:41196) by debbugs.gnu.org with esmtps (TLS1.2:ECDHE_RSA_AES_256_GCM_SHA384:256) (Exim 4.84_2) (envelope-from <ludo@HIDDEN>) id 1tvMw7-0006Qz-0i for 75810 <at> debbugs.gnu.org; Thu, 20 Mar 2025 16:56:21 -0400 Received: from fencepost.gnu.org ([2001:470:142:3::e]) by eggs.gnu.org with esmtps (TLS1.2:ECDHE_RSA_AES_256_GCM_SHA384:256) (Exim 4.90_1) (envelope-from <ludo@HIDDEN>) id 1tvMw1-0001GI-3V; Thu, 20 Mar 2025 16:56:13 -0400 DKIM-Signature: v=1; a=rsa-sha256; q=dns/txt; c=relaxed/relaxed; d=gnu.org; s=fencepost-gnu-org; h=MIME-Version:References:In-Reply-To:Date:Subject:To: From; bh=3sOVW5n0d1cSpQd8PLRrsmflCadSWuH5XwPCIe/iTyM=; b=OvaQ5z0ANTbpsqF0NS2e vxv3e4Hl+Dl7rnyiGZQdX5Mql0ZLeIDoofdRmK4wSYA8CjNK2EXcmGr/d+CtOoD1qZSFt4gm7TsMA x2qdnWfmnViM1JDle3Cg4ldkssc1X02YEIVLkSLMs92oYcIRx9t075qXyvTP845N7pMWBw7kD2/h/ k4/VdhzLC2okKLqBm29fglZVMyX2Be3z/Z/lfRG+AiUJ/DoKx3kR4yPG17UlHrfldMztHG+Lpshff qBIodCntT+y8Ple/knLyzuvDGh95JOd1s8UMMC17WKOjcen+olgdoBoj+1Z8xOO7g5Ng6Vu4VACUG 3wFIz1pi9XhcUQ==; From: =?UTF-8?q?Ludovic=20Court=C3=A8s?= <ludo@HIDDEN> To: 75810 <at> debbugs.gnu.org Subject: [PATCH v7 06/16] daemon: Remount root directory as read-only. Date: Thu, 20 Mar 2025 21:54:39 +0100 Message-ID: <c6d4923957d92a21624959928f6468a3f1801394.1742503591.git.ludo@HIDDEN> X-Mailer: git-send-email 2.48.1 In-Reply-To: <cover.1742503590.git.ludo@HIDDEN> References: <cover.1742503590.git.ludo@HIDDEN> MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit X-Spam-Score: -2.3 (--) X-Debbugs-Envelope-To: 75810 Cc: =?UTF-8?q?Ludovic=20Court=C3=A8s?= <ludo@HIDDEN> X-BeenThere: debbugs-submit <at> debbugs.gnu.org X-Mailman-Version: 2.1.18 Precedence: list List-Id: <debbugs-submit.debbugs.gnu.org> List-Unsubscribe: <https://debbugs.gnu.org/cgi-bin/mailman/options/debbugs-submit>, <mailto:debbugs-submit-request <at> debbugs.gnu.org?subject=unsubscribe> List-Archive: <https://debbugs.gnu.org/cgi-bin/mailman/private/debbugs-submit/> List-Post: <mailto:debbugs-submit <at> debbugs.gnu.org> List-Help: <mailto:debbugs-submit-request <at> debbugs.gnu.org?subject=help> List-Subscribe: <https://debbugs.gnu.org/cgi-bin/mailman/listinfo/debbugs-submit>, <mailto:debbugs-submit-request <at> debbugs.gnu.org?subject=subscribe> Errors-To: debbugs-submit-bounces <at> debbugs.gnu.org Sender: "Debbugs-submit" <debbugs-submit-bounces <at> debbugs.gnu.org> X-Spam-Score: -3.3 (---) * nix/libstore/build.cc (DerivationGoal::runChild): Bind-mount the store and /tmp under ‘chrootRootDir’ to themselves as read-write. Remount / as read-only. Change-Id: I79565094c8ec8448401897c720aad75304fd1948 --- nix/libstore/build.cc | 16 ++++++++++++++++ 1 file changed, 16 insertions(+) diff --git a/nix/libstore/build.cc b/nix/libstore/build.cc index 3861a1ffd9..c8b778362a 100644 --- a/nix/libstore/build.cc +++ b/nix/libstore/build.cc @@ -2091,6 +2091,18 @@ void DerivationGoal::runChild() for (auto & i : ss) dirsInChroot[i] = i; + /* Make new mounts for the store and for /tmp. That way, when + 'chrootRootDir' is made read-only below, these two mounts will + remain writable (the store needs to be writable so derivation + outputs can be written to it, and /tmp is writable by + convention). */ + auto chrootStoreDir = chrootRootDir + settings.nixStore; + if (mount(chrootStoreDir.c_str(), chrootStoreDir.c_str(), 0, MS_BIND, 0) == -1) + throw SysError(format("read-write mount of store '%1%' failed") % chrootStoreDir); + auto chrootTmpDir = chrootRootDir + "/tmp"; + if (mount(chrootTmpDir.c_str(), chrootTmpDir.c_str(), 0, MS_BIND, 0) == -1) + throw SysError(format("read-write mount of temporary directory '%1%' failed") % chrootTmpDir); + /* Bind-mount all the directories from the "host" filesystem that we want in the chroot environment. */ @@ -2164,6 +2176,10 @@ void DerivationGoal::runChild() if (rmdir("real-root") == -1) throw SysError("cannot remove real-root directory"); + + /* Remount root as read-only. */ + if (mount("/", "/", 0, MS_BIND | MS_REMOUNT | MS_RDONLY, 0) == -1) + throw SysError(format("read-only remount of build root '%1%' failed") % chrootRootDir); } #endif -- 2.48.1
guix-patches@HIDDEN
:bug#75810
; Package guix-patches
.
Full text available.Received: (at 75810) by debbugs.gnu.org; 20 Mar 2025 20:56:42 +0000 From debbugs-submit-bounces <at> debbugs.gnu.org Thu Mar 20 16:56:41 2025 Received: from localhost ([127.0.0.1]:59176 helo=debbugs.gnu.org) by debbugs.gnu.org with esmtp (Exim 4.84_2) (envelope-from <debbugs-submit-bounces <at> debbugs.gnu.org>) id 1tvMwO-0006Ue-Ue for submit <at> debbugs.gnu.org; Thu, 20 Mar 2025 16:56:41 -0400 Received: from eggs.gnu.org ([2001:470:142:3::10]:41192) by debbugs.gnu.org with esmtps (TLS1.2:ECDHE_RSA_AES_256_GCM_SHA384:256) (Exim 4.84_2) (envelope-from <ludo@HIDDEN>) id 1tvMw5-0006Qx-RY for 75810 <at> debbugs.gnu.org; Thu, 20 Mar 2025 16:56:19 -0400 Received: from fencepost.gnu.org ([2001:470:142:3::e]) by eggs.gnu.org with esmtps (TLS1.2:ECDHE_RSA_AES_256_GCM_SHA384:256) (Exim 4.90_1) (envelope-from <ludo@HIDDEN>) id 1tvMvt-0001F0-QO; Thu, 20 Mar 2025 16:56:05 -0400 DKIM-Signature: v=1; a=rsa-sha256; q=dns/txt; c=relaxed/relaxed; d=gnu.org; s=fencepost-gnu-org; h=MIME-Version:Date:Subject:To:From:in-reply-to: references; bh=UhcTHomJLMz+Z22SzzpugSALo+1Q3w2wJJxYBdsyIsc=; b=C65VQVLDqDZt3I 5RM3nPTA39Ico3LbrrW5MYZf9GMEodFTN/Uj9fN4k4TG0Ts8O6AsBMOThcZIADOqmOQduuTwwH/k/ rS238C7X7WbFuIzkpi5EpPPR+buL6TjAb75EXUjpH24ETHuOYF5jF1pmc/9s3wbSfjq/XasRUSqaZ 1O/dd+L+9hEwNGa3odN8CuDFaJUplESyZ2F1ZvhNgyWfgxwsbIFnl8JPgHfNl8D+/Ff4kSVZ0r/9D 113+7Civmab/kOWaAhh82dzE2+kMnp42CMJNJcrqSAAZtaplGP8HZeR6Qc3KAVk+qlwCkHhKSIKD2 hogX3HNQHrrapG4O9rTA==; From: =?UTF-8?q?Ludovic=20Court=C3=A8s?= <ludo@HIDDEN> To: 75810 <at> debbugs.gnu.org Subject: [PATCH v7 00/16] Rootless guix-daemon Date: Thu, 20 Mar 2025 21:54:33 +0100 Message-ID: <cover.1742503590.git.ludo@HIDDEN> X-Mailer: git-send-email 2.48.1 MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit X-Spam-Score: -2.3 (--) X-Debbugs-Envelope-To: 75810 Cc: =?UTF-8?q?Ludovic=20Court=C3=A8s?= <ludo@HIDDEN>, Reepca Russelstein <reepca@HIDDEN> X-BeenThere: debbugs-submit <at> debbugs.gnu.org X-Mailman-Version: 2.1.18 Precedence: list List-Id: <debbugs-submit.debbugs.gnu.org> List-Unsubscribe: <https://debbugs.gnu.org/cgi-bin/mailman/options/debbugs-submit>, <mailto:debbugs-submit-request <at> debbugs.gnu.org?subject=unsubscribe> List-Archive: <https://debbugs.gnu.org/cgi-bin/mailman/private/debbugs-submit/> List-Post: <mailto:debbugs-submit <at> debbugs.gnu.org> List-Help: <mailto:debbugs-submit-request <at> debbugs.gnu.org?subject=help> List-Subscribe: <https://debbugs.gnu.org/cgi-bin/mailman/listinfo/debbugs-submit>, <mailto:debbugs-submit-request <at> debbugs.gnu.org?subject=subscribe> Errors-To: debbugs-submit-bounces <at> debbugs.gnu.org Sender: "Debbugs-submit" <debbugs-submit-bounces <at> debbugs.gnu.org> X-Spam-Score: -1.0 (-) Hello, Changes compared to v6 (all suggested by Reepca): • Canonicalize the builder’s file name before ‘execve’ and add the “builder is outside the store” test in ‘tests/derivations.scm’ (though the test would already succeed before due to the ELF interpreter being unavailable in the chroot). • Explicitly close both ends of the ‘readiness’ pipe. • Use ‘mkdir -p’ to create /var/log/guix in ‘guix-install.sh’. Thoughts? Ludo’. Ludovic Courtès (16): daemon: Use ‘close_range’ where available. daemon: Close the read end of the logging pipe. daemon: Bind-mount /etc/nsswitch.conf & co. only if it exists. daemon: Bind-mount all the inputs, not just directories. daemon: Remount inputs as read-only. daemon: Remount root directory as read-only. daemon: Allow running as non-root with unprivileged user namespaces. daemon: Create /var/guix/profiles/per-user unconditionally. daemon: Drop Linux ambient capabilities before executing builder. daemon: Move comments where they belong. linux-container: ‘unprivileged-user-namespace-supported?’ returns #f on non-Linux. tests: Add missing derivation inputs. tests: Run in a chroot and unprivileged user namespaces. etc: systemd services: Run ‘guix-daemon’ as an unprivileged user. guix-install.sh: Support the unprivileged daemon where possible. DRAFT gnu: guix: Update to f447941. build-aux/test-env.in | 18 +- config-daemon.ac | 5 +- doc/guix.texi | 102 ++++++++--- etc/gnu-store.mount.in | 3 +- etc/guix-daemon.service.in | 22 ++- etc/guix-install.sh | 124 ++++++++++--- gnu/build/linux-container.scm | 4 +- gnu/packages/package-management.scm | 6 +- guix/substitutes.scm | 2 +- nix/libstore/build.cc | 271 ++++++++++++++++++++++------ nix/libstore/local-store.cc | 26 ++- nix/libutil/util.cc | 26 ++- tests/derivations.scm | 34 +++- tests/packages.scm | 13 +- tests/processes.scm | 9 +- tests/store.scm | 247 +++++++++++++++++++++---- 16 files changed, 726 insertions(+), 186 deletions(-) base-commit: cbd2db98954739db1cdda208e1667c5d50976bf1 -- 2.48.1
guix-patches@HIDDEN
:bug#75810
; Package guix-patches
.
Full text available.Received: (at 75810) by debbugs.gnu.org; 20 Mar 2025 20:56:37 +0000 From debbugs-submit-bounces <at> debbugs.gnu.org Thu Mar 20 16:56:36 2025 Received: from localhost ([127.0.0.1]:59174 helo=debbugs.gnu.org) by debbugs.gnu.org with esmtp (Exim 4.84_2) (envelope-from <debbugs-submit-bounces <at> debbugs.gnu.org>) id 1tvMwO-0006UY-B1 for submit <at> debbugs.gnu.org; Thu, 20 Mar 2025 16:56:36 -0400 Received: from eggs.gnu.org ([2001:470:142:3::10]:50862) by debbugs.gnu.org with esmtps (TLS1.2:ECDHE_RSA_AES_256_GCM_SHA384:256) (Exim 4.84_2) (envelope-from <ludo@HIDDEN>) id 1tvMw1-0006Qe-J7 for 75810 <at> debbugs.gnu.org; Thu, 20 Mar 2025 16:56:18 -0400 Received: from fencepost.gnu.org ([2001:470:142:3::e]) by eggs.gnu.org with esmtps (TLS1.2:ECDHE_RSA_AES_256_GCM_SHA384:256) (Exim 4.90_1) (envelope-from <ludo@HIDDEN>) id 1tvMvv-0001FR-IA; Thu, 20 Mar 2025 16:56:07 -0400 DKIM-Signature: v=1; a=rsa-sha256; q=dns/txt; c=relaxed/relaxed; d=gnu.org; s=fencepost-gnu-org; h=MIME-Version:References:In-Reply-To:Date:Subject:To: From; bh=gj2HkSqKqMC6OnWJO11zAMx01vOVuopEBzKWBjgHWEs=; b=AJ6hBdsHuxeZ9FdMi1YS qnH1XarggqYw/zbOMP896o92PbkKafqB/+syv3cPWJcOgny4emAuYuWKebwYhDZs/IbzjbiXZps2M ppJri1jymguwmQDxc6v1kpFg9Ru15V/Qpnt38dmdAp8wgl6KC5iSdZq4L7b9f7uUHBjfvZmUttXtv m9gKrSrLnU6m9j6/J+NogaNG2/s/G3itEkbPnHsphCY4HWXUSTkrgkALm5xmUeNbrKyZ9sgKwZMPb NEBPbiUTAaW1OS/asMDPcO22G19SPqw2Xf7L37IjrxwfSok5GunrWVXCTtBEBhcob9pdCtcfgnbAy jJfmeHZcKxsckQ==; From: =?UTF-8?q?Ludovic=20Court=C3=A8s?= <ludo@HIDDEN> To: 75810 <at> debbugs.gnu.org Subject: [PATCH v7 01/16] =?UTF-8?q?daemon:=20Use=20=E2=80=98close=5Frange?= =?UTF-8?q?=E2=80=99=20where=20available.?= Date: Thu, 20 Mar 2025 21:54:34 +0100 Message-ID: <5edb7d923d441d4be77fe8d699199678c4acb390.1742503591.git.ludo@HIDDEN> X-Mailer: git-send-email 2.48.1 In-Reply-To: <cover.1742503590.git.ludo@HIDDEN> References: <cover.1742503590.git.ludo@HIDDEN> MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit X-Spam-Score: -2.3 (--) X-Debbugs-Envelope-To: 75810 Cc: =?UTF-8?q?Ludovic=20Court=C3=A8s?= <ludo@HIDDEN> X-BeenThere: debbugs-submit <at> debbugs.gnu.org X-Mailman-Version: 2.1.18 Precedence: list List-Id: <debbugs-submit.debbugs.gnu.org> List-Unsubscribe: <https://debbugs.gnu.org/cgi-bin/mailman/options/debbugs-submit>, <mailto:debbugs-submit-request <at> debbugs.gnu.org?subject=unsubscribe> List-Archive: <https://debbugs.gnu.org/cgi-bin/mailman/private/debbugs-submit/> List-Post: <mailto:debbugs-submit <at> debbugs.gnu.org> List-Help: <mailto:debbugs-submit-request <at> debbugs.gnu.org?subject=help> List-Subscribe: <https://debbugs.gnu.org/cgi-bin/mailman/listinfo/debbugs-submit>, <mailto:debbugs-submit-request <at> debbugs.gnu.org?subject=subscribe> Errors-To: debbugs-submit-bounces <at> debbugs.gnu.org Sender: "Debbugs-submit" <debbugs-submit-bounces <at> debbugs.gnu.org> X-Spam-Score: -3.3 (---) * nix/libutil/util.cc (closeMostFDs) [HAVE_CLOSE_RANGE]: Use ‘close_range’ when ‘exceptions’ is empty. * config-daemon.ac: Check for <linux/close_range.h> and the ‘close_range’ symbol. Change-Id: I12fa3bde58b003fcce5ea5a1fee1dcf9a92c0359 --- config-daemon.ac | 5 +++-- nix/libutil/util.cc | 23 +++++++++++++++++------ 2 files changed, 20 insertions(+), 8 deletions(-) diff --git a/config-daemon.ac b/config-daemon.ac index 6731c68bc3..4e949bc88a 100644 --- a/config-daemon.ac +++ b/config-daemon.ac @@ -78,7 +78,8 @@ if test "x$guix_build_daemon" = "xyes"; then dnl Chroot support. AC_CHECK_FUNCS([chroot unshare]) - AC_CHECK_HEADERS([sched.h sys/param.h sys/mount.h sys/syscall.h]) + AC_CHECK_HEADERS([sched.h sys/param.h sys/mount.h sys/syscall.h \ + linux/close_range.h]) if test "x$ac_cv_func_chroot" != "xyes"; then AC_MSG_ERROR(['chroot' function missing, bailing out]) @@ -95,7 +96,7 @@ if test "x$guix_build_daemon" = "xyes"; then dnl strsignal: for error reporting. dnl statx: fine-grain 'stat' call, new in glibc 2.28. AC_CHECK_FUNCS([lutimes lchown posix_fallocate sched_setaffinity \ - statvfs nanosleep strsignal statx]) + statvfs nanosleep strsignal statx close_range]) dnl Check for <locale>. AC_LANG_PUSH(C++) diff --git a/nix/libutil/util.cc b/nix/libutil/util.cc index 3206dea11b..eb2d16e1cc 100644 --- a/nix/libutil/util.cc +++ b/nix/libutil/util.cc @@ -23,6 +23,10 @@ #include <sys/prctl.h> #endif +#ifdef HAVE_LINUX_CLOSE_RANGE_H +# include <linux/close_range.h> +#endif + extern char * * environ; @@ -1087,12 +1091,19 @@ string runProgram(Path program, bool searchPath, const Strings & args) void closeMostFDs(const set<int> & exceptions) { - int maxFD = 0; - maxFD = sysconf(_SC_OPEN_MAX); - for (int fd = 0; fd < maxFD; ++fd) - if (fd != STDIN_FILENO && fd != STDOUT_FILENO && fd != STDERR_FILENO - && exceptions.find(fd) == exceptions.end()) - close(fd); /* ignore result */ +#ifdef HAVE_CLOSE_RANGE + if (exceptions.empty()) + close_range(3, ~0U, 0); + else +#endif + { + int maxFD = 0; + maxFD = sysconf(_SC_OPEN_MAX); + for (int fd = 0; fd < maxFD; ++fd) + if (fd != STDIN_FILENO && fd != STDOUT_FILENO && fd != STDERR_FILENO + && exceptions.find(fd) == exceptions.end()) + close(fd); /* ignore result */ + } } -- 2.48.1
guix-patches@HIDDEN
:bug#75810
; Package guix-patches
.
Full text available.Received: (at 75810) by debbugs.gnu.org; 20 Mar 2025 20:56:20 +0000 From debbugs-submit-bounces <at> debbugs.gnu.org Thu Mar 20 16:56:20 2025 Received: from localhost ([127.0.0.1]:59144 helo=debbugs.gnu.org) by debbugs.gnu.org with esmtp (Exim 4.84_2) (envelope-from <debbugs-submit-bounces <at> debbugs.gnu.org>) id 1tvMw6-0006RW-Lc for submit <at> debbugs.gnu.org; Thu, 20 Mar 2025 16:56:20 -0400 Received: from eggs.gnu.org ([2001:470:142:3::10]:41184) by debbugs.gnu.org with esmtps (TLS1.2:ECDHE_RSA_AES_256_GCM_SHA384:256) (Exim 4.84_2) (envelope-from <ludo@HIDDEN>) id 1tvMw3-0006Qh-9N for 75810 <at> debbugs.gnu.org; Thu, 20 Mar 2025 16:56:16 -0400 Received: from fencepost.gnu.org ([2001:470:142:3::e]) by eggs.gnu.org with esmtps (TLS1.2:ECDHE_RSA_AES_256_GCM_SHA384:256) (Exim 4.90_1) (envelope-from <ludo@HIDDEN>) id 1tvMvy-0001Fq-04; Thu, 20 Mar 2025 16:56:10 -0400 DKIM-Signature: v=1; a=rsa-sha256; q=dns/txt; c=relaxed/relaxed; d=gnu.org; s=fencepost-gnu-org; h=MIME-Version:References:In-Reply-To:Date:Subject:To: From; bh=5fbggu8STjwEXFRRV3Gq/UXyTgxUmf6fh1UKO8gjNXs=; b=jiMcrU0OgmsffH/MwQz+ fke3F+QHzmR3bL+Q6kbCjg9zTsaMnWJFaHR+4U0lUwU6oO5LggHptPRYWWVFTJ+Qh7LwElkWtwlUd VQuD0lRPeIe32y5B3R1gdea7cfe1eNPfMqkFzQULWApXwityjOYIaUMcSVXteL4inBCSdHaRRXAv4 nSOTv3H0Fe9++jcnNVwN2xqYfg1vIZEg9q+AmpWkHk5qQfxKFDs8axVA8xZcwhQYSMse7bh2ePhYu uY56LNkNlehh5cFM8XYeels1R0xTasBrB/mmP7rdvqMfVo5QeymZ0U7jT+7FUDja3gdeUAGW58lf6 fLsqPImAXtZ9uw==; From: =?UTF-8?q?Ludovic=20Court=C3=A8s?= <ludo@HIDDEN> To: 75810 <at> debbugs.gnu.org Subject: [PATCH v7 03/16] daemon: Bind-mount /etc/nsswitch.conf & co. only if it exists. Date: Thu, 20 Mar 2025 21:54:36 +0100 Message-ID: <685be9a097b408871ef5313205552c9fbce748a6.1742503591.git.ludo@HIDDEN> X-Mailer: git-send-email 2.48.1 In-Reply-To: <cover.1742503590.git.ludo@HIDDEN> References: <cover.1742503590.git.ludo@HIDDEN> MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit X-Spam-Score: -2.3 (--) X-Debbugs-Envelope-To: 75810 Cc: =?UTF-8?q?Ludovic=20Court=C3=A8s?= <ludo@HIDDEN> X-BeenThere: debbugs-submit <at> debbugs.gnu.org X-Mailman-Version: 2.1.18 Precedence: list List-Id: <debbugs-submit.debbugs.gnu.org> List-Unsubscribe: <https://debbugs.gnu.org/cgi-bin/mailman/options/debbugs-submit>, <mailto:debbugs-submit-request <at> debbugs.gnu.org?subject=unsubscribe> List-Archive: <https://debbugs.gnu.org/cgi-bin/mailman/private/debbugs-submit/> List-Post: <mailto:debbugs-submit <at> debbugs.gnu.org> List-Help: <mailto:debbugs-submit-request <at> debbugs.gnu.org?subject=help> List-Subscribe: <https://debbugs.gnu.org/cgi-bin/mailman/listinfo/debbugs-submit>, <mailto:debbugs-submit-request <at> debbugs.gnu.org?subject=subscribe> Errors-To: debbugs-submit-bounces <at> debbugs.gnu.org Sender: "Debbugs-submit" <debbugs-submit-bounces <at> debbugs.gnu.org> X-Spam-Score: -3.3 (---) Those files may be missing in some contexts, for instance within the build environment. * nix/libstore/build.cc (DerivationGoal::runChild): Add /etc/resolv.conf and related files to ‘ss’ only if they exist. Change-Id: Ie19664a86c8101a1dc82cf39ad4b7abb10f8250a --- nix/libstore/build.cc | 9 +++++---- 1 file changed, 5 insertions(+), 4 deletions(-) diff --git a/nix/libstore/build.cc b/nix/libstore/build.cc index edd01bab34..8ca5e5b732 100644 --- a/nix/libstore/build.cc +++ b/nix/libstore/build.cc @@ -2093,10 +2093,11 @@ void DerivationGoal::runChild() network, so give them access to /etc/resolv.conf and so on. */ if (fixedOutput) { - ss.push_back("/etc/resolv.conf"); - ss.push_back("/etc/nsswitch.conf"); - ss.push_back("/etc/services"); - ss.push_back("/etc/hosts"); + auto files = { "/etc/resolv.conf", "/etc/nsswitch.conf", + "/etc/services", "/etc/hosts" }; + for (auto & file: files) { + if (pathExists(file)) ss.push_back(file); + } } for (auto & i : ss) dirsInChroot[i] = i; -- 2.48.1
guix-patches@HIDDEN
:bug#75810
; Package guix-patches
.
Full text available.Received: (at 75810) by debbugs.gnu.org; 18 Mar 2025 23:20:09 +0000 From debbugs-submit-bounces <at> debbugs.gnu.org Tue Mar 18 19:20:08 2025 Received: from localhost ([127.0.0.1]:43797 helo=debbugs.gnu.org) by debbugs.gnu.org with esmtp (Exim 4.84_2) (envelope-from <debbugs-submit-bounces <at> debbugs.gnu.org>) id 1tugE5-00065w-5U for submit <at> debbugs.gnu.org; Tue, 18 Mar 2025 19:20:07 -0400 Received: from mailout.russelstein.xyz ([2605:6400:20:11e::1]:44014) by debbugs.gnu.org with esmtps (TLS1.2:ECDHE_RSA_AES_256_GCM_SHA384:256) (Exim 4.84_2) (envelope-from <reepca@HIDDEN>) id 1tugE1-00065U-4R for 75810 <at> debbugs.gnu.org; Tue, 18 Mar 2025 19:20:00 -0400 DKIM-Signature: v=1; a=ed25519-sha256; q=dns/txt; c=relaxed/relaxed; d=russelstein.xyz; s=ed25519; h=Content-Type:MIME-Version:Message-ID:Date: References:In-Reply-To:Subject:Cc:To:From:Sender:Reply-To: Content-Transfer-Encoding:Content-ID:Content-Description:Resent-Date: Resent-From:Resent-Sender:Resent-To:Resent-Cc:Resent-Message-ID:List-Id: List-Help:List-Unsubscribe:List-Subscribe:List-Post:List-Owner:List-Archive; bh=xC5j2+GyW8bJxXUP0MHSlCH2C5mIoHUfrpLHSky3Rz8=; b=LCzI9S2Z0eneQfOT9RfNXHEQZo ecxLU0nVdOhVtW9uXbLpV0DBIywu0hENX0TGHGc3LMluL/R9PM+xQR2jwpAg==; DKIM-Signature: v=1; a=rsa-sha256; q=dns/txt; c=relaxed/relaxed; d=russelstein.xyz; s=rsa; h=Content-Type:MIME-Version:Message-ID:Date: References:In-Reply-To:Subject:Cc:To:From:Sender:Reply-To: Content-Transfer-Encoding:Content-ID:Content-Description:Resent-Date: Resent-From:Resent-Sender:Resent-To:Resent-Cc:Resent-Message-ID:List-Id: List-Help:List-Unsubscribe:List-Subscribe:List-Post:List-Owner:List-Archive; bh=xC5j2+GyW8bJxXUP0MHSlCH2C5mIoHUfrpLHSky3Rz8=; b=yWVZvPO9eurNPOfySCBFIRq0U8 aG9mSDv7MVnW+hwR9Pl3+Wu0qA1oNGrcTOWAtivgoIn1hu0c7CyvypE+U2qXum98p1cyflBzyUKdT oZe42Cot7kf9fRUo9ufBbeBAXYrxq/Untg+wlqCNKtkALhxM/4PyRCaYb3MXIpSlmIaU5tugfReGf f6hhjwCpNHJr7wux2E6zxvnOzGjlpGhsMnA/wecOXla+YICT4RVigr+tIxDB1nSPLyoyqc0vfnUQO ccnvbkT62Avx/8T5Dd2a9qeBNYPKQ/GD3cvRDlrqZC3MwU+gPSElZYvbB6+kG7tSwKV6AwCYipZBu peZG+sxMGeMhH41EZUJq1If8oQ5qijfRng8CfEAjZ26Q0kMDQ6Mk/LIPh/pImhzbWLbN9dI8yJesi ZG3SgDLX5cTNmWH4Wsbt/cUVF+kmGaQDqMvB60oaQCHBSAoeswozT9jUgtzHIbwQiy4IxCYpwYxJk azPmD6ddiBAHOJUTTueMPjxcwllaDtpEP8Oa7ag73JvE/QwBoaDExSM0ECxYlSqFsQ8emNmtDDC/a khCKcBUqX69d/YDKaGlpFFOFknEc9De6A7+WFnAY2LsiHube3mea8MIIQtvRMD9dt5ennEHH3mrqy V7AfIbeK2r/zqTRMMRNJCLMOJG3+H9VRqhkzs1GQ4=; Received: by russelstein.xyz with esmtpsa (TLS1.3:ECDHE_SECP256R1__RSA_PSS_RSAE_SHA256__AES_256_GCM:256) (Exim 4.98) (envelope-from <reepca@HIDDEN>) id 1tugDs-000000005NU-3y3y; Tue, 18 Mar 2025 18:19:54 -0500 From: Reepca Russelstein <reepca@HIDDEN> To: Ludovic =?utf-8?Q?Court=C3=A8s?= <ludo@HIDDEN> Subject: Re: [bug#75810] [PATCH v6 00/16] Rootless guix-daemon In-Reply-To: <87v7s6h21b.fsf@HIDDEN> ("Ludovic =?utf-8?Q?Court=C3=A8s=22'?= =?utf-8?Q?s?= message of "Tue, 18 Mar 2025 15:00:16 +0100") References: <cover.1742230219.git.ludo@HIDDEN> <875xk7594u.fsf@HIDDEN> <87v7s6h21b.fsf@HIDDEN> Date: Tue, 18 Mar 2025 18:19:04 -0500 Message-ID: <871puu53mf.fsf@HIDDEN> User-Agent: Gnus/5.13 (Gnus v5.13) MIME-Version: 1.0 Content-Type: multipart/signed; boundary="=-=-="; micalg=pgp-sha256; protocol="application/pgp-signature" X-Spam-Score: 0.5 X-Spam-Bar: / X-Spam-Score-Int: 5 X-Spam-Report: Spam detection software, running on the system "Sanctum", has NOT identified this incoming email as spam. The original message has been attached to this so you can view it or label similar future email. If you have any questions, see the administrator of that system for details. Content preview: Ludovic Courtès <ludo@HIDDEN> writes: >> For my two cents, I do think that it's still a tradeoff - not just >> because of the reliance on different kernel mechanisms for security, but >> also because the rootless daemon currently causes v [...] Content analysis details: (0.5 points, 5.0 required) pts rule name description ---- ---------------------- -------------------------------------------------- -0.0 NO_RELAYS Informational: message was not relayed via SMTP 0.5 FROM_SUSPICIOUS_NTLD From abused NTLD X-Spam-Score: 2.0 (++) X-Spam-Report: Spam detection software, running on the system "debbugs.gnu.org", has NOT identified this incoming email as spam. The original message has been attached to this so you can view it or label similar future email. If you have any questions, see the administrator of that system for details. Content preview: Ludovic Courtès <ludo@HIDDEN> writes: >> For my two cents, I do think that it's still a tradeoff - not just >> because of the reliance on different kernel mechanisms for security, but >> also because the rootless daemon currently causes v [...] Content analysis details: (2.0 points, 10.0 required) pts rule name description ---- ---------------------- -------------------------------------------------- -0.0 SPF_PASS SPF: sender matches SPF record 1.5 PDS_OTHER_BAD_TLD Untrustworthy TLDs [URI: russelstein.xyz (xyz)] 0.0 SPF_HELO_NONE SPF: HELO does not publish an SPF Record 0.5 FROM_SUSPICIOUS_NTLD From abused NTLD X-Debbugs-Envelope-To: 75810 Cc: 75810 <at> debbugs.gnu.org X-BeenThere: debbugs-submit <at> debbugs.gnu.org X-Mailman-Version: 2.1.18 Precedence: list List-Id: <debbugs-submit.debbugs.gnu.org> List-Unsubscribe: <https://debbugs.gnu.org/cgi-bin/mailman/options/debbugs-submit>, <mailto:debbugs-submit-request <at> debbugs.gnu.org?subject=unsubscribe> List-Archive: <https://debbugs.gnu.org/cgi-bin/mailman/private/debbugs-submit/> List-Post: <mailto:debbugs-submit <at> debbugs.gnu.org> List-Help: <mailto:debbugs-submit-request <at> debbugs.gnu.org?subject=help> List-Subscribe: <https://debbugs.gnu.org/cgi-bin/mailman/listinfo/debbugs-submit>, <mailto:debbugs-submit-request <at> debbugs.gnu.org?subject=subscribe> Errors-To: debbugs-submit-bounces <at> debbugs.gnu.org Sender: "Debbugs-submit" <debbugs-submit-bounces <at> debbugs.gnu.org> X-Spam-Score: 2.0 (++) X-Spam-Report: Spam detection software, running on the system "debbugs.gnu.org", has NOT identified this incoming email as spam. The original message has been attached to this so you can view it or label similar future email. If you have any questions, see the administrator of that system for details. Content preview: Ludovic Courtès <ludo@HIDDEN> writes: >> For my two cents, I do think that it's still a tradeoff - not just >> because of the reliance on different kernel mechanisms for security, but >> also because the rootless daemon currently causes v [...] Content analysis details: (2.0 points, 10.0 required) pts rule name description ---- ---------------------- -------------------------------------------------- -0.0 SPF_PASS SPF: sender matches SPF record 1.5 PDS_OTHER_BAD_TLD Untrustworthy TLDs [URI: russelstein.xyz (xyz)] 0.0 SPF_HELO_NONE SPF: HELO does not publish an SPF Record 0.5 FROM_SUSPICIOUS_NTLD From abused NTLD 1.0 BULK_RE_SUSP_NTLD Precedence bulk and RE: from a suspicious TLD -1.0 MAILING_LIST_MULTI Multiple indicators imply a widely-seen list manager --=-=-= Content-Type: text/plain; charset=utf-8 Content-Transfer-Encoding: quoted-printable Ludovic Court=C3=A8s <ludo@HIDDEN> writes: >> For my two cents, I do think that it's still a tradeoff - not just >> because of the reliance on different kernel mechanisms for security, but >> also because the rootless daemon currently causes visible changes to the >> build environment (EROFS on /, and nothing owned by root, for example). >> Which one should we consider the "canonical" build environment going >> forward? > > The way I see it, we would gradually move to the non-root daemon: > > =E2=80=A2 First step here is to enable it by default on systemd distros. > > =E2=80=A2 Second step would be to allow Guix System users to migrate to > non-root daemon, keeping the default unchanged. > > =E2=80=A2 Third step (a year later maybe?) would be to default to non-r= oot > daemon on Guix System and on remaining distros (though for these it > might be trickier because we probably cannot rely on CAP_SYS_CHOWN, > not as easily as with systemd at least). > > The visible changes in the build environment are unfortunate; I=E2=80=99m= hoping > they won=E2=80=99t have any practical impact, not any more than the other > parameters that may change currently (build UID, binfmt_misc, file > system, etc.) We could test this hypothesis by rebuilding at least the > entire set of packages up to =E2=80=98hello=E2=80=99. (I tried doing it = just now in a > Debian VM but failed since the main partition cannot easily be extended; > it=E2=80=99ll be easier to do with Guix System.) > For what it's worth, the visible changes could be avoided with subordinate ids, as I wrote in https://debbugs.gnu.org/cgi/bugreport.cgi?bug=3D75810#86. We could try it as-is and see how it goes, and if there are problems with reproducibility add on using subordinate ids. I would expect it to be a much smaller change than the root->rootless transition. Hopefully it works well enough as-is that offload systems could be set up without any special permissions. > Then there are 3 possibilities: > > 1. If /proc/self/exe points to (say) /usr/bin/guix-daemon, outside the > store, execve fails with ENOENT because that file is not mounted in > the chroot. No, like I wrote, /proc/self/exe, despite being reported as a symlink by stat, does not follow the usual symlink semantics. This is much like how the files in /proc/self/fd work, e.g.: scheme@(guile-user)> (open-file "/tmp/freshfile" "w+") $1 =3D #<input-output: /tmp/freshfile 13> scheme@(guile-user)> (delete-file "/tmp/freshfile") scheme@(guile-user)> (stat:type (lstat "/proc/self/fd/13")) $3 =3D symlink scheme@(guile-user)> (readlink "/proc/self/fd/13") $4 =3D "/tmp/freshfile (deleted)" scheme@(guile-user)> (open-file "/proc/self/fd/13" "w+") $5 =3D #<input-output: /proc/self/fd/13 14> Here is a test program to demonstrate this (it's unfortunately rather tricky to demonstrate using usual command line tools): =2D-8<---------------cut here---------------start------------->8--- /* Test program to demonstrate that /proc/self/exe does not behave like a symlink, and a process can exec /proc/self/exe even if there is no other filename by which the currently-executing program can be reached. Compile with -static (may require a 'guix shell gcc-toolchain glibc:stat= ic') and run. */ #define _GNU_SOURCE #include <stdio.h> #include <stdlib.h> #include <stdint.h> #include <string.h> #include <unistd.h> #include <sched.h> #include <sys/param.h> #include <sys/mount.h> #include <sys/syscall.h> #include <sys/wait.h> #include <sys/stat.h> #include <errno.h> #include <signal.h> #define die(msg, status) \ do \ { \ perror(msg); \ exit(status); \ } while(0); \ =20=20 #define pivot_root(new_root, put_old) (syscall(SYS_pivot_root, new_root,put= _old)) int child_main(void * arg) { int *pipefds =3D (int *) arg; char *argv[2] =3D {"???", NULL}; int saved_errno; char c; if(close(pipefds[1])) die("Child closing write end of pipe", 20); if(read(pipefds[0], &c, 1 * sizeof(char)) < (1 * sizeof(char))) die("Reading from pipe", 21); if(c !=3D 'y') die("Parent setup failed", 22); if(close(pipefds[0])) die("Child closing read end of pipe", 23); if(mkdir("/tmp/test-chroot", 0700) && errno !=3D EEXIST) die("mkdir(\"/tmp/test-chroot\")", 24); if(mount(0, "/", 0, MS_REC|MS_PRIVATE, 0)) die("making / private", 25); if(mount("/tmp/test-chroot", "/tmp/test-chroot", 0, MS_BIND, 0)) die("making /tmp/test-chroot its own filesystem", 26); if(mkdir("/tmp/test-chroot/proc", 0700) && errno !=3D EEXIST) die("mkdir(\"/tmp/test-chroot/proc\")", 27); if(mount("none", "/tmp/test-chroot/proc", "proc", 0, 0)) die("mount procfs", 28); if(chdir("/tmp/test-chroot")) die("chdir to /tmp/test-chroot", 29); if(mkdir("real-root", 0)) die("mkdir(\"real-root\")", 30); if(pivot_root(".", "real-root")) die("pivot_root", 31); if(chroot(".")) die("chroot", 32); if(umount2("real-root", MNT_DETACH)) die("unmounting real root", 33); if(rmdir("real-root")) die("removing real root directory", 34); if(execve("/proc/self/exe", argv, environ)) { saved_errno =3D errno; fprintf(stderr, "execve errno: %d\n", saved_errno); errno =3D saved_errno; die("execve", 35); } } int main(int argc, char **argv) { pid_t child_pid =3D -1; char stack[32 * 1024]; int flags; int result; int status; FILE * f; char strbuf[512]; int j; int pipefds[2]; if(getenv("TEST_PROGRAM_MAGIC_ENV_VAR")) { fprintf(stderr, "Self-exec'ed!\n"); fprintf(stderr, "Arguments: \n"); for(j =3D 0; j < argc; j++) fprintf(stderr, "%s\n", argv[j]); j =3D readlink("/proc/self/exe", strbuf, sizeof(strbuf) - 1); if(j >=3D 0) { strbuf[j] =3D '\0'; fprintf(stderr, "/proc/self/exe readlink result: %s\n", strbuf); f =3D fopen(strbuf, "r"); if(f) { fprintf(stderr, "... and that file exists!\n"); fclose(f); } else { perror("fopen /proc/self/exe readlink result error"); fprintf(stderr, "... and that file does not exist.\n"); } f =3D fopen("/proc/self/exe", "r"); if(f) { fprintf(stderr, "/proc/self/exe can be opened\n"); fclose(f); } else { perror("fopen /proc/self/exe error"); fprintf(stderr, "/proc/self/exe cannot be opened\n"); } } return 0; } setenv("TEST_PROGRAM_MAGIC_ENV_VAR", "1", 1); =20=20 if(pipe(pipefds)) die("pipe()", 1); flags =3D CLONE_NEWPID | CLONE_NEWNS | CLONE_NEWIPC | CLONE_NEWUTS | CLON= E_NEWUSER; flags =3D flags | SIGCHLD;=20 child_pid =3D clone(child_main, (char *)(((uintptr_t)stack + sizeof(stack) - 8) & ~((ui= ntptr_t)0xf)), flags, (void *) pipefds); if(child_pid =3D=3D -1) die("clone()", 1); if(close(pipefds[0])) die("parent closing read pipe end", 2); if(snprintf(strbuf, sizeof(strbuf), "/proc/%d/uid_map", child_pid) >=3D sizeof(strbuf)) die("uid_map snprintf", 3); f =3D fopen(strbuf, "w"); if(!f) die("uid_map fopen", 4); if(snprintf(strbuf, sizeof(strbuf), "%u %u 1", geteuid(), geteuid()) >=3D sizeof(strbuf)) die("uid_map contents snprintf", 5); if(fwrite(strbuf, strlen(strbuf) * sizeof(char), 1, f) < 1) die("uid_map fwrite", 6); if(fclose(f) =3D=3D EOF) die("uid_map fclose", 7); if(snprintf(strbuf, sizeof(strbuf), "/proc/%d/setgroups", child_pid) >=3D sizeof(strbuf)) die("setgroups snprintf", 8); f =3D fopen(strbuf, "w"); if(!f) die("setgroups fopen", 9); if(fwrite("deny", 4 * sizeof(char), 1, f) < 1) die("setgroups fwrite", 10); if(fclose(f) =3D=3D EOF) die("setgroups fclose", 11); if(snprintf(strbuf, sizeof(strbuf), "/proc/%d/gid_map", child_pid) >=3D sizeof(strbuf)) die("gid_map snprintf", 12); f =3D fopen(strbuf, "w"); if(!f) die("gid_map fopen", 13); if(snprintf(strbuf, sizeof(strbuf), "%u %u 1", getegid(), getegid()) >=3D sizeof(strbuf)) die("gid_map contents snprintf", 14); if(fwrite(strbuf, strlen(strbuf) * sizeof(char), 1, f) < 1) die("gid_map fwrite", 15); if(fclose(f) =3D=3D EOF) die("gid_map fclose", 16); if(write(pipefds[1], "y", sizeof("y") - (1 * sizeof(char))) < (1 * sizeof= (char))) die("writing to pipe", 17); if(close(pipefds[1])) die("parent closing write pipe end", 18) while (1) { result =3D waitpid(child_pid, &status, 0); if(result =3D=3D child_pid) return WEXITSTATUS(status); if(result =3D=3D -1 && errno !=3D EINTR) die("waitpid", 19); } } =2D-8<---------------cut here---------------end--------------->8--- Here's what it looks like when I run it: =2D-8<---------------cut here---------------start------------->8--- $ /tmp/test-program Self-exec'ed! Arguments:=20 ??? /proc/self/exe readlink result: /tmp/test-program fopen /proc/self/exe readlink result error: No such file or directory ... and that file does not exist. /proc/self/exe can be opened =2D-8<---------------cut here---------------end--------------->8--- > Here=E2=80=99s a test that fails both =E2=80=9Crootfull=E2=80=9D and =E2= =80=9Crootless=E2=80=9D: > > (let* ((builder (add-file-tree-to-store %store > `("builder" symlink "/proc/self/e= xe"))) > (drv (derivation %store "attempt-to-run-guix-daemon" builder '() > #:env-vars > '(("LD_PRELOAD" . "attacker-controlled.so"))))) > (guard (c ((store-protocol-error? c) c)) > (build-derivations %store (list drv)) > #f)) From=20'man 2 execve': ENOENT The file pathname or a script *or ELF interpreter* does not e= xist. (emphasis mine). The dynamic linker registered in guix-daemon's binary is not likely to exist in the container in this test, but an attacker could easily make it so as long as it's in the store. > diff --git a/nix/libstore/build.cc b/nix/libstore/build.cc > index 7484ea8fcf..970107c265 100644 > --- a/nix/libstore/build.cc > +++ b/nix/libstore/build.cc > @@ -2374,6 +2374,15 @@ void DerivationGoal::runChild() > writeFull(STDERR_FILENO, "error: " + string(e.what()) + = "\n"); > _exit(1); > } > + } else { > + /* Ensure that the builder is within the store. This prevents > + users from using /proc/self/exe (or a symlink to it) as their > + builder, which could allow them to overwrite the guix-daemon > + binary (CVE-2019-5736). */ > + drv.builder =3D canonPath(drv.builder, true); > + printMsg(lvlError, format("builder is `%1%'") % drv.builder); > + if (!isInStore(drv.builder)) > + throw Error(format("derivation builder '%1%' is outside the store") % = drv.builder); > } >=20=20 > /* Fill in the arguments. */ Note that we should still supply the original name or basename as argv[0]. While ensuring that what actually gets execve'd is in the store suffices to eliminate the vulnerability, it may be "conceptually purer" to require that the links pointing to it are all in the store as well. For example, while a builder that is a symlink pointing to /proc/self/exe wouldn't be able to modify the daemon binary, it's still a piece of basically "undefined behavior" as far as the build environment is concerned, which could be closed up. But that can come later just as well. One more consideration I noticed when looking at v6's patch 14/16 (the guix-daemon.service one): we don't do anything to set the gid. I know on guix system we usually use both dedicated privilege separation users and groups for services. Should we use a dedicated group for guix-daemon as well? Note that currently the chroot directories have 0750 permissions, so it's very important that their group not be accessible to others. =2D reepca --=-=-= Content-Type: application/pgp-signature; name="signature.asc" -----BEGIN PGP SIGNATURE----- iQFLBAEBCAA1FiEEdNapMPRLm4SepVYGwWaqSV9/GJwFAmfZ/2gXHHJlZXBjYUBy dXNzZWxzdGVpbi54eXoACgkQwWaqSV9/GJzgNQgAivP6ufFRwOhu+zlbtnCx2tnT 8jfxwDlpj6KkwhlFiuQIYnIMicg7OG3oi4JaLHzDlXIDxJe3y75Tp/PZ1T5w+kUJ 1yH/dM63kFcPpqQmF0g9NfInuPAeIyvHAWmn9afWFafwOxXYERWoQFBEgkbJzjmY dfyV2Zctf6v4qOk5IqZ4CJcSM/5EOBMn29MnI7C6gDM8AA7KzQYEmlErI0IWw8yB ASOA4mq9GauQNUah+f++zsQGK1qOcrgqBWkiGktBkZqB9R9ac9ooEdx+JLXmLjUP ISKMYjlSiHqgFrZm6vpeZXaHezWtZ5SUDg1cyp3OHqg+9Th8Li5LJNAOAcwNQQ== =NFgQ -----END PGP SIGNATURE----- --=-=-=--
guix-patches@HIDDEN
:bug#75810
; Package guix-patches
.
Full text available.Received: (at 75810) by debbugs.gnu.org; 18 Mar 2025 14:00:38 +0000 From debbugs-submit-bounces <at> debbugs.gnu.org Tue Mar 18 10:00:38 2025 Received: from localhost ([127.0.0.1]:41297 helo=debbugs.gnu.org) by debbugs.gnu.org with esmtp (Exim 4.84_2) (envelope-from <debbugs-submit-bounces <at> debbugs.gnu.org>) id 1tuXUj-0000qT-7d for submit <at> debbugs.gnu.org; Tue, 18 Mar 2025 10:00:38 -0400 Received: from hera.aquilenet.fr ([185.233.100.1]:43422) by debbugs.gnu.org with esmtps (TLS1.2:ECDHE_RSA_AES_256_GCM_SHA384:256) (Exim 4.84_2) (envelope-from <ludo@HIDDEN>) id 1tuXUZ-0000p9-Gy for 75810 <at> debbugs.gnu.org; Tue, 18 Mar 2025 10:00:34 -0400 Received: from localhost (localhost [127.0.0.1]) by hera.aquilenet.fr (Postfix) with ESMTP id BCC793D7; Tue, 18 Mar 2025 15:00:19 +0100 (CET) Authentication-Results: hera.aquilenet.fr; none X-Virus-Scanned: Debian amavis at hera.aquilenet.fr Received: from hera.aquilenet.fr ([127.0.0.1]) by localhost (hera.aquilenet.fr [127.0.0.1]) (amavis, port 10024) with ESMTP id b3XMQXplc12u; Tue, 18 Mar 2025 15:00:18 +0100 (CET) Received: from ribbon (unknown [193.50.110.142]) by hera.aquilenet.fr (Postfix) with ESMTPSA id EFC5930A; Tue, 18 Mar 2025 15:00:17 +0100 (CET) From: =?utf-8?Q?Ludovic_Court=C3=A8s?= <ludo@HIDDEN> To: Reepca Russelstein <reepca@HIDDEN> Subject: Re: [bug#75810] [PATCH v6 00/16] Rootless guix-daemon In-Reply-To: <875xk7594u.fsf@HIDDEN> (Reepca Russelstein's message of "Mon, 17 Mar 2025 22:07:45 -0500") References: <cover.1742230219.git.ludo@HIDDEN> <875xk7594u.fsf@HIDDEN> Date: Tue, 18 Mar 2025 15:00:16 +0100 Message-ID: <87v7s6h21b.fsf@HIDDEN> User-Agent: Gnus/5.13 (Gnus v5.13) MIME-Version: 1.0 Content-Type: multipart/mixed; boundary="=-=-=" X-Rspamd-Queue-Id: BCC793D7 X-Spamd-Result: default: False [4.90 / 15.00]; SPAM_FLAG(5.00)[]; BAYES_HAM(-3.00)[100.00%]; NEURAL_SPAM(3.00)[1.000]; MIME_GOOD(-0.10)[multipart/mixed,text/plain,text/x-patch]; RCVD_COUNT_TWO(0.00)[2]; FROM_EQ_ENVFROM(0.00)[]; MIME_TRACE(0.00)[0:+,1:+,2:+,3:+]; RCPT_COUNT_TWO(0.00)[2]; ARC_NA(0.00)[]; TO_MATCH_ENVRCPT_ALL(0.00)[]; RCVD_VIA_SMTP_AUTH(0.00)[]; RCVD_TLS_ALL(0.00)[]; FROM_HAS_DN(0.00)[]; TO_DN_SOME(0.00)[]; MID_RHS_MATCH_FROM(0.00)[] X-Spam-Level: **** X-Rspamd-Action: no action X-Spamd-Bar: ++++ X-Rspamd-Server: hera X-Spam-Score: 2.4 (++) X-Spam-Report: Spam detection software, running on the system "debbugs.gnu.org", has NOT identified this incoming email as spam. The original message has been attached to this so you can view it or label similar future email. If you have any questions, see the administrator of that system for details. Content preview: Hi! Reepca Russelstein <reepca@HIDDEN> skribis: > (in patch 7/16, in nix/libstore/build.cc) > > Strictly speaking we should check whether the fds are >= 0, not > 0, > since 0 is technically a valid file descriptor, and we use -1 to > indicate the a [...] Content analysis details: (2.4 points, 10.0 required) pts rule name description ---- ---------------------- -------------------------------------------------- 0.0 RCVD_IN_VALIDITY_CERTIFIED_BLOCKED RBL: ADMINISTRATOR NOTICE: The query to Validity was blocked. See https://knowledge.validity.com/hc/en-us/articles/20961730681243 for more information. [185.233.100.1 listed in sa-trusted.bondedsender.org] 0.0 RCVD_IN_VALIDITY_RPBL_BLOCKED RBL: ADMINISTRATOR NOTICE: The query to Validity was blocked. See https://knowledge.validity.com/hc/en-us/articles/20961730681243 for more information. [185.233.100.1 listed in bl.score.senderscore.com] 1.0 SPF_SOFTFAIL SPF: sender does not match SPF record (softfail) -0.0 SPF_HELO_PASS SPF: HELO matches SPF record 1.5 PDS_OTHER_BAD_TLD Untrustworthy TLDs [URI: russelstein.xyz (xyz)] X-Debbugs-Envelope-To: 75810 Cc: 75810 <at> debbugs.gnu.org X-BeenThere: debbugs-submit <at> debbugs.gnu.org X-Mailman-Version: 2.1.18 Precedence: list List-Id: <debbugs-submit.debbugs.gnu.org> List-Unsubscribe: <https://debbugs.gnu.org/cgi-bin/mailman/options/debbugs-submit>, <mailto:debbugs-submit-request <at> debbugs.gnu.org?subject=unsubscribe> List-Archive: <https://debbugs.gnu.org/cgi-bin/mailman/private/debbugs-submit/> List-Post: <mailto:debbugs-submit <at> debbugs.gnu.org> List-Help: <mailto:debbugs-submit-request <at> debbugs.gnu.org?subject=help> List-Subscribe: <https://debbugs.gnu.org/cgi-bin/mailman/listinfo/debbugs-submit>, <mailto:debbugs-submit-request <at> debbugs.gnu.org?subject=subscribe> Errors-To: debbugs-submit-bounces <at> debbugs.gnu.org Sender: "Debbugs-submit" <debbugs-submit-bounces <at> debbugs.gnu.org> X-Spam-Score: 1.4 (+) X-Spam-Report: Spam detection software, running on the system "debbugs.gnu.org", has NOT identified this incoming email as spam. The original message has been attached to this so you can view it or label similar future email. If you have any questions, see the administrator of that system for details. Content preview: Hi! Reepca Russelstein <reepca@HIDDEN> skribis: > (in patch 7/16, in nix/libstore/build.cc) > > Strictly speaking we should check whether the fds are >= 0, not > 0, > since 0 is technically a valid file descriptor, and we use -1 to > indicate the a [...] Content analysis details: (1.4 points, 10.0 required) pts rule name description ---- ---------------------- -------------------------------------------------- 0.0 RCVD_IN_VALIDITY_CERTIFIED_BLOCKED RBL: ADMINISTRATOR NOTICE: The query to Validity was blocked. See https://knowledge.validity.com/hc/en-us/articles/20961730681243 for more information. [185.233.100.1 listed in sa-trusted.bondedsender.org] 0.0 RCVD_IN_VALIDITY_RPBL_BLOCKED RBL: ADMINISTRATOR NOTICE: The query to Validity was blocked. See https://knowledge.validity.com/hc/en-us/articles/20961730681243 for more information. [185.233.100.1 listed in bl.score.senderscore.com] 1.0 SPF_SOFTFAIL SPF: sender does not match SPF record (softfail) -0.0 SPF_HELO_PASS SPF: HELO matches SPF record 1.5 PDS_OTHER_BAD_TLD Untrustworthy TLDs [URI: russelstein.xyz (xyz)] -1.0 MAILING_LIST_MULTI Multiple indicators imply a widely-seen list manager --=-=-= Content-Type: text/plain; charset=utf-8 Content-Transfer-Encoding: quoted-printable Hi! Reepca Russelstein <reepca@HIDDEN> skribis: > (in patch 7/16, in nix/libstore/build.cc) > > Strictly speaking we should check whether the fds are >=3D 0, not > 0, > since 0 is technically a valid file descriptor, and we use -1 to > indicate the absence of a file descriptor. > > Also, readiness.readSide isn't explicitly closed in the child after > we're done with it. Right, fixed. >> + # The unprivileged daemon cannot create the log directory by itself. >> + mkdir /var/log/guix >> + chown guix-daemon:guix-daemon /var/log/guix >> + chmod 755 /var/log/guix > > (in patch 15/16, in etc/guix-install.sh) > > Should this be 'mkdir -p' or some other conditional creation? If I > understand correctly this will fail when overwriting an existing install > using GUIX_ALLOW_OVERWRITE. Correct, fixed as well. (I=E2=80=99ve updated the branch on Codeberg.) > Concerning guix-install.sh, to be clear, is the intent to specifically > not support installing the rootful daemon on systemd systems? > > For my two cents, I do think that it's still a tradeoff - not just > because of the reliance on different kernel mechanisms for security, but > also because the rootless daemon currently causes visible changes to the > build environment (EROFS on /, and nothing owned by root, for example). > Which one should we consider the "canonical" build environment going > forward? The way I see it, we would gradually move to the non-root daemon: =E2=80=A2 First step here is to enable it by default on systemd distros. =E2=80=A2 Second step would be to allow Guix System users to migrate to non-root daemon, keeping the default unchanged. =E2=80=A2 Third step (a year later maybe?) would be to default to non-root daemon on Guix System and on remaining distros (though for these it might be trickier because we probably cannot rely on CAP_SYS_CHOWN, not as easily as with systemd at least). The visible changes in the build environment are unfortunate; I=E2=80=99m h= oping they won=E2=80=99t have any practical impact, not any more than the other parameters that may change currently (build UID, binfmt_misc, file system, etc.) We could test this hypothesis by rebuilding at least the entire set of packages up to =E2=80=98hello=E2=80=99. (I tried doing it ju= st now in a Debian VM but failed since the main partition cannot easily be extended; it=E2=80=99ll be easier to do with Guix System.) > The demo, modified for guix circumstances, would go something like this: > > 1. A derivation is created whose builder is /proc/self/exe, and whose > LD_PRELOAD environment variable points into a malicious store item > for one of its shared libraries - for example, libc. > 2. The daemon reads this in, and, to my knowledge, does no verification > of the builder string. Note that this aspect isn't actually > necessary, as the builder could also be a symlink to /proc/self/exe > from the store. > 3. The daemon sets up the build environment, and execs /proc/self/exe. Then there are 3 possibilities: 1. If /proc/self/exe points to (say) /usr/bin/guix-daemon, outside the store, execve fails with ENOENT because that file is not mounted in the chroot. 2. If /proc/self/exe points to a guix-daemon file inside the store: 2a. If the store item containing guix-daemon is not an input of the derivation, execv fails with ENOENT. 2b. If the store item containing guix-daemon is an input of the derivation, then it=E2=80=99s been remounted read-only and attempt= s to write to it fail with EROFS. Here=E2=80=99s a test that fails both =E2=80=9Crootfull=E2=80=9D and =E2=80= =9Crootless=E2=80=9D: --8<---------------cut here---------------start------------->8--- (let* ((builder (add-file-tree-to-store %store `("builder" symlink "/proc/self/exe= "))) (drv (derivation %store "attempt-to-run-guix-daemon" builder '() #:env-vars '(("LD_PRELOAD" . "attacker-controlled.so"))))) (guard (c ((store-protocol-error? c) c)) (build-derivations %store (list drv)) #f)) --8<---------------cut here---------------end--------------->8--- > There are several points at which that particular attack could be > stopped, and I'd like to try to stop it at as many of them as possible. > A good start would be canonicalizing the builder prior to executing it > and then checking to make sure it is in the store. A more general > solution could look like writing out and then executing a tiny binary, > something like /tmp/runbuilder, that does nothing but unlink itself and > then exec the actual program. If the above is correct, we=E2=80=99re already safe against this particular attack. Canonicalizing the builder cannot hurt (it=E2=80=99s useful in the =E2=80=98--disable-chroot=E2=80=99 case though mostly to prevent programmin= g errors rather than from a security perspective since there are many other issues in that case), apart from adding more code to an already long function. For reference, the extra check I tried but that I=E2=80=99m inclined to not include since it cannot catch anything new: --=-=-= Content-Type: text/x-patch Content-Disposition: inline diff --git a/nix/libstore/build.cc b/nix/libstore/build.cc index 7484ea8fcf..970107c265 100644 --- a/nix/libstore/build.cc +++ b/nix/libstore/build.cc @@ -2374,6 +2374,15 @@ void DerivationGoal::runChild() writeFull(STDERR_FILENO, "error: " + string(e.what()) + "\n"); _exit(1); } + } else { + /* Ensure that the builder is within the store. This prevents + users from using /proc/self/exe (or a symlink to it) as their + builder, which could allow them to overwrite the guix-daemon + binary (CVE-2019-5736). */ + drv.builder = canonPath(drv.builder, true); + printMsg(lvlError, format("builder is `%1%'") % drv.builder); + if (!isInStore(drv.builder)) + throw Error(format("derivation builder '%1%' is outside the store") % drv.builder); } /* Fill in the arguments. */ --=-=-= Content-Type: text/plain; charset=utf-8 Content-Transfer-Encoding: quoted-printable Let me know what you think and I=E2=80=99ll send v7 accordingly. Ludo=E2=80=99. --=-=-=--
guix-patches@HIDDEN
:bug#75810
; Package guix-patches
.
Full text available.Received: (at 75810) by debbugs.gnu.org; 18 Mar 2025 09:35:08 +0000 From debbugs-submit-bounces <at> debbugs.gnu.org Tue Mar 18 05:35:07 2025 Received: from localhost ([127.0.0.1]:36942 helo=debbugs.gnu.org) by debbugs.gnu.org with esmtp (Exim 4.84_2) (envelope-from <debbugs-submit-bounces <at> debbugs.gnu.org>) id 1tuTLi-0007cQ-3G for submit <at> debbugs.gnu.org; Tue, 18 Mar 2025 05:35:07 -0400 Received: from hera.aquilenet.fr ([185.233.100.1]:49696) by debbugs.gnu.org with esmtps (TLS1.2:ECDHE_RSA_AES_256_GCM_SHA384:256) (Exim 4.84_2) (envelope-from <ludo@HIDDEN>) id 1tuTLe-0007ax-Ab for 75810 <at> debbugs.gnu.org; Tue, 18 Mar 2025 05:34:59 -0400 Received: from localhost (localhost [127.0.0.1]) by hera.aquilenet.fr (Postfix) with ESMTP id 62A09421; Tue, 18 Mar 2025 10:34:51 +0100 (CET) Authentication-Results: hera.aquilenet.fr; none X-Virus-Scanned: Debian amavis at hera.aquilenet.fr Received: from hera.aquilenet.fr ([127.0.0.1]) by localhost (hera.aquilenet.fr [127.0.0.1]) (amavis, port 10024) with ESMTP id 926-veHgLcvp; Tue, 18 Mar 2025 10:34:50 +0100 (CET) Received: from ribbon (unknown [193.50.110.142]) by hera.aquilenet.fr (Postfix) with ESMTPSA id DDDAF1BE; Tue, 18 Mar 2025 10:34:49 +0100 (CET) From: =?utf-8?Q?Ludovic_Court=C3=A8s?= <ludo@HIDDEN> To: Reepca Russelstein <reepca@HIDDEN> Subject: Re: [bug#75810] [PATCH v5 00/14] Rootless guix-daemon In-Reply-To: <87h63t6er2.fsf@HIDDEN> (Reepca Russelstein's message of "Sat, 15 Mar 2025 18:44:17 -0500") References: <cover.1741973869.git.ludo@HIDDEN> <87h63t6er2.fsf@HIDDEN> Date: Tue, 18 Mar 2025 10:34:49 +0100 Message-ID: <87jz8mlm12.fsf@HIDDEN> User-Agent: Gnus/5.13 (Gnus v5.13) MIME-Version: 1.0 Content-Type: text/plain; charset=utf-8 Content-Transfer-Encoding: quoted-printable X-Rspamd-Queue-Id: 62A09421 X-Spamd-Result: default: False [4.90 / 15.00]; SPAM_FLAG(5.00)[]; BAYES_HAM(-3.00)[100.00%]; NEURAL_SPAM(3.00)[1.000]; MIME_GOOD(-0.10)[text/plain]; RCVD_COUNT_TWO(0.00)[2]; FROM_EQ_ENVFROM(0.00)[]; MIME_TRACE(0.00)[0:+]; RCPT_COUNT_TWO(0.00)[2]; ARC_NA(0.00)[]; TO_MATCH_ENVRCPT_ALL(0.00)[]; RCVD_VIA_SMTP_AUTH(0.00)[]; RCVD_TLS_ALL(0.00)[]; FROM_HAS_DN(0.00)[]; TO_DN_SOME(0.00)[]; MID_RHS_MATCH_FROM(0.00)[] X-Spam-Level: **** X-Rspamd-Action: no action X-Spamd-Bar: ++++ X-Rspamd-Server: hera X-Spam-Score: 2.4 (++) X-Spam-Report: Spam detection software, running on the system "debbugs.gnu.org", has NOT identified this incoming email as spam. The original message has been attached to this so you can view it or label similar future email. If you have any questions, see the administrator of that system for details. Content preview: Hi! (Oops, forgot to hit “send” on this one…) Reepca Russelstein <reepca@HIDDEN> skribis: Content analysis details: (2.4 points, 10.0 required) pts rule name description ---- ---------------------- -------------------------------------------------- 0.0 RCVD_IN_VALIDITY_CERTIFIED_BLOCKED RBL: ADMINISTRATOR NOTICE: The query to Validity was blocked. See https://knowledge.validity.com/hc/en-us/articles/20961730681243 for more information. [185.233.100.1 listed in sa-accredit.habeas.com] 0.0 RCVD_IN_VALIDITY_RPBL_BLOCKED RBL: ADMINISTRATOR NOTICE: The query to Validity was blocked. See https://knowledge.validity.com/hc/en-us/articles/20961730681243 for more information. [185.233.100.1 listed in bl.score.senderscore.com] 1.0 SPF_SOFTFAIL SPF: sender does not match SPF record (softfail) -0.0 SPF_HELO_PASS SPF: HELO matches SPF record 1.5 PDS_OTHER_BAD_TLD Untrustworthy TLDs [URI: russelstein.xyz (xyz)] X-Debbugs-Envelope-To: 75810 Cc: 75810 <at> debbugs.gnu.org X-BeenThere: debbugs-submit <at> debbugs.gnu.org X-Mailman-Version: 2.1.18 Precedence: list List-Id: <debbugs-submit.debbugs.gnu.org> List-Unsubscribe: <https://debbugs.gnu.org/cgi-bin/mailman/options/debbugs-submit>, <mailto:debbugs-submit-request <at> debbugs.gnu.org?subject=unsubscribe> List-Archive: <https://debbugs.gnu.org/cgi-bin/mailman/private/debbugs-submit/> List-Post: <mailto:debbugs-submit <at> debbugs.gnu.org> List-Help: <mailto:debbugs-submit-request <at> debbugs.gnu.org?subject=help> List-Subscribe: <https://debbugs.gnu.org/cgi-bin/mailman/listinfo/debbugs-submit>, <mailto:debbugs-submit-request <at> debbugs.gnu.org?subject=subscribe> Errors-To: debbugs-submit-bounces <at> debbugs.gnu.org Sender: "Debbugs-submit" <debbugs-submit-bounces <at> debbugs.gnu.org> X-Spam-Score: 1.4 (+) X-Spam-Report: Spam detection software, running on the system "debbugs.gnu.org", has NOT identified this incoming email as spam. The original message has been attached to this so you can view it or label similar future email. If you have any questions, see the administrator of that system for details. Content preview: Hi! (Oops, forgot to hit “send” on this one…) Reepca Russelstein <reepca@HIDDEN> skribis: Content analysis details: (1.4 points, 10.0 required) pts rule name description ---- ---------------------- -------------------------------------------------- 0.0 RCVD_IN_VALIDITY_CERTIFIED_BLOCKED RBL: ADMINISTRATOR NOTICE: The query to Validity was blocked. See https://knowledge.validity.com/hc/en-us/articles/20961730681243 for more information. [185.233.100.1 listed in sa-trusted.bondedsender.org] 0.0 RCVD_IN_VALIDITY_RPBL_BLOCKED RBL: ADMINISTRATOR NOTICE: The query to Validity was blocked. See https://knowledge.validity.com/hc/en-us/articles/20961730681243 for more information. [185.233.100.1 listed in bl.score.senderscore.com] 1.0 SPF_SOFTFAIL SPF: sender does not match SPF record (softfail) -0.0 SPF_HELO_PASS SPF: HELO matches SPF record 1.5 PDS_OTHER_BAD_TLD Untrustworthy TLDs [URI: russelstein.xyz (xyz)] -1.0 MAILING_LIST_MULTI Multiple indicators imply a widely-seen list manager Hi! (Oops, forgot to hit =E2=80=9Csend=E2=80=9D on this one=E2=80=A6) Reepca Russelstein <reepca@HIDDEN> skribis: > Ludovic Court=C3=A8s <ludo@HIDDEN> writes: > >> =E2=80=A2 In =E2=80=98guix-daemon.service.in=E2=80=99, set >> =E2=80=98GUIX_DATABASE_DIRECTORY=3D/var/guix=E2=80=99 for forward co= mpatibility >> (I=E2=80=99m thinking of eventually changing the default database >> location when not running as root). > > Did you intend GUIX_STATE_DIRECTORY here, or GUIX_DATABASE_DIRECTORY in > the patch? GUIX_STATE_DIRECTORY is what's in the patch. Sorry, I meant GUIX_STATE_DIRECTORY. > Minor note: this could be implemented solely in terms of close_range, by > sorting the exceptions and iterating over the gaps between them. It's > fine as it is though. Yes. In practice =E2=80=98exceptions=E2=80=99 is always empty in this code= , so we should eventually remove the argument. > (in patch 06/14, in doc/guix.texi) > > In the third sentence: s/requires the user/requires the use/ Noted. >> +When using this option, you only need to create one user account, and >> +@command{guix-daemon} will run with the authority of that account: [...] > It may be somewhat confusing to the reader looking at this page in > isolation whether they still need to create this account after running > the installation script, since it was mentioned immediately before this. Note that this doesn=E2=80=99t change the situation compared to =E2=80=98ma= ster=E2=80=99: it describes what guix-daemon expects, without regard for the installation method. I=E2=80=99ll see how this can be clarified though. >> +@quotation Warning >> +Using this option is not recommended since it allows build processes to >> +gain access to undeclared dependencies, to interfere with one another, >> +and more generally to do anything that can be done with the authority of >> +the daemon---which includes at least the ability to tamper with any file >> +in the store! >> + >> +You may find it necessary, though, when support for Linux unprivileged >> +user namespaces is missing (@pxref{Build Environment Setup}). Use at >> +your own risk! >> +@end quotation > > Note that the "do anything that can be done with the authority of the > daemon" part is only true in the case where the builder and the daemon > run under the same user. For example, on Hurd, we use --disable-chroot > but still use the separate builder users. Oh right. [...] > Perhaps this would be a good place to recommend setting the permissions > of LOCALSTATEDIR/guix/daemon-socket to allow only trusted users to > access it? I don=E2=80=99t think so; we=E2=80=99re really just describing =E2=80=98--d= isable-chroot=E2=80=99 here. >> + /* Pipe to notify readiness to the child process when using unprivi= leged >> + user namespaces. */ >> + Pipe readiness; >> + >> /* Check that the derivation outputs all exist and register them >> as valid. */ >> void registerOutputs(); > > (in nix/libstore/build.cc) > > This is inside of DerivationGoal. We found out while hunting that > deadlock bug that it doesn't always get disposed of in a timely fashion. > So we probably shouldn't rely on the AutoCloseFD type of > readiness.readSide and readiness.writeSide to close them in a timely > fashion, opting instead to explicitly close the end we use immediately > after we're done with it. Yes, agreed. > On a slightly-related note, while investigating what we currently do for > the other file-descriptor-bearing objects in DerivationGoal, I noticed > that we appear to never explicitly close builderOut.readSide in the > child (we do implicitly close it eventually with closeMostFDs). > Probably not a problem in practice, since the parent never writes to the > pipe, and if the parent process gets suddenly wiped out, the possibility > of the child blocking indefinitely is probably the least of our worries, > but maybe it would be good to close it in commonChildInit. Agreed. >> + if [ ! -f /proc/sys/kernel/unprivileged_userns_clone ] \ >> + || [ "$(cat /proc/sys/kernel/unprivileged_userns_clone)" -eq 1 ]= ; then >> + extra_options=3D"" >> + else >> + extra_options=3D"--disable-chroot" [...] > I think this test for /proc/sys/kernel/unprivileged_userns_clone will > only work on linux, no? On Hurd it will see that the file doesn't exist > and assume that means it shouldn't pass --disable-chroot. Oops yes. > Maybe also require that something like /proc/self/ns/user exists? I see > in (gnu build linux-container) this is what we do for > 'user-namespace-supported?'. Perhaps > 'unprivileged-user-namespace-supported?' should also be updated to only > return true if user namespaces are supported at all? Otherwise many of > the test skips in this patch are going to do the opposite of what they > should on Hurd. OK. > Also, perhaps the "Launch the daemon without chroot support because is > ..." comment should be updated (also s/is/it/ there) or removed. OK. >> +(unless (unprivileged-user-namespace-supported?) >> + (test-skip 1)) >> +(test-assert "build root cannot be made world-readable" [...] > It may be good to forego actually creating the setuid guile here, since > it's not part of what's actually being tested, just a looming threat to > motivate what's being tested. In the event that this test fails > someday, let's be kind to our testers and leave them with only a > world-readable setuid empty file or file containing a frowny face or > something. > > ... actually, on closer inspection, won't this test never fail? The > gexp doesn't actually create #$output, so the build will always fail, > and the store-protocol-error will always be signaled, no? Oops! Done. > (in patch 12/14, in etc/guix-daemon.service.in) > > s/cran create/can create/ Done. > Also, I'm curious how this interacts with the changes to the installer > script. What happens if the installer detects that the rootless daemon > isn't supported, but the guix that it's installing only has this version > of guix-daemon.service? I haven't checked, but if the answer is "the > service is broken", perhaps we should have two variants of the service > file, and sys_enable_guix_daemon decides which one to symlink > /etc/systemd/system/guix-daemon.service to? The assumption is indeed that unprivileged user namespaces are supported. I have reasons to believe that this assumption holds these days, which is why I didn=E2=80=99t bother with the fallback you suggest. >> +can_install_unprivileged_daemon() >> +{ # Return true if we can install guix-daemon running without privilege= s. >> + [ "$INIT_SYS" =3D systemd ] && \ >> + grep -q "User=3Dguix-daemon" \ >> + ~root/.config/guix/current/lib/systemd/system/guix-daemon.service= \ >> + && ([ ! -f /proc/sys/kernel/unprivileged_userns_clone ] \ >> + || [ "$(cat /proc/sys/kernel/unprivileged_userns_clone)" -eq 1 ]) >> +} > > (in patch 13/14, in etc/guix-install.sh) > > I vaguely recall hearing that systemd only supports linux, so it might > not be strictly necessary to check whether user namespaces are supported > at all here like it was in test-env. If we get support for the rootless > daemon working for the other init systems a check like that may be > necessary, though. Right, systemd is Linux-only, but you=E2=80=99re right that this should be changed like ./test-env for other systems. > It does indeed look like it's going to be necessary to make some changes > to make the script able to support installing a newer guix to a > systemd-using system that doesn't support unprivileged user namespaces. A system running systemd definitely supports unprivileged user namespaces; it is still possible to disable it manually, but I=E2=80=99m wi= lling to assume that it=E2=80=99s uncommon. I=E2=80=99m sending v6 with these changes. Ludo=E2=80=99.
guix-patches@HIDDEN
:bug#75810
; Package guix-patches
.
Full text available.Received: (at 75810) by debbugs.gnu.org; 18 Mar 2025 03:08:17 +0000 From debbugs-submit-bounces <at> debbugs.gnu.org Mon Mar 17 23:08:17 2025 Received: from localhost ([127.0.0.1]:34204 helo=debbugs.gnu.org) by debbugs.gnu.org with esmtp (Exim 4.84_2) (envelope-from <debbugs-submit-bounces <at> debbugs.gnu.org>) id 1tuNJQ-0004kU-EM for submit <at> debbugs.gnu.org; Mon, 17 Mar 2025 23:08:17 -0400 Received: from mailout.russelstein.xyz ([2605:6400:20:11e::1]:37160) by debbugs.gnu.org with esmtps (TLS1.2:ECDHE_RSA_AES_256_GCM_SHA384:256) (Exim 4.84_2) (envelope-from <reepca@HIDDEN>) id 1tuNJH-0004ih-F3 for 75810 <at> debbugs.gnu.org; Mon, 17 Mar 2025 23:08:13 -0400 DKIM-Signature: v=1; a=ed25519-sha256; q=dns/txt; c=relaxed/relaxed; d=russelstein.xyz; s=ed25519; h=Content-Type:MIME-Version:Message-ID:Date: References:In-Reply-To:Subject:Cc:To:From:Sender:Reply-To: Content-Transfer-Encoding:Content-ID:Content-Description:Resent-Date: Resent-From:Resent-Sender:Resent-To:Resent-Cc:Resent-Message-ID:List-Id: List-Help:List-Unsubscribe:List-Subscribe:List-Post:List-Owner:List-Archive; bh=ohvYRyuiaLxDWoQ9ZvhhLkW3bu6oFfY6dqFjst5bmn8=; b=p4wmTyxsDbJays1TuBNvt6Ad37 VrgRc9t6nuj9svYFFwhC1h2nBv6mzwnfLLb9e2deVvqsF4E66fu1WsNB9bCA==; DKIM-Signature: v=1; a=rsa-sha256; q=dns/txt; c=relaxed/relaxed; d=russelstein.xyz; s=rsa; h=Content-Type:MIME-Version:Message-ID:Date: References:In-Reply-To:Subject:Cc:To:From:Sender:Reply-To: Content-Transfer-Encoding:Content-ID:Content-Description:Resent-Date: Resent-From:Resent-Sender:Resent-To:Resent-Cc:Resent-Message-ID:List-Id: List-Help:List-Unsubscribe:List-Subscribe:List-Post:List-Owner:List-Archive; bh=ohvYRyuiaLxDWoQ9ZvhhLkW3bu6oFfY6dqFjst5bmn8=; b=WZWjOB3l2DVVSA0SQH1gfFjuqr wHBJBhz5aFUuOt265+q4AovWCb3ebGVVdPQ+b1V/GxmzYexf1MQ5cZ0+xen2daKXk7SvCxJa0HKN+ 8yFVtK2atLFdAJxjtoJq6Y+rQwkBMrfWmnHEj9Ffv25ojDCoyHax8Suz1JzvgiR7goEQtmuFVxh54 Bbz2DSk1v1+3L+nOxi5SU+gXi2eAVrWrmdOMsUHtCWAsrJD7DlbJLWsEUBFCfodJJkQaIFvpddBUv GPuuqIx6vNavTppWNE1sJfILa0I22tSm8wmybUqoKupM/LhHfgk6aA3mFirUK9q+XRSZdlGk3RJN8 n08iObqtgb0hA/98pO5V680Aj2ZpBpaANhXYhMCoyNs9r0O/EjN3tubBkU3/razxPo7EtDTXbCkuC fmgKR0KbQmhIRy6LTUpN1FCVxJO0cWhLTY/SrMnJARol+us7OwNNT2PEeGsx8pMNSNYSPP2RM8y3I s1Wblvs0BQ3aU7QSbyL5BvZrURcMfKDMCwu48WGPQztsRl/+w1O77jJLkkOBaDerFfhKUA5YHvfXF DazvQci5CDp5eTjKtlmrC/gGI9RxN6UpZfosGrcnPyEU9U49Zpj9fALuKOEUdARxQspHUMl1wiwxu VtQZRBXsXChFfYQEETeKWBQ5BhHnpnJPLMyK1mejI=; Received: by russelstein.xyz with esmtpsa (TLS1.3:ECDHE_SECP256R1__RSA_PSS_RSAE_SHA256__AES_256_GCM:256) (Exim 4.98) (envelope-from <reepca@HIDDEN>) id 1tuNJC-000000002dP-3i85; Mon, 17 Mar 2025 22:08:03 -0500 From: Reepca Russelstein <reepca@HIDDEN> To: Ludovic =?utf-8?Q?Court=C3=A8s?= <ludo@HIDDEN> Subject: Re: [PATCH v6 00/16] Rootless guix-daemon In-Reply-To: <cover.1742230219.git.ludo@HIDDEN> ("Ludovic =?utf-8?Q?Court?= =?utf-8?Q?=C3=A8s=22's?= message of "Mon, 17 Mar 2025 18:02:43 +0100") References: <cover.1742230219.git.ludo@HIDDEN> User-Agent: Gnus/5.13 (Gnus v5.13) Date: Mon, 17 Mar 2025 22:07:45 -0500 Message-ID: <875xk7594u.fsf@HIDDEN> MIME-Version: 1.0 Content-Type: multipart/signed; boundary="=-=-="; micalg=pgp-sha256; protocol="application/pgp-signature" X-Spam-Score: 0.5 X-Spam-Bar: / X-Spam-Score-Int: 5 X-Spam-Report: Spam detection software, running on the system "Sanctum", has NOT identified this incoming email as spam. The original message has been attached to this so you can view it or label similar future email. If you have any questions, see the administrator of that system for details. Content preview: Ludovic Courtès <ludo@HIDDEN> writes: > @@ -2013,23 +2057,36 @@ void DerivationGoal::runChild() > > _writeToStderr = 0; > > + if (readiness.writeSide > 0) readiness.writeSide.close(); > + > + if (readiness.readSide > 0) { > + /* Wait for [...] Content analysis details: (0.5 points, 5.0 required) pts rule name description ---- ---------------------- -------------------------------------------------- -0.0 NO_RELAYS Informational: message was not relayed via SMTP 0.5 FROM_SUSPICIOUS_NTLD From abused NTLD X-Spam-Score: 2.0 (++) X-Spam-Report: Spam detection software, running on the system "debbugs.gnu.org", has NOT identified this incoming email as spam. The original message has been attached to this so you can view it or label similar future email. If you have any questions, see the administrator of that system for details. Content preview: Ludovic Courtès <ludo@HIDDEN> writes: > @@ -2013,23 +2057,36 @@ void DerivationGoal::runChild() > > _writeToStderr = 0; > > + if (readiness.writeSide > 0) readiness.writeSide.close(); > + > + if (readiness.readSide > 0) { > + /* Wait for [...] Content analysis details: (2.0 points, 10.0 required) pts rule name description ---- ---------------------- -------------------------------------------------- 0.0 SPF_HELO_NONE SPF: HELO does not publish an SPF Record -0.0 SPF_PASS SPF: sender matches SPF record 1.5 PDS_OTHER_BAD_TLD Untrustworthy TLDs [URI: russelstein.xyz (xyz)] 0.5 FROM_SUSPICIOUS_NTLD From abused NTLD X-Debbugs-Envelope-To: 75810 Cc: 75810 <at> debbugs.gnu.org X-BeenThere: debbugs-submit <at> debbugs.gnu.org X-Mailman-Version: 2.1.18 Precedence: list List-Id: <debbugs-submit.debbugs.gnu.org> List-Unsubscribe: <https://debbugs.gnu.org/cgi-bin/mailman/options/debbugs-submit>, <mailto:debbugs-submit-request <at> debbugs.gnu.org?subject=unsubscribe> List-Archive: <https://debbugs.gnu.org/cgi-bin/mailman/private/debbugs-submit/> List-Post: <mailto:debbugs-submit <at> debbugs.gnu.org> List-Help: <mailto:debbugs-submit-request <at> debbugs.gnu.org?subject=help> List-Subscribe: <https://debbugs.gnu.org/cgi-bin/mailman/listinfo/debbugs-submit>, <mailto:debbugs-submit-request <at> debbugs.gnu.org?subject=subscribe> Errors-To: debbugs-submit-bounces <at> debbugs.gnu.org Sender: "Debbugs-submit" <debbugs-submit-bounces <at> debbugs.gnu.org> X-Spam-Score: 2.0 (++) X-Spam-Report: Spam detection software, running on the system "debbugs.gnu.org", has NOT identified this incoming email as spam. The original message has been attached to this so you can view it or label similar future email. If you have any questions, see the administrator of that system for details. Content preview: Ludovic Courtès <ludo@HIDDEN> writes: > @@ -2013,23 +2057,36 @@ void DerivationGoal::runChild() > > _writeToStderr = 0; > > + if (readiness.writeSide > 0) readiness.writeSide.close(); > + > + if (readiness.readSide > 0) { > + /* Wait for [...] Content analysis details: (2.0 points, 10.0 required) pts rule name description ---- ---------------------- -------------------------------------------------- 0.0 SPF_HELO_NONE SPF: HELO does not publish an SPF Record -0.0 SPF_PASS SPF: sender matches SPF record 1.5 PDS_OTHER_BAD_TLD Untrustworthy TLDs [URI: russelstein.xyz (xyz)] 0.5 FROM_SUSPICIOUS_NTLD From abused NTLD 1.0 BULK_RE_SUSP_NTLD Precedence bulk and RE: from a suspicious TLD -1.0 MAILING_LIST_MULTI Multiple indicators imply a widely-seen list manager --=-=-= Content-Type: text/plain; charset=utf-8 Content-Transfer-Encoding: quoted-printable Ludovic Court=C3=A8s <ludo@HIDDEN> writes: > @@ -2013,23 +2057,36 @@ void DerivationGoal::runChild() >=20=20 > _writeToStderr =3D 0; >=20=20 > + if (readiness.writeSide > 0) readiness.writeSide.close(); > + > + if (readiness.readSide > 0) { > + /* Wait for the parent process to initialize the UID/GID mapping > + of our user namespace. */ > + char str[20] =3D { '\0' }; > + readFull(readiness.readSide, (unsigned char*)str, 3); > + if (strcmp(str, "go\n") !=3D 0) > + throw Error("failed to initialize process in unprivileged user names= pace"); > + } > + > restoreAffinity(); (in patch 7/16, in nix/libstore/build.cc) Strictly speaking we should check whether the fds are >=3D 0, not > 0, since 0 is technically a valid file descriptor, and we use -1 to indicate the absence of a file descriptor. Also, readiness.readSide isn't explicitly closed in the child after we're done with it. > + > + # The unprivileged daemon cannot create the log directory by itself. > + mkdir /var/log/guix > + chown guix-daemon:guix-daemon /var/log/guix > + chmod 755 /var/log/guix (in patch 15/16, in etc/guix-install.sh) Should this be 'mkdir -p' or some other conditional creation? If I understand correctly this will fail when overwriting an existing install using GUIX_ALLOW_OVERWRITE. Concerning guix-install.sh, to be clear, is the intent to specifically not support installing the rootful daemon on systemd systems? For my two cents, I do think that it's still a tradeoff - not just because of the reliance on different kernel mechanisms for security, but also because the rootless daemon currently causes visible changes to the build environment (EROFS on /, and nothing owned by root, for example). Which one should we consider the "canonical" build environment going forward? I decided to do some searching for container escapes / vulnerabilities online, just to be extra careful, and found one that relies on the container entry point being run as the user that owns the program that execs the container entry point: CVE-2019-5736. It exploits the fact that /proc/self/exe, despite being displayed like a symlink in the output of ls, does not actually act like a symlink, and indeed acts more like a hardlink that readlink happens to have some associated data for. The demo, modified for guix circumstances, would go something like this: 1. A derivation is created whose builder is /proc/self/exe, and whose LD_PRELOAD environment variable points into a malicious store item for one of its shared libraries - for example, libc. 2. The daemon reads this in, and, to my knowledge, does no verification of the builder string. Note that this aspect isn't actually necessary, as the builder could also be a symlink to /proc/self/exe from the store. 3. The daemon sets up the build environment, and execs /proc/self/exe. 4. An attacker-controlled load-time function gets run. 5. It opens /proc/self/exe, initially read-only because it can't be opened writable while a process is executing it. It then execs another attacker-controlled process, which inherits the open file descriptor and subsequently opens it via /proc/self/fd/<fd>, this time read-write (it can do this because it owns the file, and even if it's not writable, a quick fchmod will fix that, and the filesystem it was originally opened from isn't read-only, because guix-daemon starts before gnu-store.mount bind-mounts /gnu/store to itself prior to making it read-only). It then overwrites the resulting file descriptor with whatever contents it wants. 6. The next time guix-daemon is started outside the container, it runs attacker-controlled code. There are several points at which that particular attack could be stopped, and I'd like to try to stop it at as many of them as possible. A good start would be canonicalizing the builder prior to executing it and then checking to make sure it is in the store. A more general solution could look like writing out and then executing a tiny binary, something like /tmp/runbuilder, that does nothing but unlink itself and then exec the actual program. Here's a writeup of the CVE in question: https://unit42.paloaltonetworks.com/breaking-docker-via-runc-explaining-cve= -2019-5736/ Aside from all that, it looks good to me. =2D reepca --=-=-= Content-Type: application/pgp-signature; name="signature.asc" -----BEGIN PGP SIGNATURE----- iQFLBAEBCAA1FiEEdNapMPRLm4SepVYGwWaqSV9/GJwFAmfY44IXHHJlZXBjYUBy dXNzZWxzdGVpbi54eXoACgkQwWaqSV9/GJyySggAiIt4eVH0B5wCuOlT0Z8/82fi cwM/RG2aItSkznzF3Y6Twl4MUdymMopgoexg0DsbPks11rXFFvYbIRDiTCXm4/5C cvFJKoxqY0HqIeZ02hm4E1XwIK6gxGl5rwXeKW2ZcZ+kMvk7eAlOORK64BGslWEA hjhyTsn7Cypr7laBTUqCQY44l/um9YcHVbyUkkF8b8ay7i+FKXQ9po0KZljMO8bN yioyZBUd9KuOVXE0bsC1hac9tc7f975xms1T1FUZdB8b9N7aJ+lONRoeBYGSimqA H7rwOJLZ+fG2F9cuG6ZsBrnPG7HdKV2je5su7a4ASBORclmJlGWXhWdGC6Z2gQ== =1zV3 -----END PGP SIGNATURE----- --=-=-=--
guix-patches@HIDDEN
:bug#75810
; Package guix-patches
.
Full text available.Received: (at 75810) by debbugs.gnu.org; 17 Mar 2025 17:06:19 +0000 From debbugs-submit-bounces <at> debbugs.gnu.org Mon Mar 17 13:06:19 2025 Received: from localhost ([127.0.0.1]:60713 helo=debbugs.gnu.org) by debbugs.gnu.org with esmtp (Exim 4.84_2) (envelope-from <debbugs-submit-bounces <at> debbugs.gnu.org>) id 1tuDup-00033Y-BI for submit <at> debbugs.gnu.org; Mon, 17 Mar 2025 13:06:19 -0400 Received: from eggs.gnu.org ([2001:470:142:3::10]:58512) by debbugs.gnu.org with esmtps (TLS1.2:ECDHE_RSA_AES_256_GCM_SHA384:256) (Exim 4.84_2) (envelope-from <ludo@HIDDEN>) id 1tuDtb-0002kH-Bk for 75810 <at> debbugs.gnu.org; Mon, 17 Mar 2025 13:05:00 -0400 Received: from fencepost.gnu.org ([2001:470:142:3::e]) by eggs.gnu.org with esmtps (TLS1.2:ECDHE_RSA_AES_256_GCM_SHA384:256) (Exim 4.90_1) (envelope-from <ludo@HIDDEN>) id 1tuDtU-0005Rh-L1; Mon, 17 Mar 2025 13:04:52 -0400 DKIM-Signature: v=1; a=rsa-sha256; q=dns/txt; c=relaxed/relaxed; d=gnu.org; s=fencepost-gnu-org; h=MIME-Version:References:In-Reply-To:Date:Subject:To: From; bh=Ngm8ANKAcfFhwlcmZn793WD7YKtaQddq8o8d6i84570=; b=QCMcrqlyjO/46sY3a6ef OOxEQC6uFme+ZgxHpDVsrdk7bqM0L9IJZ/eCTOmV7aqv+dyndEY/CKWKEgIARwIg7qyP+vTlBjCIM mLDQsP5r7f5fwCeEK6Ar+Vtpzp+kK1J/604VRD5v/t4ynyv7sWd+FSjuSl08Cu7MH6APfmtF5nFih q/0zKmHfWElmky4rmpvCZ7nhmwBRh46GlqYRw7+Wn0UFvqqsEkRVYeYIk5MVNHRas38BhDCNcrK3u rZ384f5Nuc9gj2QUz/4rb0/zx7I078gTt3IamCdWiwomeBUndlQLQMQGsrw3yxRd8rqCKlumiWFj2 8yovB3r1/KZp4w==; From: =?UTF-8?q?Ludovic=20Court=C3=A8s?= <ludo@HIDDEN> To: 75810 <at> debbugs.gnu.org Subject: [PATCH v6 14/16] =?UTF-8?q?etc:=20systemd=20services:=20Run=20?= =?UTF-8?q?=E2=80=98guix-daemon=E2=80=99=20as=20an=20unprivileged=20user.?= Date: Mon, 17 Mar 2025 18:02:57 +0100 Message-ID: <f2236d569fa75147015a4f5a16648c2f826412cc.1742230220.git.ludo@HIDDEN> X-Mailer: git-send-email 2.48.1 In-Reply-To: <cover.1742230219.git.ludo@HIDDEN> References: <cover.1742230219.git.ludo@HIDDEN> MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit X-Spam-Score: -2.3 (--) X-Debbugs-Envelope-To: 75810 Cc: =?UTF-8?q?Ludovic=20Court=C3=A8s?= <ludo@HIDDEN> X-BeenThere: debbugs-submit <at> debbugs.gnu.org X-Mailman-Version: 2.1.18 Precedence: list List-Id: <debbugs-submit.debbugs.gnu.org> List-Unsubscribe: <https://debbugs.gnu.org/cgi-bin/mailman/options/debbugs-submit>, <mailto:debbugs-submit-request <at> debbugs.gnu.org?subject=unsubscribe> List-Archive: <https://debbugs.gnu.org/cgi-bin/mailman/private/debbugs-submit/> List-Post: <mailto:debbugs-submit <at> debbugs.gnu.org> List-Help: <mailto:debbugs-submit-request <at> debbugs.gnu.org?subject=help> List-Subscribe: <https://debbugs.gnu.org/cgi-bin/mailman/listinfo/debbugs-submit>, <mailto:debbugs-submit-request <at> debbugs.gnu.org?subject=subscribe> Errors-To: debbugs-submit-bounces <at> debbugs.gnu.org Sender: "Debbugs-submit" <debbugs-submit-bounces <at> debbugs.gnu.org> X-Spam-Score: -3.3 (---) * etc/guix-daemon.service.in (ExecStart): Remove ‘--build-users-group’. (Environment): Add ‘GUIX_STATE_DIRECTORY’. (Before, User, AmbientCapabilities, PrivateMounts, BindPaths): New fields. * etc/gnu-store.mount.in (Before): Remove. (WantedBy): Change to ‘multi-user.target’. Change-Id: Id826b8ab535844b6024d777f6bd15fd49db6d65e --- etc/gnu-store.mount.in | 3 +-- etc/guix-daemon.service.in | 22 ++++++++++++++++++++-- 2 files changed, 21 insertions(+), 4 deletions(-) diff --git a/etc/gnu-store.mount.in b/etc/gnu-store.mount.in index c94f2db72b..f9918c9e52 100644 --- a/etc/gnu-store.mount.in +++ b/etc/gnu-store.mount.in @@ -2,10 +2,9 @@ Description=Read-only @storedir@ for GNU Guix DefaultDependencies=no ConditionPathExists=@storedir@ -Before=guix-daemon.service [Install] -WantedBy=guix-daemon.service +WantedBy=multi-user.target [Mount] What=@storedir@ diff --git a/etc/guix-daemon.service.in b/etc/guix-daemon.service.in index 5c43d9b7f1..6a5ef97f9b 100644 --- a/etc/guix-daemon.service.in +++ b/etc/guix-daemon.service.in @@ -5,11 +5,29 @@ [Unit] Description=Build daemon for GNU Guix +# Start before 'gnu-store.mount' to get a writable view of the store. +Before=gnu-store.mount + [Service] ExecStart=@localstatedir@/guix/profiles/per-user/root/current-guix/bin/guix-daemon \ - --build-users-group=guixbuild --discover=no \ + --discover=no \ --substitute-urls='@GUIX_SUBSTITUTE_URLS@' -Environment='GUIX_LOCPATH=@localstatedir@/guix/profiles/per-user/root/guix-profile/lib/locale' LC_ALL=en_US.utf8 +Environment='GUIX_STATE_DIRECTORY=@localstatedir@/guix' 'GUIX_LOCPATH=@localstatedir@/guix/profiles/per-user/root/guix-profile/lib/locale' LC_ALL=en_US.utf8 + +# Run under a dedicated unprivileged user account. +User=guix-daemon + +# Bind-mount the store read-write in a private namespace, to counter the +# effect of 'gnu-store.mount'. +PrivateMounts=true +BindPaths=@storedir@ + +# Provide the CAP_CHOWN capability so that guix-daemon can create and chown +# /var/guix/profiles/per-user/$USER and also chown failed build directories +# when using '--keep-failed'. Note that guix-daemon explicitly drops ambient +# capabilities before executing build processes so they don't inherit them. +AmbientCapabilities=CAP_CHOWN + StandardOutput=journal StandardError=journal -- 2.48.1
guix-patches@HIDDEN
:bug#75810
; Package guix-patches
.
Full text available.Received: (at 75810) by debbugs.gnu.org; 17 Mar 2025 17:06:06 +0000 From debbugs-submit-bounces <at> debbugs.gnu.org Mon Mar 17 13:06:05 2025 Received: from localhost ([127.0.0.1]:60708 helo=debbugs.gnu.org) by debbugs.gnu.org with esmtp (Exim 4.84_2) (envelope-from <debbugs-submit-bounces <at> debbugs.gnu.org>) id 1tuDuZ-00031H-Tn for submit <at> debbugs.gnu.org; Mon, 17 Mar 2025 13:06:04 -0400 Received: from eggs.gnu.org ([2001:470:142:3::10]:58526) by debbugs.gnu.org with esmtps (TLS1.2:ECDHE_RSA_AES_256_GCM_SHA384:256) (Exim 4.84_2) (envelope-from <ludo@HIDDEN>) id 1tuDtb-0002kK-HY for 75810 <at> debbugs.gnu.org; Mon, 17 Mar 2025 13:05:00 -0400 Received: from fencepost.gnu.org ([2001:470:142:3::e]) by eggs.gnu.org with esmtps (TLS1.2:ECDHE_RSA_AES_256_GCM_SHA384:256) (Exim 4.90_1) (envelope-from <ludo@HIDDEN>) id 1tuDtV-0005SA-QG; Mon, 17 Mar 2025 13:04:53 -0400 DKIM-Signature: v=1; a=rsa-sha256; q=dns/txt; c=relaxed/relaxed; d=gnu.org; s=fencepost-gnu-org; h=MIME-Version:References:In-Reply-To:Date:Subject:To: From; bh=AJlK2QAuKjco1IVqQ+QWTule1xdp+HyiHot4+iuRsE8=; b=HkrWaQ3bfhMzBjK1kxMl Rj+Z5nJ4wiT1jwhGqB5ar9NyXB4rSXdZHLALFsZUCTynGbf5J+A2gp8BbN8agQ/TnLW7uormsbAIK bGkTufH40ZrccYlMCjo7Nk6xD98JRj7118EzkXb7lU3gqxeUx0C1UtlI8l8gqnuvNaimusurB6zVB 9zXQXe+QYsh0QbbQ9j65Fi3WL26u1L4bl4uSf+4A9dOY0UdKc+wt+nNH9qVLpfoa9O6XLQw4rN9Ff dRddj2mFbVJcQCEKdeknoB/CTz+gT3SzZbr54552kJpWmE4pD4T/g+/llII7yW5F0rlnhLISyDNK0 Pdi3GuocIbCeYw==; From: =?UTF-8?q?Ludovic=20Court=C3=A8s?= <ludo@HIDDEN> To: 75810 <at> debbugs.gnu.org Subject: [PATCH v6 16/16] DRAFT gnu: guix: Update to 07c5b1b Date: Mon, 17 Mar 2025 18:02:59 +0100 Message-ID: <19b479fe168b1afdc6dbc46f8c363d797cfb7178.1742230220.git.ludo@HIDDEN> X-Mailer: git-send-email 2.48.1 In-Reply-To: <cover.1742230219.git.ludo@HIDDEN> References: <cover.1742230219.git.ludo@HIDDEN> MIME-Version: 1.0 Content-Transfer-Encoding: 8bit X-Spam-Score: -2.3 (--) X-Debbugs-Envelope-To: 75810 Cc: =?UTF-8?q?Ludovic=20Court=C3=A8s?= <ludo@HIDDEN> X-BeenThere: debbugs-submit <at> debbugs.gnu.org X-Mailman-Version: 2.1.18 Precedence: list List-Id: <debbugs-submit.debbugs.gnu.org> List-Unsubscribe: <https://debbugs.gnu.org/cgi-bin/mailman/options/debbugs-submit>, <mailto:debbugs-submit-request <at> debbugs.gnu.org?subject=unsubscribe> List-Archive: <https://debbugs.gnu.org/cgi-bin/mailman/private/debbugs-submit/> List-Post: <mailto:debbugs-submit <at> debbugs.gnu.org> List-Help: <mailto:debbugs-submit-request <at> debbugs.gnu.org?subject=help> List-Subscribe: <https://debbugs.gnu.org/cgi-bin/mailman/listinfo/debbugs-submit>, <mailto:debbugs-submit-request <at> debbugs.gnu.org?subject=subscribe> Errors-To: debbugs-submit-bounces <at> debbugs.gnu.org Sender: "Debbugs-submit" <debbugs-submit-bounces <at> debbugs.gnu.org> X-Spam-Score: -3.3 (---) DRAFT: Temporary commit. * gnu/packages/package-management.scm (guix): Update to 07c5b1b. Change-Id: Id7c3275da249075cdb23d7f4f63fd1bcf7dd933b --- gnu/packages/package-management.scm | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/gnu/packages/package-management.scm b/gnu/packages/package-management.scm index a4a96878f7..11cfd10197 100644 --- a/gnu/packages/package-management.scm +++ b/gnu/packages/package-management.scm @@ -179,8 +179,8 @@ (define-public guix ;; Note: the 'update-guix-package.scm' script expects this definition to ;; start precisely like this. (let ((version "1.4.0") - (commit "5058b40aba825ab6e7b9e518dd1147d1e35fd7de") - (revision 34)) + (commit "07c5b1b1ef05c002ad7092976e67eceb45f0c5da") + (revision 35)) (package (name "guix") @@ -196,7 +196,7 @@ (define-public guix (commit commit))) (sha256 (base32 - "04vk4lslcd6h22yj5pxvb1pdyyxd8421gjfyvyb1bl3xn7c77246")) + "0hl692xzb8jylc8rwwvmgbdv08dnx35dx116vsw1s4c0ph8fr50a")) (file-name (string-append "guix-" version "-checkout")))) (build-system gnu-build-system) (arguments -- 2.48.1
guix-patches@HIDDEN
:bug#75810
; Package guix-patches
.
Full text available.Received: (at 75810) by debbugs.gnu.org; 17 Mar 2025 17:06:00 +0000 From debbugs-submit-bounces <at> debbugs.gnu.org Mon Mar 17 13:05:59 2025 Received: from localhost ([127.0.0.1]:60706 helo=debbugs.gnu.org) by debbugs.gnu.org with esmtp (Exim 4.84_2) (envelope-from <debbugs-submit-bounces <at> debbugs.gnu.org>) id 1tuDuW-00030e-5I for submit <at> debbugs.gnu.org; Mon, 17 Mar 2025 13:05:59 -0400 Received: from eggs.gnu.org ([2001:470:142:3::10]:58502) by debbugs.gnu.org with esmtps (TLS1.2:ECDHE_RSA_AES_256_GCM_SHA384:256) (Exim 4.84_2) (envelope-from <ludo@HIDDEN>) id 1tuDtZ-0002ju-EE for 75810 <at> debbugs.gnu.org; Mon, 17 Mar 2025 13:05:01 -0400 Received: from fencepost.gnu.org ([2001:470:142:3::e]) by eggs.gnu.org with esmtps (TLS1.2:ECDHE_RSA_AES_256_GCM_SHA384:256) (Exim 4.90_1) (envelope-from <ludo@HIDDEN>) id 1tuDtT-0005Qw-EM; Mon, 17 Mar 2025 13:04:51 -0400 DKIM-Signature: v=1; a=rsa-sha256; q=dns/txt; c=relaxed/relaxed; d=gnu.org; s=fencepost-gnu-org; h=MIME-Version:References:In-Reply-To:Date:Subject:To: From; bh=46sXtSC4BF2MFB1vCWkw8ErjEqxl/gPSRof2zzVtuu0=; b=c7fEqH3BwJMEHv6TrpVs 42Em7eglXrTZBEfxsy01GEbvbfIQ25eWDI15UyXR5ASBTgf4f1vwITchdkaiGH/7BAqCZTgCkyAEl CegHIUr9FH/OSMlZ3TAVKlAuIxpRkG57IxY7w1GkdhC1Ne4M3m8c8anuBQveLanYg3Ino1ejpUCaT SXAhTq1cpfQwVK2bMN7iSYVzgiGdJTcM0EOgPgYG0WfDOaSubh3gBJWNrKubrWLNhNEvqk8UBFks+ /0AUZ9AQJrpUHOEAgGV/f3jDH+2VGfek/jm0QkG4rbb3JyVohzpVnhlYFf+cWwjRyWI4VNUhd/fSa NS7cQUCKyTm2ug==; From: =?UTF-8?q?Ludovic=20Court=C3=A8s?= <ludo@HIDDEN> To: 75810 <at> debbugs.gnu.org Subject: [PATCH v6 13/16] tests: Run in a chroot and unprivileged user namespaces. Date: Mon, 17 Mar 2025 18:02:56 +0100 Message-ID: <5a3d8d90c08fd27dddf5d8c94465597bf2cded92.1742230220.git.ludo@HIDDEN> X-Mailer: git-send-email 2.48.1 In-Reply-To: <cover.1742230219.git.ludo@HIDDEN> References: <cover.1742230219.git.ludo@HIDDEN> MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit X-Spam-Score: -2.3 (--) X-Debbugs-Envelope-To: 75810 Cc: =?UTF-8?q?Ludovic=20Court=C3=A8s?= <ludo@HIDDEN> X-BeenThere: debbugs-submit <at> debbugs.gnu.org X-Mailman-Version: 2.1.18 Precedence: list List-Id: <debbugs-submit.debbugs.gnu.org> List-Unsubscribe: <https://debbugs.gnu.org/cgi-bin/mailman/options/debbugs-submit>, <mailto:debbugs-submit-request <at> debbugs.gnu.org?subject=unsubscribe> List-Archive: <https://debbugs.gnu.org/cgi-bin/mailman/private/debbugs-submit/> List-Post: <mailto:debbugs-submit <at> debbugs.gnu.org> List-Help: <mailto:debbugs-submit-request <at> debbugs.gnu.org?subject=help> List-Subscribe: <https://debbugs.gnu.org/cgi-bin/mailman/listinfo/debbugs-submit>, <mailto:debbugs-submit-request <at> debbugs.gnu.org?subject=subscribe> Errors-To: debbugs-submit-bounces <at> debbugs.gnu.org Sender: "Debbugs-submit" <debbugs-submit-bounces <at> debbugs.gnu.org> X-Spam-Score: -3.3 (---) * build-aux/test-env.in: Pass ‘--disable-chroot’ only when unprivileged user namespace support is lacking and warn in that case. * tests/store.scm ("build-things, check mode"): Use ‘gettimeofday’ rather than a shared file as a source of entropy. ("symlink is symlink") ("isolated environment", "inputs are read-only") ("inputs cannot be remounted read-write") ("build root cannot be made world-readable") ("/tmp, store, and /dev/{null,full} are writable") ("network is unreachable"): New tests. * tests/processes.scm ("client + lock"): Skip when ‘unprivileged-user-namespace-supported?’ returns true. Change-Id: I3b3c3ebdf6db5fd36ee70251d07b893c17ca1b84 --- build-aux/test-env.in | 18 ++- tests/processes.scm | 9 +- tests/store.scm | 247 ++++++++++++++++++++++++++++++++++++------ 3 files changed, 236 insertions(+), 38 deletions(-) diff --git a/build-aux/test-env.in b/build-aux/test-env.in index 9caa29da58..86c2e585d7 100644 --- a/build-aux/test-env.in +++ b/build-aux/test-env.in @@ -1,7 +1,7 @@ #!/bin/sh # GNU Guix --- Functional package management for GNU -# Copyright © 2012, 2013, 2014, 2015, 2016, 2017, 2018, 2019, 2021 Ludovic Courtès <ludo@HIDDEN> +# Copyright © 2012-2019, 2021, 2025 Ludovic Courtès <ludo@HIDDEN> # # This file is part of GNU Guix. # @@ -102,10 +102,24 @@ then rm -rf "$GUIX_STATE_DIRECTORY/daemon-socket" mkdir -m 0700 "$GUIX_STATE_DIRECTORY/daemon-socket" + # If unprivileged user namespaces are not supported, pass + # '--disable-chroot'. + if [ -f /proc/self/ns/user ] \ + && { [ ! -f /proc/sys/kernel/unprivileged_userns_clone ] \ + || [ "$(cat /proc/sys/kernel/unprivileged_userns_clone)" -eq 1 ]; } + then + extra_options="" + else + extra_options="--disable-chroot" + echo "unprivileged user namespaces not supported; \ +running 'guix-daemon $extra_options'" >&2 + fi + # Launch the daemon without chroot support because is may be # unavailable, for instance if we're not running as root. "@abs_top_builddir@/pre-inst-env" \ - "@abs_top_builddir@/guix-daemon" --disable-chroot \ + "@abs_top_builddir@/guix-daemon" \ + $extra_options \ --substitute-urls="$GUIX_BINARY_SUBSTITUTE_URL" & daemon_pid=$! diff --git a/tests/processes.scm b/tests/processes.scm index ba518f2d9e..a72ba16f58 100644 --- a/tests/processes.scm +++ b/tests/processes.scm @@ -1,5 +1,5 @@ ;;; GNU Guix --- Functional package management for GNU -;;; Copyright © 2018 Ludovic Courtès <ludo@HIDDEN> +;;; Copyright © 2018, 2025 Ludovic Courtès <ludo@HIDDEN> ;;; Copyright © 2019 Mathieu Othacehe <m.othacehe@HIDDEN> ;;; ;;; This file is part of GNU Guix. @@ -25,6 +25,8 @@ (define-module (test-processes) #:use-module (guix gexp) #:use-module ((guix utils) #:select (call-with-temporary-directory)) #:use-module (gnu packages bootstrap) + #:use-module ((gnu build linux-container) + #:select (unprivileged-user-namespace-supported?)) #:use-module (guix tests) #:use-module (srfi srfi-1) #:use-module (srfi srfi-64) @@ -84,6 +86,11 @@ (define-syntax-rule (test-assert* description exp) (and (kill (process-id daemon) 0) (string-suffix? "guix-daemon" (first (process-command daemon))))))) +(when (unprivileged-user-namespace-supported?) + ;; The test below assumes the build process can communicate with the outside + ;; world via the TOKEN1 and TOKEN2 files, which is impossible when + ;; guix-daemon is set up to build in separate namespaces. + (test-skip 1)) (test-assert* "client + lock" (with-store store (call-with-temporary-directory diff --git a/tests/store.scm b/tests/store.scm index 45948f4f43..b1ddff2082 100644 --- a/tests/store.scm +++ b/tests/store.scm @@ -1,5 +1,5 @@ ;;; GNU Guix --- Functional package management for GNU -;;; Copyright © 2012-2021, 2023 Ludovic Courtès <ludo@HIDDEN> +;;; Copyright © 2012-2021, 2023, 2025 Ludovic Courtès <ludo@HIDDEN> ;;; ;;; This file is part of GNU Guix. ;;; @@ -28,8 +28,12 @@ (define-module (test-store) #:use-module (guix base32) #:use-module (guix packages) #:use-module (guix derivations) + #:use-module ((guix modules) + #:select (source-module-closure)) #:use-module (guix serialization) #:use-module (guix build utils) + #:use-module ((gnu build linux-container) + #:select (unprivileged-user-namespace-supported?)) #:use-module (guix gexp) #:use-module (gnu packages) #:use-module (gnu packages bootstrap) @@ -391,6 +395,188 @@ (define %shell (equal? (valid-derivers %store o) (list (derivation-file-name d)))))) +(test-assert "symlink is symlink" + (let* ((a (add-text-to-store %store "hello.txt" (random-text))) + (b (build-expression->derivation + %store "symlink" + '(symlink (assoc-ref %build-inputs "a") %output) + #:inputs `(("a" ,a)))) + (c (build-expression->derivation + %store "symlink-reference" + `(call-with-output-file %output + (lambda (port) + ;; Check that B is indeed visible as a symlink. This should + ;; always be the case, both in the '--disable-chroot' and in + ;; the user namespace setups. + (pk 'stat (lstat (assoc-ref %build-inputs "b"))) + (display (readlink (assoc-ref %build-inputs "b")) + port))) + #:inputs `(("b" ,b))))) + (and (build-derivations %store (list c)) + (string=? (call-with-input-file (derivation->output-path c) + get-string-all) + a)))) + +(unless (unprivileged-user-namespace-supported?) + (test-skip 1)) +(test-equal "isolated environment" + (string-join (append + '("PID: 1" "UID: 30001") + (delete-duplicates + (sort (list "/dev" "/tmp" "/proc" "/etc" + (match (string-tokenize (%store-prefix) + (char-set-complement + (char-set #\/))) + ((top _ ...) (string-append "/" top)))) + string<?)) + '("/etc/group" "/etc/hosts" "/etc/passwd"))) + (let* ((b (add-text-to-store %store "build.sh" + "echo -n PID: $$ UID: $UID /* /etc/* > $out")) + (s (add-to-store %store "bash" #t "sha256" + (search-bootstrap-binary "bash" + (%current-system)))) + (d (derivation %store "the-thing" + s `("-e" ,b) + #:env-vars `(("foo" . ,(random-text))) + #:sources (list b s))) + (o (derivation->output-path d))) + (and (build-derivations %store (list d)) + (call-with-input-file o get-string-all)))) + +(unless (unprivileged-user-namespace-supported?) + (test-skip 1)) +(test-equal "inputs are read-only" + "All good!" + (let* ((input (plain-file (string-append "might-be-tampered-with-" + (number->string + (car (gettimeofday)) + 16)) + "All good!")) + (drv + (run-with-store %store + (gexp->derivation + "attempt-to-write-to-input" + (with-imported-modules (source-module-closure + '((guix build syscalls))) + #~(begin + (use-modules (guix build syscalls)) + + (let ((input #$input)) + (chmod input #o666) + (call-with-output-file input + (lambda (port) + (display "BAD!" port))) + (mkdir #$output)))))))) + (and (guard (c ((store-protocol-error? c) #t)) + (build-derivations %store (list drv))) + (call-with-input-file (run-with-store %store + (lower-object input)) + get-string-all)))) + +(unless (unprivileged-user-namespace-supported?) + (test-skip 1)) +(test-assert "inputs cannot be remounted read-write" + (let ((drv + (run-with-store %store + (gexp->derivation + "attempt-to-remount-input-read-write" + (with-imported-modules (source-module-closure + '((guix build syscalls))) + #~(begin + (use-modules (guix build syscalls)) + + (let ((input #$(plain-file "input-that-might-be-tampered-with" + "All good!"))) + (mount "none" input "none" (logior MS_BIND MS_REMOUNT)) + (call-with-output-file input + (lambda (port) + (display "BAD!" port))) + (mkdir #$output)))))))) + (guard (c ((store-protocol-error? c) #t)) + (build-derivations %store (list drv)) + #f))) + +(unless (unprivileged-user-namespace-supported?) + (test-skip 1)) +(test-assert "build root cannot be made world-readable" + (let ((drv + (run-with-store %store + (gexp->derivation + "attempt-to-make-root-world-readable" + (with-imported-modules (source-module-closure + '((guix build syscalls))) + #~(begin + (use-modules (guix build syscalls)) + + (catch 'system-error + (lambda () + (chmod "/" #o777)) + (lambda args + (format #t "failed to make root writable: ~a~%" + (strerror (system-error-errno args))) + (format #t "attempting read-write remount~%") + (mount "none" "/" "/" (logior MS_BIND MS_REMOUNT)) + (chmod "/" #o777))) + + ;; At this point, the build process could create a + ;; world-readable setuid binary under its root (so in the + ;; store) that would remain visible until the build + ;; completes. + (mkdir #$output))))))) + (guard (c ((store-protocol-error? c) #t)) + (build-derivations %store (list drv)) + #f))) + +(unless (unprivileged-user-namespace-supported?) + (test-skip 1)) +(test-assert "/tmp, store, and /dev/{null,full} are writable" + ;; All of /tmp and all of the store must be writable (the store is writable + ;; so that derivation outputs can be written to it, but in practice it's + ;; always been wide open). Things like /dev/null must be writable too. + (let ((drv (run-with-store %store + (gexp->derivation + "check-tmp-and-store-are-writable" + #~(begin + (mkdir "/tmp/something") + (mkdir (in-vicinity (getenv "NIX_STORE") + "some-other-thing")) + (call-with-output-file "/dev/null" + (lambda (port) + (display "Welcome to the void." port))) + (catch 'system-error + (lambda () + (call-with-output-file "/dev/full" + (lambda (port) + (display "No space left!" port))) + (error "Should have thrown!")) + (lambda args + (unless (= ENOSPC (system-error-errno args)) + (apply throw args)))) + (mkdir #$output)))))) + (build-derivations %store (list drv)))) + +(unless (unprivileged-user-namespace-supported?) + (test-skip 1)) +(test-assert "network is unreachable" + (let ((drv (run-with-store %store + (gexp->derivation + "check-network-unreachable" + #~(let ((check-connection-failure + (lambda (address expected-code) + (let ((s (socket AF_INET SOCK_STREAM 0))) + (catch 'system-error + (lambda () + (connect s AF_INET (inet-pton AF_INET address) 80)) + (lambda args + (let ((errno (system-error-errno args))) + (unless (= expected-code errno) + (error "wrong error code" + errno (strerror errno)))))))))) + (check-connection-failure "127.0.0.1" ECONNREFUSED) + (check-connection-failure "9.9.9.9" ENETUNREACH) + (mkdir #$output)))))) + (build-derivations %store (list drv)))) + (test-equal "with-build-handler" 'success (let* ((b (add-text-to-store %store "build" "echo $foo > $out" '())) @@ -1333,40 +1519,31 @@ (define %shell (test-assert "build-things, check mode" (with-store store - (call-with-temporary-output-file - (lambda (entropy entropy-port) - (write (random-text) entropy-port) - (force-output entropy-port) - (let* ((drv (build-expression->derivation - store "non-deterministic" - `(begin - (use-modules (rnrs io ports)) - (let ((out (assoc-ref %outputs "out"))) - (call-with-output-file out - (lambda (port) - ;; Rely on the fact that tests do not use the - ;; chroot, and thus ENTROPY is readable. - (display (call-with-input-file ,entropy - get-string-all) - port))) - #t)) - #:guile-for-build - (package-derivation store %bootstrap-guile (%current-system)))) - (file (derivation->output-path drv))) - (and (build-things store (list (derivation-file-name drv))) - (begin - (write (random-text) entropy-port) - (force-output entropy-port) - (guard (c ((store-protocol-error? c) - (pk 'determinism-exception c) - (and (not (zero? (store-protocol-error-status c))) - (string-contains (store-protocol-error-message c) - "deterministic")))) - ;; This one will produce a different result. Since we're in - ;; 'check' mode, this must fail. - (build-things store (list (derivation-file-name drv)) - (build-mode check)) - #f)))))))) + (let* ((drv (build-expression->derivation + store "non-deterministic" + `(begin + (use-modules (rnrs io ports)) + (let ((out (assoc-ref %outputs "out"))) + (call-with-output-file out + (lambda (port) + (let ((now (gettimeofday))) + (display (+ (car now) (cdr now)) port)))) + #t)) + #:guile-for-build + (package-derivation store %bootstrap-guile (%current-system)))) + (file (derivation->output-path drv))) + (and (build-things store (list (derivation-file-name drv))) + (begin + (guard (c ((store-protocol-error? c) + (pk 'determinism-exception c) + (and (not (zero? (store-protocol-error-status c))) + (string-contains (store-protocol-error-message c) + "deterministic")))) + ;; This one will produce a different result. Since we're in + ;; 'check' mode, this must fail. + (build-things store (list (derivation-file-name drv)) + (build-mode check)) + #f)))))) (test-assert "build-succeeded trace in check mode" (string-contains -- 2.48.1
guix-patches@HIDDEN
:bug#75810
; Package guix-patches
.
Full text available.Received: (at 75810) by debbugs.gnu.org; 17 Mar 2025 17:05:56 +0000 From debbugs-submit-bounces <at> debbugs.gnu.org Mon Mar 17 13:05:56 2025 Received: from localhost ([127.0.0.1]:60704 helo=debbugs.gnu.org) by debbugs.gnu.org with esmtp (Exim 4.84_2) (envelope-from <debbugs-submit-bounces <at> debbugs.gnu.org>) id 1tuDuU-00030J-1h for submit <at> debbugs.gnu.org; Mon, 17 Mar 2025 13:05:56 -0400 Received: from eggs.gnu.org ([2001:470:142:3::10]:58514) by debbugs.gnu.org with esmtps (TLS1.2:ECDHE_RSA_AES_256_GCM_SHA384:256) (Exim 4.84_2) (envelope-from <ludo@HIDDEN>) id 1tuDta-0002k6-Fz for 75810 <at> debbugs.gnu.org; Mon, 17 Mar 2025 13:04:59 -0400 Received: from fencepost.gnu.org ([2001:470:142:3::e]) by eggs.gnu.org with esmtps (TLS1.2:ECDHE_RSA_AES_256_GCM_SHA384:256) (Exim 4.90_1) (envelope-from <ludo@HIDDEN>) id 1tuDtU-0005Rj-Lx; Mon, 17 Mar 2025 13:04:52 -0400 DKIM-Signature: v=1; a=rsa-sha256; q=dns/txt; c=relaxed/relaxed; d=gnu.org; s=fencepost-gnu-org; h=MIME-Version:References:In-Reply-To:Date:Subject:To: From; bh=zRzyCRKNi7OLYtMltAIWBXxpQUCJgq5z2G4rnUFbrMY=; b=h62nyM8vYaVwGKubCdFq PONw6a8oB5bLl4a3cWbte5PhVAmLUQ6JrGX2FKo9oFe8trha3S8LKiB8y3IbGbxj9fXsL+SAaF8AW aLkTbSPn8jgIdAhBXWhhv0j/5kXMsS10gFgRV1mmSIblDmayudaf6nm132UMmeiekROPzauowudCJ 3j10ylsWwkXzpez/6yhtF9I1rI3nHcUpN4F9/5njogbetbfZcgNaoNZ64sBdVnLhvKqh/klATnLIM zbU8+wCDu5FplQETzhDMv8lmtbGwt6hwLLgwLP4HeMZkVUZgmJ5t2l603Agj1gKkFQ0Dkaos1DQNf xp2Ikj5+O1/qYQ==; From: =?UTF-8?q?Ludovic=20Court=C3=A8s?= <ludo@HIDDEN> To: 75810 <at> debbugs.gnu.org Subject: [PATCH v6 15/16] guix-install.sh: Support the unprivileged daemon where possible. Date: Mon, 17 Mar 2025 18:02:58 +0100 Message-ID: <07c5b1b1ef05c002ad7092976e67eceb45f0c5da.1742230220.git.ludo@HIDDEN> X-Mailer: git-send-email 2.48.1 In-Reply-To: <cover.1742230219.git.ludo@HIDDEN> References: <cover.1742230219.git.ludo@HIDDEN> MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit X-Spam-Score: -2.3 (--) X-Debbugs-Envelope-To: 75810 Cc: =?UTF-8?q?Ludovic=20Court=C3=A8s?= <ludo@HIDDEN> X-BeenThere: debbugs-submit <at> debbugs.gnu.org X-Mailman-Version: 2.1.18 Precedence: list List-Id: <debbugs-submit.debbugs.gnu.org> List-Unsubscribe: <https://debbugs.gnu.org/cgi-bin/mailman/options/debbugs-submit>, <mailto:debbugs-submit-request <at> debbugs.gnu.org?subject=unsubscribe> List-Archive: <https://debbugs.gnu.org/cgi-bin/mailman/private/debbugs-submit/> List-Post: <mailto:debbugs-submit <at> debbugs.gnu.org> List-Help: <mailto:debbugs-submit-request <at> debbugs.gnu.org?subject=help> List-Subscribe: <https://debbugs.gnu.org/cgi-bin/mailman/listinfo/debbugs-submit>, <mailto:debbugs-submit-request <at> debbugs.gnu.org?subject=subscribe> Errors-To: debbugs-submit-bounces <at> debbugs.gnu.org Sender: "Debbugs-submit" <debbugs-submit-bounces <at> debbugs.gnu.org> X-Spam-Score: -3.3 (---) * etc/guix-install.sh (create_account): New function. (sys_create_build_user): Use it. When ‘guix-daemon.service’ contains “User=guix-daemon” only create the ‘guix-daemon’ user and group. (sys_delete_build_user): Delete the ‘guix-daemon’ user and group. (can_install_unprivileged_daemon): New function. (sys_create_store): When installing the unprivileged daemon, change ownership of /gnu and /var/guix, and create /var/log/guix. (sys_authorize_build_farms): When the ‘guix-daemon’ account exists, change ownership of /etc/guix. Change-Id: I73e573f1cc5c0cb3794aaaa6b576616b66e0c5e9 --- etc/guix-install.sh | 124 +++++++++++++++++++++++++++++++++++--------- 1 file changed, 99 insertions(+), 25 deletions(-) diff --git a/etc/guix-install.sh b/etc/guix-install.sh index 8887204df4..30e4bc4223 100755 --- a/etc/guix-install.sh +++ b/etc/guix-install.sh @@ -414,6 +414,11 @@ sys_create_store() cd "$tmp_path" _msg_info "Installing /var/guix and /gnu..." # Strip (skip) the leading ‘.’ component, which fails on read-only ‘/’. + # + # TODO: Eventually extract with ‘--owner=guix-daemon’ when installing + # and unprivileged guix-daemon service; for now, this script may install + # from both an old release that does not support unprivileged guix-daemon + # and a new release that does, so ‘chown -R’ later if needed. tar --extract --strip-components=1 --file "$pkg" -C / _msg_info "Linking the root user's profile" @@ -441,38 +446,95 @@ sys_delete_store() rm -rf ~root/.config/guix } +create_account() +{ + local user="$1" + local group="$2" + local supplementary_groups="$3" + local comment="$4" + + if id "$user" &>/dev/null; then + _msg_info "user '$user' is already in the system, reset" + usermod -g "$group" -G "$supplementary_groups" \ + -d /var/empty -s "$(which nologin)" \ + -c "$comment" "$user" + else + useradd -g "$group" -G "$supplementary_groups" \ + -d /var/empty -s "$(which nologin)" \ + -c "$comment" --system "$user" + _msg_pass "user added <$user>" + fi +} + +install_unprivileged_daemon() +{ # Return true when installing guix-daemon running without privileges. + [ "$INIT_SYS" = systemd ] && \ + grep -q "User=guix-daemon" \ + ~root/.config/guix/current/lib/systemd/system/guix-daemon.service +} + sys_create_build_user() { # Create the group and user accounts for build users. _debug "--- [ ${FUNCNAME[0]} ] ---" - if getent group guixbuild > /dev/null; then - _msg_info "group guixbuild exists" - else - groupadd --system guixbuild - _msg_pass "group <guixbuild> created" - fi - if getent group kvm > /dev/null; then _msg_info "group kvm exists and build users will be added to it" local KVMGROUP=,kvm fi - for i in $(seq -w 1 10); do - if id "guixbuilder${i}" &>/dev/null; then - _msg_info "user is already in the system, reset" - usermod -g guixbuild -G guixbuild"$KVMGROUP" \ - -d /var/empty -s "$(which nologin)" \ - -c "Guix build user $i" \ - "guixbuilder${i}"; - else - useradd -g guixbuild -G guixbuild"$KVMGROUP" \ - -d /var/empty -s "$(which nologin)" \ - -c "Guix build user $i" --system \ - "guixbuilder${i}"; - _msg_pass "user added <guixbuilder${i}>" - fi - done + if install_unprivileged_daemon + then + _msg_info "installing guix-daemon to run as an unprivileged user" + + # Installing guix-daemon to run as a non-root user requires + # unprivileged user namespaces. + if [ -f /proc/sys/kernel/unprivileged_userns_clone ] \ + && [ "$(cat /proc/sys/kernel/unprivileged_userns_clone)" -ne 1 ] + then + echo 1 > /proc/sys/kernel/unprivileged_userns_clone || \ + _err "failed to enable unprivileged user namespaces" + + _msg_warn "Unprivileged user namespaces were disabled and have been enabled now." + _msg_warn "This Linux feature is required by guix-daemon. To enable it permanently, run:" + _msg_warn ' echo 1 > /proc/sys/kernel/unprivileged_userns_clone' + _msg_warn "from the relevant startup script." + fi + + + if getent group guix-daemon > /dev/null; then + _msg_info "group guix-daemon exists" + else + groupadd --system guix-daemon + _msg_pass "group guix-daemon created" + fi + + create_account guix-daemon guix-daemon \ + guix-daemon$KVMGROUP \ + "Unprivileged Guix Daemon User" + + # ‘tar xf’ creates root:root files. Change that. + chown -R guix-daemon:guix-daemon /gnu /var/guix + chown -R root:root /var/guix/profiles/per-user/root + + # The unprivileged daemon cannot create the log directory by itself. + mkdir /var/log/guix + chown guix-daemon:guix-daemon /var/log/guix + chmod 755 /var/log/guix + else + if getent group guixbuild > /dev/null; then + _msg_info "group guixbuild exists" + else + groupadd --system guixbuild + _msg_pass "group <guixbuild> created" + fi + + for i in $(seq -w 1 10); do + create_account "guixbuilder${i}" "guixbuild" \ + "guixbuild${KVMGROUP}" \ + "Guix build user $i" + done + fi } sys_delete_build_user() @@ -487,6 +549,14 @@ sys_delete_build_user() if getent group guixbuild &>/dev/null; then groupdel -f guixbuild fi + + _msg_info "remove guix-daemon user" + if id guix-daemon &>/dev/null; then + userdel -f guix-daemon + fi + if getent group guix-daemon &>/dev/null; then + groupdel -f guix-daemon + fi } sys_enable_guix_daemon() @@ -529,11 +599,11 @@ sys_enable_guix_daemon() # Install after guix-daemon.service to avoid a harmless warning. # systemd .mount units must be named after the target directory. - # Here we assume a hard-coded name of /gnu/store. - install_unit gnu-store.mount + install_unit gnu-store.mount systemctl daemon-reload && - systemctl start guix-daemon; } && + systemctl start guix-daemon && + systemctl start gnu-store.mount; } && _msg_pass "enabled Guix daemon via systemd" ;; sysv-init) @@ -654,6 +724,10 @@ project's build farms?"; then && guix archive --authorize < "$key" \ && _msg_pass "Authorized public key for $host" done + if id guix-daemon &>/dev/null; then + # /etc/guix/acl must be readable by the unprivileged guix-daemon. + chown -R guix-daemon:guix-daemon /etc/guix + fi else _msg_info "Skipped authorizing build farm public keys" fi -- 2.48.1
guix-patches@HIDDEN
:bug#75810
; Package guix-patches
.
Full text available.Received: (at 75810) by debbugs.gnu.org; 17 Mar 2025 17:05:10 +0000 From debbugs-submit-bounces <at> debbugs.gnu.org Mon Mar 17 13:05:10 2025 Received: from localhost ([127.0.0.1]:60686 helo=debbugs.gnu.org) by debbugs.gnu.org with esmtp (Exim 4.84_2) (envelope-from <debbugs-submit-bounces <at> debbugs.gnu.org>) id 1tuDtj-0002o1-IM for submit <at> debbugs.gnu.org; Mon, 17 Mar 2025 13:05:10 -0400 Received: from eggs.gnu.org ([2001:470:142:3::10]:58488) by debbugs.gnu.org with esmtps (TLS1.2:ECDHE_RSA_AES_256_GCM_SHA384:256) (Exim 4.84_2) (envelope-from <ludo@HIDDEN>) id 1tuDtZ-0002jr-4o for 75810 <at> debbugs.gnu.org; Mon, 17 Mar 2025 13:04:58 -0400 Received: from fencepost.gnu.org ([2001:470:142:3::e]) by eggs.gnu.org with esmtps (TLS1.2:ECDHE_RSA_AES_256_GCM_SHA384:256) (Exim 4.90_1) (envelope-from <ludo@HIDDEN>) id 1tuDtR-0005Qh-Ez; Mon, 17 Mar 2025 13:04:49 -0400 DKIM-Signature: v=1; a=rsa-sha256; q=dns/txt; c=relaxed/relaxed; d=gnu.org; s=fencepost-gnu-org; h=MIME-Version:References:In-Reply-To:Date:Subject:To: From; bh=b8CNe7Kd4LDHNqpleCFnb1ypaRvesBWH130JtOnxyOw=; b=IAvTkoPFgaQ7403jl2xe 5AS96mRUYph6k95Y99rabeGOavSli3AOCUaYKzrndU+HxdxLn88AAa94aItB2xTNnh7l2UrM9SS4L wpjtIObGUqsCvIR0aYoJNKbX/2DqMWym/l9HeRvfolepSWateDRnl1LBLgF8f2TbcO9/6DA8HeBbG j9aiJGSEIMm6FoHJKZx1R3SwrDtULvT/mAkHr60cwajkgS7OKjM2689YEE1Yq3/VltY/+cd4dHbH5 TGJvBY351tvFKfs+waLzfciuUN5oR2sguTvS20wvhb2jABJuN/2kOmQzruMMC4McPnPhcqk0iQtkR RdFDyyC6V78a7A==; From: =?UTF-8?q?Ludovic=20Court=C3=A8s?= <ludo@HIDDEN> To: 75810 <at> debbugs.gnu.org Subject: [PATCH v6 12/16] tests: Add missing derivation inputs. Date: Mon, 17 Mar 2025 18:02:55 +0100 Message-ID: <1521a5f93fbcc986c8d814298bc2cd0af5a73444.1742230220.git.ludo@HIDDEN> X-Mailer: git-send-email 2.48.1 In-Reply-To: <cover.1742230219.git.ludo@HIDDEN> References: <cover.1742230219.git.ludo@HIDDEN> MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit X-Spam-Score: -2.3 (--) X-Debbugs-Envelope-To: 75810 Cc: =?UTF-8?q?Ludovic=20Court=C3=A8s?= <ludo@HIDDEN> X-BeenThere: debbugs-submit <at> debbugs.gnu.org X-Mailman-Version: 2.1.18 Precedence: list List-Id: <debbugs-submit.debbugs.gnu.org> List-Unsubscribe: <https://debbugs.gnu.org/cgi-bin/mailman/options/debbugs-submit>, <mailto:debbugs-submit-request <at> debbugs.gnu.org?subject=unsubscribe> List-Archive: <https://debbugs.gnu.org/cgi-bin/mailman/private/debbugs-submit/> List-Post: <mailto:debbugs-submit <at> debbugs.gnu.org> List-Help: <mailto:debbugs-submit-request <at> debbugs.gnu.org?subject=help> List-Subscribe: <https://debbugs.gnu.org/cgi-bin/mailman/listinfo/debbugs-submit>, <mailto:debbugs-submit-request <at> debbugs.gnu.org?subject=subscribe> Errors-To: debbugs-submit-bounces <at> debbugs.gnu.org Sender: "Debbugs-submit" <debbugs-submit-bounces <at> debbugs.gnu.org> X-Spam-Score: -3.3 (---) These missing inputs go unnoticed when running ‘guix-daemon --disable-chroot’ but are immediately visible otherwise. * tests/derivations.scm ("fixed-output derivation"): Add %BASH to #:sources. ("fixed-output derivation: output paths are equal"): ("fixed-output derivation, recursive"): ("derivation with a fixed-output input"): ("derivation with duplicate fixed-output inputs"): ("derivation with equivalent fixed-output inputs"): ("build derivation with coreutils"): Likewise. * tests/packages.scm (bootstrap-binary): New procedure. ("package-source-derivation, origin, sha512"): Use it instead of ‘search-bootstrap-binary’ and add BASH to #:sources. ("package-source-derivation, origin, sha3-512"): Likewise. Change-Id: I4c9087df23c47729a3aff15e9e1435b7266e36e2 --- tests/derivations.scm | 24 +++++++++++++++--------- tests/packages.scm | 13 +++++++++---- 2 files changed, 24 insertions(+), 13 deletions(-) diff --git a/tests/derivations.scm b/tests/derivations.scm index 72ea9aa9cc..f30f05474e 100644 --- a/tests/derivations.scm +++ b/tests/derivations.scm @@ -1,5 +1,5 @@ ;;; GNU Guix --- Functional package management for GNU -;;; Copyright © 2012-2024 Ludovic Courtès <ludo@HIDDEN> +;;; Copyright © 2012-2025 Ludovic Courtès <ludo@HIDDEN> ;;; ;;; This file is part of GNU Guix. ;;; @@ -443,7 +443,7 @@ (define* (directory-contents dir #:optional (slurp get-bytevector-all)) (string-append "fixed-" (symbol->string hash-algorithm)) %bash `(,builder) - #:sources `(,builder) ;optional + #:sources (list %bash builder) #:hash hash #:hash-algo hash-algorithm))) (build-derivations %store (list drv)) @@ -462,9 +462,11 @@ (define* (directory-contents dir #:optional (slurp get-bytevector-all)) (hash (gcrypt:sha256 (string->utf8 "hello"))) (drv1 (derivation %store "fixed" %bash `(,builder1) + #:sources (list %bash builder1) #:hash hash #:hash-algo 'sha256)) (drv2 (derivation %store "fixed" %bash `(,builder2) + #:sources (list %bash builder2) #:hash hash #:hash-algo 'sha256)) (succeeded? (build-derivations %store (list drv1 drv2)))) (and succeeded? @@ -477,7 +479,7 @@ (define* (directory-contents dir #:optional (slurp get-bytevector-all)) (hash (gcrypt:sha256 (string->utf8 "hello"))) (drv (derivation %store "fixed-rec" %bash `(,builder) - #:sources (list builder) + #:sources (list %bash builder) #:hash (base32 "0sg9f58l1jj88w6pdrfdpj5x9b1zrwszk84j81zvby36q9whhhqa") #:hash-algo 'sha256 #:recursive? #t)) @@ -511,9 +513,11 @@ (define* (directory-contents dir #:optional (slurp get-bytevector-all)) (hash (gcrypt:sha256 (string->utf8 "hello"))) (fixed1 (derivation %store "fixed" %bash `(,builder1) + #:sources (list %bash builder1) #:hash hash #:hash-algo 'sha256)) (fixed2 (derivation %store "fixed" %bash `(,builder2) + #:sources (list %bash builder2) #:hash hash #:hash-algo 'sha256)) (fixed-out (derivation->output-path fixed1)) (builder3 (add-text-to-store @@ -548,9 +552,11 @@ (define* (directory-contents dir #:optional (slurp get-bytevector-all)) (hash (gcrypt:sha256 (string->utf8 "hello"))) (fixed1 (derivation %store "fixed" %bash `(,builder1) + #:sources (list %bash builder1) #:hash hash #:hash-algo 'sha256)) (fixed2 (derivation %store "fixed" %bash `(,builder2) + #:sources (list %bash builder2) #:hash hash #:hash-algo 'sha256)) (builder3 (add-text-to-store %store "builder.sh" "echo fake builder")) @@ -580,21 +586,21 @@ (define* (directory-contents dir #:optional (slurp get-bytevector-all)) '())) (hash (gcrypt:sha256 (string->utf8 "hello"))) (drv1 (derivation %store "fixed" %bash (list builder1) - #:sources (list builder1) + #:sources (list %bash builder1) #:hash hash #:hash-algo 'sha256)) (drv2 (derivation %store "fixed" %bash (list builder2) - #:sources (list builder2) + #:sources (list %bash builder2) #:hash hash #:hash-algo 'sha256)) (drv3a (derivation %store "fixed-user" %bash (list builder3) #:outputs '("one" "two") - #:sources (list builder3) + #:sources (list %bash builder3) #:inputs (list (derivation-input drv1)))) (drv3b (derivation %store "fixed-user" %bash (list builder3) #:outputs '("one" "two") - #:sources (list builder3) + #:sources (list %bash builder3) #:inputs (list (derivation-input drv2)))) (drv4 (derivation %store "fixed-user-user" %bash (list builder1) - #:sources (list builder1) + #:sources (list %bash builder1) #:inputs (list (derivation-input drv3a '("one")) (derivation-input drv3b '("two")))))) (match (derivation-inputs drv4) @@ -878,7 +884,7 @@ (define %coreutils ,(string-append (derivation->output-path %coreutils) "/bin"))) - #:sources (list builder) + #:sources (list %bash builder) #:inputs (list (derivation-input %coreutils)))) (succeeded? (build-derivations %store (list drv)))) diff --git a/tests/packages.scm b/tests/packages.scm index 50c1cab915..f56c63128d 100644 --- a/tests/packages.scm +++ b/tests/packages.scm @@ -80,6 +80,11 @@ (define %store ;; When grafting, do not add dependency on 'glibc-utf8-locales'. (%graft-with-utf8-locale? #f) +(define (bootstrap-binary name) + (let ((bin (search-bootstrap-binary name (%current-system)))) + (and %store + (add-to-store %store name #t "sha256" bin)))) + (test-begin "packages") @@ -609,14 +614,14 @@ (define %store (test-equal "package-source-derivation, origin, sha512" "hello" - (let* ((bash (search-bootstrap-binary "bash" (%current-system))) + (let* ((bash (bootstrap-binary "bash")) (builder (add-text-to-store %store "my-fixed-builder.sh" "echo -n hello > $out" '())) (method (lambda* (url hash-algo hash #:optional name #:rest rest) (and (eq? hash-algo 'sha512) (raw-derivation name bash (list builder) - #:sources (list builder) + #:sources (list bash builder) #:hash hash #:hash-algo hash-algo)))) (source (origin @@ -635,14 +640,14 @@ (define %store (test-equal "package-source-derivation, origin, sha3-512" "hello, sha3" - (let* ((bash (search-bootstrap-binary "bash" (%current-system))) + (let* ((bash (bootstrap-binary "bash")) (builder (add-text-to-store %store "my-fixed-builder.sh" "echo -n hello, sha3 > $out" '())) (method (lambda* (url hash-algo hash #:optional name #:rest rest) (and (eq? hash-algo 'sha3-512) (raw-derivation name bash (list builder) - #:sources (list builder) + #:sources (list bash builder) #:hash hash #:hash-algo hash-algo)))) (source (origin -- 2.48.1
guix-patches@HIDDEN
:bug#75810
; Package guix-patches
.
Full text available.Received: (at 75810) by debbugs.gnu.org; 17 Mar 2025 17:05:07 +0000 From debbugs-submit-bounces <at> debbugs.gnu.org Mon Mar 17 13:05:07 2025 Received: from localhost ([127.0.0.1]:60683 helo=debbugs.gnu.org) by debbugs.gnu.org with esmtp (Exim 4.84_2) (envelope-from <debbugs-submit-bounces <at> debbugs.gnu.org>) id 1tuDth-0002nH-RC for submit <at> debbugs.gnu.org; Mon, 17 Mar 2025 13:05:07 -0400 Received: from eggs.gnu.org ([2001:470:142:3::10]:58482) by debbugs.gnu.org with esmtps (TLS1.2:ECDHE_RSA_AES_256_GCM_SHA384:256) (Exim 4.84_2) (envelope-from <ludo@HIDDEN>) id 1tuDtY-0002je-2K for 75810 <at> debbugs.gnu.org; Mon, 17 Mar 2025 13:04:56 -0400 Received: from fencepost.gnu.org ([2001:470:142:3::e]) by eggs.gnu.org with esmtps (TLS1.2:ECDHE_RSA_AES_256_GCM_SHA384:256) (Exim 4.90_1) (envelope-from <ludo@HIDDEN>) id 1tuDtQ-0005QN-Fc; Mon, 17 Mar 2025 13:04:48 -0400 DKIM-Signature: v=1; a=rsa-sha256; q=dns/txt; c=relaxed/relaxed; d=gnu.org; s=fencepost-gnu-org; h=MIME-Version:References:In-Reply-To:Date:Subject:To: From; bh=VxUd1aOcvzD/pYxOxBWjge8/c0+rM0LNoWab4Huyg4s=; b=UEQuv85I/vuSWiKvC4CI IcavIKQ9UskkSrQ9Idf/AxP3Q/KA4LQemcLzCU+0wHtmBpYuJNWUqzyEIacy+aS8UHcFdR4lBXn6V LZcc/qKPkZe+N989CGm+9UVnKSMIdcY4nmKXnGlsGeu7nTZc61M8ELnrFN0pdSoKeYVIZrk2kILwR QNSKXfUSL+zLV8GcSqU0r4pQSXSE3hX2FuFytkbTF1kdogL+MTgl62iRTcfVgz6Hymt1cHcAlAupc FStmyNroCFhadgH9olY4ut4AmOAXeJm/Dk6mzlRyJVklnh3A3JR8NHEwoEumzZ6ZjVK8jhtUr5LGa z+tOhRfJnUZWRw==; From: =?UTF-8?q?Ludovic=20Court=C3=A8s?= <ludo@HIDDEN> To: 75810 <at> debbugs.gnu.org Subject: [PATCH v6 11/16] =?UTF-8?q?linux-container:=20=E2=80=98unprivileg?= =?UTF-8?q?ed-user-namespace-supported=3F=E2=80=99=20returns=20#f=20on=20n?= =?UTF-8?q?on-Linux.?= Date: Mon, 17 Mar 2025 18:02:54 +0100 Message-ID: <a2bea8f1119e7273e953337780d481d76017f209.1742230219.git.ludo@HIDDEN> X-Mailer: git-send-email 2.48.1 In-Reply-To: <cover.1742230219.git.ludo@HIDDEN> References: <cover.1742230219.git.ludo@HIDDEN> MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit X-Spam-Score: -0.8 (/) X-Debbugs-Envelope-To: 75810 Cc: =?UTF-8?q?Ludovic=20Court=C3=A8s?= <ludo@HIDDEN>, Reepca Russelstein <reepca@HIDDEN> X-BeenThere: debbugs-submit <at> debbugs.gnu.org X-Mailman-Version: 2.1.18 Precedence: list List-Id: <debbugs-submit.debbugs.gnu.org> List-Unsubscribe: <https://debbugs.gnu.org/cgi-bin/mailman/options/debbugs-submit>, <mailto:debbugs-submit-request <at> debbugs.gnu.org?subject=unsubscribe> List-Archive: <https://debbugs.gnu.org/cgi-bin/mailman/private/debbugs-submit/> List-Post: <mailto:debbugs-submit <at> debbugs.gnu.org> List-Help: <mailto:debbugs-submit-request <at> debbugs.gnu.org?subject=help> List-Subscribe: <https://debbugs.gnu.org/cgi-bin/mailman/listinfo/debbugs-submit>, <mailto:debbugs-submit-request <at> debbugs.gnu.org?subject=subscribe> Errors-To: debbugs-submit-bounces <at> debbugs.gnu.org Sender: "Debbugs-submit" <debbugs-submit-bounces <at> debbugs.gnu.org> X-Spam-Score: -1.8 (-) Previously this procedure would return #t on non-Linux systems. * gnu/build/linux-container.scm (unprivileged-user-namespace-supported?): When USERNS-FILE doesn’t exist, return (user-namespace-supported?). Reported-by: Reepca Russelstein <reepca@HIDDEN> Change-Id: I92050338b8b68bc3bd87100317eba69fcdf14a0a --- gnu/build/linux-container.scm | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/gnu/build/linux-container.scm b/gnu/build/linux-container.scm index 5c303da8c8..a5c5d8962e 100644 --- a/gnu/build/linux-container.scm +++ b/gnu/build/linux-container.scm @@ -1,6 +1,6 @@ ;;; GNU Guix --- Functional package management for GNU ;;; Copyright © 2015 David Thompson <davet@HIDDEN> -;;; Copyright © 2017-2019, 2022, 2023 Ludovic Courtès <ludo@HIDDEN> +;;; Copyright © 2017-2019, 2022-2023, 2025 Ludovic Courtès <ludo@HIDDEN> ;;; ;;; This file is part of GNU Guix. ;;; @@ -44,7 +44,7 @@ (define (unprivileged-user-namespace-supported?) (let ((userns-file "/proc/sys/kernel/unprivileged_userns_clone")) (if (file-exists? userns-file) (eqv? #\1 (call-with-input-file userns-file read-char)) - #t))) + (user-namespace-supported?)))) (define (setgroups-supported?) "Return #t if the setgroups proc file, introduced in Linux-libre 3.19, -- 2.48.1
guix-patches@HIDDEN
:bug#75810
; Package guix-patches
.
Full text available.Received: (at 75810) by debbugs.gnu.org; 17 Mar 2025 17:05:05 +0000 From debbugs-submit-bounces <at> debbugs.gnu.org Mon Mar 17 13:05:05 2025 Received: from localhost ([127.0.0.1]:60681 helo=debbugs.gnu.org) by debbugs.gnu.org with esmtp (Exim 4.84_2) (envelope-from <debbugs-submit-bounces <at> debbugs.gnu.org>) id 1tuDtg-0002mi-SU for submit <at> debbugs.gnu.org; Mon, 17 Mar 2025 13:05:05 -0400 Received: from eggs.gnu.org ([2001:470:142:3::10]:36070) by debbugs.gnu.org with esmtps (TLS1.2:ECDHE_RSA_AES_256_GCM_SHA384:256) (Exim 4.84_2) (envelope-from <ludo@HIDDEN>) id 1tuDtR-0002ib-Lu for 75810 <at> debbugs.gnu.org; Mon, 17 Mar 2025 13:04:50 -0400 Received: from fencepost.gnu.org ([2001:470:142:3::e]) by eggs.gnu.org with esmtps (TLS1.2:ECDHE_RSA_AES_256_GCM_SHA384:256) (Exim 4.90_1) (envelope-from <ludo@HIDDEN>) id 1tuDtL-0005O6-8m; Mon, 17 Mar 2025 13:04:43 -0400 DKIM-Signature: v=1; a=rsa-sha256; q=dns/txt; c=relaxed/relaxed; d=gnu.org; s=fencepost-gnu-org; h=MIME-Version:References:In-Reply-To:Date:Subject:To: From; bh=UutMX9pAeYaOKM9If5j0ljEqrH6oIEE2IroKoS0wm4Q=; b=IwYZ/Lce+2YicytLDwe8 sd+3dHW1Y7b6me3vQxN2qyjUZfuV19HVYpUDCjX0CITTe+0IaMUhaEuulPxSTeKjc+oQVpc8nSTOm U4Q0LRaZwtl66Jw2PqzGxbNZWPLYBenMiheNrm7ZdAllXri90OIzNu07DmrcVyXBzr6yXws5iNar2 NI+tuTYy7wLbKID3y/U2v2T9FazNMUy/a+57pYO7rKxkD+7eYGGgWpozKQUmb1kXdN3BBF2zAEKTY mNJzj94esVKNZUcjYVJ9AhPN/5h6ZDIFg3mjgw4rUdgV10UspsfZUiPrmQ1tLFeiy07NrQsQtVWJk LJDAmI0IB59xNg==; From: =?UTF-8?q?Ludovic=20Court=C3=A8s?= <ludo@HIDDEN> To: 75810 <at> debbugs.gnu.org Subject: [PATCH v6 10/16] daemon: Move comments where they belong. Date: Mon, 17 Mar 2025 18:02:53 +0100 Message-ID: <a6a2fca34e1785e77c7d5c752d7711e275f0fb4f.1742230219.git.ludo@HIDDEN> X-Mailer: git-send-email 2.48.1 In-Reply-To: <cover.1742230219.git.ludo@HIDDEN> References: <cover.1742230219.git.ludo@HIDDEN> MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit X-Spam-Score: -2.3 (--) X-Debbugs-Envelope-To: 75810 Cc: =?UTF-8?q?Ludovic=20Court=C3=A8s?= <ludo@HIDDEN> X-BeenThere: debbugs-submit <at> debbugs.gnu.org X-Mailman-Version: 2.1.18 Precedence: list List-Id: <debbugs-submit.debbugs.gnu.org> List-Unsubscribe: <https://debbugs.gnu.org/cgi-bin/mailman/options/debbugs-submit>, <mailto:debbugs-submit-request <at> debbugs.gnu.org?subject=unsubscribe> List-Archive: <https://debbugs.gnu.org/cgi-bin/mailman/private/debbugs-submit/> List-Post: <mailto:debbugs-submit <at> debbugs.gnu.org> List-Help: <mailto:debbugs-submit-request <at> debbugs.gnu.org?subject=help> List-Subscribe: <https://debbugs.gnu.org/cgi-bin/mailman/listinfo/debbugs-submit>, <mailto:debbugs-submit-request <at> debbugs.gnu.org?subject=subscribe> Errors-To: debbugs-submit-bounces <at> debbugs.gnu.org Sender: "Debbugs-submit" <debbugs-submit-bounces <at> debbugs.gnu.org> X-Spam-Score: -3.3 (---) * nix/libstore/build.cc (DerivationGoal::startBuilder): Shuffle comments for clarity. Change-Id: I6557c103ade4a3ab046354548ea193c68f8c9c05 --- nix/libstore/build.cc | 13 +++++++------ 1 file changed, 7 insertions(+), 6 deletions(-) diff --git a/nix/libstore/build.cc b/nix/libstore/build.cc index 51ac11e235..54d2996dd1 100644 --- a/nix/libstore/build.cc +++ b/nix/libstore/build.cc @@ -1870,18 +1870,19 @@ void DerivationGoal::startBuilder() } dirsInChroot[tmpDirInSandbox] = tmpDir; - /* Make the closure of the inputs available in the chroot, - rather than the whole store. This prevents any access - to undeclared dependencies. !!! As an extra security - precaution, make the fake store only writable by the - build user. */ + /* Create the fake store. */ Path chrootStoreDir = chrootRootDir + settings.nixStore; createDirs(chrootStoreDir); chmod_(chrootStoreDir, 01775); if (buildUser.enabled() && chown(chrootStoreDir.c_str(), 0, buildUser.getGID()) == -1) - throw SysError(format("cannot change ownership of ‘%1%’") % chrootStoreDir); + /* As an extra security precaution, make the fake store only + writable by the build user. */ + throw SysError(format("cannot change ownership of ‘%1%’") % chrootStoreDir); + /* Make the closure of the inputs available in the chroot, rather than + the whole store. This prevents any access to undeclared + dependencies. */ foreach (PathSet::iterator, i, inputPaths) { struct stat st; if (lstat(i->c_str(), &st)) -- 2.48.1
guix-patches@HIDDEN
:bug#75810
; Package guix-patches
.
Full text available.Received: (at 75810) by debbugs.gnu.org; 17 Mar 2025 17:05:05 +0000 From debbugs-submit-bounces <at> debbugs.gnu.org Mon Mar 17 13:05:04 2025 Received: from localhost ([127.0.0.1]:60677 helo=debbugs.gnu.org) by debbugs.gnu.org with esmtp (Exim 4.84_2) (envelope-from <debbugs-submit-bounces <at> debbugs.gnu.org>) id 1tuDtf-0002mQ-R8 for submit <at> debbugs.gnu.org; Mon, 17 Mar 2025 13:05:04 -0400 Received: from eggs.gnu.org ([2001:470:142:3::10]:36064) by debbugs.gnu.org with esmtps (TLS1.2:ECDHE_RSA_AES_256_GCM_SHA384:256) (Exim 4.84_2) (envelope-from <ludo@HIDDEN>) id 1tuDtQ-0002iQ-RC for 75810 <at> debbugs.gnu.org; Mon, 17 Mar 2025 13:04:49 -0400 Received: from fencepost.gnu.org ([2001:470:142:3::e]) by eggs.gnu.org with esmtps (TLS1.2:ECDHE_RSA_AES_256_GCM_SHA384:256) (Exim 4.90_1) (envelope-from <ludo@HIDDEN>) id 1tuDtJ-0005NP-PS; Mon, 17 Mar 2025 13:04:41 -0400 DKIM-Signature: v=1; a=rsa-sha256; q=dns/txt; c=relaxed/relaxed; d=gnu.org; s=fencepost-gnu-org; h=MIME-Version:References:In-Reply-To:Date:Subject:To: From; bh=ZFzrFk7nTXhAfaat5FBy/2gARokuQM84I/u4c9YnLJQ=; b=kHFB1Kn5vBHcBokpzK+I /aDH3ixUyNQG4YTRjOkw+KOMU9SKQHNw7PlAIcOOUDD80bBziV78JgJN8YrAT8+/Bp7h7eYbw4lL2 FLpUCue/6xXycBJQzf0LRBFJmTr+Hnf5xBTGfC8oEER+Vc4G8lCmlLuouGErCaG7HaMBhjCtT0YyJ Qa/cAqLcYOgvMa8PaudBLt0IpGO72+divoNw7McqbnQD5sFYORUQcDDIWG4a4Jga67G3izToJ1NWB xxjicemMBw7hBaQpy6n81Zq0kadqUiP8o8SSGTgMwbGxLG8qUAAA1d5kTVUgPnjyNtm5NqgKwUaT8 T7Cu/tiNP9v/Iw==; From: =?UTF-8?q?Ludovic=20Court=C3=A8s?= <ludo@HIDDEN> To: 75810 <at> debbugs.gnu.org Subject: [PATCH v6 09/16] daemon: Drop Linux ambient capabilities before executing builder. Date: Mon, 17 Mar 2025 18:02:52 +0100 Message-ID: <bdc48d5ced58ff7177c11f1fcd65985a7fc14ba9.1742230219.git.ludo@HIDDEN> X-Mailer: git-send-email 2.48.1 In-Reply-To: <cover.1742230219.git.ludo@HIDDEN> References: <cover.1742230219.git.ludo@HIDDEN> MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit X-Spam-Score: -2.3 (--) X-Debbugs-Envelope-To: 75810 Cc: =?UTF-8?q?Ludovic=20Court=C3=A8s?= <ludo@HIDDEN> X-BeenThere: debbugs-submit <at> debbugs.gnu.org X-Mailman-Version: 2.1.18 Precedence: list List-Id: <debbugs-submit.debbugs.gnu.org> List-Unsubscribe: <https://debbugs.gnu.org/cgi-bin/mailman/options/debbugs-submit>, <mailto:debbugs-submit-request <at> debbugs.gnu.org?subject=unsubscribe> List-Archive: <https://debbugs.gnu.org/cgi-bin/mailman/private/debbugs-submit/> List-Post: <mailto:debbugs-submit <at> debbugs.gnu.org> List-Help: <mailto:debbugs-submit-request <at> debbugs.gnu.org?subject=help> List-Subscribe: <https://debbugs.gnu.org/cgi-bin/mailman/listinfo/debbugs-submit>, <mailto:debbugs-submit-request <at> debbugs.gnu.org?subject=subscribe> Errors-To: debbugs-submit-bounces <at> debbugs.gnu.org Sender: "Debbugs-submit" <debbugs-submit-bounces <at> debbugs.gnu.org> X-Spam-Score: -3.3 (---) * config-daemon.ac: Check for <sys/prctl.h>. * nix/libstore/build.cc (DerivationGoal::runChild): When ‘useChroot’ is true, call ‘prctl’ to drop all ambient capabilities. Change-Id: If34637fc508e5fb6d278167f5df7802fc595284f --- config-daemon.ac | 2 +- nix/libstore/build.cc | 9 +++++++++ 2 files changed, 10 insertions(+), 1 deletion(-) diff --git a/config-daemon.ac b/config-daemon.ac index 4e949bc88a..35d9c8cd56 100644 --- a/config-daemon.ac +++ b/config-daemon.ac @@ -79,7 +79,7 @@ if test "x$guix_build_daemon" = "xyes"; then dnl Chroot support. AC_CHECK_FUNCS([chroot unshare]) AC_CHECK_HEADERS([sched.h sys/param.h sys/mount.h sys/syscall.h \ - linux/close_range.h]) + linux/close_range.h sys/prctl.h]) if test "x$ac_cv_func_chroot" != "xyes"; then AC_MSG_ERROR(['chroot' function missing, bailing out]) diff --git a/nix/libstore/build.cc b/nix/libstore/build.cc index 9a8278cd08..51ac11e235 100644 --- a/nix/libstore/build.cc +++ b/nix/libstore/build.cc @@ -50,6 +50,9 @@ #if HAVE_SCHED_H #include <sched.h> #endif +#if HAVE_SYS_PRCTL_H +#include <sys/prctl.h> +#endif #define CHROOT_ENABLED HAVE_CHROOT && HAVE_SYS_MOUNT_H && defined(MS_BIND) && defined(MS_PRIVATE) @@ -2074,6 +2077,12 @@ void DerivationGoal::runChild() #if CHROOT_ENABLED if (useChroot) { +# if HAVE_SYS_PRCTL_H + /* Drop ambient capabilities such as CAP_CHOWN that might have + been granted when starting guix-daemon. */ + prctl(PR_CAP_AMBIENT, PR_CAP_AMBIENT_CLEAR_ALL, 0, 0, 0); +# endif + if (!fixedOutput) { /* Initialise the loopback interface. */ AutoCloseFD fd(socket(PF_INET, SOCK_DGRAM, IPPROTO_IP)); -- 2.48.1
guix-patches@HIDDEN
:bug#75810
; Package guix-patches
.
Full text available.Received: (at 75810) by debbugs.gnu.org; 17 Mar 2025 17:05:04 +0000 From debbugs-submit-bounces <at> debbugs.gnu.org Mon Mar 17 13:05:03 2025 Received: from localhost ([127.0.0.1]:60670 helo=debbugs.gnu.org) by debbugs.gnu.org with esmtp (Exim 4.84_2) (envelope-from <debbugs-submit-bounces <at> debbugs.gnu.org>) id 1tuDta-0002l8-TV for submit <at> debbugs.gnu.org; Mon, 17 Mar 2025 13:05:03 -0400 Received: from eggs.gnu.org ([2001:470:142:3::10]:56116) by debbugs.gnu.org with esmtps (TLS1.2:ECDHE_RSA_AES_256_GCM_SHA384:256) (Exim 4.84_2) (envelope-from <ludo@HIDDEN>) id 1tuDtM-0002hf-KG for 75810 <at> debbugs.gnu.org; Mon, 17 Mar 2025 13:04:48 -0400 Received: from fencepost.gnu.org ([2001:470:142:3::e]) by eggs.gnu.org with esmtps (TLS1.2:ECDHE_RSA_AES_256_GCM_SHA384:256) (Exim 4.90_1) (envelope-from <ludo@HIDDEN>) id 1tuDtC-0005Lp-SN; Mon, 17 Mar 2025 13:04:34 -0400 DKIM-Signature: v=1; a=rsa-sha256; q=dns/txt; c=relaxed/relaxed; d=gnu.org; s=fencepost-gnu-org; h=MIME-Version:References:In-Reply-To:Date:Subject:To: From; bh=lw8eToDQRScmZyoUY2V/zcziQfC7ZYPhSA4pL3j2gTI=; b=VppEuf++0Z0nDuLj8ONT eksnvv+z6S9njtyUy6Lfeztumsba5FR3d2+hpzIp/nCvtrizfXqS0o0VTWKvVwWIghaCBV683J3IG qxfqKji99pQpqR8sLHdwH5NXBuiVDuoXqTCiWKHRTcM5B8lUg9eHYcMpk0ZGyAubIG3OozvaNfCVS JaUlLvE9g6dzi+Sk8GrVb+trf3oUCUSQRnAT4/bj81RX2ihfDO4pAcTuWruDUI/G314aWotFNTpkC g6k/KILJgKdwmofU42qKudKAdJQr2hBR7fK0nrAJptPaUpxju8xRl8w8QGNF5kTrmH9p5rz6SQEi5 QPHg/qBi1X3lyA==; From: =?UTF-8?q?Ludovic=20Court=C3=A8s?= <ludo@HIDDEN> To: 75810 <at> debbugs.gnu.org Subject: [PATCH v6 07/16] daemon: Allow running as non-root with unprivileged user namespaces. Date: Mon, 17 Mar 2025 18:02:50 +0100 Message-ID: <33467d5ca0a53bff069542c7bb4314aad1c80a71.1742230219.git.ludo@HIDDEN> X-Mailer: git-send-email 2.48.1 In-Reply-To: <cover.1742230219.git.ludo@HIDDEN> References: <cover.1742230219.git.ludo@HIDDEN> MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 X-Debbugs-Cc: Christopher Baines <guix@HIDDEN>, Josselin Poiret <dev@HIDDEN>, Ludovic Courtès <ludo@HIDDEN>, Mathieu Othacehe <othacehe@HIDDEN>, Maxim Cournoyer <maxim.cournoyer@HIDDEN>, Simon Tournier <zimon.toutoune@HIDDEN>, Tobias Geerinckx-Rice <me@HIDDEN> Content-Transfer-Encoding: 8bit X-Spam-Score: -0.8 (/) X-Debbugs-Envelope-To: 75810 Cc: =?UTF-8?q?Ludovic=20Court=C3=A8s?= <ludovic.courtes@HIDDEN>, Reepca Russelstein <reepca@HIDDEN> X-BeenThere: debbugs-submit <at> debbugs.gnu.org X-Mailman-Version: 2.1.18 Precedence: list List-Id: <debbugs-submit.debbugs.gnu.org> List-Unsubscribe: <https://debbugs.gnu.org/cgi-bin/mailman/options/debbugs-submit>, <mailto:debbugs-submit-request <at> debbugs.gnu.org?subject=unsubscribe> List-Archive: <https://debbugs.gnu.org/cgi-bin/mailman/private/debbugs-submit/> List-Post: <mailto:debbugs-submit <at> debbugs.gnu.org> List-Help: <mailto:debbugs-submit-request <at> debbugs.gnu.org?subject=help> List-Subscribe: <https://debbugs.gnu.org/cgi-bin/mailman/listinfo/debbugs-submit>, <mailto:debbugs-submit-request <at> debbugs.gnu.org?subject=subscribe> Errors-To: debbugs-submit-bounces <at> debbugs.gnu.org Sender: "Debbugs-submit" <debbugs-submit-bounces <at> debbugs.gnu.org> X-Spam-Score: -1.8 (-) From: Ludovic Courtès <ludovic.courtes@HIDDEN> Many thanks to Reepca Russelstein for their review and guidance on these changes. * nix/libstore/build.cc (guestUID, guestGID): New variables. (DerivationGoal)[readiness]: New field. (initializeUserNamespace): New function. (DerivationGoal::runChild): When ‘readiness.readSide’ is positive, read from it. (DerivationGoal::startBuilder): Call ‘chown’ only when ‘buildUser.enabled()’ is true. Pass CLONE_NEWUSER to ‘clone’ when ‘buildUser.enabled()’ is false or not running as root. Retry ‘clone’ without CLONE_NEWUSER upon EPERM. (DerivationGoal::registerOutputs): Make ‘actualPath’ writable before ‘rename’. (DerivationGoal::deleteTmpDir): Catch ‘SysError’ around ‘_chown’ call. * nix/libstore/local-store.cc (LocalStore::createUser): Do nothing if ‘dirs’ already exists. Warn instead of failing when failing to chown ‘dir’. * guix/substitutes.scm (%narinfo-cache-directory): Check for ‘_NIX_OPTIONS’ rather than getuid() == 0 to determine the cache location. * doc/guix.texi (Build Environment Setup): Reorganize a bit. Add section headings “Daemon Running as Root” and “The Isolated Build Environment”. Add “Daemon Running Without Privileges” subsection. Remove paragraph about ‘--disable-chroot’. (Invoking guix-daemon): Warn against ‘--disable-chroot’ and explain why. Reviewed-by: Reepca Russelstein <reepca@HIDDEN> --- doc/guix.texi | 102 +++++++++++++++++------ guix/substitutes.scm | 2 +- nix/libstore/build.cc | 160 +++++++++++++++++++++++++++++++----- nix/libstore/local-store.cc | 18 ++-- 4 files changed, 229 insertions(+), 53 deletions(-) diff --git a/doc/guix.texi b/doc/guix.texi index d109877a32..87943afec7 100644 --- a/doc/guix.texi +++ b/doc/guix.texi @@ -877,6 +877,7 @@ Setting Up the Daemon @section Setting Up the Daemon @cindex daemon +@cindex build daemon During installation, the @dfn{build daemon} that must be running to use Guix has already been set up and you can run @command{guix} commands in your terminal program, @pxref{Getting Started}: @@ -921,20 +922,38 @@ Build Environment Setup @cindex build environment In a standard multi-user setup, Guix and its daemon---the @command{guix-daemon} program---are installed by the system -administrator; @file{/gnu/store} is owned by @code{root} and -@command{guix-daemon} runs as @code{root}. Unprivileged users may use -Guix tools to build packages or otherwise access the store, and the -daemon will do it on their behalf, ensuring that the store is kept in a -consistent state, and allowing built packages to be shared among users. +administrator. Unprivileged users may use Guix tools to build packages +or otherwise access the store, and the daemon will do it on their +behalf, ensuring that the store is kept in a consistent state, and +allowing built packages to be shared among users. + +There are currently two ways to set up and run the build daemon: + +@enumerate +@item +running @command{guix-daemon} as ``root'', letting it run build +processes as unprivileged users taken from a pool of build users---this +is the historical approach; + +@item +running @command{guix-daemon} as a separate unprivileged user, relying +on Linux's @dfn{unprivileged user namespace} functionality to set up +isolated environments---this is the option chosen when installing Guix +on a systemd-based distribution with the installation script +(@pxref{Binary Installation}). +@end enumerate + +The sections below describe each of these two configurations in more +detail and summarize the kind of build isolation they provide. + +@unnumberedsubsubsec Daemon Running as Root @cindex build users When @command{guix-daemon} runs as @code{root}, you may not want package build processes themselves to run as @code{root} too, for obvious security reasons. To avoid that, a special pool of @dfn{build users} should be created for use by build processes started by the daemon. -These build users need not have a shell and a home directory: they will -just be used when the daemon drops @code{root} privileges in build -processes. Having several such users allows the daemon to launch +Having several such users allows the daemon to launch distinct build processes under separate UIDs, which guarantees that they do not interfere with each other---an essential feature since builds are regarded as pure functions (@pxref{Introduction}). @@ -977,11 +996,45 @@ Build Environment Setup # guix-daemon --build-users-group=guixbuild @end example +In this setup, @file{/gnu/store} is owned by @code{root}. + +@unnumberedsubsubsec Daemon Running Without Privileges + +@cindex rootless build daemon +@cindex unprivileged build daemon +@cindex build daemon, unprivileged +The second and preferred option is to run @command{guix-daemon} +@emph{as an unprivileged user}. It has the advantage of reducing the +harm that can be done should a build process manage to exploit a +vulnerability in the daemon. This option requires the use of Linux's +unprivileged user namespace mechanism; today it is available and enabled +by most GNU/Linux distributions but can still be disabled. The +installation script automatically determines whether this option is +available on your system (@pxref{Binary Installation}). + +When using this option, you only need to create one user account, and +@command{guix-daemon} will run with the authority of that account: + +@example +# groupadd --system guix-daemon +# useradd -g guix-daemon -G guix-daemon \ + -d /var/empty -s $(which nologin) \ + -c "Guix daemon privilege separation user" \ + --system guix-daemon +@end example + +In this configuration, @file{/gnu/store} is owned by the +@code{guix-daemon} user. + +@unnumberedsubsubsec The Isolated Build Environment + @cindex chroot -@noindent -This way, the daemon starts build processes in a chroot, under one of -the @code{guixbuilder} users. On GNU/Linux, by default, the chroot -environment contains nothing but: +@cindex build environment isolation +@cindex isolated build environment +@cindex hermetic build environment +In both cases, the daemon starts build processes without privileges in +an @emph{isolated} or @emph{hermetic} build environment---a ``chroot''. +On GNU/Linux, by default, the build environment contains nothing but: @c Keep this list in sync with libstore/build.cc! ----------------------- @itemize @@ -1015,7 +1068,7 @@ Build Environment Setup @file{/homeless-shelter}. This helps to highlight inappropriate uses of @env{HOME} in the build scripts of packages. -All this usually enough to ensure details of the environment do not +All this is usually enough to ensure details of the environment do not influence build processes. In some exceptional cases where more control is needed---typically over the date, kernel, or CPU---you can resort to a virtual build machine (@pxref{build-vm, virtual build machines}). @@ -1035,14 +1088,6 @@ Build Environment Setup for fixed-output derivations (@pxref{Derivations}) or for substitutes (@pxref{Substitutes}). -If you are installing Guix as an unprivileged user, it is still possible -to run @command{guix-daemon} provided you pass @option{--disable-chroot}. -However, build processes will not be isolated from one another, and not -from the rest of the system. Thus, build processes may interfere with -each other, and may access programs, libraries, and other files -available on the system---making it much harder to view them as -@emph{pure} functions. - @node Daemon Offload Setup @subsection Using the Offload Facility @@ -1567,10 +1612,17 @@ Invoking guix-daemon @item --disable-chroot Disable chroot builds. -Using this option is not recommended since, again, it would allow build -processes to gain access to undeclared dependencies. It is necessary, -though, when @command{guix-daemon} is running under an unprivileged user -account. +@quotation Warning +Using this option is not recommended since it allows build processes to +gain access to undeclared dependencies, to interfere with one another, +and more generally to do anything that can be done with the authority of +build users or that of the daemon---which includes at least the ability +to tamper with any file in the store! + +You may find it necessary, though, when support for Linux unprivileged +user namespaces is missing (@pxref{Build Environment Setup}). Use at +your own risk! +@end quotation @item --log-compression=@var{type} Compress build logs according to @var{type}, one of @code{gzip}, diff --git a/guix/substitutes.scm b/guix/substitutes.scm index 7ca55788d5..86b9f5472a 100644 --- a/guix/substitutes.scm +++ b/guix/substitutes.scm @@ -79,7 +79,7 @@ (define %narinfo-cache-directory ;; time, 'guix substitute' is called by guix-daemon as root and stores its ;; cached data in /var/guix/…. However, when invoked from 'guix challenge' ;; as a user, it stores its cache in ~/.cache. - (if (zero? (getuid)) + (if (getenv "_NIX_OPTIONS") ;invoked by guix-daemon (or (and=> (getenv "XDG_CACHE_HOME") (cut string-append <> "/guix/substitute")) (string-append %state-directory "/substitute/cache")) diff --git a/nix/libstore/build.cc b/nix/libstore/build.cc index c8b778362a..9a8278cd08 100644 --- a/nix/libstore/build.cc +++ b/nix/libstore/build.cc @@ -744,6 +744,10 @@ private: friend int childEntry(void *); + /* Pipe to notify readiness to the child process when using unprivileged + user namespaces. */ + Pipe readiness; + /* Check that the derivation outputs all exist and register them as valid. */ void registerOutputs(); @@ -1619,6 +1623,24 @@ int childEntry(void * arg) } +/* UID and GID of the build user inside its own user namespace. */ +static const uid_t guestUID = 30001; +static const gid_t guestGID = 30000; + +/* Initialize the user namespace of CHILD. */ +static void initializeUserNamespace(pid_t child, + uid_t hostUID = getuid(), + gid_t hostGID = getgid()) +{ + writeFile("/proc/" + std::to_string(child) + "/uid_map", + (format("%d %d 1") % guestUID % hostUID).str()); + + writeFile("/proc/" + std::to_string(child) + "/setgroups", "deny"); + + writeFile("/proc/" + std::to_string(child) + "/gid_map", + (format("%d %d 1") % guestGID % hostGID).str()); +} + void DerivationGoal::startBuilder() { auto f = format( @@ -1682,7 +1704,7 @@ void DerivationGoal::startBuilder() then an attacker could create in it a hardlink to a root-owned file such as /etc/shadow. If 'keepFailed' is true, the daemon would then chown that hardlink to the user, giving them write access to - that file. */ + that file. See CVE-2021-27851. */ tmpDir += "/top"; if (mkdir(tmpDir.c_str(), 0700) == 1) throw SysError("creating top-level build directory"); @@ -1799,7 +1821,7 @@ void DerivationGoal::startBuilder() if (mkdir(chrootRootDir.c_str(), 0750) == -1) throw SysError(format("cannot create ‘%1%’") % chrootRootDir); - if (chown(chrootRootDir.c_str(), 0, buildUser.getGID()) == -1) + if (buildUser.enabled() && chown(chrootRootDir.c_str(), 0, buildUser.getGID()) == -1) throw SysError(format("cannot change ownership of ‘%1%’") % chrootRootDir); /* Create a writable /tmp in the chroot. Many builders need @@ -1818,8 +1840,8 @@ void DerivationGoal::startBuilder() (format( "nixbld:x:%1%:%2%:Nix build user:/:/noshell\n" "nobody:x:65534:65534:Nobody:/:/noshell\n") - % (buildUser.enabled() ? buildUser.getUID() : getuid()) - % (buildUser.enabled() ? buildUser.getGID() : getgid())).str()); + % (buildUser.enabled() ? buildUser.getUID() : guestUID) + % (buildUser.enabled() ? buildUser.getGID() : guestGID)).str()); /* Declare the build user's group so that programs get a consistent view of the system (e.g., "id -gn"). */ @@ -1854,7 +1876,7 @@ void DerivationGoal::startBuilder() createDirs(chrootStoreDir); chmod_(chrootStoreDir, 01775); - if (chown(chrootStoreDir.c_str(), 0, buildUser.getGID()) == -1) + if (buildUser.enabled() && chown(chrootStoreDir.c_str(), 0, buildUser.getGID()) == -1) throw SysError(format("cannot change ownership of ‘%1%’") % chrootStoreDir); foreach (PathSet::iterator, i, inputPaths) { @@ -1960,14 +1982,36 @@ void DerivationGoal::startBuilder() if (useChroot) { char stack[32 * 1024]; int flags = CLONE_NEWPID | CLONE_NEWNS | CLONE_NEWIPC | CLONE_NEWUTS | SIGCHLD; - if (!fixedOutput) flags |= CLONE_NEWNET; + if (!fixedOutput) { + flags |= CLONE_NEWNET; + } + if (!buildUser.enabled() || getuid() != 0) { + flags |= CLONE_NEWUSER; + readiness.create(); + } + /* Ensure proper alignment on the stack. On aarch64, it has to be 16 bytes. */ - pid = clone(childEntry, + pid = clone(childEntry, (char *)(((uintptr_t)stack + sizeof(stack) - 8) & ~(uintptr_t)0xf), flags, this); - if (pid == -1) - throw SysError("cloning builder process"); + if (pid == -1) { + if ((flags & CLONE_NEWUSER) != 0 && getuid() != 0) + /* 'clone' fails with EPERM on distros where unprivileged user + namespaces are disabled. Error out instead of giving up on + isolation. */ + throw SysError("cannot create process in unprivileged user namespace"); + else + throw SysError("cloning builder process"); + } + + readiness.readSide.close(); + if ((flags & CLONE_NEWUSER) != 0) { + /* Initialize the UID/GID mapping of the child process. */ + initializeUserNamespace(pid); + writeFull(readiness.writeSide, (unsigned char*)"go\n", 3); + } + readiness.writeSide.close(); } else #endif { @@ -2013,23 +2057,36 @@ void DerivationGoal::runChild() _writeToStderr = 0; + if (readiness.writeSide > 0) readiness.writeSide.close(); + + if (readiness.readSide > 0) { + /* Wait for the parent process to initialize the UID/GID mapping + of our user namespace. */ + char str[20] = { '\0' }; + readFull(readiness.readSide, (unsigned char*)str, 3); + if (strcmp(str, "go\n") != 0) + throw Error("failed to initialize process in unprivileged user namespace"); + } + restoreAffinity(); commonChildInit(builderOut); #if CHROOT_ENABLED if (useChroot) { - /* Initialise the loopback interface. */ - AutoCloseFD fd(socket(PF_INET, SOCK_DGRAM, IPPROTO_IP)); - if (fd == -1) throw SysError("cannot open IP socket"); + if (!fixedOutput) { + /* Initialise the loopback interface. */ + AutoCloseFD fd(socket(PF_INET, SOCK_DGRAM, IPPROTO_IP)); + if (fd == -1) throw SysError("cannot open IP socket"); - struct ifreq ifr; - strcpy(ifr.ifr_name, "lo"); - ifr.ifr_flags = IFF_UP | IFF_LOOPBACK | IFF_RUNNING; - if (ioctl(fd, SIOCSIFFLAGS, &ifr) == -1) - throw SysError("cannot set loopback interface flags"); + struct ifreq ifr; + strcpy(ifr.ifr_name, "lo"); + ifr.ifr_flags = IFF_UP | IFF_LOOPBACK | IFF_RUNNING; + if (ioctl(fd, SIOCSIFFLAGS, &ifr) == -1) + throw SysError("cannot set loopback interface flags"); - fd.close(); + fd.close(); + } /* Set the hostname etc. to fixed values. */ char hostname[] = "localhost"; @@ -2180,6 +2237,27 @@ void DerivationGoal::runChild() /* Remount root as read-only. */ if (mount("/", "/", 0, MS_BIND | MS_REMOUNT | MS_RDONLY, 0) == -1) throw SysError(format("read-only remount of build root '%1%' failed") % chrootRootDir); + + if (getuid() != 0) { + /* Create a new mount namespace to "lock" previous mounts. + See mount_namespaces(7). */ + auto uid = getuid(); + auto gid = getgid(); + + if (unshare(CLONE_NEWNS | CLONE_NEWUSER) == -1) + throw SysError(format("creating new user and mount namespaces")); + + initializeUserNamespace(getpid(), uid, gid); + + /* Check that mounts within the build environment are "locked" + together and cannot be separated from within the build + environment namespace. Since + umount(2) is documented to fail with EINVAL when attempting + to unmount one of the mounts that are locked together, + check that this is what we get. */ + int ret = umount(tmpDirInSandbox.c_str()); + assert(ret == -1 && errno == EINVAL); + } } #endif @@ -2476,8 +2554,16 @@ void DerivationGoal::registerOutputs() 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) { + if (S_ISDIR(st.st_mode)) + /* Change mode on the directory to allow for + rename(2). */ + chmod(actualPath.c_str(), st.st_mode | 0700); + if (rename(actualPath.c_str(), path.c_str()) == -1) + throw SysError(format("moving build output `%1%' from the chroot to the store") % path); + if (S_ISDIR(st.st_mode) && chmod(path.c_str(), st.st_mode) == -1) + throw SysError(format("restoring permissions on directory `%1%'") % actualPath); + } } if (buildMode != bmCheck) actualPath = path; } @@ -2736,16 +2822,46 @@ void DerivationGoal::deleteTmpDir(bool force) // Change the ownership if clientUid is set. Never change the // ownership or the group to "root" for security reasons. if (settings.clientUid != (uid_t) -1 && settings.clientUid != 0) { - _chown(tmpDir, settings.clientUid, - settings.clientGid != 0 ? settings.clientGid : -1); + uid_t uid = settings.clientUid; + gid_t gid = settings.clientGid != 0 ? settings.clientGid : -1; + bool reown = false; + + /* First remove setuid/setgid bits. */ + secureFilePerms(tmpDir); + + try { + _chown(tmpDir, uid, gid); + + if (getuid() != 0) { + /* If, without being root, the '_chown' call above + succeeded, then it means we have CAP_CHOWN. Retake + ownership of tmpDir itself so it can be renamed + below. */ + reown = true; + } + + } catch (SysError & e) { + /* When running as an unprivileged user and without + CAP_CHOWN, we cannot chown the build tree. Print a + message and keep going. */ + printMsg(lvlInfo, format("cannot change ownership of build directory '%1%': %2%") + % tmpDir % strerror(e.errNo)); + } if (top != tmpDir) { + if (reown) chown(tmpDir.c_str(), getuid(), getgid()); + // Rename tmpDir to its parent, with an intermediate step. string pivot = top + ".pivot"; if (rename(top.c_str(), pivot.c_str()) == -1) throw SysError("pivoting failed build tree"); if (rename((pivot + "/top").c_str(), top.c_str()) == -1) throw SysError("renaming failed build tree"); + + if (reown) + /* Running unprivileged but with CAP_CHOWN. */ + chown(top.c_str(), uid, gid); + rmdir(pivot.c_str()); } } diff --git a/nix/libstore/local-store.cc b/nix/libstore/local-store.cc index 0883a4bbce..83e6c3e16e 100644 --- a/nix/libstore/local-store.cc +++ b/nix/libstore/local-store.cc @@ -1614,11 +1614,19 @@ void LocalStore::createUser(const std::string & userName, uid_t userId) { auto dir = settings.nixStateDir + "/profiles/per-user/" + userName; - createDirs(dir); - if (chmod(dir.c_str(), 0755) == -1) - throw SysError(format("changing permissions of directory '%s'") % dir); - if (chown(dir.c_str(), userId, -1) == -1) - throw SysError(format("changing owner of directory '%s'") % dir); + auto created = createDirs(dir); + if (!created.empty()) { + if (chmod(dir.c_str(), 0755) == -1) + throw SysError(format("changing permissions of directory '%s'") % dir); + + /* The following operation requires CAP_CHOWN or can be handled + manually by a user with CAP_CHOWN. */ + if (chown(dir.c_str(), userId, -1) == -1) { + rmdir(dir.c_str()); + string message = strerror(errno); + printMsg(lvlInfo, format("failed to change owner of directory '%1%' to %2%: %3%") % dir % userId % message); + } + } } -- 2.48.1
guix@HIDDEN, dev@HIDDEN, ludo@HIDDEN, othacehe@HIDDEN, maxim.cournoyer@HIDDEN, zimon.toutoune@HIDDEN, me@HIDDEN, guix-patches@HIDDEN
:bug#75810
; Package guix-patches
.
Full text available.Received: (at 75810) by debbugs.gnu.org; 17 Mar 2025 17:04:51 +0000 From debbugs-submit-bounces <at> debbugs.gnu.org Mon Mar 17 13:04:50 2025 Received: from localhost ([127.0.0.1]:60660 helo=debbugs.gnu.org) by debbugs.gnu.org with esmtp (Exim 4.84_2) (envelope-from <debbugs-submit-bounces <at> debbugs.gnu.org>) id 1tuDtS-0002jT-0l for submit <at> debbugs.gnu.org; Mon, 17 Mar 2025 13:04:50 -0400 Received: from eggs.gnu.org ([2001:470:142:3::10]:56122) by debbugs.gnu.org with esmtps (TLS1.2:ECDHE_RSA_AES_256_GCM_SHA384:256) (Exim 4.84_2) (envelope-from <ludo@HIDDEN>) id 1tuDtM-0002hh-NJ for 75810 <at> debbugs.gnu.org; Mon, 17 Mar 2025 13:04:46 -0400 Received: from fencepost.gnu.org ([2001:470:142:3::e]) by eggs.gnu.org with esmtps (TLS1.2:ECDHE_RSA_AES_256_GCM_SHA384:256) (Exim 4.90_1) (envelope-from <ludo@HIDDEN>) id 1tuDtG-0005Ms-Rm; Mon, 17 Mar 2025 13:04:38 -0400 DKIM-Signature: v=1; a=rsa-sha256; q=dns/txt; c=relaxed/relaxed; d=gnu.org; s=fencepost-gnu-org; h=MIME-Version:References:In-Reply-To:Date:Subject:To: From; bh=wZDaJpSBiec4HWURn73Fvz7bhdz1AmvaDkV9vu9Mxas=; b=gfgYXk+t/QfGuiRKGrVJ yL4G8ETXmaQHj8SbWq6Pg0vt+e55CX4oP9187t+QTZYgy9GBdiRZ/+UcO29toiCThK57+6gHeClAF 5Q5riGt9cso3nFI/HCFlRs7XdHMETuQHQHBYw4SI0Kc9x+m3yiBMP+S35pAd6HPmZ2RZq9AXc1mre Il2LK9IuIL3am3id0qYCabUtB2SCuSQZ5qHLNuaEUZuNjd7wsA6IOfBHyf4T3b4m+x+qumghv+mxu Is37RBFqU2NlQ4n/RghfRijvrk5GyVIi7GyKFJrzAJyJzMo36nX2EEcFskr28A9ckNjz2EREbC1j2 gHltaDvJSSwEKA==; From: =?UTF-8?q?Ludovic=20Court=C3=A8s?= <ludo@HIDDEN> To: 75810 <at> debbugs.gnu.org Subject: [PATCH v6 08/16] daemon: Create /var/guix/profiles/per-user unconditionally. Date: Mon, 17 Mar 2025 18:02:51 +0100 Message-ID: <821f4eee184122c4a0b0f8859e436e742a78e6e0.1742230219.git.ludo@HIDDEN> X-Mailer: git-send-email 2.48.1 In-Reply-To: <cover.1742230219.git.ludo@HIDDEN> References: <cover.1742230219.git.ludo@HIDDEN> MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit X-Spam-Score: -2.3 (--) X-Debbugs-Envelope-To: 75810 Cc: =?UTF-8?q?Ludovic=20Court=C3=A8s?= <ludo@HIDDEN> X-BeenThere: debbugs-submit <at> debbugs.gnu.org X-Mailman-Version: 2.1.18 Precedence: list List-Id: <debbugs-submit.debbugs.gnu.org> List-Unsubscribe: <https://debbugs.gnu.org/cgi-bin/mailman/options/debbugs-submit>, <mailto:debbugs-submit-request <at> debbugs.gnu.org?subject=unsubscribe> List-Archive: <https://debbugs.gnu.org/cgi-bin/mailman/private/debbugs-submit/> List-Post: <mailto:debbugs-submit <at> debbugs.gnu.org> List-Help: <mailto:debbugs-submit-request <at> debbugs.gnu.org?subject=help> List-Subscribe: <https://debbugs.gnu.org/cgi-bin/mailman/listinfo/debbugs-submit>, <mailto:debbugs-submit-request <at> debbugs.gnu.org?subject=subscribe> Errors-To: debbugs-submit-bounces <at> debbugs.gnu.org Sender: "Debbugs-submit" <debbugs-submit-bounces <at> debbugs.gnu.org> X-Spam-Score: -3.3 (---) * nix/libstore/local-store.cc (LocalStore::LocalStore): Create ‘perUserDir’ unconditionally. Change-Id: I5188320f9630a81d16f79212d0fffabd55d94abe --- nix/libstore/local-store.cc | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/nix/libstore/local-store.cc b/nix/libstore/local-store.cc index 83e6c3e16e..f6540c2117 100644 --- a/nix/libstore/local-store.cc +++ b/nix/libstore/local-store.cc @@ -79,12 +79,12 @@ LocalStore::LocalStore(bool reserveSpace) createSymlink(profilesDir, gcRootsDir + "/profiles"); } - /* Optionally, create directories and set permissions for a - multi-user install. */ + Path perUserDir = profilesDir + "/per-user"; + createDirs(perUserDir); + + /* Optionally, set permissions for a multi-user install. */ if (getuid() == 0 && settings.buildUsersGroup != "") { - Path perUserDir = profilesDir + "/per-user"; - createDirs(perUserDir); if (chmod(perUserDir.c_str(), 0755) == -1) throw SysError(format("could not set permissions on '%1%' to 755") % perUserDir); -- 2.48.1
guix-patches@HIDDEN
:bug#75810
; Package guix-patches
.
Full text available.Received: (at 75810) by debbugs.gnu.org; 17 Mar 2025 17:04:16 +0000 From debbugs-submit-bounces <at> debbugs.gnu.org Mon Mar 17 13:04:15 2025 Received: from localhost ([127.0.0.1]:60650 helo=debbugs.gnu.org) by debbugs.gnu.org with esmtp (Exim 4.84_2) (envelope-from <debbugs-submit-bounces <at> debbugs.gnu.org>) id 1tuDsr-0002ei-FL for submit <at> debbugs.gnu.org; Mon, 17 Mar 2025 13:04:15 -0400 Received: from eggs.gnu.org ([2001:470:142:3::10]:34958) by debbugs.gnu.org with esmtps (TLS1.2:ECDHE_RSA_AES_256_GCM_SHA384:256) (Exim 4.84_2) (envelope-from <ludo@HIDDEN>) id 1tuDsd-0002am-4K for 75810 <at> debbugs.gnu.org; Mon, 17 Mar 2025 13:04:02 -0400 Received: from fencepost.gnu.org ([2001:470:142:3::e]) by eggs.gnu.org with esmtps (TLS1.2:ECDHE_RSA_AES_256_GCM_SHA384:256) (Exim 4.90_1) (envelope-from <ludo@HIDDEN>) id 1tuDsS-00056P-W8; Mon, 17 Mar 2025 13:03:49 -0400 DKIM-Signature: v=1; a=rsa-sha256; q=dns/txt; c=relaxed/relaxed; d=gnu.org; s=fencepost-gnu-org; h=MIME-Version:References:In-Reply-To:Date:Subject:To: From; bh=ozQM+lYqSSPDiTg6Dp/w4oPIGKDs4CrGaOeKp99rZWg=; b=ezBIk7WDTVrD0bQGziaO u3xmUfLca4YXEfQwNelHc4W2vfiKYrVep9UgCZ4G1oi54nktgAIpOr1rbk9x4LTkc+g9DToHBzy3T juWnOvovzCqI42yRzZl4f698SqLe0xH/jZRor1PNpMpLXkWowz2YP6hr5UTppjvAc/Eb5YMBdaH0C 2AgkU6jRKwxk5TVl13g//AJ5VzAR2EQwLXJYw8koCLvGvYyqLcQTGDzOzmABLX3+ouVPn9MdATLAq ycJ/XbJBujCmdPe0+PKVzVTMjBQP+497SCxJojz0Lv6THD13Al2zkdt2SBIs4hxNfRxgUD60k5WKp 6S5+9CAYD/CHdg==; From: =?UTF-8?q?Ludovic=20Court=C3=A8s?= <ludo@HIDDEN> To: 75810 <at> debbugs.gnu.org Subject: [PATCH v6 05/16] daemon: Remount inputs as read-only. Date: Mon, 17 Mar 2025 18:02:48 +0100 Message-ID: <7bd937c5bb4882476092162aaf7d2dcd6080a9e8.1742230219.git.ludo@HIDDEN> X-Mailer: git-send-email 2.48.1 In-Reply-To: <cover.1742230219.git.ludo@HIDDEN> References: <cover.1742230219.git.ludo@HIDDEN> MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit X-Spam-Score: -0.8 (/) X-Debbugs-Envelope-To: 75810 Cc: =?UTF-8?q?Ludovic=20Court=C3=A8s?= <ludo@HIDDEN>, Reepca Russelstein <reepca@HIDDEN> X-BeenThere: debbugs-submit <at> debbugs.gnu.org X-Mailman-Version: 2.1.18 Precedence: list List-Id: <debbugs-submit.debbugs.gnu.org> List-Unsubscribe: <https://debbugs.gnu.org/cgi-bin/mailman/options/debbugs-submit>, <mailto:debbugs-submit-request <at> debbugs.gnu.org?subject=unsubscribe> List-Archive: <https://debbugs.gnu.org/cgi-bin/mailman/private/debbugs-submit/> List-Post: <mailto:debbugs-submit <at> debbugs.gnu.org> List-Help: <mailto:debbugs-submit-request <at> debbugs.gnu.org?subject=help> List-Subscribe: <https://debbugs.gnu.org/cgi-bin/mailman/listinfo/debbugs-submit>, <mailto:debbugs-submit-request <at> debbugs.gnu.org?subject=subscribe> Errors-To: debbugs-submit-bounces <at> debbugs.gnu.org Sender: "Debbugs-submit" <debbugs-submit-bounces <at> debbugs.gnu.org> X-Spam-Score: -1.8 (-) * nix/libstore/build.cc (DerivationGoal::runChild): Remount ‘target’ as read-only. Reported-by: Reepca Russelstein <reepca@HIDDEN> Change-Id: Ib7201bcf4363be566f205d23d17fe2f55d3ad666 --- nix/libstore/build.cc | 7 +++++++ 1 file changed, 7 insertions(+) diff --git a/nix/libstore/build.cc b/nix/libstore/build.cc index 193b279b88..3861a1ffd9 100644 --- a/nix/libstore/build.cc +++ b/nix/libstore/build.cc @@ -2107,8 +2107,15 @@ void DerivationGoal::runChild() createDirs(dirOf(target)); writeFile(target, ""); } + + /* Extra flags passed with MS_BIND are ignored, hence the + extra MS_REMOUNT. */ if (mount(source.c_str(), target.c_str(), "", MS_BIND, 0) == -1) throw SysError(format("bind mount from `%1%' to `%2%' failed") % source % target); + if (source.compare(0, settings.nixStore.length(), settings.nixStore) == 0) { + if (mount(source.c_str(), target.c_str(), "", MS_BIND | MS_REMOUNT | MS_RDONLY, 0) == -1) + throw SysError(format("read-only remount of `%1%' failed") % target); + } } /* Bind a new instance of procfs on /proc to reflect our -- 2.48.1
guix-patches@HIDDEN
:bug#75810
; Package guix-patches
.
Full text available.Received: (at 75810) by debbugs.gnu.org; 17 Mar 2025 17:04:14 +0000 From debbugs-submit-bounces <at> debbugs.gnu.org Mon Mar 17 13:04:13 2025 Received: from localhost ([127.0.0.1]:60648 helo=debbugs.gnu.org) by debbugs.gnu.org with esmtp (Exim 4.84_2) (envelope-from <debbugs-submit-bounces <at> debbugs.gnu.org>) id 1tuDsp-0002eL-Tq for submit <at> debbugs.gnu.org; Mon, 17 Mar 2025 13:04:13 -0400 Received: from eggs.gnu.org ([2001:470:142:3::10]:34942) by debbugs.gnu.org with esmtps (TLS1.2:ECDHE_RSA_AES_256_GCM_SHA384:256) (Exim 4.84_2) (envelope-from <ludo@HIDDEN>) id 1tuDsb-0002aO-Cu for 75810 <at> debbugs.gnu.org; Mon, 17 Mar 2025 13:03:59 -0400 Received: from fencepost.gnu.org ([2001:470:142:3::e]) by eggs.gnu.org with esmtps (TLS1.2:ECDHE_RSA_AES_256_GCM_SHA384:256) (Exim 4.90_1) (envelope-from <ludo@HIDDEN>) id 1tuDsV-00057a-4w; Mon, 17 Mar 2025 13:03:51 -0400 DKIM-Signature: v=1; a=rsa-sha256; q=dns/txt; c=relaxed/relaxed; d=gnu.org; s=fencepost-gnu-org; h=MIME-Version:References:In-Reply-To:Date:Subject:To: From; bh=3sOVW5n0d1cSpQd8PLRrsmflCadSWuH5XwPCIe/iTyM=; b=DQ54cPzuL/mSP1qf4akB qryPUChROs9LsSf6L0HjxSTMFy2e2XtMHrTs4/51jMpyt2nB/LJf3SN2UtEfiZS1fsSeIpKEakTcs p2uUHyga9KK0AdBmb7ubLWMD0dQFeyOdxwStuarfiq37UWdd0rUh9+eKlILtZd6fwDYy7ggrG+azu gZPvo2siO9d0Hs27mFZm73z8TJeGPzLhiC2xQrm+Go+iwBu1cpCLF/mdlSYxnIOgYN9E6Z7uuluoe r7X9FmKsRu/QOsxYxfuqJuedmIMzHHDmWi53nTf8w8ugmD048JD0wPKkCmK5hx6IXLKRYN7t+DmJS fXdkCGj663DujA==; From: =?UTF-8?q?Ludovic=20Court=C3=A8s?= <ludo@HIDDEN> To: 75810 <at> debbugs.gnu.org Subject: [PATCH v6 06/16] daemon: Remount root directory as read-only. Date: Mon, 17 Mar 2025 18:02:49 +0100 Message-ID: <a308fcd418a6921ebfb3c1140f0353649d9698d1.1742230219.git.ludo@HIDDEN> X-Mailer: git-send-email 2.48.1 In-Reply-To: <cover.1742230219.git.ludo@HIDDEN> References: <cover.1742230219.git.ludo@HIDDEN> MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit X-Spam-Score: -2.3 (--) X-Debbugs-Envelope-To: 75810 Cc: =?UTF-8?q?Ludovic=20Court=C3=A8s?= <ludo@HIDDEN> X-BeenThere: debbugs-submit <at> debbugs.gnu.org X-Mailman-Version: 2.1.18 Precedence: list List-Id: <debbugs-submit.debbugs.gnu.org> List-Unsubscribe: <https://debbugs.gnu.org/cgi-bin/mailman/options/debbugs-submit>, <mailto:debbugs-submit-request <at> debbugs.gnu.org?subject=unsubscribe> List-Archive: <https://debbugs.gnu.org/cgi-bin/mailman/private/debbugs-submit/> List-Post: <mailto:debbugs-submit <at> debbugs.gnu.org> List-Help: <mailto:debbugs-submit-request <at> debbugs.gnu.org?subject=help> List-Subscribe: <https://debbugs.gnu.org/cgi-bin/mailman/listinfo/debbugs-submit>, <mailto:debbugs-submit-request <at> debbugs.gnu.org?subject=subscribe> Errors-To: debbugs-submit-bounces <at> debbugs.gnu.org Sender: "Debbugs-submit" <debbugs-submit-bounces <at> debbugs.gnu.org> X-Spam-Score: -3.3 (---) * nix/libstore/build.cc (DerivationGoal::runChild): Bind-mount the store and /tmp under ‘chrootRootDir’ to themselves as read-write. Remount / as read-only. Change-Id: I79565094c8ec8448401897c720aad75304fd1948 --- nix/libstore/build.cc | 16 ++++++++++++++++ 1 file changed, 16 insertions(+) diff --git a/nix/libstore/build.cc b/nix/libstore/build.cc index 3861a1ffd9..c8b778362a 100644 --- a/nix/libstore/build.cc +++ b/nix/libstore/build.cc @@ -2091,6 +2091,18 @@ void DerivationGoal::runChild() for (auto & i : ss) dirsInChroot[i] = i; + /* Make new mounts for the store and for /tmp. That way, when + 'chrootRootDir' is made read-only below, these two mounts will + remain writable (the store needs to be writable so derivation + outputs can be written to it, and /tmp is writable by + convention). */ + auto chrootStoreDir = chrootRootDir + settings.nixStore; + if (mount(chrootStoreDir.c_str(), chrootStoreDir.c_str(), 0, MS_BIND, 0) == -1) + throw SysError(format("read-write mount of store '%1%' failed") % chrootStoreDir); + auto chrootTmpDir = chrootRootDir + "/tmp"; + if (mount(chrootTmpDir.c_str(), chrootTmpDir.c_str(), 0, MS_BIND, 0) == -1) + throw SysError(format("read-write mount of temporary directory '%1%' failed") % chrootTmpDir); + /* Bind-mount all the directories from the "host" filesystem that we want in the chroot environment. */ @@ -2164,6 +2176,10 @@ void DerivationGoal::runChild() if (rmdir("real-root") == -1) throw SysError("cannot remove real-root directory"); + + /* Remount root as read-only. */ + if (mount("/", "/", 0, MS_BIND | MS_REMOUNT | MS_RDONLY, 0) == -1) + throw SysError(format("read-only remount of build root '%1%' failed") % chrootRootDir); } #endif -- 2.48.1
guix-patches@HIDDEN
:bug#75810
; Package guix-patches
.
Full text available.Received: (at 75810) by debbugs.gnu.org; 17 Mar 2025 17:04:12 +0000 From debbugs-submit-bounces <at> debbugs.gnu.org Mon Mar 17 13:04:12 2025 Received: from localhost ([127.0.0.1]:60646 helo=debbugs.gnu.org) by debbugs.gnu.org with esmtp (Exim 4.84_2) (envelope-from <debbugs-submit-bounces <at> debbugs.gnu.org>) id 1tuDso-0002e7-T3 for submit <at> debbugs.gnu.org; Mon, 17 Mar 2025 13:04:11 -0400 Received: from eggs.gnu.org ([2001:470:142:3::10]:42128) by debbugs.gnu.org with esmtps (TLS1.2:ECDHE_RSA_AES_256_GCM_SHA384:256) (Exim 4.84_2) (envelope-from <ludo@HIDDEN>) id 1tuDsM-0002XX-9V for 75810 <at> debbugs.gnu.org; Mon, 17 Mar 2025 13:03:44 -0400 Received: from fencepost.gnu.org ([2001:470:142:3::e]) by eggs.gnu.org with esmtps (TLS1.2:ECDHE_RSA_AES_256_GCM_SHA384:256) (Exim 4.90_1) (envelope-from <ludo@HIDDEN>) id 1tuDsE-000543-Ir; Mon, 17 Mar 2025 13:03:35 -0400 DKIM-Signature: v=1; a=rsa-sha256; q=dns/txt; c=relaxed/relaxed; d=gnu.org; s=fencepost-gnu-org; h=MIME-Version:References:In-Reply-To:Date:Subject:To: From; bh=OHeVSHlKl++yMNnhWaubdTXXSn3UUkG8AbIkWMisgq8=; b=P8ET9BnuSV8myBnnmarl NqHO1QvQ4caTptaIUVmcZi466TVUunrpE5JUNOIkmnw0R3by5q9mVc84oszm1K3+mZ+Vc3LK5DVGg GyeC7lp9eId3uHuaDLeJfMdVtzy2gFw+BXv8/hS7nCupQ2im2LFLWQ/TLLb4timTEXQHqueWiQIom qdH7wCdOmo/pItCFEn5SHLsIQmx7eoqjwru2JQ+u0fIfzEo39eaOLdNXww+uz31kBcJ5xw7GXtVsX zEWeLMeoBLkC2b7nEr7FSysgU8rw0UsFxCK8bKp2reIrpB9xqm96FD45yA8CIRlLnqh6cqxNukF4J 5XeeYiNXrqdYzg==; From: =?UTF-8?q?Ludovic=20Court=C3=A8s?= <ludo@HIDDEN> To: 75810 <at> debbugs.gnu.org Subject: [PATCH v6 04/16] daemon: Bind-mount all the inputs, not just directories. Date: Mon, 17 Mar 2025 18:02:47 +0100 Message-ID: <4744bfb6ab859af7e64a387d29ad6c99cb2a7aac.1742230219.git.ludo@HIDDEN> X-Mailer: git-send-email 2.48.1 In-Reply-To: <cover.1742230219.git.ludo@HIDDEN> References: <cover.1742230219.git.ludo@HIDDEN> MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit X-Spam-Score: -0.8 (/) X-Debbugs-Envelope-To: 75810 Cc: =?UTF-8?q?Ludovic=20Court=C3=A8s?= <ludo@HIDDEN>, Reepca Russelstein <reepca@HIDDEN> X-BeenThere: debbugs-submit <at> debbugs.gnu.org X-Mailman-Version: 2.1.18 Precedence: list List-Id: <debbugs-submit.debbugs.gnu.org> List-Unsubscribe: <https://debbugs.gnu.org/cgi-bin/mailman/options/debbugs-submit>, <mailto:debbugs-submit-request <at> debbugs.gnu.org?subject=unsubscribe> List-Archive: <https://debbugs.gnu.org/cgi-bin/mailman/private/debbugs-submit/> List-Post: <mailto:debbugs-submit <at> debbugs.gnu.org> List-Help: <mailto:debbugs-submit-request <at> debbugs.gnu.org?subject=help> List-Subscribe: <https://debbugs.gnu.org/cgi-bin/mailman/listinfo/debbugs-submit>, <mailto:debbugs-submit-request <at> debbugs.gnu.org?subject=subscribe> Errors-To: debbugs-submit-bounces <at> debbugs.gnu.org Sender: "Debbugs-submit" <debbugs-submit-bounces <at> debbugs.gnu.org> X-Spam-Score: -1.8 (-) * nix/libstore/build.cc (DerivationGoal::startBuilder): Add all of ‘inputPaths’ to ‘dirsInChroot’ instead of hard-linking regular files. Special-case symlinks. (DerivationGoal)[regularInputPaths]: Remove. Reported-by: Reepca Russelstein <reepca@HIDDEN> Change-Id: I070987f92d73f187f7826a975bee9ee309d67f56 --- nix/libstore/build.cc | 39 ++++++++++++++------------------------- 1 file changed, 14 insertions(+), 25 deletions(-) diff --git a/nix/libstore/build.cc b/nix/libstore/build.cc index 8ca5e5b732..193b279b88 100644 --- a/nix/libstore/build.cc +++ b/nix/libstore/build.cc @@ -659,9 +659,6 @@ private: /* RAII object to delete the chroot directory. */ std::shared_ptr<AutoDelete> autoDelChroot; - /* All inputs that are regular files. */ - PathSet regularInputPaths; - /* Whether this is a fixed-output derivation. */ bool fixedOutput; @@ -1850,9 +1847,7 @@ void DerivationGoal::startBuilder() /* Make the closure of the inputs available in the chroot, rather than the whole store. This prevents any access - to undeclared dependencies. Directories are bind-mounted, - while other inputs are hard-linked (since only directories - can be bind-mounted). !!! As an extra security + to undeclared dependencies. !!! As an extra security precaution, make the fake store only writable by the build user. */ Path chrootStoreDir = chrootRootDir + settings.nixStore; @@ -1863,28 +1858,22 @@ void DerivationGoal::startBuilder() throw SysError(format("cannot change ownership of ‘%1%’") % chrootStoreDir); foreach (PathSet::iterator, i, inputPaths) { - struct stat st; + struct stat st; if (lstat(i->c_str(), &st)) throw SysError(format("getting attributes of path `%1%'") % *i); - if (S_ISDIR(st.st_mode)) - dirsInChroot[*i] = *i; - else { - Path p = chrootRootDir + *i; - if (link(i->c_str(), p.c_str()) == -1) { - /* Hard-linking fails if we exceed the maximum - link count on a file (e.g. 32000 of ext3), - which is quite possible after a `nix-store - --optimise'. */ - if (errno != EMLINK) - throw SysError(format("linking `%1%' to `%2%'") % p % *i); - StringSink sink; - dumpPath(*i, sink); - StringSource source(sink.s); - restorePath(p, source); - } - regularInputPaths.insert(*i); - } + if (S_ISLNK(st.st_mode)) { + /* Since bind-mounts follow symlinks, thus representing their + target and not the symlink itself, special-case + symlinks. XXX: When running unprivileged, TARGET can be + deleted by the build process. Use 'open_tree' & co. when + it's more widely available. */ + Path target = chrootRootDir + *i; + if (symlink(readLink(*i).c_str(), target.c_str()) == -1) + throw SysError(format("failed to create symlink '%1%' to '%2%'") % target % readLink(*i)); + } + else + dirsInChroot[*i] = *i; } /* If we're repairing, checking or rebuilding part of a -- 2.48.1
guix-patches@HIDDEN
:bug#75810
; Package guix-patches
.
Full text available.Received: (at 75810) by debbugs.gnu.org; 17 Mar 2025 17:04:10 +0000 From debbugs-submit-bounces <at> debbugs.gnu.org Mon Mar 17 13:04:10 2025 Received: from localhost ([127.0.0.1]:60644 helo=debbugs.gnu.org) by debbugs.gnu.org with esmtp (Exim 4.84_2) (envelope-from <debbugs-submit-bounces <at> debbugs.gnu.org>) id 1tuDso-0002dx-6E for submit <at> debbugs.gnu.org; Mon, 17 Mar 2025 13:04:10 -0400 Received: from eggs.gnu.org ([2001:470:142:3::10]:42112) by debbugs.gnu.org with esmtps (TLS1.2:ECDHE_RSA_AES_256_GCM_SHA384:256) (Exim 4.84_2) (envelope-from <ludo@HIDDEN>) id 1tuDsH-0002Wu-AS for 75810 <at> debbugs.gnu.org; Mon, 17 Mar 2025 13:03:43 -0400 Received: from fencepost.gnu.org ([2001:470:142:3::e]) by eggs.gnu.org with esmtps (TLS1.2:ECDHE_RSA_AES_256_GCM_SHA384:256) (Exim 4.90_1) (envelope-from <ludo@HIDDEN>) id 1tuDsA-00052t-OQ; Mon, 17 Mar 2025 13:03:30 -0400 DKIM-Signature: v=1; a=rsa-sha256; q=dns/txt; c=relaxed/relaxed; d=gnu.org; s=fencepost-gnu-org; h=MIME-Version:References:In-Reply-To:Date:Subject:To: From; bh=fUCaHHG/eO75rZDRlbk9XFL7p37y9SICE8zVkSS6pAE=; b=cRR4pe3g4WK250IKJKcM 9pQ5FLJluEu/eCuBg4b2XxHeM3JUwkZWQhbvfA3oMViouJ7w8YDvm5/aj4hBQDjl/xHc2p0C0q6TP NjKKvvJbB6z1tgTWqYNTeJlu+3b/j1ZOPyLvLtGjITH60wjW9XILUieDVAi+zoZwEsB81AtTCN7gy 2nrTIi67ELAA6P+JjUw7mulrbrDUuScadiNkmrBueouto06N2NLfZWaNy/yuIb3poJmZjIOU5hjaO EP2KyJAKmH0MY4N4uHFR4GLJxJspKPJYYRTRE7KLVVACi3NnuaY+/l6iop8LtzevE5RfDEvQY/2fb Pf98ldlwGP5YKg==; From: =?UTF-8?q?Ludovic=20Court=C3=A8s?= <ludo@HIDDEN> To: 75810 <at> debbugs.gnu.org Subject: [PATCH v6 02/16] daemon: Close the read end of the logging pipe. Date: Mon, 17 Mar 2025 18:02:45 +0100 Message-ID: <b4f08920874bad9386a1bdb390859c3c78be5aa1.1742230219.git.ludo@HIDDEN> X-Mailer: git-send-email 2.48.1 In-Reply-To: <cover.1742230219.git.ludo@HIDDEN> References: <cover.1742230219.git.ludo@HIDDEN> MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit X-Spam-Score: -0.8 (/) X-Debbugs-Envelope-To: 75810 Cc: =?UTF-8?q?Ludovic=20Court=C3=A8s?= <ludo@HIDDEN>, Reepca Russelstein <reepca@HIDDEN> X-BeenThere: debbugs-submit <at> debbugs.gnu.org X-Mailman-Version: 2.1.18 Precedence: list List-Id: <debbugs-submit.debbugs.gnu.org> List-Unsubscribe: <https://debbugs.gnu.org/cgi-bin/mailman/options/debbugs-submit>, <mailto:debbugs-submit-request <at> debbugs.gnu.org?subject=unsubscribe> List-Archive: <https://debbugs.gnu.org/cgi-bin/mailman/private/debbugs-submit/> List-Post: <mailto:debbugs-submit <at> debbugs.gnu.org> List-Help: <mailto:debbugs-submit-request <at> debbugs.gnu.org?subject=help> List-Subscribe: <https://debbugs.gnu.org/cgi-bin/mailman/listinfo/debbugs-submit>, <mailto:debbugs-submit-request <at> debbugs.gnu.org?subject=subscribe> Errors-To: debbugs-submit-bounces <at> debbugs.gnu.org Sender: "Debbugs-submit" <debbugs-submit-bounces <at> debbugs.gnu.org> X-Spam-Score: -1.8 (-) * nix/libutil/util.cc (commonChildInit): Close ‘logPipe.readSide’. Reported-by: Reepca Russelstein <reepca@HIDDEN> Change-Id: Ia9e48d1afb85d7af52770e016f2b6832792044dd --- nix/libutil/util.cc | 3 +++ 1 file changed, 3 insertions(+) diff --git a/nix/libutil/util.cc b/nix/libutil/util.cc index eb2d16e1cc..56f116046c 100644 --- a/nix/libutil/util.cc +++ b/nix/libutil/util.cc @@ -1279,6 +1279,9 @@ void commonChildInit(Pipe & logPipe) if (setsid() == -1) throw SysError(format("creating a new session")); + /* Close the read end so only the parent holds a reference to it. */ + logPipe.readSide.close(); + /* Dup the write side of the logger pipe into stderr. */ if (dup2(logPipe.writeSide, STDERR_FILENO) == -1) throw SysError("cannot pipe standard error into log file"); -- 2.48.1
guix-patches@HIDDEN
:bug#75810
; Package guix-patches
.
Full text available.Received: (at 75810) by debbugs.gnu.org; 17 Mar 2025 17:04:10 +0000 From debbugs-submit-bounces <at> debbugs.gnu.org Mon Mar 17 13:04:10 2025 Received: from localhost ([127.0.0.1]:60642 helo=debbugs.gnu.org) by debbugs.gnu.org with esmtp (Exim 4.84_2) (envelope-from <debbugs-submit-bounces <at> debbugs.gnu.org>) id 1tuDsm-0002di-VK for submit <at> debbugs.gnu.org; Mon, 17 Mar 2025 13:04:09 -0400 Received: from eggs.gnu.org ([2001:470:142:3::10]:42114) by debbugs.gnu.org with esmtps (TLS1.2:ECDHE_RSA_AES_256_GCM_SHA384:256) (Exim 4.84_2) (envelope-from <ludo@HIDDEN>) id 1tuDsJ-0002Wy-DO for 75810 <at> debbugs.gnu.org; Mon, 17 Mar 2025 13:03:43 -0400 Received: from fencepost.gnu.org ([2001:470:142:3::e]) by eggs.gnu.org with esmtps (TLS1.2:ECDHE_RSA_AES_256_GCM_SHA384:256) (Exim 4.90_1) (envelope-from <ludo@HIDDEN>) id 1tuDsC-00053A-T7; Mon, 17 Mar 2025 13:03:33 -0400 DKIM-Signature: v=1; a=rsa-sha256; q=dns/txt; c=relaxed/relaxed; d=gnu.org; s=fencepost-gnu-org; h=MIME-Version:References:In-Reply-To:Date:Subject:To: From; bh=5fbggu8STjwEXFRRV3Gq/UXyTgxUmf6fh1UKO8gjNXs=; b=KEyusKSTpns+y0uK7zkb SGlGL68UI/Zccd8yBo2zuzubOv6wDUZvPNDSiaLxTib6cK0cr18WFjp0UbPh2F8sZDflrn4qvwpG+ tPrg6rbjXG6icAqpFEncmRjL2L1FSiLaEzgo6tVd3HLZn76i1yREybpNMQB4nWqt2EmV7NsYVkR45 4te4oedE/KQeP0gg0e7w0Cd9kISgFtL9OBq1XZjecy+VAOI/ylTU0FyWrWc0llJ2JEnT2ii/nod7+ u8Zsyg+I7MQ/pAkClHaGZKMf2a8HNgIjEnh2b0K1dqz32I8Jmx1JePf6jtrglf21uvziiIsUAsgSN iRTnhaf2oD+3AA==; From: =?UTF-8?q?Ludovic=20Court=C3=A8s?= <ludo@HIDDEN> To: 75810 <at> debbugs.gnu.org Subject: [PATCH v6 03/16] daemon: Bind-mount /etc/nsswitch.conf & co. only if it exists. Date: Mon, 17 Mar 2025 18:02:46 +0100 Message-ID: <2818f5c7b1eaa746d3981d9fcee48aaa35b57263.1742230219.git.ludo@HIDDEN> X-Mailer: git-send-email 2.48.1 In-Reply-To: <cover.1742230219.git.ludo@HIDDEN> References: <cover.1742230219.git.ludo@HIDDEN> MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit X-Spam-Score: -2.3 (--) X-Debbugs-Envelope-To: 75810 Cc: =?UTF-8?q?Ludovic=20Court=C3=A8s?= <ludo@HIDDEN> X-BeenThere: debbugs-submit <at> debbugs.gnu.org X-Mailman-Version: 2.1.18 Precedence: list List-Id: <debbugs-submit.debbugs.gnu.org> List-Unsubscribe: <https://debbugs.gnu.org/cgi-bin/mailman/options/debbugs-submit>, <mailto:debbugs-submit-request <at> debbugs.gnu.org?subject=unsubscribe> List-Archive: <https://debbugs.gnu.org/cgi-bin/mailman/private/debbugs-submit/> List-Post: <mailto:debbugs-submit <at> debbugs.gnu.org> List-Help: <mailto:debbugs-submit-request <at> debbugs.gnu.org?subject=help> List-Subscribe: <https://debbugs.gnu.org/cgi-bin/mailman/listinfo/debbugs-submit>, <mailto:debbugs-submit-request <at> debbugs.gnu.org?subject=subscribe> Errors-To: debbugs-submit-bounces <at> debbugs.gnu.org Sender: "Debbugs-submit" <debbugs-submit-bounces <at> debbugs.gnu.org> X-Spam-Score: -3.3 (---) Those files may be missing in some contexts, for instance within the build environment. * nix/libstore/build.cc (DerivationGoal::runChild): Add /etc/resolv.conf and related files to ‘ss’ only if they exist. Change-Id: Ie19664a86c8101a1dc82cf39ad4b7abb10f8250a --- nix/libstore/build.cc | 9 +++++---- 1 file changed, 5 insertions(+), 4 deletions(-) diff --git a/nix/libstore/build.cc b/nix/libstore/build.cc index edd01bab34..8ca5e5b732 100644 --- a/nix/libstore/build.cc +++ b/nix/libstore/build.cc @@ -2093,10 +2093,11 @@ void DerivationGoal::runChild() network, so give them access to /etc/resolv.conf and so on. */ if (fixedOutput) { - ss.push_back("/etc/resolv.conf"); - ss.push_back("/etc/nsswitch.conf"); - ss.push_back("/etc/services"); - ss.push_back("/etc/hosts"); + auto files = { "/etc/resolv.conf", "/etc/nsswitch.conf", + "/etc/services", "/etc/hosts" }; + for (auto & file: files) { + if (pathExists(file)) ss.push_back(file); + } } for (auto & i : ss) dirsInChroot[i] = i; -- 2.48.1
guix-patches@HIDDEN
:bug#75810
; Package guix-patches
.
Full text available.Received: (at 75810) by debbugs.gnu.org; 17 Mar 2025 17:03:54 +0000 From debbugs-submit-bounces <at> debbugs.gnu.org Mon Mar 17 13:03:53 2025 Received: from localhost ([127.0.0.1]:60634 helo=debbugs.gnu.org) by debbugs.gnu.org with esmtp (Exim 4.84_2) (envelope-from <debbugs-submit-bounces <at> debbugs.gnu.org>) id 1tuDsR-0002Ze-Dg for submit <at> debbugs.gnu.org; Mon, 17 Mar 2025 13:03:53 -0400 Received: from eggs.gnu.org ([2001:470:142:3::10]:42100) by debbugs.gnu.org with esmtps (TLS1.2:ECDHE_RSA_AES_256_GCM_SHA384:256) (Exim 4.84_2) (envelope-from <ludo@HIDDEN>) id 1tuDsH-0002Wt-3s for 75810 <at> debbugs.gnu.org; Mon, 17 Mar 2025 13:03:40 -0400 Received: from fencepost.gnu.org ([2001:470:142:3::e]) by eggs.gnu.org with esmtps (TLS1.2:ECDHE_RSA_AES_256_GCM_SHA384:256) (Exim 4.90_1) (envelope-from <ludo@HIDDEN>) id 1tuDs8-00052T-BH; Mon, 17 Mar 2025 13:03:28 -0400 DKIM-Signature: v=1; a=rsa-sha256; q=dns/txt; c=relaxed/relaxed; d=gnu.org; s=fencepost-gnu-org; h=MIME-Version:Date:Subject:To:From:in-reply-to: references; bh=w34Dg0lx8HR0/NDPhk/qpYHbFLdvAG5Ej+OMGuq/kXU=; b=UdyILmrQjrY9JN v7apXpPLIqXgcudI3qOZVguDBwouAukds4wvFcnkxoIB2Mbot+KHybNcL0bSge5B7IbUgvRMwE7+Z JQ3Ft+UhMgwxJsZsmxDXtDL5vIBSTfqr8hzLob09nBRHya4v5VsQRj9jvhlB7vwizg3RYbdOvBC84 sDHQ+iNwuNvRrbiivFQcLVWOo43zcRXkYV/Vzf8JIWSSx7an42ydNz8MKM01RC+6btMmYfV46cu/y g/WqTjl0nsbZfpdJtGsdHCmVY542sw1ECqN+fUQ2tm51YT7TlUsRYXQHhaF6h3gHl8ybWUOcx5npi 07gL5xfP/3FCL7s+990Q==; From: =?UTF-8?q?Ludovic=20Court=C3=A8s?= <ludo@HIDDEN> To: 75810 <at> debbugs.gnu.org Subject: [PATCH v6 00/16] Rootless guix-daemon Date: Mon, 17 Mar 2025 18:02:43 +0100 Message-ID: <cover.1742230219.git.ludo@HIDDEN> X-Mailer: git-send-email 2.48.1 MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit X-Spam-Score: -2.3 (--) X-Debbugs-Envelope-To: 75810 Cc: =?UTF-8?q?Ludovic=20Court=C3=A8s?= <ludo@HIDDEN>, Reepca Russelstein <reepca@HIDDEN> X-BeenThere: debbugs-submit <at> debbugs.gnu.org X-Mailman-Version: 2.1.18 Precedence: list List-Id: <debbugs-submit.debbugs.gnu.org> List-Unsubscribe: <https://debbugs.gnu.org/cgi-bin/mailman/options/debbugs-submit>, <mailto:debbugs-submit-request <at> debbugs.gnu.org?subject=unsubscribe> List-Archive: <https://debbugs.gnu.org/cgi-bin/mailman/private/debbugs-submit/> List-Post: <mailto:debbugs-submit <at> debbugs.gnu.org> List-Help: <mailto:debbugs-submit-request <at> debbugs.gnu.org?subject=help> List-Subscribe: <https://debbugs.gnu.org/cgi-bin/mailman/listinfo/debbugs-submit>, <mailto:debbugs-submit-request <at> debbugs.gnu.org?subject=subscribe> Errors-To: debbugs-submit-bounces <at> debbugs.gnu.org Sender: "Debbugs-submit" <debbugs-submit-bounces <at> debbugs.gnu.org> X-Spam-Score: -1.0 (-) Hello, This new version addresses Reepca’s latest comments¹: • Close the read end of ‘logPipe’ in ‘commonChildInit’. • Explicitly close the ‘readiness’ pipe. • Fix ‘--disable-chroot’ warning in the manual that was misleading. • Have ‘test-env’ check whether user namespaces are supported at all, which fixes non-Linux support (where it would previously fail to pass ‘--disable-chroot’.) • Change ‘unprivileged-user-namespace-supported?’ similarly. • Fix “build root cannot be made world-readable” test, which could not possibly fail and was exposing users unnecessarily. • Change ‘guix-install.sh’ on systemd machines: warn when unprivileged user namespaces are disabled, attempt to enable them, and error out if we failed to enable them. Hopefully I didn’t forget anything. I checked that the “debian-install” and “guix-daemon” system tests still pass. Thanks, Ludo’. ¹ https://issues.guix.gnu.org/75810#91 Ludovic Courtès (16): daemon: Use ‘close_range’ where available. daemon: Close the read end of the logging pipe. daemon: Bind-mount /etc/nsswitch.conf & co. only if it exists. daemon: Bind-mount all the inputs, not just directories. daemon: Remount inputs as read-only. daemon: Remount root directory as read-only. daemon: Allow running as non-root with unprivileged user namespaces. daemon: Create /var/guix/profiles/per-user unconditionally. daemon: Drop Linux ambient capabilities before executing builder. daemon: Move comments where they belong. linux-container: ‘unprivileged-user-namespace-supported?’ returns #f on non-Linux. tests: Add missing derivation inputs. tests: Run in a chroot and unprivileged user namespaces. etc: systemd services: Run ‘guix-daemon’ as an unprivileged user. guix-install.sh: Support the unprivileged daemon where possible. DRAFT gnu: guix: Update to 07c5b1b build-aux/test-env.in | 18 +- config-daemon.ac | 5 +- doc/guix.texi | 102 ++++++++--- etc/gnu-store.mount.in | 3 +- etc/guix-daemon.service.in | 22 ++- etc/guix-install.sh | 124 +++++++++++--- gnu/build/linux-container.scm | 4 +- gnu/packages/package-management.scm | 6 +- guix/substitutes.scm | 2 +- nix/libstore/build.cc | 251 +++++++++++++++++++++------- nix/libstore/local-store.cc | 26 ++- nix/libutil/util.cc | 26 ++- tests/derivations.scm | 24 ++- tests/packages.scm | 13 +- tests/processes.scm | 9 +- tests/store.scm | 247 +++++++++++++++++++++++---- 16 files changed, 698 insertions(+), 184 deletions(-) base-commit: 0c497c87ac47206b3e8c6dfa2e1e9b5f3e452292 -- 2.48.1
guix-patches@HIDDEN
:bug#75810
; Package guix-patches
.
Full text available.Received: (at 75810) by debbugs.gnu.org; 17 Mar 2025 17:03:47 +0000 From debbugs-submit-bounces <at> debbugs.gnu.org Mon Mar 17 13:03:47 2025 Received: from localhost ([127.0.0.1]:60632 helo=debbugs.gnu.org) by debbugs.gnu.org with esmtp (Exim 4.84_2) (envelope-from <debbugs-submit-bounces <at> debbugs.gnu.org>) id 1tuDsO-0002Z8-6R for submit <at> debbugs.gnu.org; Mon, 17 Mar 2025 13:03:47 -0400 Received: from eggs.gnu.org ([2001:470:142:3::10]:42088) by debbugs.gnu.org with esmtps (TLS1.2:ECDHE_RSA_AES_256_GCM_SHA384:256) (Exim 4.84_2) (envelope-from <ludo@HIDDEN>) id 1tuDsG-0002Ws-Pq for 75810 <at> debbugs.gnu.org; Mon, 17 Mar 2025 13:03:40 -0400 Received: from fencepost.gnu.org ([2001:470:142:3::e]) by eggs.gnu.org with esmtps (TLS1.2:ECDHE_RSA_AES_256_GCM_SHA384:256) (Exim 4.90_1) (envelope-from <ludo@HIDDEN>) id 1tuDs9-00052c-6M; Mon, 17 Mar 2025 13:03:29 -0400 DKIM-Signature: v=1; a=rsa-sha256; q=dns/txt; c=relaxed/relaxed; d=gnu.org; s=fencepost-gnu-org; h=MIME-Version:References:In-Reply-To:Date:Subject:To: From; bh=gj2HkSqKqMC6OnWJO11zAMx01vOVuopEBzKWBjgHWEs=; b=hszcIaMPoR6xxiJkkZjJ xCwan8g7WYMTRYWjuTMES6IzX3Cs+agtTh4qz1WTMfUT+1zsbicLacDDZ7kZTqOp+x6vCJLtXGnBW 9d6JRmzCf34WLM7A/gl9hMpUifWSbyZScFM4lekPvHUP28+SRScOdkv63V8jCG6nb6Xq1AnJYBuum /LiJA+QdGrXZ3zaBnpPRoBon+9asHVfWBXBc1PhyhTfrqwIBMAPI7haY9NjRRDzC5HZ1EvDPgx4ux 2OVhpKxq2AET10Y0gWeQlZra4lfnoroMmEkGugfvl9B4LXyr0sO03Gq+DhkYD2un8fxBvdEhbwXXq EiAXaqP//Qu0KQ==; From: =?UTF-8?q?Ludovic=20Court=C3=A8s?= <ludo@HIDDEN> To: 75810 <at> debbugs.gnu.org Subject: [PATCH v6 01/16] =?UTF-8?q?daemon:=20Use=20=E2=80=98close=5Frange?= =?UTF-8?q?=E2=80=99=20where=20available.?= Date: Mon, 17 Mar 2025 18:02:44 +0100 Message-ID: <bba84cef11327acccc18b7a953c33a85fdec430e.1742230219.git.ludo@HIDDEN> X-Mailer: git-send-email 2.48.1 In-Reply-To: <cover.1742230219.git.ludo@HIDDEN> References: <cover.1742230219.git.ludo@HIDDEN> MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit X-Spam-Score: -0.0 (/) X-Debbugs-Envelope-To: 75810 Cc: =?UTF-8?q?Ludovic=20Court=C3=A8s?= <ludo@HIDDEN> X-BeenThere: debbugs-submit <at> debbugs.gnu.org X-Mailman-Version: 2.1.18 Precedence: list List-Id: <debbugs-submit.debbugs.gnu.org> List-Unsubscribe: <https://debbugs.gnu.org/cgi-bin/mailman/options/debbugs-submit>, <mailto:debbugs-submit-request <at> debbugs.gnu.org?subject=unsubscribe> List-Archive: <https://debbugs.gnu.org/cgi-bin/mailman/private/debbugs-submit/> List-Post: <mailto:debbugs-submit <at> debbugs.gnu.org> List-Help: <mailto:debbugs-submit-request <at> debbugs.gnu.org?subject=help> List-Subscribe: <https://debbugs.gnu.org/cgi-bin/mailman/listinfo/debbugs-submit>, <mailto:debbugs-submit-request <at> debbugs.gnu.org?subject=subscribe> Errors-To: debbugs-submit-bounces <at> debbugs.gnu.org Sender: "Debbugs-submit" <debbugs-submit-bounces <at> debbugs.gnu.org> X-Spam-Score: -3.3 (---) * nix/libutil/util.cc (closeMostFDs) [HAVE_CLOSE_RANGE]: Use ‘close_range’ when ‘exceptions’ is empty. * config-daemon.ac: Check for <linux/close_range.h> and the ‘close_range’ symbol. Change-Id: I12fa3bde58b003fcce5ea5a1fee1dcf9a92c0359 --- config-daemon.ac | 5 +++-- nix/libutil/util.cc | 23 +++++++++++++++++------ 2 files changed, 20 insertions(+), 8 deletions(-) diff --git a/config-daemon.ac b/config-daemon.ac index 6731c68bc3..4e949bc88a 100644 --- a/config-daemon.ac +++ b/config-daemon.ac @@ -78,7 +78,8 @@ if test "x$guix_build_daemon" = "xyes"; then dnl Chroot support. AC_CHECK_FUNCS([chroot unshare]) - AC_CHECK_HEADERS([sched.h sys/param.h sys/mount.h sys/syscall.h]) + AC_CHECK_HEADERS([sched.h sys/param.h sys/mount.h sys/syscall.h \ + linux/close_range.h]) if test "x$ac_cv_func_chroot" != "xyes"; then AC_MSG_ERROR(['chroot' function missing, bailing out]) @@ -95,7 +96,7 @@ if test "x$guix_build_daemon" = "xyes"; then dnl strsignal: for error reporting. dnl statx: fine-grain 'stat' call, new in glibc 2.28. AC_CHECK_FUNCS([lutimes lchown posix_fallocate sched_setaffinity \ - statvfs nanosleep strsignal statx]) + statvfs nanosleep strsignal statx close_range]) dnl Check for <locale>. AC_LANG_PUSH(C++) diff --git a/nix/libutil/util.cc b/nix/libutil/util.cc index 3206dea11b..eb2d16e1cc 100644 --- a/nix/libutil/util.cc +++ b/nix/libutil/util.cc @@ -23,6 +23,10 @@ #include <sys/prctl.h> #endif +#ifdef HAVE_LINUX_CLOSE_RANGE_H +# include <linux/close_range.h> +#endif + extern char * * environ; @@ -1087,12 +1091,19 @@ string runProgram(Path program, bool searchPath, const Strings & args) void closeMostFDs(const set<int> & exceptions) { - int maxFD = 0; - maxFD = sysconf(_SC_OPEN_MAX); - for (int fd = 0; fd < maxFD; ++fd) - if (fd != STDIN_FILENO && fd != STDOUT_FILENO && fd != STDERR_FILENO - && exceptions.find(fd) == exceptions.end()) - close(fd); /* ignore result */ +#ifdef HAVE_CLOSE_RANGE + if (exceptions.empty()) + close_range(3, ~0U, 0); + else +#endif + { + int maxFD = 0; + maxFD = sysconf(_SC_OPEN_MAX); + for (int fd = 0; fd < maxFD; ++fd) + if (fd != STDIN_FILENO && fd != STDOUT_FILENO && fd != STDERR_FILENO + && exceptions.find(fd) == exceptions.end()) + close(fd); /* ignore result */ + } } -- 2.48.1
guix-patches@HIDDEN
:bug#75810
; Package guix-patches
.
Full text available.Received: (at 75810) by debbugs.gnu.org; 15 Mar 2025 23:45:09 +0000 From debbugs-submit-bounces <at> debbugs.gnu.org Sat Mar 15 19:45:08 2025 Received: from localhost ([127.0.0.1]:44097 helo=debbugs.gnu.org) by debbugs.gnu.org with esmtp (Exim 4.84_2) (envelope-from <debbugs-submit-bounces <at> debbugs.gnu.org>) id 1ttbBh-0002I3-FY for submit <at> debbugs.gnu.org; Sat, 15 Mar 2025 19:45:08 -0400 Received: from mailout.russelstein.xyz ([2605:6400:20:11e::1]:39628) by debbugs.gnu.org with esmtps (TLS1.2:ECDHE_RSA_AES_256_GCM_SHA384:256) (Exim 4.84_2) (envelope-from <reepca@HIDDEN>) id 1ttbBa-0002Fz-Lx for 75810 <at> debbugs.gnu.org; Sat, 15 Mar 2025 19:45:02 -0400 DKIM-Signature: v=1; a=ed25519-sha256; q=dns/txt; c=relaxed/relaxed; d=russelstein.xyz; s=ed25519; h=Content-Type:MIME-Version:Message-ID:Date: References:In-Reply-To:Subject:Cc:To:From:Sender:Reply-To: Content-Transfer-Encoding:Content-ID:Content-Description:Resent-Date: Resent-From:Resent-Sender:Resent-To:Resent-Cc:Resent-Message-ID:List-Id: List-Help:List-Unsubscribe:List-Subscribe:List-Post:List-Owner:List-Archive; bh=KJhm3TKDhXctKKrXEJE6/VRDG6EGRqPeZsRkkiA/5SI=; b=kir/AI1GbD51IN725gBDE5ZLZ4 qK6/XZsj1PKpleL1h3FjXbCn46yN1vqBGsvzSyYr6FY9hmZRzriZNYtTLTBA==; DKIM-Signature: v=1; a=rsa-sha256; q=dns/txt; c=relaxed/relaxed; d=russelstein.xyz; s=rsa; h=Content-Type:MIME-Version:Message-ID:Date: References:In-Reply-To:Subject:Cc:To:From:Sender:Reply-To: Content-Transfer-Encoding:Content-ID:Content-Description:Resent-Date: Resent-From:Resent-Sender:Resent-To:Resent-Cc:Resent-Message-ID:List-Id: List-Help:List-Unsubscribe:List-Subscribe:List-Post:List-Owner:List-Archive; bh=KJhm3TKDhXctKKrXEJE6/VRDG6EGRqPeZsRkkiA/5SI=; b=jSdxEiPJ/Pm17n6wZLFTTEWk5w ZqzXflE2fXtozXmP7ziEtEyZfbFOY36HancXSSu3F/HyhGNYe+Au0W7gyiEgXmp1VLihBlKzPQLzO EQ7mHOLj7GAYzpBxoxTfHu97aAo62uZ+v8V8IhTUuxBJfmgUP8iVuGFMGXukjxHIIWzJvBWNs39A2 C1NPbdfXZzbK4jAyrSXw6jxvj7c33oIOSB05fjNA7gDGLmaGDK13W0HFj47PyzBnW/OpK5ProeAsO 0HNuxdclpoEUnwv6NSzJxVh32K5Pg6G6JDoGK45nUdyvR5NMsKfssiquYU16HukQ+Btg71I1rHml9 ZQQPzkKIMM/CJJ+crsl+cI8YVgvkBXVVwDl7mgvYN21wr2Kx7ISLdih4xNuM0qVTOrVS5erTaWZ2F YvNX5rjdiVgTmFXXZBES4yrU2INj9E061QEISZlaEKOdlHHP2Cx8d72cGajjtb9dQ+Df6xqsSAmwJ OguH/4jrv16MkqCFAe9mYK2GgrAlAMJ/jOwc6Y2pnSzQ7pWwg7y7NikjxHxNhzi5yZNDBF7cgXpbJ 8SJXMmEmM66FVti3Et/ZKQaGMzI4oGDaVyZ2DysZ5v7EDPGXex8k8PE8brLi87X6fdHwqTRNHFrDe +22H7ckkqLxB1Y2Yywc+pgHG83UxnfA+squ3YnyZY=; Received: by russelstein.xyz with esmtpsa (TLS1.3:ECDHE_SECP256R1__RSA_PSS_RSAE_SHA256__AES_256_GCM:256) (Exim 4.98) (envelope-from <reepca@HIDDEN>) id 1ttbBV-0000000047y-17fP; Sat, 15 Mar 2025 18:44:55 -0500 From: Reepca Russelstein <reepca@HIDDEN> To: Ludovic =?utf-8?Q?Court=C3=A8s?= <ludo@HIDDEN> Subject: Re: [PATCH v5 00/14] Rootless guix-daemon In-Reply-To: <cover.1741973869.git.ludo@HIDDEN> ("Ludovic =?utf-8?Q?Court?= =?utf-8?Q?=C3=A8s=22's?= message of "Fri, 14 Mar 2025 18:47:57 +0100") References: <cover.1741973869.git.ludo@HIDDEN> Date: Sat, 15 Mar 2025 18:44:17 -0500 Message-ID: <87h63t6er2.fsf@HIDDEN> User-Agent: Gnus/5.13 (Gnus v5.13) MIME-Version: 1.0 Content-Type: multipart/signed; boundary="=-=-="; micalg=pgp-sha256; protocol="application/pgp-signature" X-Spam-Score: 0.5 X-Spam-Bar: / X-Spam-Score-Int: 5 X-Spam-Report: Spam detection software, running on the system "Sanctum", has NOT identified this incoming email as spam. The original message has been attached to this so you can view it or label similar future email. If you have any questions, see the administrator of that system for details. Content preview: Ludovic Courtès <ludo@HIDDEN> writes: > • In ‘guix-daemon.service.in’, set > ‘GUIX_DATABASE_DIRECTORY=/var/guix’ for forward compatibility > (I’m thinking of eventually changing the default database > location when not running [...] Content analysis details: (0.5 points, 5.0 required) pts rule name description ---- ---------------------- -------------------------------------------------- -0.0 NO_RELAYS Informational: message was not relayed via SMTP 0.5 FROM_SUSPICIOUS_NTLD From abused NTLD X-Spam-Score: 1.4 (+) X-Spam-Report: Spam detection software, running on the system "debbugs.gnu.org", has NOT identified this incoming email as spam. The original message has been attached to this so you can view it or label similar future email. If you have any questions, see the administrator of that system for details. Content preview: Ludovic Courtès <ludo@HIDDEN> writes: > • In ‘guix-daemon.service.in’, set > ‘GUIX_DATABASE_DIRECTORY=/var/guix’ for forward compatibility > (I’m thinking of eventually changing the default database > location when not running [...] Content analysis details: (1.4 points, 10.0 required) pts rule name description ---- ---------------------- -------------------------------------------------- 0.9 PDS_OTHER_BAD_TLD Untrustworthy TLDs [URI: russelstein.xyz (xyz)] -0.0 SPF_PASS SPF: sender matches SPF record 0.0 SPF_HELO_NONE SPF: HELO does not publish an SPF Record 0.5 FROM_SUSPICIOUS_NTLD From abused NTLD X-Debbugs-Envelope-To: 75810 Cc: 75810 <at> debbugs.gnu.org X-BeenThere: debbugs-submit <at> debbugs.gnu.org X-Mailman-Version: 2.1.18 Precedence: list List-Id: <debbugs-submit.debbugs.gnu.org> List-Unsubscribe: <https://debbugs.gnu.org/cgi-bin/mailman/options/debbugs-submit>, <mailto:debbugs-submit-request <at> debbugs.gnu.org?subject=unsubscribe> List-Archive: <https://debbugs.gnu.org/cgi-bin/mailman/private/debbugs-submit/> List-Post: <mailto:debbugs-submit <at> debbugs.gnu.org> List-Help: <mailto:debbugs-submit-request <at> debbugs.gnu.org?subject=help> List-Subscribe: <https://debbugs.gnu.org/cgi-bin/mailman/listinfo/debbugs-submit>, <mailto:debbugs-submit-request <at> debbugs.gnu.org?subject=subscribe> Errors-To: debbugs-submit-bounces <at> debbugs.gnu.org Sender: "Debbugs-submit" <debbugs-submit-bounces <at> debbugs.gnu.org> X-Spam-Score: 1.4 (+) X-Spam-Report: Spam detection software, running on the system "debbugs.gnu.org", has NOT identified this incoming email as spam. The original message has been attached to this so you can view it or label similar future email. If you have any questions, see the administrator of that system for details. Content preview: Ludovic Courtès <ludo@HIDDEN> writes: > • In ‘guix-daemon.service.in’, set > ‘GUIX_DATABASE_DIRECTORY=/var/guix’ for forward compatibility > (I’m thinking of eventually changing the default database > location when not running [...] Content analysis details: (1.4 points, 10.0 required) pts rule name description ---- ---------------------- -------------------------------------------------- 0.9 PDS_OTHER_BAD_TLD Untrustworthy TLDs [URI: russelstein.xyz (xyz)] -0.0 SPF_PASS SPF: sender matches SPF record 0.0 SPF_HELO_NONE SPF: HELO does not publish an SPF Record 1.0 BULK_RE_SUSP_NTLD Precedence bulk and RE: from a suspicious TLD 0.5 FROM_SUSPICIOUS_NTLD From abused NTLD -1.0 MAILING_LIST_MULTI Multiple indicators imply a widely-seen list manager --=-=-= Content-Type: text/plain; charset=utf-8 Content-Transfer-Encoding: quoted-printable Ludovic Court=C3=A8s <ludo@HIDDEN> writes: > =E2=80=A2 In =E2=80=98guix-daemon.service.in=E2=80=99, set > =E2=80=98GUIX_DATABASE_DIRECTORY=3D/var/guix=E2=80=99 for forward com= patibility > (I=E2=80=99m thinking of eventually changing the default database > location when not running as root). Did you intend GUIX_STATE_DIRECTORY here, or GUIX_DATABASE_DIRECTORY in the patch? GUIX_STATE_DIRECTORY is what's in the patch. > @@ -1087,12 +1091,19 @@ string runProgram(Path program, bool searchPath, = const Strings & args) >=20=20 > void closeMostFDs(const set<int> & exceptions) > { > - int maxFD =3D 0; > - maxFD =3D sysconf(_SC_OPEN_MAX); > - for (int fd =3D 0; fd < maxFD; ++fd) > - if (fd !=3D STDIN_FILENO && fd !=3D STDOUT_FILENO && fd !=3D STD= ERR_FILENO > - && exceptions.find(fd) =3D=3D exceptions.end()) > - close(fd); /* ignore result */ > +#ifdef HAVE_CLOSE_RANGE > + if (exceptions.empty()) > + close_range(3, ~0U, 0); > + else > +#endif > + { > + int maxFD =3D 0; > + maxFD =3D sysconf(_SC_OPEN_MAX); > + for (int fd =3D 0; fd < maxFD; ++fd) > + if (fd !=3D STDIN_FILENO && fd !=3D STDOUT_FILENO && fd !=3D STDE= RR_FILENO > + && exceptions.find(fd) =3D=3D exceptions.end()) > + close(fd); /* ignore result */ > + } > } (in patch 01/14, in nix/libutil/util.cc) Minor note: this could be implemented solely in terms of close_range, by sorting the exceptions and iterating over the gaps between them. It's fine as it is though. > +The second and preferred option is to run @command{guix-daemon} > +@emph{as an unprivileged user}. It has the advantage of reducing the > +harm that can be done should a build process manage to exploit a > +vulnerability in the daemon. This option requires the user of Linux's > +unprivileged user namespace mechanism; today it is available and enabled > +by most GNU/Linux distributions but can still be disabled. The > +installation script automatically determines whether this option is > +available on your system (@pxref{Binary Installation}). (in patch 06/14, in doc/guix.texi) In the third sentence: s/requires the user/requires the use/ > +When using this option, you only need to create one user account, and > +@command{guix-daemon} will run with the authority of that account: > + > +@example > +# groupadd --system guix-daemon > +# useradd -g guix-daemon -G guix-daemon \ > + -d /var/empty -s $(which nologin) \ > + -c "Guix daemon privilege separation user" \ > + --system guix-daemon > +@end example > + > +In this configuration, @file{/gnu/store} is owned by the > +@code{guix-daemon} user. It may be somewhat confusing to the reader looking at this page in isolation whether they still need to create this account after running the installation script, since it was mentioned immediately before this. > @@ -1567,10 +1612,17 @@ Invoking guix-daemon > @item --disable-chroot > Disable chroot builds. >=20 > -Using this option is not recommended since, again, it would allow build > -processes to gain access to undeclared dependencies. It is necessary, > -though, when @command{guix-daemon} is running under an unprivileged user > -account. > +@quotation Warning > +Using this option is not recommended since it allows build processes to > +gain access to undeclared dependencies, to interfere with one another, > +and more generally to do anything that can be done with the authority of > +the daemon---which includes at least the ability to tamper with any file > +in the store! > + > +You may find it necessary, though, when support for Linux unprivileged > +user namespaces is missing (@pxref{Build Environment Setup}). Use at > +your own risk! > +@end quotation Note that the "do anything that can be done with the authority of the daemon" part is only true in the case where the builder and the daemon run under the same user. For example, on Hurd, we use --disable-chroot but still use the separate builder users. More generally, =2D-disable-chroot allows any user that can start builds to gain the privileges of the build user their build runs as. While this allows for the output of any build run as that user to be controlled, to my knowledge it can't change the contents of existing outputs (unless they can be gc'ed and rebuilt, of course). Perhaps this would be a good place to recommend setting the permissions of LOCALSTATEDIR/guix/daemon-socket to allow only trusted users to access it? > diff --git a/nix/libstore/build.cc b/nix/libstore/build.cc > index c8b778362a..76f75e00df 100644 > --- a/nix/libstore/build.cc > +++ b/nix/libstore/build.cc > @@ -744,6 +744,10 @@ private: >=20=20 > friend int childEntry(void *); >=20=20 > + /* Pipe to notify readiness to the child process when using unprivil= eged > + user namespaces. */ > + Pipe readiness; > + > /* Check that the derivation outputs all exist and register them > as valid. */ > void registerOutputs(); (in nix/libstore/build.cc) This is inside of DerivationGoal. We found out while hunting that deadlock bug that it doesn't always get disposed of in a timely fashion. So we probably shouldn't rely on the AutoCloseFD type of readiness.readSide and readiness.writeSide to close them in a timely fashion, opting instead to explicitly close the end we use immediately after we're done with it. It would also probably be wise to follow the usual practice of the reader closing the write end before reading, and the writer closing the read end before writing, lest any sudden-process-death cause indefinite hangs. On a slightly-related note, while investigating what we currently do for the other file-descriptor-bearing objects in DerivationGoal, I noticed that we appear to never explicitly close builderOut.readSide in the child (we do implicitly close it eventually with closeMostFDs). Probably not a problem in practice, since the parent never writes to the pipe, and if the parent process gets suddenly wiped out, the possibility of the child blocking indefinitely is probably the least of our worries, but maybe it would be good to close it in commonChildInit. > @@ -102,10 +102,22 @@ then > rm -rf "$GUIX_STATE_DIRECTORY/daemon-socket" > mkdir -m 0700 "$GUIX_STATE_DIRECTORY/daemon-socket" >=20=20 > + # If unprivileged user namespaces are not supported, pass > + # '--disable-chroot'. > + if [ ! -f /proc/sys/kernel/unprivileged_userns_clone ] \ > + || [ "$(cat /proc/sys/kernel/unprivileged_userns_clone)" -eq 1 ];= then > + extra_options=3D"" > + else > + extra_options=3D"--disable-chroot" > + echo "unprivileged user namespaces not supported; \ > +running 'guix-daemon $extra_options'" >&2 > + fi > + > # Launch the daemon without chroot support because is may be > # unavailable, for instance if we're not running as root. > "@abs_top_builddir@/pre-inst-env" \ > - "@abs_top_builddir@/guix-daemon" --disable-chroot \ > + "@abs_top_builddir@/guix-daemon" \ > + $extra_options \ > --substitute-urls=3D"$GUIX_BINARY_SUBSTITUTE_URL" & (in patch 11/14, in build-aux/test-env.in) I think this test for /proc/sys/kernel/unprivileged_userns_clone will only work on linux, no? On Hurd it will see that the file doesn't exist and assume that means it shouldn't pass --disable-chroot. Maybe also require that something like /proc/self/ns/user exists? I see in (gnu build linux-container) this is what we do for 'user-namespace-supported?'. Perhaps 'unprivileged-user-namespace-supported?' should also be updated to only return true if user namespaces are supported at all? Otherwise many of the test skips in this patch are going to do the opposite of what they should on Hurd. Also, perhaps the "Launch the daemon without chroot support because is ..." comment should be updated (also s/is/it/ there) or removed. > +(unless (unprivileged-user-namespace-supported?) > + (test-skip 1)) > +(test-assert "build root cannot be made world-readable" > + (let ((drv > + (run-with-store %store > + (gexp->derivation > + "attempt-to-make-root-world-readable" > + (with-imported-modules (source-module-closure > + '((guix build syscalls))) > + #~(begin > + (use-modules (guix build syscalls)) > + > + (let ((guile (string-append (assoc-ref %guile-build-in= fo > + 'bindir) > + "/guile"))) > + (catch 'system-error > + (lambda () > + (chmod "/" #o777)) > + (lambda args > + (format #t "failed to make root writable: ~a~%" > + (strerror (system-error-errno args))) > + (format #t "attempting read-write remount~%") > + (mount "none" "/" "/" (logior MS_BIND MS_REMOUNT= )) > + (chmod "/" #o777))) > + (copy-file guile "/guile") > + (chmod "/guile" #o6755) > + ;; At this point, there's a world-readable setuid 'g= uile' > + ;; binary in the store that remains visible until th= is > + ;; build completes. > + (list #$output)))))))) > + (guard (c ((store-protocol-error? c) #t)) > + (build-derivations %store (list drv)) > + #f))) (in tests/store.scm) It may be good to forego actually creating the setuid guile here, since it's not part of what's actually being tested, just a looming threat to motivate what's being tested. In the event that this test fails someday, let's be kind to our testers and leave them with only a world-readable setuid empty file or file containing a frowny face or something. ... actually, on closer inspection, won't this test never fail? The gexp doesn't actually create #$output, so the build will always fail, and the store-protocol-error will always be signaled, no? > +# Provide the CAP_CHOWN capability so that guix-daemon cran create and c= hown > +# /var/guix/profiles/per-user/$USER and also chown failed build director= ies > +# when using '--keep-failed'. Note that guix-daemon explicitly drops am= bient > +# capabilities before executing build processes so they don't inherit th= em. > +AmbientCapabilities=3DCAP_CHOWN (in patch 12/14, in etc/guix-daemon.service.in) s/cran create/can create/ Also, I'm curious how this interacts with the changes to the installer script. What happens if the installer detects that the rootless daemon isn't supported, but the guix that it's installing only has this version of guix-daemon.service? I haven't checked, but if the answer is "the service is broken", perhaps we should have two variants of the service file, and sys_enable_guix_daemon decides which one to symlink /etc/systemd/system/guix-daemon.service to? > +can_install_unprivileged_daemon() > +{ # Return true if we can install guix-daemon running without privileges. > + [ "$INIT_SYS" =3D systemd ] && \ > + grep -q "User=3Dguix-daemon" \ > + ~root/.config/guix/current/lib/systemd/system/guix-daemon.service \ > + && ([ ! -f /proc/sys/kernel/unprivileged_userns_clone ] \ > + || [ "$(cat /proc/sys/kernel/unprivileged_userns_clone)" -eq 1 ]) > +} (in patch 13/14, in etc/guix-install.sh) I vaguely recall hearing that systemd only supports linux, so it might not be strictly necessary to check whether user namespaces are supported at all here like it was in test-env. If we get support for the rootless daemon working for the other init systems a check like that may be necessary, though. It does indeed look like it's going to be necessary to make some changes to make the script able to support installing a newer guix to a systemd-using system that doesn't support unprivileged user namespaces. Perhaps a test case should be added for this system configuration? We're getting close indeed! =2D reepca --=-=-= Content-Type: application/pgp-signature; name="signature.asc" -----BEGIN PGP SIGNATURE----- iQFLBAEBCAA1FiEEdNapMPRLm4SepVYGwWaqSV9/GJwFAmfWENEXHHJlZXBjYUBy dXNzZWxzdGVpbi54eXoACgkQwWaqSV9/GJwuJggAlSeC7Ckq71SLU5qkZAV0cvl2 zfaJpKlEvCCuaJH5bwrdldGubYIFHiK+G86h+A96jsUzM0lHMeZUR3JGLKv4NuPq ksBfTHy5yK9xISM5CoXHad4otXy3u/QIH+7N00QzmThis68B/AxAQin0+ebzXyPi k4CzxNL4RgDJUpwssHpN4cMMpEabLTiYIY+IDAG00Lxo1gfxPVF3N6g+ox7krDuU Ox4UD3Kglc47Tmrq2YfpQwspBrGkgyFTLRmcGKuILnDDk1Jmc6Dw99zVvnS0Pcvd mKR8x8pkqcgcvHQoA27zo9hnv/v/3/y8lKAHMufmm+8KHBJYrB1GHucIEC4gVA== =Bq6N -----END PGP SIGNATURE----- --=-=-=--
guix-patches@HIDDEN
:bug#75810
; Package guix-patches
.
Full text available.Received: (at 75810) by debbugs.gnu.org; 14 Mar 2025 17:50:19 +0000 From debbugs-submit-bounces <at> debbugs.gnu.org Fri Mar 14 13:50:19 2025 Received: from localhost ([127.0.0.1]:36059 helo=debbugs.gnu.org) by debbugs.gnu.org with esmtp (Exim 4.84_2) (envelope-from <debbugs-submit-bounces <at> debbugs.gnu.org>) id 1tt9Ao-0004Y4-SI for submit <at> debbugs.gnu.org; Fri, 14 Mar 2025 13:50:19 -0400 Received: from eggs.gnu.org ([2001:470:142:3::10]:34888) by debbugs.gnu.org with esmtps (TLS1.2:ECDHE_RSA_AES_256_GCM_SHA384:256) (Exim 4.84_2) (envelope-from <ludo@HIDDEN>) id 1tt9AY-0004Q6-Ib for 75810 <at> debbugs.gnu.org; Fri, 14 Mar 2025 13:50:04 -0400 Received: from fencepost.gnu.org ([2001:470:142:3::e]) by eggs.gnu.org with esmtps (TLS1.2:ECDHE_RSA_AES_256_GCM_SHA384:256) (Exim 4.90_1) (envelope-from <ludo@HIDDEN>) id 1tt9AT-000200-5G; Fri, 14 Mar 2025 13:49:57 -0400 DKIM-Signature: v=1; a=rsa-sha256; q=dns/txt; c=relaxed/relaxed; d=gnu.org; s=fencepost-gnu-org; h=MIME-Version:References:In-Reply-To:Date:Subject:To: From; bh=NI59LRaDUVYi2djUVX63YOr2tAfeOTTamhbicaDSA3g=; b=Y8WTarYKAyybaPMEV3nz OCgbR3q9tAqDzH527+o4lbdKZ2xptXKXs1ff7t+yW78wiPOlJMNhX8CEuhtPMtegnxiENtKUtruDu eN/s3mVPumm8EeeFqBj2pgV17Jr84PsVaHYI3IB1988MLLhlj62IMkiXtBDD4ns56uf3GsAE6xcr7 1a1Ygx6rGWaihdvGjkrmqZlExbF7/Jbpb1wJ7Rm90xgiQ6YARGbnFmXi+xVPwbPX7qlAhVar04cN2 hqusxjXrN4MRYvAnL26dV/6Kb60eRAVl5s52k7COlrxDqG4R9Bx80RG5g42GaSIzNTrmoTW5YX1tP a1R6B6CljBzsaw==; From: =?UTF-8?q?Ludovic=20Court=C3=A8s?= <ludo@HIDDEN> To: 75810 <at> debbugs.gnu.org Subject: [PATCH v5 14/14] DRAFT gnu: guix: Update to 00562be. Date: Fri, 14 Mar 2025 18:48:11 +0100 Message-ID: <e74cd10d82895f7f62a635ea52a776309c3cdf66.1741973869.git.ludo@HIDDEN> X-Mailer: git-send-email 2.48.1 In-Reply-To: <cover.1741973869.git.ludo@HIDDEN> References: <cover.1741973869.git.ludo@HIDDEN> MIME-Version: 1.0 Content-Transfer-Encoding: 8bit X-Spam-Score: -2.3 (--) X-Debbugs-Envelope-To: 75810 Cc: =?UTF-8?q?Ludovic=20Court=C3=A8s?= <ludo@HIDDEN> X-BeenThere: debbugs-submit <at> debbugs.gnu.org X-Mailman-Version: 2.1.18 Precedence: list List-Id: <debbugs-submit.debbugs.gnu.org> List-Unsubscribe: <https://debbugs.gnu.org/cgi-bin/mailman/options/debbugs-submit>, <mailto:debbugs-submit-request <at> debbugs.gnu.org?subject=unsubscribe> List-Archive: <https://debbugs.gnu.org/cgi-bin/mailman/private/debbugs-submit/> List-Post: <mailto:debbugs-submit <at> debbugs.gnu.org> List-Help: <mailto:debbugs-submit-request <at> debbugs.gnu.org?subject=help> List-Subscribe: <https://debbugs.gnu.org/cgi-bin/mailman/listinfo/debbugs-submit>, <mailto:debbugs-submit-request <at> debbugs.gnu.org?subject=subscribe> Errors-To: debbugs-submit-bounces <at> debbugs.gnu.org Sender: "Debbugs-submit" <debbugs-submit-bounces <at> debbugs.gnu.org> X-Spam-Score: -3.3 (---) DRAFT: Temporary commit. * gnu/packages/package-management.scm (guix): Update to 00562be. Change-Id: I34ef62c3b12391b145916bd6f44f4da3b497754e --- gnu/packages/package-management.scm | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/gnu/packages/package-management.scm b/gnu/packages/package-management.scm index b0e8ad0d2a..6a48216961 100644 --- a/gnu/packages/package-management.scm +++ b/gnu/packages/package-management.scm @@ -179,8 +179,8 @@ (define-public guix ;; Note: the 'update-guix-package.scm' script expects this definition to ;; start precisely like this. (let ((version "1.4.0") - (commit "5058b40aba825ab6e7b9e518dd1147d1e35fd7de") - (revision 34)) + (commit "00562be83ffe965836a8a23674d379bb9b45dfc9") + (revision 35)) (package (name "guix") @@ -196,7 +196,7 @@ (define-public guix (commit commit))) (sha256 (base32 - "04vk4lslcd6h22yj5pxvb1pdyyxd8421gjfyvyb1bl3xn7c77246")) + "1ixrs1hlipv81y90q60v6rhjjg7sz3f0rgpq201lvgvbl9pl19i9")) (file-name (string-append "guix-" version "-checkout")))) (build-system gnu-build-system) (arguments -- 2.48.1
guix-patches@HIDDEN
:bug#75810
; Package guix-patches
.
Full text available.Received: (at 75810) by debbugs.gnu.org; 14 Mar 2025 17:50:18 +0000 From debbugs-submit-bounces <at> debbugs.gnu.org Fri Mar 14 13:50:18 2025 Received: from localhost ([127.0.0.1]:36057 helo=debbugs.gnu.org) by debbugs.gnu.org with esmtp (Exim 4.84_2) (envelope-from <debbugs-submit-bounces <at> debbugs.gnu.org>) id 1tt9Ao-0004Xk-5S for submit <at> debbugs.gnu.org; Fri, 14 Mar 2025 13:50:18 -0400 Received: from eggs.gnu.org ([2001:470:142:3::10]:34878) by debbugs.gnu.org with esmtps (TLS1.2:ECDHE_RSA_AES_256_GCM_SHA384:256) (Exim 4.84_2) (envelope-from <ludo@HIDDEN>) id 1tt9AY-0004Q5-Aj for 75810 <at> debbugs.gnu.org; Fri, 14 Mar 2025 13:50:03 -0400 Received: from fencepost.gnu.org ([2001:470:142:3::e]) by eggs.gnu.org with esmtps (TLS1.2:ECDHE_RSA_AES_256_GCM_SHA384:256) (Exim 4.90_1) (envelope-from <ludo@HIDDEN>) id 1tt9AS-0001zv-PS; Fri, 14 Mar 2025 13:49:56 -0400 DKIM-Signature: v=1; a=rsa-sha256; q=dns/txt; c=relaxed/relaxed; d=gnu.org; s=fencepost-gnu-org; h=MIME-Version:References:In-Reply-To:Date:Subject:To: From; bh=CUXV6UHPknqgvxLUw2u/RN9HeGPwYQJy5e03yApbb00=; b=VvhPH4NK1harIpPTY7gf 7Gk1qDnV/yavM8Zp54vCR9cs24VG3+WVO6Y7L0zjnyU0PqEt5/Nhw+z26iGpeB9N2ne/9EMQ5QSC4 Ma7Ygr1/K81NIOOXBXy4BWiprHLvFqxsPlnVlrWWoaHLFyKJvSz0qFa/Au9bpjQPDnIGWPQZPdfAi PnmA0y2Te9J4TNHEJ5m7E6JnBD2NlODE4BElnqc6PgX55xFTAibybQkGoLpum9g4NSPgeAXMSaD4j 65dzEda7NNrJTV2/cUHsQiVv6pW4spDlzL3wX+rV2nwKjQko2DhJiW+BpEhx7t5hsvNokAOfnJ/gn 3eDjWJjmyY/kIQ==; From: =?UTF-8?q?Ludovic=20Court=C3=A8s?= <ludo@HIDDEN> To: 75810 <at> debbugs.gnu.org Subject: [PATCH v5 13/14] guix-install.sh: Support the unprivileged daemon where possible. Date: Fri, 14 Mar 2025 18:48:10 +0100 Message-ID: <00562be83ffe965836a8a23674d379bb9b45dfc9.1741973869.git.ludo@HIDDEN> X-Mailer: git-send-email 2.48.1 In-Reply-To: <cover.1741973869.git.ludo@HIDDEN> References: <cover.1741973869.git.ludo@HIDDEN> MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit X-Spam-Score: -2.3 (--) X-Debbugs-Envelope-To: 75810 Cc: =?UTF-8?q?Ludovic=20Court=C3=A8s?= <ludo@HIDDEN> X-BeenThere: debbugs-submit <at> debbugs.gnu.org X-Mailman-Version: 2.1.18 Precedence: list List-Id: <debbugs-submit.debbugs.gnu.org> List-Unsubscribe: <https://debbugs.gnu.org/cgi-bin/mailman/options/debbugs-submit>, <mailto:debbugs-submit-request <at> debbugs.gnu.org?subject=unsubscribe> List-Archive: <https://debbugs.gnu.org/cgi-bin/mailman/private/debbugs-submit/> List-Post: <mailto:debbugs-submit <at> debbugs.gnu.org> List-Help: <mailto:debbugs-submit-request <at> debbugs.gnu.org?subject=help> List-Subscribe: <https://debbugs.gnu.org/cgi-bin/mailman/listinfo/debbugs-submit>, <mailto:debbugs-submit-request <at> debbugs.gnu.org?subject=subscribe> Errors-To: debbugs-submit-bounces <at> debbugs.gnu.org Sender: "Debbugs-submit" <debbugs-submit-bounces <at> debbugs.gnu.org> X-Spam-Score: -3.3 (---) * etc/guix-install.sh (create_account): New function. (sys_create_build_user): Use it. When ‘guix-daemon.service’ contains “User=guix-daemon” only create the ‘guix-daemon’ user and group. (sys_delete_build_user): Delete the ‘guix-daemon’ user and group. (can_install_unprivileged_daemon): New function. (sys_create_store): When installing the unprivileged daemon, change ownership of /gnu and /var/guix, and create /var/log/guix. (sys_authorize_build_farms): When the ‘guix-daemon’ account exists, change ownership of /etc/guix. Change-Id: I73e573f1cc5c0cb3794aaaa6b576616b66e0c5e9 --- etc/guix-install.sh | 109 ++++++++++++++++++++++++++++++++++---------- 1 file changed, 84 insertions(+), 25 deletions(-) diff --git a/etc/guix-install.sh b/etc/guix-install.sh index 8887204df4..eb1093c577 100755 --- a/etc/guix-install.sh +++ b/etc/guix-install.sh @@ -414,6 +414,11 @@ sys_create_store() cd "$tmp_path" _msg_info "Installing /var/guix and /gnu..." # Strip (skip) the leading ‘.’ component, which fails on read-only ‘/’. + # + # TODO: Eventually extract with ‘--owner=guix-daemon’ when installing + # and unprivileged guix-daemon service; for now, this script may install + # from both an old release that does not support unprivileged guix-daemon + # and a new release that does, so ‘chown -R’ later if needed. tar --extract --strip-components=1 --file "$pkg" -C / _msg_info "Linking the root user's profile" @@ -441,38 +446,80 @@ sys_delete_store() rm -rf ~root/.config/guix } +create_account() +{ + local user="$1" + local group="$2" + local supplementary_groups="$3" + local comment="$4" + + if id "$user" &>/dev/null; then + _msg_info "user '$user' is already in the system, reset" + usermod -g "$group" -G "$supplementary_groups" \ + -d /var/empty -s "$(which nologin)" \ + -c "$comment" "$user" + else + useradd -g "$group" -G "$supplementary_groups" \ + -d /var/empty -s "$(which nologin)" \ + -c "$comment" --system "$user" + _msg_pass "user added <$user>" + fi +} + +can_install_unprivileged_daemon() +{ # Return true if we can install guix-daemon running without privileges. + [ "$INIT_SYS" = systemd ] && \ + grep -q "User=guix-daemon" \ + ~root/.config/guix/current/lib/systemd/system/guix-daemon.service \ + && ([ ! -f /proc/sys/kernel/unprivileged_userns_clone ] \ + || [ "$(cat /proc/sys/kernel/unprivileged_userns_clone)" -eq 1 ]) +} + sys_create_build_user() { # Create the group and user accounts for build users. _debug "--- [ ${FUNCNAME[0]} ] ---" - if getent group guixbuild > /dev/null; then - _msg_info "group guixbuild exists" - else - groupadd --system guixbuild - _msg_pass "group <guixbuild> created" - fi - if getent group kvm > /dev/null; then _msg_info "group kvm exists and build users will be added to it" local KVMGROUP=,kvm fi - for i in $(seq -w 1 10); do - if id "guixbuilder${i}" &>/dev/null; then - _msg_info "user is already in the system, reset" - usermod -g guixbuild -G guixbuild"$KVMGROUP" \ - -d /var/empty -s "$(which nologin)" \ - -c "Guix build user $i" \ - "guixbuilder${i}"; - else - useradd -g guixbuild -G guixbuild"$KVMGROUP" \ - -d /var/empty -s "$(which nologin)" \ - -c "Guix build user $i" --system \ - "guixbuilder${i}"; - _msg_pass "user added <guixbuilder${i}>" - fi - done + if can_install_unprivileged_daemon + then + if getent group guix-daemon > /dev/null; then + _msg_info "group guix-daemon exists" + else + groupadd --system guix-daemon + _msg_pass "group guix-daemon created" + fi + + create_account guix-daemon guix-daemon \ + guix-daemon$KVMGROUP \ + "Unprivileged Guix Daemon User" + + # ‘tar xf’ creates root:root files. Change that. + chown -R guix-daemon:guix-daemon /gnu /var/guix + chown -R root:root /var/guix/profiles/per-user/root + + # The unprivileged daemon cannot create the log directory by itself. + mkdir /var/log/guix + chown guix-daemon:guix-daemon /var/log/guix + chmod 755 /var/log/guix + else + if getent group guixbuild > /dev/null; then + _msg_info "group guixbuild exists" + else + groupadd --system guixbuild + _msg_pass "group <guixbuild> created" + fi + + for i in $(seq -w 1 10); do + create_account "guixbuilder${i}" "guixbuild" \ + "guixbuild${KVMGROUP}" \ + "Guix build user $i" + done + fi } sys_delete_build_user() @@ -487,6 +534,14 @@ sys_delete_build_user() if getent group guixbuild &>/dev/null; then groupdel -f guixbuild fi + + _msg_info "remove guix-daemon user" + if id guix-daemon &>/dev/null; then + userdel -f guix-daemon + fi + if getent group guix-daemon &>/dev/null; then + groupdel -f guix-daemon + fi } sys_enable_guix_daemon() @@ -529,11 +584,11 @@ sys_enable_guix_daemon() # Install after guix-daemon.service to avoid a harmless warning. # systemd .mount units must be named after the target directory. - # Here we assume a hard-coded name of /gnu/store. - install_unit gnu-store.mount + install_unit gnu-store.mount systemctl daemon-reload && - systemctl start guix-daemon; } && + systemctl start guix-daemon && + systemctl start gnu-store.mount; } && _msg_pass "enabled Guix daemon via systemd" ;; sysv-init) @@ -654,6 +709,10 @@ project's build farms?"; then && guix archive --authorize < "$key" \ && _msg_pass "Authorized public key for $host" done + if id guix-daemon &>/dev/null; then + # /etc/guix/acl must be readable by the unprivileged guix-daemon. + chown -R guix-daemon:guix-daemon /etc/guix + fi else _msg_info "Skipped authorizing build farm public keys" fi -- 2.48.1
guix-patches@HIDDEN
:bug#75810
; Package guix-patches
.
Full text available.Received: (at 75810) by debbugs.gnu.org; 14 Mar 2025 17:50:18 +0000 From debbugs-submit-bounces <at> debbugs.gnu.org Fri Mar 14 13:50:18 2025 Received: from localhost ([127.0.0.1]:36053 helo=debbugs.gnu.org) by debbugs.gnu.org with esmtp (Exim 4.84_2) (envelope-from <debbugs-submit-bounces <at> debbugs.gnu.org>) id 1tt9Am-0004Wl-Ik for submit <at> debbugs.gnu.org; Fri, 14 Mar 2025 13:50:17 -0400 Received: from eggs.gnu.org ([2001:470:142:3::10]:34862) by debbugs.gnu.org with esmtps (TLS1.2:ECDHE_RSA_AES_256_GCM_SHA384:256) (Exim 4.84_2) (envelope-from <ludo@HIDDEN>) id 1tt9AU-0004Pl-GP for 75810 <at> debbugs.gnu.org; Fri, 14 Mar 2025 13:49:59 -0400 Received: from fencepost.gnu.org ([2001:470:142:3::e]) by eggs.gnu.org with esmtps (TLS1.2:ECDHE_RSA_AES_256_GCM_SHA384:256) (Exim 4.90_1) (envelope-from <ludo@HIDDEN>) id 1tt9AO-0001zT-PX; Fri, 14 Mar 2025 13:49:52 -0400 DKIM-Signature: v=1; a=rsa-sha256; q=dns/txt; c=relaxed/relaxed; d=gnu.org; s=fencepost-gnu-org; h=MIME-Version:References:In-Reply-To:Date:Subject:To: From; bh=ilkq8T90NgjE4yRlAWgTqOqGPLo2p9/2ak11UYRf6PE=; b=Rmvh0JeO2p3YpzEMRmXa /uTB2k+420w7wDPhE93VG6xvZr88v59IqpdbffvyBNjb3YpUxXUdfhqZLJUzyQ/r3z+wBCzDaoAb2 nwEDMnkMH2iIomJsh5N/0XO+d+mZ7WgRMhqBXj5N1qozeS9uNIAEudKIyDMwzPGX3oJE5UPALkVYE b623ByXHsA8vWs+JUS4bQIwxkU+bYVWPYTr7VVosHWsQGFPEVeJYshRcf7tpXTygZVRdf2nmESRHa RPFHJK0XHkqD/R9oRToSxOXpdv7R5NkZS3nt7u0K4sYdGMPEqIukk6PdXdNFZBBsmAA1MbifCDzqz nHFQTYSnbK5IoQ==; From: =?UTF-8?q?Ludovic=20Court=C3=A8s?= <ludo@HIDDEN> To: 75810 <at> debbugs.gnu.org Subject: [PATCH v5 11/14] tests: Run in a chroot and unprivileged user namespaces. Date: Fri, 14 Mar 2025 18:48:08 +0100 Message-ID: <ca04870eced97c5b67e160b64cae32c218765d00.1741973869.git.ludo@HIDDEN> X-Mailer: git-send-email 2.48.1 In-Reply-To: <cover.1741973869.git.ludo@HIDDEN> References: <cover.1741973869.git.ludo@HIDDEN> MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit X-Spam-Score: -2.3 (--) X-Debbugs-Envelope-To: 75810 Cc: =?UTF-8?q?Ludovic=20Court=C3=A8s?= <ludo@HIDDEN> X-BeenThere: debbugs-submit <at> debbugs.gnu.org X-Mailman-Version: 2.1.18 Precedence: list List-Id: <debbugs-submit.debbugs.gnu.org> List-Unsubscribe: <https://debbugs.gnu.org/cgi-bin/mailman/options/debbugs-submit>, <mailto:debbugs-submit-request <at> debbugs.gnu.org?subject=unsubscribe> List-Archive: <https://debbugs.gnu.org/cgi-bin/mailman/private/debbugs-submit/> List-Post: <mailto:debbugs-submit <at> debbugs.gnu.org> List-Help: <mailto:debbugs-submit-request <at> debbugs.gnu.org?subject=help> List-Subscribe: <https://debbugs.gnu.org/cgi-bin/mailman/listinfo/debbugs-submit>, <mailto:debbugs-submit-request <at> debbugs.gnu.org?subject=subscribe> Errors-To: debbugs-submit-bounces <at> debbugs.gnu.org Sender: "Debbugs-submit" <debbugs-submit-bounces <at> debbugs.gnu.org> X-Spam-Score: -3.3 (---) * build-aux/test-env.in: Pass ‘--disable-chroot’ only when unprivileged user namespace support is lacking and warn in that case. * tests/store.scm ("build-things, check mode"): Use ‘gettimeofday’ rather than a shared file as a source of entropy. ("symlink is symlink") ("isolated environment", "inputs are read-only") ("inputs cannot be remounted read-write") ("build root cannot be made world-readable") ("/tmp, store, and /dev/{null,full} are writable") ("network is unreachable"): New tests. * tests/processes.scm ("client + lock"): Skip when ‘unprivileged-user-namespace-supported?’ returns true. Change-Id: I3b3c3ebdf6db5fd36ee70251d07b893c17ca1b84 --- build-aux/test-env.in | 16 ++- tests/processes.scm | 9 +- tests/store.scm | 250 ++++++++++++++++++++++++++++++++++++------ 3 files changed, 237 insertions(+), 38 deletions(-) diff --git a/build-aux/test-env.in b/build-aux/test-env.in index 9caa29da58..a3f225582d 100644 --- a/build-aux/test-env.in +++ b/build-aux/test-env.in @@ -1,7 +1,7 @@ #!/bin/sh # GNU Guix --- Functional package management for GNU -# Copyright © 2012, 2013, 2014, 2015, 2016, 2017, 2018, 2019, 2021 Ludovic Courtès <ludo@HIDDEN> +# Copyright © 2012-2019, 2021, 2025 Ludovic Courtès <ludo@HIDDEN> # # This file is part of GNU Guix. # @@ -102,10 +102,22 @@ then rm -rf "$GUIX_STATE_DIRECTORY/daemon-socket" mkdir -m 0700 "$GUIX_STATE_DIRECTORY/daemon-socket" + # If unprivileged user namespaces are not supported, pass + # '--disable-chroot'. + if [ ! -f /proc/sys/kernel/unprivileged_userns_clone ] \ + || [ "$(cat /proc/sys/kernel/unprivileged_userns_clone)" -eq 1 ]; then + extra_options="" + else + extra_options="--disable-chroot" + echo "unprivileged user namespaces not supported; \ +running 'guix-daemon $extra_options'" >&2 + fi + # Launch the daemon without chroot support because is may be # unavailable, for instance if we're not running as root. "@abs_top_builddir@/pre-inst-env" \ - "@abs_top_builddir@/guix-daemon" --disable-chroot \ + "@abs_top_builddir@/guix-daemon" \ + $extra_options \ --substitute-urls="$GUIX_BINARY_SUBSTITUTE_URL" & daemon_pid=$! diff --git a/tests/processes.scm b/tests/processes.scm index ba518f2d9e..a72ba16f58 100644 --- a/tests/processes.scm +++ b/tests/processes.scm @@ -1,5 +1,5 @@ ;;; GNU Guix --- Functional package management for GNU -;;; Copyright © 2018 Ludovic Courtès <ludo@HIDDEN> +;;; Copyright © 2018, 2025 Ludovic Courtès <ludo@HIDDEN> ;;; Copyright © 2019 Mathieu Othacehe <m.othacehe@HIDDEN> ;;; ;;; This file is part of GNU Guix. @@ -25,6 +25,8 @@ (define-module (test-processes) #:use-module (guix gexp) #:use-module ((guix utils) #:select (call-with-temporary-directory)) #:use-module (gnu packages bootstrap) + #:use-module ((gnu build linux-container) + #:select (unprivileged-user-namespace-supported?)) #:use-module (guix tests) #:use-module (srfi srfi-1) #:use-module (srfi srfi-64) @@ -84,6 +86,11 @@ (define-syntax-rule (test-assert* description exp) (and (kill (process-id daemon) 0) (string-suffix? "guix-daemon" (first (process-command daemon))))))) +(when (unprivileged-user-namespace-supported?) + ;; The test below assumes the build process can communicate with the outside + ;; world via the TOKEN1 and TOKEN2 files, which is impossible when + ;; guix-daemon is set up to build in separate namespaces. + (test-skip 1)) (test-assert* "client + lock" (with-store store (call-with-temporary-directory diff --git a/tests/store.scm b/tests/store.scm index 45948f4f43..aa2477ef75 100644 --- a/tests/store.scm +++ b/tests/store.scm @@ -1,5 +1,5 @@ ;;; GNU Guix --- Functional package management for GNU -;;; Copyright © 2012-2021, 2023 Ludovic Courtès <ludo@HIDDEN> +;;; Copyright © 2012-2021, 2023, 2025 Ludovic Courtès <ludo@HIDDEN> ;;; ;;; This file is part of GNU Guix. ;;; @@ -28,8 +28,12 @@ (define-module (test-store) #:use-module (guix base32) #:use-module (guix packages) #:use-module (guix derivations) + #:use-module ((guix modules) + #:select (source-module-closure)) #:use-module (guix serialization) #:use-module (guix build utils) + #:use-module ((gnu build linux-container) + #:select (unprivileged-user-namespace-supported?)) #:use-module (guix gexp) #:use-module (gnu packages) #:use-module (gnu packages bootstrap) @@ -391,6 +395,191 @@ (define %shell (equal? (valid-derivers %store o) (list (derivation-file-name d)))))) +(test-assert "symlink is symlink" + (let* ((a (add-text-to-store %store "hello.txt" (random-text))) + (b (build-expression->derivation + %store "symlink" + '(symlink (assoc-ref %build-inputs "a") %output) + #:inputs `(("a" ,a)))) + (c (build-expression->derivation + %store "symlink-reference" + `(call-with-output-file %output + (lambda (port) + ;; Check that B is indeed visible as a symlink. This should + ;; always be the case, both in the '--disable-chroot' and in + ;; the user namespace setups. + (pk 'stat (lstat (assoc-ref %build-inputs "b"))) + (display (readlink (assoc-ref %build-inputs "b")) + port))) + #:inputs `(("b" ,b))))) + (and (build-derivations %store (list c)) + (string=? (call-with-input-file (derivation->output-path c) + get-string-all) + a)))) + +(unless (unprivileged-user-namespace-supported?) + (test-skip 1)) +(test-equal "isolated environment" + (string-join (append + '("PID: 1" "UID: 30001") + (delete-duplicates + (sort (list "/dev" "/tmp" "/proc" "/etc" + (match (string-tokenize (%store-prefix) + (char-set-complement + (char-set #\/))) + ((top _ ...) (string-append "/" top)))) + string<?)) + '("/etc/group" "/etc/hosts" "/etc/passwd"))) + (let* ((b (add-text-to-store %store "build.sh" + "echo -n PID: $$ UID: $UID /* /etc/* > $out")) + (s (add-to-store %store "bash" #t "sha256" + (search-bootstrap-binary "bash" + (%current-system)))) + (d (derivation %store "the-thing" + s `("-e" ,b) + #:env-vars `(("foo" . ,(random-text))) + #:sources (list b s))) + (o (derivation->output-path d))) + (and (build-derivations %store (list d)) + (call-with-input-file o get-string-all)))) + +(unless (unprivileged-user-namespace-supported?) + (test-skip 1)) +(test-equal "inputs are read-only" + "All good!" + (let* ((input (plain-file (string-append "might-be-tampered-with-" + (number->string + (car (gettimeofday)) + 16)) + "All good!")) + (drv + (run-with-store %store + (gexp->derivation + "attempt-to-write-to-input" + (with-imported-modules (source-module-closure + '((guix build syscalls))) + #~(begin + (use-modules (guix build syscalls)) + + (let ((input #$input)) + (chmod input #o666) + (call-with-output-file input + (lambda (port) + (display "BAD!" port))) + (mkdir #$output)))))))) + (and (guard (c ((store-protocol-error? c) #t)) + (build-derivations %store (list drv))) + (call-with-input-file (run-with-store %store + (lower-object input)) + get-string-all)))) + +(unless (unprivileged-user-namespace-supported?) + (test-skip 1)) +(test-assert "inputs cannot be remounted read-write" + (let ((drv + (run-with-store %store + (gexp->derivation + "attempt-to-remount-input-read-write" + (with-imported-modules (source-module-closure + '((guix build syscalls))) + #~(begin + (use-modules (guix build syscalls)) + + (let ((input #$(plain-file "input-that-might-be-tampered-with" + "All good!"))) + (mount "none" input "none" (logior MS_BIND MS_REMOUNT)) + (call-with-output-file input + (lambda (port) + (display "BAD!" port))) + (mkdir #$output)))))))) + (guard (c ((store-protocol-error? c) #t)) + (build-derivations %store (list drv)) + #f))) + +(unless (unprivileged-user-namespace-supported?) + (test-skip 1)) +(test-assert "build root cannot be made world-readable" + (let ((drv + (run-with-store %store + (gexp->derivation + "attempt-to-make-root-world-readable" + (with-imported-modules (source-module-closure + '((guix build syscalls))) + #~(begin + (use-modules (guix build syscalls)) + + (let ((guile (string-append (assoc-ref %guile-build-info + 'bindir) + "/guile"))) + (catch 'system-error + (lambda () + (chmod "/" #o777)) + (lambda args + (format #t "failed to make root writable: ~a~%" + (strerror (system-error-errno args))) + (format #t "attempting read-write remount~%") + (mount "none" "/" "/" (logior MS_BIND MS_REMOUNT)) + (chmod "/" #o777))) + (copy-file guile "/guile") + (chmod "/guile" #o6755) + ;; At this point, there's a world-readable setuid 'guile' + ;; binary in the store that remains visible until this + ;; build completes. + (list #$output)))))))) + (guard (c ((store-protocol-error? c) #t)) + (build-derivations %store (list drv)) + #f))) + +(unless (unprivileged-user-namespace-supported?) + (test-skip 1)) +(test-assert "/tmp, store, and /dev/{null,full} are writable" + ;; All of /tmp and all of the store must be writable (the store is writable + ;; so that derivation outputs can be written to it, but in practice it's + ;; always been wide open). Things like /dev/null must be writable too. + (let ((drv (run-with-store %store + (gexp->derivation + "check-tmp-and-store-are-writable" + #~(begin + (mkdir "/tmp/something") + (mkdir (in-vicinity (getenv "NIX_STORE") + "some-other-thing")) + (call-with-output-file "/dev/null" + (lambda (port) + (display "Welcome to the void." port))) + (catch 'system-error + (lambda () + (call-with-output-file "/dev/full" + (lambda (port) + (display "No space left!" port))) + (error "Should have thrown!")) + (lambda args + (unless (= ENOSPC (system-error-errno args)) + (apply throw args)))) + (mkdir #$output)))))) + (build-derivations %store (list drv)))) + +(unless (unprivileged-user-namespace-supported?) + (test-skip 1)) +(test-assert "network is unreachable" + (let ((drv (run-with-store %store + (gexp->derivation + "check-network-unreachable" + #~(let ((check-connection-failure + (lambda (address expected-code) + (let ((s (socket AF_INET SOCK_STREAM 0))) + (catch 'system-error + (lambda () + (connect s AF_INET (inet-pton AF_INET address) 80)) + (lambda args + (let ((errno (system-error-errno args))) + (unless (= expected-code errno) + (error "wrong error code" + errno (strerror errno)))))))))) + (check-connection-failure "127.0.0.1" ECONNREFUSED) + (check-connection-failure "9.9.9.9" ENETUNREACH) + (mkdir #$output)))))) + (build-derivations %store (list drv)))) + (test-equal "with-build-handler" 'success (let* ((b (add-text-to-store %store "build" "echo $foo > $out" '())) @@ -1333,40 +1522,31 @@ (define %shell (test-assert "build-things, check mode" (with-store store - (call-with-temporary-output-file - (lambda (entropy entropy-port) - (write (random-text) entropy-port) - (force-output entropy-port) - (let* ((drv (build-expression->derivation - store "non-deterministic" - `(begin - (use-modules (rnrs io ports)) - (let ((out (assoc-ref %outputs "out"))) - (call-with-output-file out - (lambda (port) - ;; Rely on the fact that tests do not use the - ;; chroot, and thus ENTROPY is readable. - (display (call-with-input-file ,entropy - get-string-all) - port))) - #t)) - #:guile-for-build - (package-derivation store %bootstrap-guile (%current-system)))) - (file (derivation->output-path drv))) - (and (build-things store (list (derivation-file-name drv))) - (begin - (write (random-text) entropy-port) - (force-output entropy-port) - (guard (c ((store-protocol-error? c) - (pk 'determinism-exception c) - (and (not (zero? (store-protocol-error-status c))) - (string-contains (store-protocol-error-message c) - "deterministic")))) - ;; This one will produce a different result. Since we're in - ;; 'check' mode, this must fail. - (build-things store (list (derivation-file-name drv)) - (build-mode check)) - #f)))))))) + (let* ((drv (build-expression->derivation + store "non-deterministic" + `(begin + (use-modules (rnrs io ports)) + (let ((out (assoc-ref %outputs "out"))) + (call-with-output-file out + (lambda (port) + (let ((now (gettimeofday))) + (display (+ (car now) (cdr now)) port)))) + #t)) + #:guile-for-build + (package-derivation store %bootstrap-guile (%current-system)))) + (file (derivation->output-path drv))) + (and (build-things store (list (derivation-file-name drv))) + (begin + (guard (c ((store-protocol-error? c) + (pk 'determinism-exception c) + (and (not (zero? (store-protocol-error-status c))) + (string-contains (store-protocol-error-message c) + "deterministic")))) + ;; This one will produce a different result. Since we're in + ;; 'check' mode, this must fail. + (build-things store (list (derivation-file-name drv)) + (build-mode check)) + #f)))))) (test-assert "build-succeeded trace in check mode" (string-contains -- 2.48.1
guix-patches@HIDDEN
:bug#75810
; Package guix-patches
.
Full text available.Received: (at 75810) by debbugs.gnu.org; 14 Mar 2025 17:50:16 +0000 From debbugs-submit-bounces <at> debbugs.gnu.org Fri Mar 14 13:50:16 2025 Received: from localhost ([127.0.0.1]:36050 helo=debbugs.gnu.org) by debbugs.gnu.org with esmtp (Exim 4.84_2) (envelope-from <debbugs-submit-bounces <at> debbugs.gnu.org>) id 1tt9Al-0004WH-Ve for submit <at> debbugs.gnu.org; Fri, 14 Mar 2025 13:50:16 -0400 Received: from eggs.gnu.org ([2001:470:142:3::10]:34870) by debbugs.gnu.org with esmtps (TLS1.2:ECDHE_RSA_AES_256_GCM_SHA384:256) (Exim 4.84_2) (envelope-from <ludo@HIDDEN>) id 1tt9AV-0004Pn-AW for 75810 <at> debbugs.gnu.org; Fri, 14 Mar 2025 13:49:59 -0400 Received: from fencepost.gnu.org ([2001:470:142:3::e]) by eggs.gnu.org with esmtps (TLS1.2:ECDHE_RSA_AES_256_GCM_SHA384:256) (Exim 4.90_1) (envelope-from <ludo@HIDDEN>) id 1tt9AP-0001zc-Uk; Fri, 14 Mar 2025 13:49:53 -0400 DKIM-Signature: v=1; a=rsa-sha256; q=dns/txt; c=relaxed/relaxed; d=gnu.org; s=fencepost-gnu-org; h=MIME-Version:References:In-Reply-To:Date:Subject:To: From; bh=UDEk6vq1C9HSdyxCSLuhOLlaq0xO7wxGb0uACXLDe0E=; b=iapH6kUEi5LfXKp6PIfD jFZXwIuKVmqObTSsIPvfb7sOITzsTzi9J07lWXodwzvHcBqUT3MzMlUHXvGd5tLnt2E1dahSl1ddc BdoEPBotOc0aSI4/59w3fjK0aXaP3YHJT8QCP7dExV5elATOZlDEAF64A2EoQwtFNgHoy+bwgzTef /4t/5GAUOqoqaiAc6h95CQXK0OErYPfbk0YqTcxZV9ivNytYy2AYyIPKe8F0POnXDS+sD/49ZNZKG CdsRbHoQWp3+oN2NypNuMi6/tMMnHKC4N73BgCPpboL/I5X3+fYIsSA6Pmor4uXN/fosc/ZNAeWfB Kfi3+75sw8irEg==; From: =?UTF-8?q?Ludovic=20Court=C3=A8s?= <ludo@HIDDEN> To: 75810 <at> debbugs.gnu.org Subject: [PATCH v5 12/14] =?UTF-8?q?etc:=20systemd=20services:=20Run=20?= =?UTF-8?q?=E2=80=98guix-daemon=E2=80=99=20as=20an=20unprivileged=20user.?= Date: Fri, 14 Mar 2025 18:48:09 +0100 Message-ID: <00d1d9c120c7d8e33fe09a57df7f0818b5ff0df4.1741973869.git.ludo@HIDDEN> X-Mailer: git-send-email 2.48.1 In-Reply-To: <cover.1741973869.git.ludo@HIDDEN> References: <cover.1741973869.git.ludo@HIDDEN> MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit X-Spam-Score: -2.3 (--) X-Debbugs-Envelope-To: 75810 Cc: =?UTF-8?q?Ludovic=20Court=C3=A8s?= <ludo@HIDDEN> X-BeenThere: debbugs-submit <at> debbugs.gnu.org X-Mailman-Version: 2.1.18 Precedence: list List-Id: <debbugs-submit.debbugs.gnu.org> List-Unsubscribe: <https://debbugs.gnu.org/cgi-bin/mailman/options/debbugs-submit>, <mailto:debbugs-submit-request <at> debbugs.gnu.org?subject=unsubscribe> List-Archive: <https://debbugs.gnu.org/cgi-bin/mailman/private/debbugs-submit/> List-Post: <mailto:debbugs-submit <at> debbugs.gnu.org> List-Help: <mailto:debbugs-submit-request <at> debbugs.gnu.org?subject=help> List-Subscribe: <https://debbugs.gnu.org/cgi-bin/mailman/listinfo/debbugs-submit>, <mailto:debbugs-submit-request <at> debbugs.gnu.org?subject=subscribe> Errors-To: debbugs-submit-bounces <at> debbugs.gnu.org Sender: "Debbugs-submit" <debbugs-submit-bounces <at> debbugs.gnu.org> X-Spam-Score: -3.3 (---) * etc/guix-daemon.service.in (ExecStart): Remove ‘--build-users-group’. (Environment): Add ‘GUIX_STATE_DIRECTORY’. (Before, User, AmbientCapabilities, PrivateMounts, BindPaths): New fields. * etc/gnu-store.mount.in (Before): Remove. (WantedBy): Change to ‘multi-user.target’. Change-Id: Id826b8ab535844b6024d777f6bd15fd49db6d65e --- etc/gnu-store.mount.in | 3 +-- etc/guix-daemon.service.in | 22 ++++++++++++++++++++-- 2 files changed, 21 insertions(+), 4 deletions(-) diff --git a/etc/gnu-store.mount.in b/etc/gnu-store.mount.in index c94f2db72b..f9918c9e52 100644 --- a/etc/gnu-store.mount.in +++ b/etc/gnu-store.mount.in @@ -2,10 +2,9 @@ Description=Read-only @storedir@ for GNU Guix DefaultDependencies=no ConditionPathExists=@storedir@ -Before=guix-daemon.service [Install] -WantedBy=guix-daemon.service +WantedBy=multi-user.target [Mount] What=@storedir@ diff --git a/etc/guix-daemon.service.in b/etc/guix-daemon.service.in index 5c43d9b7f1..c4faf1bcfe 100644 --- a/etc/guix-daemon.service.in +++ b/etc/guix-daemon.service.in @@ -5,11 +5,29 @@ [Unit] Description=Build daemon for GNU Guix +# Start before 'gnu-store.mount' to get a writable view of the store. +Before=gnu-store.mount + [Service] ExecStart=@localstatedir@/guix/profiles/per-user/root/current-guix/bin/guix-daemon \ - --build-users-group=guixbuild --discover=no \ + --discover=no \ --substitute-urls='@GUIX_SUBSTITUTE_URLS@' -Environment='GUIX_LOCPATH=@localstatedir@/guix/profiles/per-user/root/guix-profile/lib/locale' LC_ALL=en_US.utf8 +Environment='GUIX_STATE_DIRECTORY=@localstatedir@/guix' 'GUIX_LOCPATH=@localstatedir@/guix/profiles/per-user/root/guix-profile/lib/locale' LC_ALL=en_US.utf8 + +# Run under a dedicated unprivileged user account. +User=guix-daemon + +# Bind-mount the store read-write in a private namespace, to counter the +# effect of 'gnu-store.mount'. +PrivateMounts=true +BindPaths=@storedir@ + +# Provide the CAP_CHOWN capability so that guix-daemon cran create and chown +# /var/guix/profiles/per-user/$USER and also chown failed build directories +# when using '--keep-failed'. Note that guix-daemon explicitly drops ambient +# capabilities before executing build processes so they don't inherit them. +AmbientCapabilities=CAP_CHOWN + StandardOutput=journal StandardError=journal -- 2.48.1
guix-patches@HIDDEN
:bug#75810
; Package guix-patches
.
Full text available.Received: (at 75810) by debbugs.gnu.org; 14 Mar 2025 17:50:16 +0000 From debbugs-submit-bounces <at> debbugs.gnu.org Fri Mar 14 13:50:15 2025 Received: from localhost ([127.0.0.1]:36048 helo=debbugs.gnu.org) by debbugs.gnu.org with esmtp (Exim 4.84_2) (envelope-from <debbugs-submit-bounces <at> debbugs.gnu.org>) id 1tt9Al-0004VI-4E for submit <at> debbugs.gnu.org; Fri, 14 Mar 2025 13:50:15 -0400 Received: from eggs.gnu.org ([2001:470:142:3::10]:34846) by debbugs.gnu.org with esmtps (TLS1.2:ECDHE_RSA_AES_256_GCM_SHA384:256) (Exim 4.84_2) (envelope-from <ludo@HIDDEN>) id 1tt9AT-0004Pf-LA for 75810 <at> debbugs.gnu.org; Fri, 14 Mar 2025 13:49:58 -0400 Received: from fencepost.gnu.org ([2001:470:142:3::e]) by eggs.gnu.org with esmtps (TLS1.2:ECDHE_RSA_AES_256_GCM_SHA384:256) (Exim 4.90_1) (envelope-from <ludo@HIDDEN>) id 1tt9AO-0001zH-AJ; Fri, 14 Mar 2025 13:49:52 -0400 DKIM-Signature: v=1; a=rsa-sha256; q=dns/txt; c=relaxed/relaxed; d=gnu.org; s=fencepost-gnu-org; h=MIME-Version:References:In-Reply-To:Date:Subject:To: From; bh=b8CNe7Kd4LDHNqpleCFnb1ypaRvesBWH130JtOnxyOw=; b=GGMjXAO8N8MLER7NgguD SVKnv3tn45QP6WY/U/MdbLBIXoe+82LxXPfQaaaIK8+urj0a1f+X5u+ugA7J2fuZF7I9fy/uXkjBs 6yVZOt8h1op8C3ssOIQtoudQmnSXIPte+t0vqs6qhzV9heDXaB4jcu3B/VxUOJiB8e4cHZvSCcHui frog92Z9l6ENYf9LJ9EFLwVqRSwl74kZc0uQbgDSEnxTe4DPFcCwq56Yt4ThG9as+kTacwf/L17xX h3/4QWWja2IbsR+O6YrMS3NB+fN54YXvwWBPy7eXcVMQAucx0I6yoKsvS7t7fVfOK6MaDcnTbvV8o a+BXIoNmeaZviA==; From: =?UTF-8?q?Ludovic=20Court=C3=A8s?= <ludo@HIDDEN> To: 75810 <at> debbugs.gnu.org Subject: [PATCH v5 10/14] tests: Add missing derivation inputs. Date: Fri, 14 Mar 2025 18:48:07 +0100 Message-ID: <817d91a82d60546476736e014acd28eb8043b63f.1741973869.git.ludo@HIDDEN> X-Mailer: git-send-email 2.48.1 In-Reply-To: <cover.1741973869.git.ludo@HIDDEN> References: <cover.1741973869.git.ludo@HIDDEN> MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit X-Spam-Score: -2.3 (--) X-Debbugs-Envelope-To: 75810 Cc: =?UTF-8?q?Ludovic=20Court=C3=A8s?= <ludo@HIDDEN> X-BeenThere: debbugs-submit <at> debbugs.gnu.org X-Mailman-Version: 2.1.18 Precedence: list List-Id: <debbugs-submit.debbugs.gnu.org> List-Unsubscribe: <https://debbugs.gnu.org/cgi-bin/mailman/options/debbugs-submit>, <mailto:debbugs-submit-request <at> debbugs.gnu.org?subject=unsubscribe> List-Archive: <https://debbugs.gnu.org/cgi-bin/mailman/private/debbugs-submit/> List-Post: <mailto:debbugs-submit <at> debbugs.gnu.org> List-Help: <mailto:debbugs-submit-request <at> debbugs.gnu.org?subject=help> List-Subscribe: <https://debbugs.gnu.org/cgi-bin/mailman/listinfo/debbugs-submit>, <mailto:debbugs-submit-request <at> debbugs.gnu.org?subject=subscribe> Errors-To: debbugs-submit-bounces <at> debbugs.gnu.org Sender: "Debbugs-submit" <debbugs-submit-bounces <at> debbugs.gnu.org> X-Spam-Score: -3.3 (---) These missing inputs go unnoticed when running ‘guix-daemon --disable-chroot’ but are immediately visible otherwise. * tests/derivations.scm ("fixed-output derivation"): Add %BASH to #:sources. ("fixed-output derivation: output paths are equal"): ("fixed-output derivation, recursive"): ("derivation with a fixed-output input"): ("derivation with duplicate fixed-output inputs"): ("derivation with equivalent fixed-output inputs"): ("build derivation with coreutils"): Likewise. * tests/packages.scm (bootstrap-binary): New procedure. ("package-source-derivation, origin, sha512"): Use it instead of ‘search-bootstrap-binary’ and add BASH to #:sources. ("package-source-derivation, origin, sha3-512"): Likewise. Change-Id: I4c9087df23c47729a3aff15e9e1435b7266e36e2 --- tests/derivations.scm | 24 +++++++++++++++--------- tests/packages.scm | 13 +++++++++---- 2 files changed, 24 insertions(+), 13 deletions(-) diff --git a/tests/derivations.scm b/tests/derivations.scm index 72ea9aa9cc..f30f05474e 100644 --- a/tests/derivations.scm +++ b/tests/derivations.scm @@ -1,5 +1,5 @@ ;;; GNU Guix --- Functional package management for GNU -;;; Copyright © 2012-2024 Ludovic Courtès <ludo@HIDDEN> +;;; Copyright © 2012-2025 Ludovic Courtès <ludo@HIDDEN> ;;; ;;; This file is part of GNU Guix. ;;; @@ -443,7 +443,7 @@ (define* (directory-contents dir #:optional (slurp get-bytevector-all)) (string-append "fixed-" (symbol->string hash-algorithm)) %bash `(,builder) - #:sources `(,builder) ;optional + #:sources (list %bash builder) #:hash hash #:hash-algo hash-algorithm))) (build-derivations %store (list drv)) @@ -462,9 +462,11 @@ (define* (directory-contents dir #:optional (slurp get-bytevector-all)) (hash (gcrypt:sha256 (string->utf8 "hello"))) (drv1 (derivation %store "fixed" %bash `(,builder1) + #:sources (list %bash builder1) #:hash hash #:hash-algo 'sha256)) (drv2 (derivation %store "fixed" %bash `(,builder2) + #:sources (list %bash builder2) #:hash hash #:hash-algo 'sha256)) (succeeded? (build-derivations %store (list drv1 drv2)))) (and succeeded? @@ -477,7 +479,7 @@ (define* (directory-contents dir #:optional (slurp get-bytevector-all)) (hash (gcrypt:sha256 (string->utf8 "hello"))) (drv (derivation %store "fixed-rec" %bash `(,builder) - #:sources (list builder) + #:sources (list %bash builder) #:hash (base32 "0sg9f58l1jj88w6pdrfdpj5x9b1zrwszk84j81zvby36q9whhhqa") #:hash-algo 'sha256 #:recursive? #t)) @@ -511,9 +513,11 @@ (define* (directory-contents dir #:optional (slurp get-bytevector-all)) (hash (gcrypt:sha256 (string->utf8 "hello"))) (fixed1 (derivation %store "fixed" %bash `(,builder1) + #:sources (list %bash builder1) #:hash hash #:hash-algo 'sha256)) (fixed2 (derivation %store "fixed" %bash `(,builder2) + #:sources (list %bash builder2) #:hash hash #:hash-algo 'sha256)) (fixed-out (derivation->output-path fixed1)) (builder3 (add-text-to-store @@ -548,9 +552,11 @@ (define* (directory-contents dir #:optional (slurp get-bytevector-all)) (hash (gcrypt:sha256 (string->utf8 "hello"))) (fixed1 (derivation %store "fixed" %bash `(,builder1) + #:sources (list %bash builder1) #:hash hash #:hash-algo 'sha256)) (fixed2 (derivation %store "fixed" %bash `(,builder2) + #:sources (list %bash builder2) #:hash hash #:hash-algo 'sha256)) (builder3 (add-text-to-store %store "builder.sh" "echo fake builder")) @@ -580,21 +586,21 @@ (define* (directory-contents dir #:optional (slurp get-bytevector-all)) '())) (hash (gcrypt:sha256 (string->utf8 "hello"))) (drv1 (derivation %store "fixed" %bash (list builder1) - #:sources (list builder1) + #:sources (list %bash builder1) #:hash hash #:hash-algo 'sha256)) (drv2 (derivation %store "fixed" %bash (list builder2) - #:sources (list builder2) + #:sources (list %bash builder2) #:hash hash #:hash-algo 'sha256)) (drv3a (derivation %store "fixed-user" %bash (list builder3) #:outputs '("one" "two") - #:sources (list builder3) + #:sources (list %bash builder3) #:inputs (list (derivation-input drv1)))) (drv3b (derivation %store "fixed-user" %bash (list builder3) #:outputs '("one" "two") - #:sources (list builder3) + #:sources (list %bash builder3) #:inputs (list (derivation-input drv2)))) (drv4 (derivation %store "fixed-user-user" %bash (list builder1) - #:sources (list builder1) + #:sources (list %bash builder1) #:inputs (list (derivation-input drv3a '("one")) (derivation-input drv3b '("two")))))) (match (derivation-inputs drv4) @@ -878,7 +884,7 @@ (define %coreutils ,(string-append (derivation->output-path %coreutils) "/bin"))) - #:sources (list builder) + #:sources (list %bash builder) #:inputs (list (derivation-input %coreutils)))) (succeeded? (build-derivations %store (list drv)))) diff --git a/tests/packages.scm b/tests/packages.scm index 50c1cab915..f56c63128d 100644 --- a/tests/packages.scm +++ b/tests/packages.scm @@ -80,6 +80,11 @@ (define %store ;; When grafting, do not add dependency on 'glibc-utf8-locales'. (%graft-with-utf8-locale? #f) +(define (bootstrap-binary name) + (let ((bin (search-bootstrap-binary name (%current-system)))) + (and %store + (add-to-store %store name #t "sha256" bin)))) + (test-begin "packages") @@ -609,14 +614,14 @@ (define %store (test-equal "package-source-derivation, origin, sha512" "hello" - (let* ((bash (search-bootstrap-binary "bash" (%current-system))) + (let* ((bash (bootstrap-binary "bash")) (builder (add-text-to-store %store "my-fixed-builder.sh" "echo -n hello > $out" '())) (method (lambda* (url hash-algo hash #:optional name #:rest rest) (and (eq? hash-algo 'sha512) (raw-derivation name bash (list builder) - #:sources (list builder) + #:sources (list bash builder) #:hash hash #:hash-algo hash-algo)))) (source (origin @@ -635,14 +640,14 @@ (define %store (test-equal "package-source-derivation, origin, sha3-512" "hello, sha3" - (let* ((bash (search-bootstrap-binary "bash" (%current-system))) + (let* ((bash (bootstrap-binary "bash")) (builder (add-text-to-store %store "my-fixed-builder.sh" "echo -n hello, sha3 > $out" '())) (method (lambda* (url hash-algo hash #:optional name #:rest rest) (and (eq? hash-algo 'sha3-512) (raw-derivation name bash (list builder) - #:sources (list builder) + #:sources (list bash builder) #:hash hash #:hash-algo hash-algo)))) (source (origin -- 2.48.1
guix-patches@HIDDEN
:bug#75810
; Package guix-patches
.
Full text available.Received: (at 75810) by debbugs.gnu.org; 14 Mar 2025 17:50:15 +0000 From debbugs-submit-bounces <at> debbugs.gnu.org Fri Mar 14 13:50:15 2025 Received: from localhost ([127.0.0.1]:36046 helo=debbugs.gnu.org) by debbugs.gnu.org with esmtp (Exim 4.84_2) (envelope-from <debbugs-submit-bounces <at> debbugs.gnu.org>) id 1tt9Ak-0004Uu-Cq for submit <at> debbugs.gnu.org; Fri, 14 Mar 2025 13:50:15 -0400 Received: from eggs.gnu.org ([2001:470:142:3::10]:34836) by debbugs.gnu.org with esmtps (TLS1.2:ECDHE_RSA_AES_256_GCM_SHA384:256) (Exim 4.84_2) (envelope-from <ludo@HIDDEN>) id 1tt9AT-0004PX-1R for 75810 <at> debbugs.gnu.org; Fri, 14 Mar 2025 13:49:57 -0400 Received: from fencepost.gnu.org ([2001:470:142:3::e]) by eggs.gnu.org with esmtps (TLS1.2:ECDHE_RSA_AES_256_GCM_SHA384:256) (Exim 4.90_1) (envelope-from <ludo@HIDDEN>) id 1tt9AM-0001z4-Ak; Fri, 14 Mar 2025 13:49:50 -0400 DKIM-Signature: v=1; a=rsa-sha256; q=dns/txt; c=relaxed/relaxed; d=gnu.org; s=fencepost-gnu-org; h=MIME-Version:References:In-Reply-To:Date:Subject:To: From; bh=3+xXW3NEhqCdaNvzOdWk4oL/UxHf2EzI+PwkPo6SGtE=; b=eQxUXS67BLShE3pn4tPG DEVTyJnPN/cg6vA+vqhbiB/t9KFiHqD1HFjPMJCoeOglfNMBErniN4mjd92C3DenRimjEPhnEq4Pu WHRK78gtKZYGtlwKLgvOK6Gnm4RLswZjv2bUn+bQIy5/0ER04PXNtqOoMoxarWR40Mae+ohudbAId ORvDh4buu1s0AEEAWHyGBS0iLHemw0w37Zkqy9+TsGvE7t18bkGIzScGZl00bkCSaEsJ0n/Y5Ton9 kTWqQQvZV4I6GxuvUw+xpYmRDLvthpWY+rCRJRv4Gx6Zkto7A0W6F7N9SoUCmWH8nuU6RrmGgq7xQ 6cCiqs2Iw0NMSQ==; From: =?UTF-8?q?Ludovic=20Court=C3=A8s?= <ludo@HIDDEN> To: 75810 <at> debbugs.gnu.org Subject: [PATCH v5 09/14] daemon: Move comments where they belong. Date: Fri, 14 Mar 2025 18:48:06 +0100 Message-ID: <86a4ed49616acee6bf2767470f76d459000f4ca3.1741973869.git.ludo@HIDDEN> X-Mailer: git-send-email 2.48.1 In-Reply-To: <cover.1741973869.git.ludo@HIDDEN> References: <cover.1741973869.git.ludo@HIDDEN> MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit X-Spam-Score: -2.3 (--) X-Debbugs-Envelope-To: 75810 Cc: =?UTF-8?q?Ludovic=20Court=C3=A8s?= <ludo@HIDDEN> X-BeenThere: debbugs-submit <at> debbugs.gnu.org X-Mailman-Version: 2.1.18 Precedence: list List-Id: <debbugs-submit.debbugs.gnu.org> List-Unsubscribe: <https://debbugs.gnu.org/cgi-bin/mailman/options/debbugs-submit>, <mailto:debbugs-submit-request <at> debbugs.gnu.org?subject=unsubscribe> List-Archive: <https://debbugs.gnu.org/cgi-bin/mailman/private/debbugs-submit/> List-Post: <mailto:debbugs-submit <at> debbugs.gnu.org> List-Help: <mailto:debbugs-submit-request <at> debbugs.gnu.org?subject=help> List-Subscribe: <https://debbugs.gnu.org/cgi-bin/mailman/listinfo/debbugs-submit>, <mailto:debbugs-submit-request <at> debbugs.gnu.org?subject=subscribe> Errors-To: debbugs-submit-bounces <at> debbugs.gnu.org Sender: "Debbugs-submit" <debbugs-submit-bounces <at> debbugs.gnu.org> X-Spam-Score: -3.3 (---) * nix/libstore/build.cc (DerivationGoal::startBuilder): Shuffle comments for clarity. Change-Id: I6557c103ade4a3ab046354548ea193c68f8c9c05 --- nix/libstore/build.cc | 13 +++++++------ 1 file changed, 7 insertions(+), 6 deletions(-) diff --git a/nix/libstore/build.cc b/nix/libstore/build.cc index 07c8ad7e1d..37c3d3bf1e 100644 --- a/nix/libstore/build.cc +++ b/nix/libstore/build.cc @@ -1870,18 +1870,19 @@ void DerivationGoal::startBuilder() } dirsInChroot[tmpDirInSandbox] = tmpDir; - /* Make the closure of the inputs available in the chroot, - rather than the whole store. This prevents any access - to undeclared dependencies. !!! As an extra security - precaution, make the fake store only writable by the - build user. */ + /* Create the fake store. */ Path chrootStoreDir = chrootRootDir + settings.nixStore; createDirs(chrootStoreDir); chmod_(chrootStoreDir, 01775); if (buildUser.enabled() && chown(chrootStoreDir.c_str(), 0, buildUser.getGID()) == -1) - throw SysError(format("cannot change ownership of ‘%1%’") % chrootStoreDir); + /* As an extra security precaution, make the fake store only + writable by the build user. */ + throw SysError(format("cannot change ownership of ‘%1%’") % chrootStoreDir); + /* Make the closure of the inputs available in the chroot, rather than + the whole store. This prevents any access to undeclared + dependencies. */ foreach (PathSet::iterator, i, inputPaths) { struct stat st; if (lstat(i->c_str(), &st)) -- 2.48.1
guix-patches@HIDDEN
:bug#75810
; Package guix-patches
.
Full text available.Received: (at 75810) by debbugs.gnu.org; 14 Mar 2025 17:50:14 +0000 From debbugs-submit-bounces <at> debbugs.gnu.org Fri Mar 14 13:50:14 2025 Received: from localhost ([127.0.0.1]:36044 helo=debbugs.gnu.org) by debbugs.gnu.org with esmtp (Exim 4.84_2) (envelope-from <debbugs-submit-bounces <at> debbugs.gnu.org>) id 1tt9Ag-0004Sb-Ht for submit <at> debbugs.gnu.org; Fri, 14 Mar 2025 13:50:14 -0400 Received: from eggs.gnu.org ([2001:470:142:3::10]:56592) by debbugs.gnu.org with esmtps (TLS1.2:ECDHE_RSA_AES_256_GCM_SHA384:256) (Exim 4.84_2) (envelope-from <ludo@HIDDEN>) id 1tt9AQ-0004P7-Cg for 75810 <at> debbugs.gnu.org; Fri, 14 Mar 2025 13:49:54 -0400 Received: from fencepost.gnu.org ([2001:470:142:3::e]) by eggs.gnu.org with esmtps (TLS1.2:ECDHE_RSA_AES_256_GCM_SHA384:256) (Exim 4.90_1) (envelope-from <ludo@HIDDEN>) id 1tt9AJ-0001yq-V7; Fri, 14 Mar 2025 13:49:47 -0400 DKIM-Signature: v=1; a=rsa-sha256; q=dns/txt; c=relaxed/relaxed; d=gnu.org; s=fencepost-gnu-org; h=MIME-Version:References:In-Reply-To:Date:Subject:To: From; bh=Cia5Ikq0N0EGZSt4F8nK8osBdkduR1atUQLZPx04ask=; b=HRaBMHV0iiIa9FDeD6uz feXGaDPSdtzUuvOOWe7OsYKfs4SS4AlSdt3Uk7kLkxLQFbahUVO3o4bzMcrHufrYgDowVckhd60Ib Ti6Vo8P885KuiDit42s4B0RTxTrjHE4hygDnfYslsvChKWt0e2AAwMtJKJ0+Jy/x279Fa1d+ClgWL kPE7+4d1rEo6RQRfw0UUZEvkcHEELp+xN0CkzhswSjx8ToauR5R2801z2iKmIzl9tty4w7ythZcAX DaxHBBpnmBNRKMHDBiUfbgFuaqEwPFPDihS6/XL+Kmv7c2An/vfgejZMvL3MnV9h76PO7Hn/xlhTI R8qzgZAgSf5/yA==; From: =?UTF-8?q?Ludovic=20Court=C3=A8s?= <ludo@HIDDEN> To: 75810 <at> debbugs.gnu.org Subject: [PATCH v5 08/14] daemon: Drop Linux ambient capabilities before executing builder. Date: Fri, 14 Mar 2025 18:48:05 +0100 Message-ID: <579aae1bcbba126fb7a779ca53d3877b70bd110e.1741973869.git.ludo@HIDDEN> X-Mailer: git-send-email 2.48.1 In-Reply-To: <cover.1741973869.git.ludo@HIDDEN> References: <cover.1741973869.git.ludo@HIDDEN> MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit X-Spam-Score: -2.3 (--) X-Debbugs-Envelope-To: 75810 Cc: =?UTF-8?q?Ludovic=20Court=C3=A8s?= <ludo@HIDDEN> X-BeenThere: debbugs-submit <at> debbugs.gnu.org X-Mailman-Version: 2.1.18 Precedence: list List-Id: <debbugs-submit.debbugs.gnu.org> List-Unsubscribe: <https://debbugs.gnu.org/cgi-bin/mailman/options/debbugs-submit>, <mailto:debbugs-submit-request <at> debbugs.gnu.org?subject=unsubscribe> List-Archive: <https://debbugs.gnu.org/cgi-bin/mailman/private/debbugs-submit/> List-Post: <mailto:debbugs-submit <at> debbugs.gnu.org> List-Help: <mailto:debbugs-submit-request <at> debbugs.gnu.org?subject=help> List-Subscribe: <https://debbugs.gnu.org/cgi-bin/mailman/listinfo/debbugs-submit>, <mailto:debbugs-submit-request <at> debbugs.gnu.org?subject=subscribe> Errors-To: debbugs-submit-bounces <at> debbugs.gnu.org Sender: "Debbugs-submit" <debbugs-submit-bounces <at> debbugs.gnu.org> X-Spam-Score: -3.3 (---) * config-daemon.ac: Check for <sys/prctl.h>. * nix/libstore/build.cc (DerivationGoal::runChild): When ‘useChroot’ is true, call ‘prctl’ to drop all ambient capabilities. Change-Id: If34637fc508e5fb6d278167f5df7802fc595284f --- config-daemon.ac | 2 +- nix/libstore/build.cc | 9 +++++++++ 2 files changed, 10 insertions(+), 1 deletion(-) diff --git a/config-daemon.ac b/config-daemon.ac index 4e949bc88a..35d9c8cd56 100644 --- a/config-daemon.ac +++ b/config-daemon.ac @@ -79,7 +79,7 @@ if test "x$guix_build_daemon" = "xyes"; then dnl Chroot support. AC_CHECK_FUNCS([chroot unshare]) AC_CHECK_HEADERS([sched.h sys/param.h sys/mount.h sys/syscall.h \ - linux/close_range.h]) + linux/close_range.h sys/prctl.h]) if test "x$ac_cv_func_chroot" != "xyes"; then AC_MSG_ERROR(['chroot' function missing, bailing out]) diff --git a/nix/libstore/build.cc b/nix/libstore/build.cc index 76f75e00df..07c8ad7e1d 100644 --- a/nix/libstore/build.cc +++ b/nix/libstore/build.cc @@ -50,6 +50,9 @@ #if HAVE_SCHED_H #include <sched.h> #endif +#if HAVE_SYS_PRCTL_H +#include <sys/prctl.h> +#endif #define CHROOT_ENABLED HAVE_CHROOT && HAVE_SYS_MOUNT_H && defined(MS_BIND) && defined(MS_PRIVATE) @@ -2070,6 +2073,12 @@ void DerivationGoal::runChild() #if CHROOT_ENABLED if (useChroot) { +# if HAVE_SYS_PRCTL_H + /* Drop ambient capabilities such as CAP_CHOWN that might have + been granted when starting guix-daemon. */ + prctl(PR_CAP_AMBIENT, PR_CAP_AMBIENT_CLEAR_ALL, 0, 0, 0); +# endif + if (!fixedOutput) { /* Initialise the loopback interface. */ AutoCloseFD fd(socket(PF_INET, SOCK_DGRAM, IPPROTO_IP)); -- 2.48.1
guix-patches@HIDDEN
:bug#75810
; Package guix-patches
.
Full text available.Received: (at 75810) by debbugs.gnu.org; 14 Mar 2025 17:50:10 +0000 From debbugs-submit-bounces <at> debbugs.gnu.org Fri Mar 14 13:50:10 2025 Received: from localhost ([127.0.0.1]:36040 helo=debbugs.gnu.org) by debbugs.gnu.org with esmtp (Exim 4.84_2) (envelope-from <debbugs-submit-bounces <at> debbugs.gnu.org>) id 1tt9Ad-0004S2-Nx for submit <at> debbugs.gnu.org; Fri, 14 Mar 2025 13:50:10 -0400 Received: from eggs.gnu.org ([2001:470:142:3::10]:56590) by debbugs.gnu.org with esmtps (TLS1.2:ECDHE_RSA_AES_256_GCM_SHA384:256) (Exim 4.84_2) (envelope-from <ludo@HIDDEN>) id 1tt9AO-0004Ov-Fa for 75810 <at> debbugs.gnu.org; Fri, 14 Mar 2025 13:49:54 -0400 Received: from fencepost.gnu.org ([2001:470:142:3::e]) by eggs.gnu.org with esmtps (TLS1.2:ECDHE_RSA_AES_256_GCM_SHA384:256) (Exim 4.90_1) (envelope-from <ludo@HIDDEN>) id 1tt9AH-0001yY-C1; Fri, 14 Mar 2025 13:49:45 -0400 DKIM-Signature: v=1; a=rsa-sha256; q=dns/txt; c=relaxed/relaxed; d=gnu.org; s=fencepost-gnu-org; h=MIME-Version:References:In-Reply-To:Date:Subject:To: From; bh=BCS7CA2n9xDeHpz/nXwjL/1CgpmeOGUI+SjqwJ9Ij+I=; b=iNxwzNh2ZW6bL6wf2ayG Zvm7pwg7u18RaY8It9WhZIFyq1n+SeeZja5IfXAksKOqWVckK0Soyg6QF3KGcvBBDyYZYoxqbs/Rv A2vQtmTJV8IGiNocNCytZhapU7I/wQBs0SaJHiXHQuYrXTls0YorninYjGSAlh7RYft1wSvf3pfyd JOIC4YO41c0s991rFEglPxCsp2j0tlpQI7JOSLpHMFEtpiupD6VUn0IXk72aczRlG02q9EJ5i5fPE 4xliVRKXJ2ytXtf9LJ/6eLCZRBKSSCngV4/CeGXlmOOJwKdlg2o6iBMCwYOY1Puuzc69rOq+c0iIl 6ogSGGGpGd+XsA==; From: =?UTF-8?q?Ludovic=20Court=C3=A8s?= <ludo@HIDDEN> To: 75810 <at> debbugs.gnu.org Subject: [PATCH v5 06/14] daemon: Allow running as non-root with unprivileged user namespaces. Date: Fri, 14 Mar 2025 18:48:03 +0100 Message-ID: <067fd1219aa1b4354c0a321dc7e2a7d414eabf1b.1741973869.git.ludo@HIDDEN> X-Mailer: git-send-email 2.48.1 In-Reply-To: <cover.1741973869.git.ludo@HIDDEN> References: <cover.1741973869.git.ludo@HIDDEN> MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 X-Debbugs-Cc: Christopher Baines <guix@HIDDEN>, Josselin Poiret <dev@HIDDEN>, Ludovic Courtès <ludo@HIDDEN>, Mathieu Othacehe <othacehe@HIDDEN>, Maxim Cournoyer <maxim.cournoyer@HIDDEN>, Simon Tournier <zimon.toutoune@HIDDEN>, Tobias Geerinckx-Rice <me@HIDDEN> Content-Transfer-Encoding: 8bit X-Spam-Score: -1.8 (-) X-Debbugs-Envelope-To: 75810 Cc: =?UTF-8?q?Ludovic=20Court=C3=A8s?= <ludovic.courtes@HIDDEN>, Reepca Russelstein <reepca@HIDDEN> X-BeenThere: debbugs-submit <at> debbugs.gnu.org X-Mailman-Version: 2.1.18 Precedence: list List-Id: <debbugs-submit.debbugs.gnu.org> List-Unsubscribe: <https://debbugs.gnu.org/cgi-bin/mailman/options/debbugs-submit>, <mailto:debbugs-submit-request <at> debbugs.gnu.org?subject=unsubscribe> List-Archive: <https://debbugs.gnu.org/cgi-bin/mailman/private/debbugs-submit/> List-Post: <mailto:debbugs-submit <at> debbugs.gnu.org> List-Help: <mailto:debbugs-submit-request <at> debbugs.gnu.org?subject=help> List-Subscribe: <https://debbugs.gnu.org/cgi-bin/mailman/listinfo/debbugs-submit>, <mailto:debbugs-submit-request <at> debbugs.gnu.org?subject=subscribe> Errors-To: debbugs-submit-bounces <at> debbugs.gnu.org Sender: "Debbugs-submit" <debbugs-submit-bounces <at> debbugs.gnu.org> X-Spam-Score: -2.8 (--) From: Ludovic Courtès <ludovic.courtes@HIDDEN> Many thanks to Reepca Russelstein for their review and guidance on these changes. * nix/libstore/build.cc (guestUID, guestGID): New variables. (DerivationGoal)[readiness]: New field. (initializeUserNamespace): New function. (DerivationGoal::runChild): When ‘readiness.readSide’ is positive, read from it. (DerivationGoal::startBuilder): Call ‘chown’ only when ‘buildUser.enabled()’ is true. Pass CLONE_NEWUSER to ‘clone’ when ‘buildUser.enabled()’ is false or not running as root. Retry ‘clone’ without CLONE_NEWUSER upon EPERM. (DerivationGoal::registerOutputs): Make ‘actualPath’ writable before ‘rename’. (DerivationGoal::deleteTmpDir): Catch ‘SysError’ around ‘_chown’ call. * nix/libstore/local-store.cc (LocalStore::createUser): Do nothing if ‘dirs’ already exists. Warn instead of failing when failing to chown ‘dir’. * guix/substitutes.scm (%narinfo-cache-directory): Check for ‘_NIX_OPTIONS’ rather than getuid() == 0 to determine the cache location. * doc/guix.texi (Build Environment Setup): Reorganize a bit. Add section headings “Daemon Running as Root” and “The Isolated Build Environment”. Add “Daemon Running Without Privileges” subsection. Remove paragraph about ‘--disable-chroot’. (Invoking guix-daemon): Warn against ‘--disable-chroot’ and explain why. Reviewed-by: Reepca Russelstein <reepca@HIDDEN> --- doc/guix.texi | 102 +++++++++++++++++------ guix/substitutes.scm | 2 +- nix/libstore/build.cc | 156 +++++++++++++++++++++++++++++++----- nix/libstore/local-store.cc | 18 +++-- 4 files changed, 225 insertions(+), 53 deletions(-) diff --git a/doc/guix.texi b/doc/guix.texi index d109877a32..66d0e42112 100644 --- a/doc/guix.texi +++ b/doc/guix.texi @@ -877,6 +877,7 @@ Setting Up the Daemon @section Setting Up the Daemon @cindex daemon +@cindex build daemon During installation, the @dfn{build daemon} that must be running to use Guix has already been set up and you can run @command{guix} commands in your terminal program, @pxref{Getting Started}: @@ -921,20 +922,38 @@ Build Environment Setup @cindex build environment In a standard multi-user setup, Guix and its daemon---the @command{guix-daemon} program---are installed by the system -administrator; @file{/gnu/store} is owned by @code{root} and -@command{guix-daemon} runs as @code{root}. Unprivileged users may use -Guix tools to build packages or otherwise access the store, and the -daemon will do it on their behalf, ensuring that the store is kept in a -consistent state, and allowing built packages to be shared among users. +administrator. Unprivileged users may use Guix tools to build packages +or otherwise access the store, and the daemon will do it on their +behalf, ensuring that the store is kept in a consistent state, and +allowing built packages to be shared among users. + +There are currently two ways to set up and run the build daemon: + +@enumerate +@item +running @command{guix-daemon} as ``root'', letting it run build +processes as unprivileged users taken from a pool of build users---this +is the historical approach; + +@item +running @command{guix-daemon} as a separate unprivileged user, relying +on Linux's @dfn{unprivileged user namespace} functionality to set up +isolated environments---this is the option chosen when installing Guix +on a systemd-based distribution with the installation script +(@pxref{Binary Installation}). +@end enumerate + +The sections below describe each of these two configurations in more +detail and summarize the kind of build isolation they provide. + +@unnumberedsubsubsec Daemon Running as Root @cindex build users When @command{guix-daemon} runs as @code{root}, you may not want package build processes themselves to run as @code{root} too, for obvious security reasons. To avoid that, a special pool of @dfn{build users} should be created for use by build processes started by the daemon. -These build users need not have a shell and a home directory: they will -just be used when the daemon drops @code{root} privileges in build -processes. Having several such users allows the daemon to launch +Having several such users allows the daemon to launch distinct build processes under separate UIDs, which guarantees that they do not interfere with each other---an essential feature since builds are regarded as pure functions (@pxref{Introduction}). @@ -977,11 +996,45 @@ Build Environment Setup # guix-daemon --build-users-group=guixbuild @end example +In this setup, @file{/gnu/store} is owned by @code{root}. + +@unnumberedsubsubsec Daemon Running Without Privileges + +@cindex rootless build daemon +@cindex unprivileged build daemon +@cindex build daemon, unprivileged +The second and preferred option is to run @command{guix-daemon} +@emph{as an unprivileged user}. It has the advantage of reducing the +harm that can be done should a build process manage to exploit a +vulnerability in the daemon. This option requires the user of Linux's +unprivileged user namespace mechanism; today it is available and enabled +by most GNU/Linux distributions but can still be disabled. The +installation script automatically determines whether this option is +available on your system (@pxref{Binary Installation}). + +When using this option, you only need to create one user account, and +@command{guix-daemon} will run with the authority of that account: + +@example +# groupadd --system guix-daemon +# useradd -g guix-daemon -G guix-daemon \ + -d /var/empty -s $(which nologin) \ + -c "Guix daemon privilege separation user" \ + --system guix-daemon +@end example + +In this configuration, @file{/gnu/store} is owned by the +@code{guix-daemon} user. + +@unnumberedsubsubsec The Isolated Build Environment + @cindex chroot -@noindent -This way, the daemon starts build processes in a chroot, under one of -the @code{guixbuilder} users. On GNU/Linux, by default, the chroot -environment contains nothing but: +@cindex build environment isolation +@cindex isolated build environment +@cindex hermetic build environment +In both cases, the daemon starts build processes without privileges in +an @emph{isolated} or @emph{hermetic} build environment---a ``chroot''. +On GNU/Linux, by default, the build environment contains nothing but: @c Keep this list in sync with libstore/build.cc! ----------------------- @itemize @@ -1015,7 +1068,7 @@ Build Environment Setup @file{/homeless-shelter}. This helps to highlight inappropriate uses of @env{HOME} in the build scripts of packages. -All this usually enough to ensure details of the environment do not +All this is usually enough to ensure details of the environment do not influence build processes. In some exceptional cases where more control is needed---typically over the date, kernel, or CPU---you can resort to a virtual build machine (@pxref{build-vm, virtual build machines}). @@ -1035,14 +1088,6 @@ Build Environment Setup for fixed-output derivations (@pxref{Derivations}) or for substitutes (@pxref{Substitutes}). -If you are installing Guix as an unprivileged user, it is still possible -to run @command{guix-daemon} provided you pass @option{--disable-chroot}. -However, build processes will not be isolated from one another, and not -from the rest of the system. Thus, build processes may interfere with -each other, and may access programs, libraries, and other files -available on the system---making it much harder to view them as -@emph{pure} functions. - @node Daemon Offload Setup @subsection Using the Offload Facility @@ -1567,10 +1612,17 @@ Invoking guix-daemon @item --disable-chroot Disable chroot builds. -Using this option is not recommended since, again, it would allow build -processes to gain access to undeclared dependencies. It is necessary, -though, when @command{guix-daemon} is running under an unprivileged user -account. +@quotation Warning +Using this option is not recommended since it allows build processes to +gain access to undeclared dependencies, to interfere with one another, +and more generally to do anything that can be done with the authority of +the daemon---which includes at least the ability to tamper with any file +in the store! + +You may find it necessary, though, when support for Linux unprivileged +user namespaces is missing (@pxref{Build Environment Setup}). Use at +your own risk! +@end quotation @item --log-compression=@var{type} Compress build logs according to @var{type}, one of @code{gzip}, diff --git a/guix/substitutes.scm b/guix/substitutes.scm index 7ca55788d5..86b9f5472a 100644 --- a/guix/substitutes.scm +++ b/guix/substitutes.scm @@ -79,7 +79,7 @@ (define %narinfo-cache-directory ;; time, 'guix substitute' is called by guix-daemon as root and stores its ;; cached data in /var/guix/…. However, when invoked from 'guix challenge' ;; as a user, it stores its cache in ~/.cache. - (if (zero? (getuid)) + (if (getenv "_NIX_OPTIONS") ;invoked by guix-daemon (or (and=> (getenv "XDG_CACHE_HOME") (cut string-append <> "/guix/substitute")) (string-append %state-directory "/substitute/cache")) diff --git a/nix/libstore/build.cc b/nix/libstore/build.cc index c8b778362a..76f75e00df 100644 --- a/nix/libstore/build.cc +++ b/nix/libstore/build.cc @@ -744,6 +744,10 @@ private: friend int childEntry(void *); + /* Pipe to notify readiness to the child process when using unprivileged + user namespaces. */ + Pipe readiness; + /* Check that the derivation outputs all exist and register them as valid. */ void registerOutputs(); @@ -1619,6 +1623,24 @@ int childEntry(void * arg) } +/* UID and GID of the build user inside its own user namespace. */ +static const uid_t guestUID = 30001; +static const gid_t guestGID = 30000; + +/* Initialize the user namespace of CHILD. */ +static void initializeUserNamespace(pid_t child, + uid_t hostUID = getuid(), + gid_t hostGID = getgid()) +{ + writeFile("/proc/" + std::to_string(child) + "/uid_map", + (format("%d %d 1") % guestUID % hostUID).str()); + + writeFile("/proc/" + std::to_string(child) + "/setgroups", "deny"); + + writeFile("/proc/" + std::to_string(child) + "/gid_map", + (format("%d %d 1") % guestGID % hostGID).str()); +} + void DerivationGoal::startBuilder() { auto f = format( @@ -1682,7 +1704,7 @@ void DerivationGoal::startBuilder() then an attacker could create in it a hardlink to a root-owned file such as /etc/shadow. If 'keepFailed' is true, the daemon would then chown that hardlink to the user, giving them write access to - that file. */ + that file. See CVE-2021-27851. */ tmpDir += "/top"; if (mkdir(tmpDir.c_str(), 0700) == 1) throw SysError("creating top-level build directory"); @@ -1799,7 +1821,7 @@ void DerivationGoal::startBuilder() if (mkdir(chrootRootDir.c_str(), 0750) == -1) throw SysError(format("cannot create ‘%1%’") % chrootRootDir); - if (chown(chrootRootDir.c_str(), 0, buildUser.getGID()) == -1) + if (buildUser.enabled() && chown(chrootRootDir.c_str(), 0, buildUser.getGID()) == -1) throw SysError(format("cannot change ownership of ‘%1%’") % chrootRootDir); /* Create a writable /tmp in the chroot. Many builders need @@ -1818,8 +1840,8 @@ void DerivationGoal::startBuilder() (format( "nixbld:x:%1%:%2%:Nix build user:/:/noshell\n" "nobody:x:65534:65534:Nobody:/:/noshell\n") - % (buildUser.enabled() ? buildUser.getUID() : getuid()) - % (buildUser.enabled() ? buildUser.getGID() : getgid())).str()); + % (buildUser.enabled() ? buildUser.getUID() : guestUID) + % (buildUser.enabled() ? buildUser.getGID() : guestGID)).str()); /* Declare the build user's group so that programs get a consistent view of the system (e.g., "id -gn"). */ @@ -1854,7 +1876,7 @@ void DerivationGoal::startBuilder() createDirs(chrootStoreDir); chmod_(chrootStoreDir, 01775); - if (chown(chrootStoreDir.c_str(), 0, buildUser.getGID()) == -1) + if (buildUser.enabled() && chown(chrootStoreDir.c_str(), 0, buildUser.getGID()) == -1) throw SysError(format("cannot change ownership of ‘%1%’") % chrootStoreDir); foreach (PathSet::iterator, i, inputPaths) { @@ -1960,14 +1982,34 @@ void DerivationGoal::startBuilder() if (useChroot) { char stack[32 * 1024]; int flags = CLONE_NEWPID | CLONE_NEWNS | CLONE_NEWIPC | CLONE_NEWUTS | SIGCHLD; - if (!fixedOutput) flags |= CLONE_NEWNET; + if (!fixedOutput) { + flags |= CLONE_NEWNET; + } + if (!buildUser.enabled() || getuid() != 0) { + flags |= CLONE_NEWUSER; + readiness.create(); + } + /* Ensure proper alignment on the stack. On aarch64, it has to be 16 bytes. */ - pid = clone(childEntry, + pid = clone(childEntry, (char *)(((uintptr_t)stack + sizeof(stack) - 8) & ~(uintptr_t)0xf), flags, this); - if (pid == -1) - throw SysError("cloning builder process"); + if (pid == -1) { + if ((flags & CLONE_NEWUSER) != 0 && getuid() != 0) + /* 'clone' fails with EPERM on distros where unprivileged user + namespaces are disabled. Error out instead of giving up on + isolation. */ + throw SysError("cannot create process in unprivileged user namespace"); + else + throw SysError("cloning builder process"); + } + + if ((flags & CLONE_NEWUSER) != 0) { + /* Initialize the UID/GID mapping of the child process. */ + initializeUserNamespace(pid); + writeFull(readiness.writeSide, (unsigned char*)"go\n", 3); + } } else #endif { @@ -2013,23 +2055,34 @@ void DerivationGoal::runChild() _writeToStderr = 0; + if (readiness.readSide > 0) { + /* Wait for the parent process to initialize the UID/GID mapping + of our user namespace. */ + char str[20] = { '\0' }; + readFull(readiness.readSide, (unsigned char*)str, 3); + if (strcmp(str, "go\n") != 0) + throw Error("failed to initialize process in unprivileged user namespace"); + } + restoreAffinity(); commonChildInit(builderOut); #if CHROOT_ENABLED if (useChroot) { - /* Initialise the loopback interface. */ - AutoCloseFD fd(socket(PF_INET, SOCK_DGRAM, IPPROTO_IP)); - if (fd == -1) throw SysError("cannot open IP socket"); + if (!fixedOutput) { + /* Initialise the loopback interface. */ + AutoCloseFD fd(socket(PF_INET, SOCK_DGRAM, IPPROTO_IP)); + if (fd == -1) throw SysError("cannot open IP socket"); - struct ifreq ifr; - strcpy(ifr.ifr_name, "lo"); - ifr.ifr_flags = IFF_UP | IFF_LOOPBACK | IFF_RUNNING; - if (ioctl(fd, SIOCSIFFLAGS, &ifr) == -1) - throw SysError("cannot set loopback interface flags"); + struct ifreq ifr; + strcpy(ifr.ifr_name, "lo"); + ifr.ifr_flags = IFF_UP | IFF_LOOPBACK | IFF_RUNNING; + if (ioctl(fd, SIOCSIFFLAGS, &ifr) == -1) + throw SysError("cannot set loopback interface flags"); - fd.close(); + fd.close(); + } /* Set the hostname etc. to fixed values. */ char hostname[] = "localhost"; @@ -2180,6 +2233,27 @@ void DerivationGoal::runChild() /* Remount root as read-only. */ if (mount("/", "/", 0, MS_BIND | MS_REMOUNT | MS_RDONLY, 0) == -1) throw SysError(format("read-only remount of build root '%1%' failed") % chrootRootDir); + + if (getuid() != 0) { + /* Create a new mount namespace to "lock" previous mounts. + See mount_namespaces(7). */ + auto uid = getuid(); + auto gid = getgid(); + + if (unshare(CLONE_NEWNS | CLONE_NEWUSER) == -1) + throw SysError(format("creating new user and mount namespaces")); + + initializeUserNamespace(getpid(), uid, gid); + + /* Check that mounts within the build environment are "locked" + together and cannot be separated from within the build + environment namespace. Since + umount(2) is documented to fail with EINVAL when attempting + to unmount one of the mounts that are locked together, + check that this is what we get. */ + int ret = umount(tmpDirInSandbox.c_str()); + assert(ret == -1 && errno == EINVAL); + } } #endif @@ -2476,8 +2550,16 @@ void DerivationGoal::registerOutputs() 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) { + if (S_ISDIR(st.st_mode)) + /* Change mode on the directory to allow for + rename(2). */ + chmod(actualPath.c_str(), st.st_mode | 0700); + if (rename(actualPath.c_str(), path.c_str()) == -1) + throw SysError(format("moving build output `%1%' from the chroot to the store") % path); + if (S_ISDIR(st.st_mode) && chmod(path.c_str(), st.st_mode) == -1) + throw SysError(format("restoring permissions on directory `%1%'") % actualPath); + } } if (buildMode != bmCheck) actualPath = path; } @@ -2736,16 +2818,46 @@ void DerivationGoal::deleteTmpDir(bool force) // Change the ownership if clientUid is set. Never change the // ownership or the group to "root" for security reasons. if (settings.clientUid != (uid_t) -1 && settings.clientUid != 0) { - _chown(tmpDir, settings.clientUid, - settings.clientGid != 0 ? settings.clientGid : -1); + uid_t uid = settings.clientUid; + gid_t gid = settings.clientGid != 0 ? settings.clientGid : -1; + bool reown = false; + + /* First remove setuid/setgid bits. */ + secureFilePerms(tmpDir); + + try { + _chown(tmpDir, uid, gid); + + if (getuid() != 0) { + /* If, without being root, the '_chown' call above + succeeded, then it means we have CAP_CHOWN. Retake + ownership of tmpDir itself so it can be renamed + below. */ + reown = true; + } + + } catch (SysError & e) { + /* When running as an unprivileged user and without + CAP_CHOWN, we cannot chown the build tree. Print a + message and keep going. */ + printMsg(lvlInfo, format("cannot change ownership of build directory '%1%': %2%") + % tmpDir % strerror(e.errNo)); + } if (top != tmpDir) { + if (reown) chown(tmpDir.c_str(), getuid(), getgid()); + // Rename tmpDir to its parent, with an intermediate step. string pivot = top + ".pivot"; if (rename(top.c_str(), pivot.c_str()) == -1) throw SysError("pivoting failed build tree"); if (rename((pivot + "/top").c_str(), top.c_str()) == -1) throw SysError("renaming failed build tree"); + + if (reown) + /* Running unprivileged but with CAP_CHOWN. */ + chown(top.c_str(), uid, gid); + rmdir(pivot.c_str()); } } diff --git a/nix/libstore/local-store.cc b/nix/libstore/local-store.cc index 0883a4bbce..83e6c3e16e 100644 --- a/nix/libstore/local-store.cc +++ b/nix/libstore/local-store.cc @@ -1614,11 +1614,19 @@ void LocalStore::createUser(const std::string & userName, uid_t userId) { auto dir = settings.nixStateDir + "/profiles/per-user/" + userName; - createDirs(dir); - if (chmod(dir.c_str(), 0755) == -1) - throw SysError(format("changing permissions of directory '%s'") % dir); - if (chown(dir.c_str(), userId, -1) == -1) - throw SysError(format("changing owner of directory '%s'") % dir); + auto created = createDirs(dir); + if (!created.empty()) { + if (chmod(dir.c_str(), 0755) == -1) + throw SysError(format("changing permissions of directory '%s'") % dir); + + /* The following operation requires CAP_CHOWN or can be handled + manually by a user with CAP_CHOWN. */ + if (chown(dir.c_str(), userId, -1) == -1) { + rmdir(dir.c_str()); + string message = strerror(errno); + printMsg(lvlInfo, format("failed to change owner of directory '%1%' to %2%: %3%") % dir % userId % message); + } + } } -- 2.48.1
guix@HIDDEN, dev@HIDDEN, ludo@HIDDEN, othacehe@HIDDEN, maxim.cournoyer@HIDDEN, zimon.toutoune@HIDDEN, me@HIDDEN, guix-patches@HIDDEN
:bug#75810
; Package guix-patches
.
Full text available.Received: (at 75810) by debbugs.gnu.org; 14 Mar 2025 17:50:08 +0000 From debbugs-submit-bounces <at> debbugs.gnu.org Fri Mar 14 13:50:07 2025 Received: from localhost ([127.0.0.1]:36037 helo=debbugs.gnu.org) by debbugs.gnu.org with esmtp (Exim 4.84_2) (envelope-from <debbugs-submit-bounces <at> debbugs.gnu.org>) id 1tt9Ad-0004Ro-0f for submit <at> debbugs.gnu.org; Fri, 14 Mar 2025 13:50:07 -0400 Received: from eggs.gnu.org ([2001:470:142:3::10]:56584) by debbugs.gnu.org with esmtps (TLS1.2:ECDHE_RSA_AES_256_GCM_SHA384:256) (Exim 4.84_2) (envelope-from <ludo@HIDDEN>) id 1tt9AO-0004Ou-7U for 75810 <at> debbugs.gnu.org; Fri, 14 Mar 2025 13:49:52 -0400 Received: from fencepost.gnu.org ([2001:470:142:3::e]) by eggs.gnu.org with esmtps (TLS1.2:ECDHE_RSA_AES_256_GCM_SHA384:256) (Exim 4.90_1) (envelope-from <ludo@HIDDEN>) id 1tt9AI-0001yf-Pm; Fri, 14 Mar 2025 13:49:46 -0400 DKIM-Signature: v=1; a=rsa-sha256; q=dns/txt; c=relaxed/relaxed; d=gnu.org; s=fencepost-gnu-org; h=MIME-Version:References:In-Reply-To:Date:Subject:To: From; bh=wZDaJpSBiec4HWURn73Fvz7bhdz1AmvaDkV9vu9Mxas=; b=Wgbn8aA26jwmIJfRLGDy Q4ZXa7YQl4XpZ+JrvAHYM5LCKM9znFPedKEUYR20Y+FOqRHEyExU7fpYn38kmNn0TwYStjNvThNpz lRdxgIuij6PlbLu5++eDIfoyW+laQwpsAPZtZFUrl8IcOXD0krBPlHdXjN6rZZvZZzCHXAwJPPukO O4OH3LRrg/+E23cRJRsznuOuBXRkgOJdHJFhTH1ioFpm9C4f6v6kl8XQvAaNvIBejv8puyP0vzv+W jtTivZJfI8yPWeSlneJcz/cwiTxazbEI18V4Vc6Wn6SI6D4QZ0LKK1boVsghoawhUYGRQu8sL/j0V Un+rhCQpWCrm3Q==; From: =?UTF-8?q?Ludovic=20Court=C3=A8s?= <ludo@HIDDEN> To: 75810 <at> debbugs.gnu.org Subject: [PATCH v5 07/14] daemon: Create /var/guix/profiles/per-user unconditionally. Date: Fri, 14 Mar 2025 18:48:04 +0100 Message-ID: <f9250ac8847822dd25562daf2975acd87abedb8e.1741973869.git.ludo@HIDDEN> X-Mailer: git-send-email 2.48.1 In-Reply-To: <cover.1741973869.git.ludo@HIDDEN> References: <cover.1741973869.git.ludo@HIDDEN> MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit X-Spam-Score: -2.3 (--) X-Debbugs-Envelope-To: 75810 Cc: =?UTF-8?q?Ludovic=20Court=C3=A8s?= <ludo@HIDDEN> X-BeenThere: debbugs-submit <at> debbugs.gnu.org X-Mailman-Version: 2.1.18 Precedence: list List-Id: <debbugs-submit.debbugs.gnu.org> List-Unsubscribe: <https://debbugs.gnu.org/cgi-bin/mailman/options/debbugs-submit>, <mailto:debbugs-submit-request <at> debbugs.gnu.org?subject=unsubscribe> List-Archive: <https://debbugs.gnu.org/cgi-bin/mailman/private/debbugs-submit/> List-Post: <mailto:debbugs-submit <at> debbugs.gnu.org> List-Help: <mailto:debbugs-submit-request <at> debbugs.gnu.org?subject=help> List-Subscribe: <https://debbugs.gnu.org/cgi-bin/mailman/listinfo/debbugs-submit>, <mailto:debbugs-submit-request <at> debbugs.gnu.org?subject=subscribe> Errors-To: debbugs-submit-bounces <at> debbugs.gnu.org Sender: "Debbugs-submit" <debbugs-submit-bounces <at> debbugs.gnu.org> X-Spam-Score: -3.3 (---) * nix/libstore/local-store.cc (LocalStore::LocalStore): Create ‘perUserDir’ unconditionally. Change-Id: I5188320f9630a81d16f79212d0fffabd55d94abe --- nix/libstore/local-store.cc | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/nix/libstore/local-store.cc b/nix/libstore/local-store.cc index 83e6c3e16e..f6540c2117 100644 --- a/nix/libstore/local-store.cc +++ b/nix/libstore/local-store.cc @@ -79,12 +79,12 @@ LocalStore::LocalStore(bool reserveSpace) createSymlink(profilesDir, gcRootsDir + "/profiles"); } - /* Optionally, create directories and set permissions for a - multi-user install. */ + Path perUserDir = profilesDir + "/per-user"; + createDirs(perUserDir); + + /* Optionally, set permissions for a multi-user install. */ if (getuid() == 0 && settings.buildUsersGroup != "") { - Path perUserDir = profilesDir + "/per-user"; - createDirs(perUserDir); if (chmod(perUserDir.c_str(), 0755) == -1) throw SysError(format("could not set permissions on '%1%' to 755") % perUserDir); -- 2.48.1
guix-patches@HIDDEN
:bug#75810
; Package guix-patches
.
Full text available.Received: (at 75810) by debbugs.gnu.org; 14 Mar 2025 17:50:07 +0000 From debbugs-submit-bounces <at> debbugs.gnu.org Fri Mar 14 13:50:07 2025 Received: from localhost ([127.0.0.1]:36034 helo=debbugs.gnu.org) by debbugs.gnu.org with esmtp (Exim 4.84_2) (envelope-from <debbugs-submit-bounces <at> debbugs.gnu.org>) id 1tt9Ab-0004Rc-Ti for submit <at> debbugs.gnu.org; Fri, 14 Mar 2025 13:50:06 -0400 Received: from eggs.gnu.org ([2001:470:142:3::10]:56554) by debbugs.gnu.org with esmtps (TLS1.2:ECDHE_RSA_AES_256_GCM_SHA384:256) (Exim 4.84_2) (envelope-from <ludo@HIDDEN>) id 1tt9AH-0004OH-Ef for 75810 <at> debbugs.gnu.org; Fri, 14 Mar 2025 13:49:49 -0400 Received: from fencepost.gnu.org ([2001:470:142:3::e]) by eggs.gnu.org with esmtps (TLS1.2:ECDHE_RSA_AES_256_GCM_SHA384:256) (Exim 4.90_1) (envelope-from <ludo@HIDDEN>) id 1tt9AB-0001xm-Bf; Fri, 14 Mar 2025 13:49:39 -0400 DKIM-Signature: v=1; a=rsa-sha256; q=dns/txt; c=relaxed/relaxed; d=gnu.org; s=fencepost-gnu-org; h=MIME-Version:References:In-Reply-To:Date:Subject:To: From; bh=OHeVSHlKl++yMNnhWaubdTXXSn3UUkG8AbIkWMisgq8=; b=qe02UEo+E68VDIFbgIp/ OhKt97sgCqgY1fMQjxjOxwHBqpKpKmvMQlIzurHbOl66tub74qgitQ5eakLn9ZCIv/pCZXEnbZy/Q zC4zIcwu1Xu19M0judXDOOEtMQkAkAN3ECJxc/BNj1ynom3auSWyijHeXSeW1FCfk5RfAkDoAE4t0 SvpEtk1NeiJdkMBznMoOeoYs4Cir34TnYf5uv6QOOHppzN/ISDqDKfMH3nUkyTyju1DS++BhEQ/Wt aUMYXUMmWR/D4AbiR3trQRlXvUerHvxcqSw5XHkT+3abPYiPfFZk3HTlJVA+WjJo7P/RcOBEGVR9m TRSPyp8DeXmgCQ==; From: =?UTF-8?q?Ludovic=20Court=C3=A8s?= <ludo@HIDDEN> To: 75810 <at> debbugs.gnu.org Subject: [PATCH v5 03/14] daemon: Bind-mount all the inputs, not just directories. Date: Fri, 14 Mar 2025 18:48:00 +0100 Message-ID: <30fc8ecc23bcb583a30d869bd9c229b775a34ef1.1741973869.git.ludo@HIDDEN> X-Mailer: git-send-email 2.48.1 In-Reply-To: <cover.1741973869.git.ludo@HIDDEN> References: <cover.1741973869.git.ludo@HIDDEN> MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit X-Spam-Score: -1.8 (-) X-Debbugs-Envelope-To: 75810 Cc: =?UTF-8?q?Ludovic=20Court=C3=A8s?= <ludo@HIDDEN>, Reepca Russelstein <reepca@HIDDEN> X-BeenThere: debbugs-submit <at> debbugs.gnu.org X-Mailman-Version: 2.1.18 Precedence: list List-Id: <debbugs-submit.debbugs.gnu.org> List-Unsubscribe: <https://debbugs.gnu.org/cgi-bin/mailman/options/debbugs-submit>, <mailto:debbugs-submit-request <at> debbugs.gnu.org?subject=unsubscribe> List-Archive: <https://debbugs.gnu.org/cgi-bin/mailman/private/debbugs-submit/> List-Post: <mailto:debbugs-submit <at> debbugs.gnu.org> List-Help: <mailto:debbugs-submit-request <at> debbugs.gnu.org?subject=help> List-Subscribe: <https://debbugs.gnu.org/cgi-bin/mailman/listinfo/debbugs-submit>, <mailto:debbugs-submit-request <at> debbugs.gnu.org?subject=subscribe> Errors-To: debbugs-submit-bounces <at> debbugs.gnu.org Sender: "Debbugs-submit" <debbugs-submit-bounces <at> debbugs.gnu.org> X-Spam-Score: -2.8 (--) * nix/libstore/build.cc (DerivationGoal::startBuilder): Add all of ‘inputPaths’ to ‘dirsInChroot’ instead of hard-linking regular files. Special-case symlinks. (DerivationGoal)[regularInputPaths]: Remove. Reported-by: Reepca Russelstein <reepca@HIDDEN> Change-Id: I070987f92d73f187f7826a975bee9ee309d67f56 --- nix/libstore/build.cc | 39 ++++++++++++++------------------------- 1 file changed, 14 insertions(+), 25 deletions(-) diff --git a/nix/libstore/build.cc b/nix/libstore/build.cc index 8ca5e5b732..193b279b88 100644 --- a/nix/libstore/build.cc +++ b/nix/libstore/build.cc @@ -659,9 +659,6 @@ private: /* RAII object to delete the chroot directory. */ std::shared_ptr<AutoDelete> autoDelChroot; - /* All inputs that are regular files. */ - PathSet regularInputPaths; - /* Whether this is a fixed-output derivation. */ bool fixedOutput; @@ -1850,9 +1847,7 @@ void DerivationGoal::startBuilder() /* Make the closure of the inputs available in the chroot, rather than the whole store. This prevents any access - to undeclared dependencies. Directories are bind-mounted, - while other inputs are hard-linked (since only directories - can be bind-mounted). !!! As an extra security + to undeclared dependencies. !!! As an extra security precaution, make the fake store only writable by the build user. */ Path chrootStoreDir = chrootRootDir + settings.nixStore; @@ -1863,28 +1858,22 @@ void DerivationGoal::startBuilder() throw SysError(format("cannot change ownership of ‘%1%’") % chrootStoreDir); foreach (PathSet::iterator, i, inputPaths) { - struct stat st; + struct stat st; if (lstat(i->c_str(), &st)) throw SysError(format("getting attributes of path `%1%'") % *i); - if (S_ISDIR(st.st_mode)) - dirsInChroot[*i] = *i; - else { - Path p = chrootRootDir + *i; - if (link(i->c_str(), p.c_str()) == -1) { - /* Hard-linking fails if we exceed the maximum - link count on a file (e.g. 32000 of ext3), - which is quite possible after a `nix-store - --optimise'. */ - if (errno != EMLINK) - throw SysError(format("linking `%1%' to `%2%'") % p % *i); - StringSink sink; - dumpPath(*i, sink); - StringSource source(sink.s); - restorePath(p, source); - } - regularInputPaths.insert(*i); - } + if (S_ISLNK(st.st_mode)) { + /* Since bind-mounts follow symlinks, thus representing their + target and not the symlink itself, special-case + symlinks. XXX: When running unprivileged, TARGET can be + deleted by the build process. Use 'open_tree' & co. when + it's more widely available. */ + Path target = chrootRootDir + *i; + if (symlink(readLink(*i).c_str(), target.c_str()) == -1) + throw SysError(format("failed to create symlink '%1%' to '%2%'") % target % readLink(*i)); + } + else + dirsInChroot[*i] = *i; } /* If we're repairing, checking or rebuilding part of a -- 2.48.1
guix-patches@HIDDEN
:bug#75810
; Package guix-patches
.
Full text available.Received: (at 75810) by debbugs.gnu.org; 14 Mar 2025 17:50:06 +0000 From debbugs-submit-bounces <at> debbugs.gnu.org Fri Mar 14 13:50:05 2025 Received: from localhost ([127.0.0.1]:36030 helo=debbugs.gnu.org) by debbugs.gnu.org with esmtp (Exim 4.84_2) (envelope-from <debbugs-submit-bounces <at> debbugs.gnu.org>) id 1tt9AZ-0004Qz-78 for submit <at> debbugs.gnu.org; Fri, 14 Mar 2025 13:50:05 -0400 Received: from eggs.gnu.org ([2001:470:142:3::10]:56568) by debbugs.gnu.org with esmtps (TLS1.2:ECDHE_RSA_AES_256_GCM_SHA384:256) (Exim 4.84_2) (envelope-from <ludo@HIDDEN>) id 1tt9AM-0004Ob-1i for 75810 <at> debbugs.gnu.org; Fri, 14 Mar 2025 13:49:50 -0400 Received: from fencepost.gnu.org ([2001:470:142:3::e]) by eggs.gnu.org with esmtps (TLS1.2:ECDHE_RSA_AES_256_GCM_SHA384:256) (Exim 4.90_1) (envelope-from <ludo@HIDDEN>) id 1tt9AE-0001y3-HA; Fri, 14 Mar 2025 13:49:42 -0400 DKIM-Signature: v=1; a=rsa-sha256; q=dns/txt; c=relaxed/relaxed; d=gnu.org; s=fencepost-gnu-org; h=MIME-Version:References:In-Reply-To:Date:Subject:To: From; bh=ozQM+lYqSSPDiTg6Dp/w4oPIGKDs4CrGaOeKp99rZWg=; b=Y0ED6kK0RtGST4cPwnjd Ao+wJWQ7PEE+lyNXYE+KWeSBL91YYLbqJHnOpEodnGZ9L5XLK2B/D/yh4hR84loaXSJDOksAYp8X7 TIeb/266/rXa2xNVhF08oSBAOuw8trZSozJ8h+6oPWDJzLh4Rl4p6Why0pwpVdP02mp++5wfj7VdK j8XuIxVpm0M9hKIrSv6Y28QzwFk6FWGfCs9wSC//+zawzV5XKnDiAF7qBJsovHf0XgaxcfRLiwzSw R+Gk3utY4yRIuxhV8Ii41tanN83Se44L43D2I/98RSmT4lXfbxy14iW3QnAauffkdSex9mc0e8tBd /O9dBRE+JzBPjQ==; From: =?UTF-8?q?Ludovic=20Court=C3=A8s?= <ludo@HIDDEN> To: 75810 <at> debbugs.gnu.org Subject: [PATCH v5 04/14] daemon: Remount inputs as read-only. Date: Fri, 14 Mar 2025 18:48:01 +0100 Message-ID: <ecc7252671bae3ef4e9c13dc35ebd1656fda884c.1741973869.git.ludo@HIDDEN> X-Mailer: git-send-email 2.48.1 In-Reply-To: <cover.1741973869.git.ludo@HIDDEN> References: <cover.1741973869.git.ludo@HIDDEN> MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit X-Spam-Score: -1.8 (-) X-Debbugs-Envelope-To: 75810 Cc: =?UTF-8?q?Ludovic=20Court=C3=A8s?= <ludo@HIDDEN>, Reepca Russelstein <reepca@HIDDEN> X-BeenThere: debbugs-submit <at> debbugs.gnu.org X-Mailman-Version: 2.1.18 Precedence: list List-Id: <debbugs-submit.debbugs.gnu.org> List-Unsubscribe: <https://debbugs.gnu.org/cgi-bin/mailman/options/debbugs-submit>, <mailto:debbugs-submit-request <at> debbugs.gnu.org?subject=unsubscribe> List-Archive: <https://debbugs.gnu.org/cgi-bin/mailman/private/debbugs-submit/> List-Post: <mailto:debbugs-submit <at> debbugs.gnu.org> List-Help: <mailto:debbugs-submit-request <at> debbugs.gnu.org?subject=help> List-Subscribe: <https://debbugs.gnu.org/cgi-bin/mailman/listinfo/debbugs-submit>, <mailto:debbugs-submit-request <at> debbugs.gnu.org?subject=subscribe> Errors-To: debbugs-submit-bounces <at> debbugs.gnu.org Sender: "Debbugs-submit" <debbugs-submit-bounces <at> debbugs.gnu.org> X-Spam-Score: -2.8 (--) * nix/libstore/build.cc (DerivationGoal::runChild): Remount ‘target’ as read-only. Reported-by: Reepca Russelstein <reepca@HIDDEN> Change-Id: Ib7201bcf4363be566f205d23d17fe2f55d3ad666 --- nix/libstore/build.cc | 7 +++++++ 1 file changed, 7 insertions(+) diff --git a/nix/libstore/build.cc b/nix/libstore/build.cc index 193b279b88..3861a1ffd9 100644 --- a/nix/libstore/build.cc +++ b/nix/libstore/build.cc @@ -2107,8 +2107,15 @@ void DerivationGoal::runChild() createDirs(dirOf(target)); writeFile(target, ""); } + + /* Extra flags passed with MS_BIND are ignored, hence the + extra MS_REMOUNT. */ if (mount(source.c_str(), target.c_str(), "", MS_BIND, 0) == -1) throw SysError(format("bind mount from `%1%' to `%2%' failed") % source % target); + if (source.compare(0, settings.nixStore.length(), settings.nixStore) == 0) { + if (mount(source.c_str(), target.c_str(), "", MS_BIND | MS_REMOUNT | MS_RDONLY, 0) == -1) + throw SysError(format("read-only remount of `%1%' failed") % target); + } } /* Bind a new instance of procfs on /proc to reflect our -- 2.48.1
guix-patches@HIDDEN
:bug#75810
; Package guix-patches
.
Full text available.Received: (at 75810) by debbugs.gnu.org; 14 Mar 2025 17:50:03 +0000 From debbugs-submit-bounces <at> debbugs.gnu.org Fri Mar 14 13:50:03 2025 Received: from localhost ([127.0.0.1]:36025 helo=debbugs.gnu.org) by debbugs.gnu.org with esmtp (Exim 4.84_2) (envelope-from <debbugs-submit-bounces <at> debbugs.gnu.org>) id 1tt9AY-0004Qn-EF for submit <at> debbugs.gnu.org; Fri, 14 Mar 2025 13:50:03 -0400 Received: from eggs.gnu.org ([2001:470:142:3::10]:56564) by debbugs.gnu.org with esmtps (TLS1.2:ECDHE_RSA_AES_256_GCM_SHA384:256) (Exim 4.84_2) (envelope-from <ludo@HIDDEN>) id 1tt9AL-0004OZ-3n for 75810 <at> debbugs.gnu.org; Fri, 14 Mar 2025 13:49:49 -0400 Received: from fencepost.gnu.org ([2001:470:142:3::e]) by eggs.gnu.org with esmtps (TLS1.2:ECDHE_RSA_AES_256_GCM_SHA384:256) (Exim 4.90_1) (envelope-from <ludo@HIDDEN>) id 1tt9AF-0001yK-IX; Fri, 14 Mar 2025 13:49:43 -0400 DKIM-Signature: v=1; a=rsa-sha256; q=dns/txt; c=relaxed/relaxed; d=gnu.org; s=fencepost-gnu-org; h=MIME-Version:References:In-Reply-To:Date:Subject:To: From; bh=3sOVW5n0d1cSpQd8PLRrsmflCadSWuH5XwPCIe/iTyM=; b=GyLCF5yPm8l/EQKWhuEC 1fmiYWpvO860bBLogwUO75G5FcJO8SX47FqZkUoTettA98AjJAo+wGmKsqhlGl7XZ+vl1h0+gNdyc bpk1Abgs8vcjc7ZR+ueIRyD0CR7Yd6vPdPDCTaGh38stJdAtTGFZiIHoygC1nIfBC/COyGL5Zzped yyt+3rPE9N+ZmAp62Qo8s8JWtQorbCK5up2wTXdRYsh87z4uJJM2P92i5+0ilxwlzy6INrtkoQGwc iZ0eYg+jnU31Jfrl2bvv8I5Frq5fpd8se73Hz0DV9BUVO1gJCb1t8t9sr383FxPe6TBRsqdd449rc g33qS7ULaCw+3w==; From: =?UTF-8?q?Ludovic=20Court=C3=A8s?= <ludo@HIDDEN> To: 75810 <at> debbugs.gnu.org Subject: [PATCH v5 05/14] daemon: Remount root directory as read-only. Date: Fri, 14 Mar 2025 18:48:02 +0100 Message-ID: <e9761dd9d4842617fa5d7f1996e354b0c7a877af.1741973869.git.ludo@HIDDEN> X-Mailer: git-send-email 2.48.1 In-Reply-To: <cover.1741973869.git.ludo@HIDDEN> References: <cover.1741973869.git.ludo@HIDDEN> MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit X-Spam-Score: -2.3 (--) X-Debbugs-Envelope-To: 75810 Cc: =?UTF-8?q?Ludovic=20Court=C3=A8s?= <ludo@HIDDEN> X-BeenThere: debbugs-submit <at> debbugs.gnu.org X-Mailman-Version: 2.1.18 Precedence: list List-Id: <debbugs-submit.debbugs.gnu.org> List-Unsubscribe: <https://debbugs.gnu.org/cgi-bin/mailman/options/debbugs-submit>, <mailto:debbugs-submit-request <at> debbugs.gnu.org?subject=unsubscribe> List-Archive: <https://debbugs.gnu.org/cgi-bin/mailman/private/debbugs-submit/> List-Post: <mailto:debbugs-submit <at> debbugs.gnu.org> List-Help: <mailto:debbugs-submit-request <at> debbugs.gnu.org?subject=help> List-Subscribe: <https://debbugs.gnu.org/cgi-bin/mailman/listinfo/debbugs-submit>, <mailto:debbugs-submit-request <at> debbugs.gnu.org?subject=subscribe> Errors-To: debbugs-submit-bounces <at> debbugs.gnu.org Sender: "Debbugs-submit" <debbugs-submit-bounces <at> debbugs.gnu.org> X-Spam-Score: -3.3 (---) * nix/libstore/build.cc (DerivationGoal::runChild): Bind-mount the store and /tmp under ‘chrootRootDir’ to themselves as read-write. Remount / as read-only. Change-Id: I79565094c8ec8448401897c720aad75304fd1948 --- nix/libstore/build.cc | 16 ++++++++++++++++ 1 file changed, 16 insertions(+) diff --git a/nix/libstore/build.cc b/nix/libstore/build.cc index 3861a1ffd9..c8b778362a 100644 --- a/nix/libstore/build.cc +++ b/nix/libstore/build.cc @@ -2091,6 +2091,18 @@ void DerivationGoal::runChild() for (auto & i : ss) dirsInChroot[i] = i; + /* Make new mounts for the store and for /tmp. That way, when + 'chrootRootDir' is made read-only below, these two mounts will + remain writable (the store needs to be writable so derivation + outputs can be written to it, and /tmp is writable by + convention). */ + auto chrootStoreDir = chrootRootDir + settings.nixStore; + if (mount(chrootStoreDir.c_str(), chrootStoreDir.c_str(), 0, MS_BIND, 0) == -1) + throw SysError(format("read-write mount of store '%1%' failed") % chrootStoreDir); + auto chrootTmpDir = chrootRootDir + "/tmp"; + if (mount(chrootTmpDir.c_str(), chrootTmpDir.c_str(), 0, MS_BIND, 0) == -1) + throw SysError(format("read-write mount of temporary directory '%1%' failed") % chrootTmpDir); + /* Bind-mount all the directories from the "host" filesystem that we want in the chroot environment. */ @@ -2164,6 +2176,10 @@ void DerivationGoal::runChild() if (rmdir("real-root") == -1) throw SysError("cannot remove real-root directory"); + + /* Remount root as read-only. */ + if (mount("/", "/", 0, MS_BIND | MS_REMOUNT | MS_RDONLY, 0) == -1) + throw SysError(format("read-only remount of build root '%1%' failed") % chrootRootDir); } #endif -- 2.48.1
guix-patches@HIDDEN
:bug#75810
; Package guix-patches
.
Full text available.Received: (at 75810) by debbugs.gnu.org; 14 Mar 2025 17:49:52 +0000 From debbugs-submit-bounces <at> debbugs.gnu.org Fri Mar 14 13:49:52 2025 Received: from localhost ([127.0.0.1]:36007 helo=debbugs.gnu.org) by debbugs.gnu.org with esmtp (Exim 4.84_2) (envelope-from <debbugs-submit-bounces <at> debbugs.gnu.org>) id 1tt9AN-0004PQ-8N for submit <at> debbugs.gnu.org; Fri, 14 Mar 2025 13:49:52 -0400 Received: from eggs.gnu.org ([2001:470:142:3::10]:44272) by debbugs.gnu.org with esmtps (TLS1.2:ECDHE_RSA_AES_256_GCM_SHA384:256) (Exim 4.84_2) (envelope-from <ludo@HIDDEN>) id 1tt9AG-0004OE-SE for 75810 <at> debbugs.gnu.org; Fri, 14 Mar 2025 13:49:45 -0400 Received: from fencepost.gnu.org ([2001:470:142:3::e]) by eggs.gnu.org with esmtps (TLS1.2:ECDHE_RSA_AES_256_GCM_SHA384:256) (Exim 4.90_1) (envelope-from <ludo@HIDDEN>) id 1tt9A8-0001xa-0d; Fri, 14 Mar 2025 13:49:37 -0400 DKIM-Signature: v=1; a=rsa-sha256; q=dns/txt; c=relaxed/relaxed; d=gnu.org; s=fencepost-gnu-org; h=MIME-Version:References:In-Reply-To:Date:Subject:To: From; bh=gj2HkSqKqMC6OnWJO11zAMx01vOVuopEBzKWBjgHWEs=; b=R+JdslMmONDeCgKhfUOn Osb0ErsquFYVgII5bWBu1CPy9Mhx3Bl9t8lfPj/6ZRI1Ib33ug4ZqPgQAIb0HF61aMcZFuaHgLh1R beJJ1ZLzARg42LqgDZ/hrzu1+p9uI5XUu7glFUd6TQomelxZNTG6YsHiuaiytgd5iwMRomlA6yzPs UhcgCHsA+6TkHruubsI8zBPrgK4ZiFQSroZDA1olT15yufkIaMfQd3mTaZxDS36kI2mSwy0eEbjOk hLUkFsqcRc02A35LMJ6/Rt12Kv+EOD/Y3MiYav93ktadgWHWGtzgDbtUUyGlQSs6j9M0fLJm33YG9 +XrArUeqGiaZlw==; From: =?UTF-8?q?Ludovic=20Court=C3=A8s?= <ludo@HIDDEN> To: 75810 <at> debbugs.gnu.org Subject: [PATCH v5 01/14] =?UTF-8?q?daemon:=20Use=20=E2=80=98close=5Frange?= =?UTF-8?q?=E2=80=99=20where=20available.?= Date: Fri, 14 Mar 2025 18:47:58 +0100 Message-ID: <8ae666d03ea7b1d96fbf3c3ff928b920f98df06a.1741973869.git.ludo@HIDDEN> X-Mailer: git-send-email 2.48.1 In-Reply-To: <cover.1741973869.git.ludo@HIDDEN> References: <cover.1741973869.git.ludo@HIDDEN> MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit X-Spam-Score: -2.3 (--) X-Debbugs-Envelope-To: 75810 Cc: =?UTF-8?q?Ludovic=20Court=C3=A8s?= <ludo@HIDDEN> X-BeenThere: debbugs-submit <at> debbugs.gnu.org X-Mailman-Version: 2.1.18 Precedence: list List-Id: <debbugs-submit.debbugs.gnu.org> List-Unsubscribe: <https://debbugs.gnu.org/cgi-bin/mailman/options/debbugs-submit>, <mailto:debbugs-submit-request <at> debbugs.gnu.org?subject=unsubscribe> List-Archive: <https://debbugs.gnu.org/cgi-bin/mailman/private/debbugs-submit/> List-Post: <mailto:debbugs-submit <at> debbugs.gnu.org> List-Help: <mailto:debbugs-submit-request <at> debbugs.gnu.org?subject=help> List-Subscribe: <https://debbugs.gnu.org/cgi-bin/mailman/listinfo/debbugs-submit>, <mailto:debbugs-submit-request <at> debbugs.gnu.org?subject=subscribe> Errors-To: debbugs-submit-bounces <at> debbugs.gnu.org Sender: "Debbugs-submit" <debbugs-submit-bounces <at> debbugs.gnu.org> X-Spam-Score: -3.3 (---) * nix/libutil/util.cc (closeMostFDs) [HAVE_CLOSE_RANGE]: Use ‘close_range’ when ‘exceptions’ is empty. * config-daemon.ac: Check for <linux/close_range.h> and the ‘close_range’ symbol. Change-Id: I12fa3bde58b003fcce5ea5a1fee1dcf9a92c0359 --- config-daemon.ac | 5 +++-- nix/libutil/util.cc | 23 +++++++++++++++++------ 2 files changed, 20 insertions(+), 8 deletions(-) diff --git a/config-daemon.ac b/config-daemon.ac index 6731c68bc3..4e949bc88a 100644 --- a/config-daemon.ac +++ b/config-daemon.ac @@ -78,7 +78,8 @@ if test "x$guix_build_daemon" = "xyes"; then dnl Chroot support. AC_CHECK_FUNCS([chroot unshare]) - AC_CHECK_HEADERS([sched.h sys/param.h sys/mount.h sys/syscall.h]) + AC_CHECK_HEADERS([sched.h sys/param.h sys/mount.h sys/syscall.h \ + linux/close_range.h]) if test "x$ac_cv_func_chroot" != "xyes"; then AC_MSG_ERROR(['chroot' function missing, bailing out]) @@ -95,7 +96,7 @@ if test "x$guix_build_daemon" = "xyes"; then dnl strsignal: for error reporting. dnl statx: fine-grain 'stat' call, new in glibc 2.28. AC_CHECK_FUNCS([lutimes lchown posix_fallocate sched_setaffinity \ - statvfs nanosleep strsignal statx]) + statvfs nanosleep strsignal statx close_range]) dnl Check for <locale>. AC_LANG_PUSH(C++) diff --git a/nix/libutil/util.cc b/nix/libutil/util.cc index 3206dea11b..eb2d16e1cc 100644 --- a/nix/libutil/util.cc +++ b/nix/libutil/util.cc @@ -23,6 +23,10 @@ #include <sys/prctl.h> #endif +#ifdef HAVE_LINUX_CLOSE_RANGE_H +# include <linux/close_range.h> +#endif + extern char * * environ; @@ -1087,12 +1091,19 @@ string runProgram(Path program, bool searchPath, const Strings & args) void closeMostFDs(const set<int> & exceptions) { - int maxFD = 0; - maxFD = sysconf(_SC_OPEN_MAX); - for (int fd = 0; fd < maxFD; ++fd) - if (fd != STDIN_FILENO && fd != STDOUT_FILENO && fd != STDERR_FILENO - && exceptions.find(fd) == exceptions.end()) - close(fd); /* ignore result */ +#ifdef HAVE_CLOSE_RANGE + if (exceptions.empty()) + close_range(3, ~0U, 0); + else +#endif + { + int maxFD = 0; + maxFD = sysconf(_SC_OPEN_MAX); + for (int fd = 0; fd < maxFD; ++fd) + if (fd != STDIN_FILENO && fd != STDOUT_FILENO && fd != STDERR_FILENO + && exceptions.find(fd) == exceptions.end()) + close(fd); /* ignore result */ + } } -- 2.48.1
guix-patches@HIDDEN
:bug#75810
; Package guix-patches
.
Full text available.Received: (at 75810) by debbugs.gnu.org; 14 Mar 2025 17:49:51 +0000 From debbugs-submit-bounces <at> debbugs.gnu.org Fri Mar 14 13:49:51 2025 Received: from localhost ([127.0.0.1]:36005 helo=debbugs.gnu.org) by debbugs.gnu.org with esmtp (Exim 4.84_2) (envelope-from <debbugs-submit-bounces <at> debbugs.gnu.org>) id 1tt9AM-0004PO-Ro for submit <at> debbugs.gnu.org; Fri, 14 Mar 2025 13:49:51 -0400 Received: from eggs.gnu.org ([2001:470:142:3::10]:44260) by debbugs.gnu.org with esmtps (TLS1.2:ECDHE_RSA_AES_256_GCM_SHA384:256) (Exim 4.84_2) (envelope-from <ludo@HIDDEN>) id 1tt9AG-0004OD-C4 for 75810 <at> debbugs.gnu.org; Fri, 14 Mar 2025 13:49:44 -0400 Received: from fencepost.gnu.org ([2001:470:142:3::e]) by eggs.gnu.org with esmtps (TLS1.2:ECDHE_RSA_AES_256_GCM_SHA384:256) (Exim 4.90_1) (envelope-from <ludo@HIDDEN>) id 1tt9AA-0001xb-9Q; Fri, 14 Mar 2025 13:49:38 -0400 DKIM-Signature: v=1; a=rsa-sha256; q=dns/txt; c=relaxed/relaxed; d=gnu.org; s=fencepost-gnu-org; h=MIME-Version:References:In-Reply-To:Date:Subject:To: From; bh=5fbggu8STjwEXFRRV3Gq/UXyTgxUmf6fh1UKO8gjNXs=; b=CDn6I66Ph4oSvPCNsgp9 zi/9luaoA7jeCiUsgsDktq5Qdpx/eoaRHvGpfOOo/bAhe1Milak0ab6FZKM8fYzkI6dTf0uPmkL7m n9qs3O+zCzEVJgZOZM9rp8l2xvmg1a+nFzLOVrzq5k6VXuq+ZrexfmlHsaJ8zMpsTFQrsqnIHgbUG xbPtYxr25HhVYPBIr7C3K3PabRMqEns1uRSu4MRhIkOZq1CgKOjcnjQ+SbPIzLsMZPSPNuoZd/sBZ V6GnoHplr3/5ZHv6i8NLwq/7csHcs7mqUFC1OigW9AUtTmkRLbRW9LoGy19tOlJ5+TjSHond+fsp4 spZMn6EPaln2lg==; From: =?UTF-8?q?Ludovic=20Court=C3=A8s?= <ludo@HIDDEN> To: 75810 <at> debbugs.gnu.org Subject: [PATCH v5 02/14] daemon: Bind-mount /etc/nsswitch.conf & co. only if it exists. Date: Fri, 14 Mar 2025 18:47:59 +0100 Message-ID: <7fa4cb05e23e14bb03832084fb60af1cbf727b39.1741973869.git.ludo@HIDDEN> X-Mailer: git-send-email 2.48.1 In-Reply-To: <cover.1741973869.git.ludo@HIDDEN> References: <cover.1741973869.git.ludo@HIDDEN> MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit X-Spam-Score: -2.3 (--) X-Debbugs-Envelope-To: 75810 Cc: =?UTF-8?q?Ludovic=20Court=C3=A8s?= <ludo@HIDDEN> X-BeenThere: debbugs-submit <at> debbugs.gnu.org X-Mailman-Version: 2.1.18 Precedence: list List-Id: <debbugs-submit.debbugs.gnu.org> List-Unsubscribe: <https://debbugs.gnu.org/cgi-bin/mailman/options/debbugs-submit>, <mailto:debbugs-submit-request <at> debbugs.gnu.org?subject=unsubscribe> List-Archive: <https://debbugs.gnu.org/cgi-bin/mailman/private/debbugs-submit/> List-Post: <mailto:debbugs-submit <at> debbugs.gnu.org> List-Help: <mailto:debbugs-submit-request <at> debbugs.gnu.org?subject=help> List-Subscribe: <https://debbugs.gnu.org/cgi-bin/mailman/listinfo/debbugs-submit>, <mailto:debbugs-submit-request <at> debbugs.gnu.org?subject=subscribe> Errors-To: debbugs-submit-bounces <at> debbugs.gnu.org Sender: "Debbugs-submit" <debbugs-submit-bounces <at> debbugs.gnu.org> X-Spam-Score: -3.3 (---) Those files may be missing in some contexts, for instance within the build environment. * nix/libstore/build.cc (DerivationGoal::runChild): Add /etc/resolv.conf and related files to ‘ss’ only if they exist. Change-Id: Ie19664a86c8101a1dc82cf39ad4b7abb10f8250a --- nix/libstore/build.cc | 9 +++++---- 1 file changed, 5 insertions(+), 4 deletions(-) diff --git a/nix/libstore/build.cc b/nix/libstore/build.cc index edd01bab34..8ca5e5b732 100644 --- a/nix/libstore/build.cc +++ b/nix/libstore/build.cc @@ -2093,10 +2093,11 @@ void DerivationGoal::runChild() network, so give them access to /etc/resolv.conf and so on. */ if (fixedOutput) { - ss.push_back("/etc/resolv.conf"); - ss.push_back("/etc/nsswitch.conf"); - ss.push_back("/etc/services"); - ss.push_back("/etc/hosts"); + auto files = { "/etc/resolv.conf", "/etc/nsswitch.conf", + "/etc/services", "/etc/hosts" }; + for (auto & file: files) { + if (pathExists(file)) ss.push_back(file); + } } for (auto & i : ss) dirsInChroot[i] = i; -- 2.48.1
guix-patches@HIDDEN
:bug#75810
; Package guix-patches
.
Full text available.Received: (at 75810) by debbugs.gnu.org; 14 Mar 2025 17:49:48 +0000 From debbugs-submit-bounces <at> debbugs.gnu.org Fri Mar 14 13:49:48 2025 Received: from localhost ([127.0.0.1]:35995 helo=debbugs.gnu.org) by debbugs.gnu.org with esmtp (Exim 4.84_2) (envelope-from <debbugs-submit-bounces <at> debbugs.gnu.org>) id 1tt9AG-0004Oh-SN for submit <at> debbugs.gnu.org; Fri, 14 Mar 2025 13:49:48 -0400 Received: from eggs.gnu.org ([2001:470:142:3::10]:44248) by debbugs.gnu.org with esmtps (TLS1.2:ECDHE_RSA_AES_256_GCM_SHA384:256) (Exim 4.84_2) (envelope-from <ludo@HIDDEN>) id 1tt9AA-0004O5-IW for 75810 <at> debbugs.gnu.org; Fri, 14 Mar 2025 13:49:42 -0400 Received: from fencepost.gnu.org ([2001:470:142:3::e]) by eggs.gnu.org with esmtps (TLS1.2:ECDHE_RSA_AES_256_GCM_SHA384:256) (Exim 4.90_1) (envelope-from <ludo@HIDDEN>) id 1tt9A2-0001xR-S4; Fri, 14 Mar 2025 13:49:30 -0400 DKIM-Signature: v=1; a=rsa-sha256; q=dns/txt; c=relaxed/relaxed; d=gnu.org; s=fencepost-gnu-org; h=MIME-Version:Date:Subject:To:From:in-reply-to: references; bh=bCaK0d/HiPtBq1zMzQwCfvjTWkFpAA0DcHPTXIeecUQ=; b=NTJO3xgFiwkMbE Jug0QaiAgx9QpsPVWGwyder5J9UFYH4fti09i9kpnfZqy6Vy9Acb1MFdt8ow6aEI/KkP1Zdvd1SvK g4D39D8LmbEHD+GJvzpL/Vrxt4Wify0aLwBtdNeLVu4GSarBMEUtnz9gQg1zYs03YYgVGlSiD1TiA wPKNt+pPAbLjqc4YnKHoocppmmGu7JYA9ODOYmoX0Rde8lPlI8e31uilF7Rc8qZDDjh3dt+DioILP lDmd6W8IA+mzgZwRjS0VGBScpIIjdsuyFZrDDAxvRqzaNFv3V5u4fb/0imeoddXufF3SBx9A0s/vs oAhnghN1GRApHdNUAi5w==; From: =?UTF-8?q?Ludovic=20Court=C3=A8s?= <ludo@HIDDEN> To: 75810 <at> debbugs.gnu.org Subject: [PATCH v5 00/14] Rootless guix-daemon Date: Fri, 14 Mar 2025 18:47:57 +0100 Message-ID: <cover.1741973869.git.ludo@HIDDEN> X-Mailer: git-send-email 2.48.1 MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit X-Spam-Score: -2.3 (--) X-Debbugs-Envelope-To: 75810 Cc: =?UTF-8?q?Ludovic=20Court=C3=A8s?= <ludo@HIDDEN>, Reepca Russelstein <reepca@HIDDEN> X-BeenThere: debbugs-submit <at> debbugs.gnu.org X-Mailman-Version: 2.1.18 Precedence: list List-Id: <debbugs-submit.debbugs.gnu.org> List-Unsubscribe: <https://debbugs.gnu.org/cgi-bin/mailman/options/debbugs-submit>, <mailto:debbugs-submit-request <at> debbugs.gnu.org?subject=unsubscribe> List-Archive: <https://debbugs.gnu.org/cgi-bin/mailman/private/debbugs-submit/> List-Post: <mailto:debbugs-submit <at> debbugs.gnu.org> List-Help: <mailto:debbugs-submit-request <at> debbugs.gnu.org?subject=help> List-Subscribe: <https://debbugs.gnu.org/cgi-bin/mailman/listinfo/debbugs-submit>, <mailto:debbugs-submit-request <at> debbugs.gnu.org?subject=subscribe> Errors-To: debbugs-submit-bounces <at> debbugs.gnu.org Sender: "Debbugs-submit" <debbugs-submit-bounces <at> debbugs.gnu.org> X-Spam-Score: -3.3 (---) Hello Guix! Changes since v4: • Remove qualifiers such as “new” from the documentation and clarify that unprivileged guix-daemon is the option chosen by default in some cases (Simon, Maxim). • Change ‘deleteTmpDir’ to deal with the case where CAP_SYS_CHOWN is available but ‘--disable-chroot’ is used (Reepca). • Add ‘unshare’ call in the build process before ‘execve’ to create new user and mount namespaces, thereby locking together all the previous mounts; check by calling ‘umount’ and ensuring that it returns EINVAL that mounts are indeed locked (Reepca). • In ‘guix-install.sh’, keep /var/guix/profiles/per-user/root root-owned (previously it was chowned to ‘guix-daemon’). • In ‘guix-install.sh’, start ‘gnu-store.mount’ explicitly since it is no longer a dependency of ‘guix-daemon.service’. • In ‘guix-daemon.service.in’, set ‘GUIX_DATABASE_DIRECTORY=/var/guix’ for forward compatibility (I’m thinking of eventually changing the default database location when not running as root). With these changes, the ‘debian-install’ and ‘guix-daemon’ system tests both pass. I think we’ve never been this close to completion. :-) Thoughts? Thanks a lot for your feedback, comrades. Ludo’. Ludovic Courtès (14): daemon: Use ‘close_range’ where available. daemon: Bind-mount /etc/nsswitch.conf & co. only if it exists. daemon: Bind-mount all the inputs, not just directories. daemon: Remount inputs as read-only. daemon: Remount root directory as read-only. daemon: Allow running as non-root with unprivileged user namespaces. daemon: Create /var/guix/profiles/per-user unconditionally. daemon: Drop Linux ambient capabilities before executing builder. daemon: Move comments where they belong. tests: Add missing derivation inputs. tests: Run in a chroot and unprivileged user namespaces. etc: systemd services: Run ‘guix-daemon’ as an unprivileged user. guix-install.sh: Support the unprivileged daemon where possible. DRAFT gnu: guix: Update to 00562be. build-aux/test-env.in | 16 +- config-daemon.ac | 5 +- doc/guix.texi | 102 +++++++++--- etc/gnu-store.mount.in | 3 +- etc/guix-daemon.service.in | 22 ++- etc/guix-install.sh | 109 +++++++++--- gnu/packages/package-management.scm | 6 +- guix/substitutes.scm | 2 +- nix/libstore/build.cc | 247 ++++++++++++++++++++------- nix/libstore/local-store.cc | 26 ++- nix/libutil/util.cc | 23 ++- tests/derivations.scm | 24 ++- tests/packages.scm | 13 +- tests/processes.scm | 9 +- tests/store.scm | 250 ++++++++++++++++++++++++---- 15 files changed, 675 insertions(+), 182 deletions(-) base-commit: 519fc51b6ecfe9ac9f2fa2f4ae052ab1984eed22 -- 2.48.1
guix-patches@HIDDEN
:bug#75810
; Package guix-patches
.
Full text available.Received: (at 75810) by debbugs.gnu.org; 13 Mar 2025 23:51:42 +0000 From debbugs-submit-bounces <at> debbugs.gnu.org Thu Mar 13 19:51:42 2025 Received: from localhost ([127.0.0.1]:58930 helo=debbugs.gnu.org) by debbugs.gnu.org with esmtp (Exim 4.84_2) (envelope-from <debbugs-submit-bounces <at> debbugs.gnu.org>) id 1tssKz-0007Vq-EF for submit <at> debbugs.gnu.org; Thu, 13 Mar 2025 19:51:42 -0400 Received: from hera.aquilenet.fr ([185.233.100.1]:48812) by debbugs.gnu.org with esmtps (TLS1.2:ECDHE_RSA_AES_256_GCM_SHA384:256) (Exim 4.84_2) (envelope-from <ludo@HIDDEN>) id 1tssKw-0007VY-Bn for 75810 <at> debbugs.gnu.org; Thu, 13 Mar 2025 19:51:39 -0400 Received: from localhost (localhost [127.0.0.1]) by hera.aquilenet.fr (Postfix) with ESMTP id 1C5FB54B; Fri, 14 Mar 2025 00:51:31 +0100 (CET) Authentication-Results: hera.aquilenet.fr; none X-Virus-Scanned: Debian amavis at hera.aquilenet.fr Received: from hera.aquilenet.fr ([127.0.0.1]) by localhost (hera.aquilenet.fr [127.0.0.1]) (amavis, port 10024) with ESMTP id Oebs9zg7MQcT; Fri, 14 Mar 2025 00:51:30 +0100 (CET) Received: from ribbon (unknown [83.118.207.42]) by hera.aquilenet.fr (Postfix) with ESMTPSA id B0A51214; Fri, 14 Mar 2025 00:51:28 +0100 (CET) From: =?utf-8?Q?Ludovic_Court=C3=A8s?= <ludo@HIDDEN> To: Reepca Russelstein <reepca@HIDDEN> Subject: Re: [bug#75810] [PATCH 0/6] Rootless guix-daemon In-Reply-To: <87ldt95uw6.fsf@HIDDEN> (Reepca Russelstein's message of "Thu, 13 Mar 2025 01:04:09 -0500") References: <cover.1737738362.git.ludo@HIDDEN> <87r04qe7dj.fsf@HIDDEN> <87bjvshrk0.fsf@HIDDEN> <875xluehn7.fsf@HIDDEN> <877c5u2ct5.fsf@HIDDEN> <87jz9sc72o.fsf@HIDDEN> <87y0xbivsh.fsf_-_@HIDDEN> <87plin5j3u.fsf@HIDDEN> <87h63xyjdh.fsf_-_@HIDDEN> <87ldt95uw6.fsf@HIDDEN> Date: Fri, 14 Mar 2025 00:51:28 +0100 Message-ID: <87a59owku7.fsf@HIDDEN> User-Agent: Gnus/5.13 (Gnus v5.13) MIME-Version: 1.0 Content-Type: text/plain; charset=utf-8 Content-Transfer-Encoding: quoted-printable X-Rspamd-Server: hera X-Rspamd-Queue-Id: 1C5FB54B X-Spamd-Result: default: False [4.90 / 15.00]; SPAM_FLAG(5.00)[]; BAYES_HAM(-3.00)[100.00%]; NEURAL_SPAM(3.00)[1.000]; MIME_GOOD(-0.10)[text/plain]; RCVD_COUNT_TWO(0.00)[2]; FROM_EQ_ENVFROM(0.00)[]; MIME_TRACE(0.00)[0:+]; RCPT_COUNT_TWO(0.00)[2]; ARC_NA(0.00)[]; TO_MATCH_ENVRCPT_ALL(0.00)[]; RCVD_VIA_SMTP_AUTH(0.00)[]; RCVD_TLS_ALL(0.00)[]; FROM_HAS_DN(0.00)[]; TO_DN_SOME(0.00)[]; MID_RHS_MATCH_FROM(0.00)[] X-Spamd-Bar: ++++ X-Rspamd-Action: no action X-Spam-Level: **** X-Spam-Score: 1.5 (+) X-Spam-Report: Spam detection software, running on the system "debbugs.gnu.org", has NOT identified this incoming email as spam. The original message has been attached to this so you can view it or label similar future email. If you have any questions, see the administrator of that system for details. Content preview: Hey, Reepca Russelstein <reepca@HIDDEN> skribis: > I failed to take into account that the setns sequence needs to start by > joining the user namespace that owns all the other namespaces, so as to > gain the necessary capabilities for joining them. [...] Content analysis details: (1.5 points, 10.0 required) pts rule name description ---- ---------------------- -------------------------------------------------- 0.0 RCVD_IN_VALIDITY_RPBL_BLOCKED RBL: ADMINISTRATOR NOTICE: The query to Validity was blocked. See https://knowledge.validity.com/hc/en-us/articles/20961730681243 for more information. [185.233.100.1 listed in bl.score.senderscore.com] 0.0 RCVD_IN_VALIDITY_SAFE_BLOCKED RBL: ADMINISTRATOR NOTICE: The query to Validity was blocked. See https://knowledge.validity.com/hc/en-us/articles/20961730681243 for more information. [185.233.100.1 listed in sa-trusted.bondedsender.org] 1.0 SPF_SOFTFAIL SPF: sender does not match SPF record (softfail) 0.5 PDS_OTHER_BAD_TLD Untrustworthy TLDs [URI: russelstein.xyz (xyz)] -0.0 SPF_HELO_PASS SPF: HELO matches SPF record X-Debbugs-Envelope-To: 75810 Cc: 75810 <at> debbugs.gnu.org X-BeenThere: debbugs-submit <at> debbugs.gnu.org X-Mailman-Version: 2.1.18 Precedence: list List-Id: <debbugs-submit.debbugs.gnu.org> List-Unsubscribe: <https://debbugs.gnu.org/cgi-bin/mailman/options/debbugs-submit>, <mailto:debbugs-submit-request <at> debbugs.gnu.org?subject=unsubscribe> List-Archive: <https://debbugs.gnu.org/cgi-bin/mailman/private/debbugs-submit/> List-Post: <mailto:debbugs-submit <at> debbugs.gnu.org> List-Help: <mailto:debbugs-submit-request <at> debbugs.gnu.org?subject=help> List-Subscribe: <https://debbugs.gnu.org/cgi-bin/mailman/listinfo/debbugs-submit>, <mailto:debbugs-submit-request <at> debbugs.gnu.org?subject=subscribe> Errors-To: debbugs-submit-bounces <at> debbugs.gnu.org Sender: "Debbugs-submit" <debbugs-submit-bounces <at> debbugs.gnu.org> X-Spam-Score: 0.5 (/) Hey, Reepca Russelstein <reepca@HIDDEN> skribis: > I failed to take into account that the setns sequence needs to start by > joining the user namespace that owns all the other namespaces, so as to > gain the necessary capabilities for joining them. But after unshare > creates the second user namespace, that first user namespace no longer > has a process in it; it only still exists due to indirect references. > Without a process to reference it by, we can't join it. Trying to join > the user namespace of the builder instead joins the inner user > namespace, then tries to use the acquired credentials to join the > namespaces owned by the outer user namespace, which naturally fails. I see; brilliant. >> If you can think of ways to do that, I=E2=80=99m all ears. :-) > > It looks like the only easy way to test this - aside from something like > scripted gdb playthroughs - might legitimately be to include a test > inside the daemon itself. Yes, that makes sense. I added a =E2=80=98umount=E2=80=99 call, checking that we get EINVAL, and c= onfirmed that this check fails if we comment out the =E2=80=98unshare=E2=80=99 call. I pushed the updated branch to Codeberg. There are test failures in the =E2=80=98debian-install=E2=80=99 test that I now need to investigate before= I send v5, notably CAP_SYS_CHOWN not working (?) when attempting to create root=E2=80= =99s profile: --8<---------------cut here---------------start------------->8--- guix install: [1;31merror: [0mdirectory `/var/guix/profiles/per-user/root' = is not owned by you [1;36mhint: [0mPlease change the owner of `/var/guix/profiles/per-user/root= ' to user "root". ls: cannot access '/root/.guix-profile': No such file or directory sh: 1: /root/.guix-profile/bin/hello: not found [=E2=80=A6] PASS: marionette works PASS: /etc/os-release PASS: mount host file store PASS: screenshot before PASS: install fake dependencies PASS: run install script PASS: create user account PASS: guix describe PASS: hello not already built PASS: guix build hello PASS: hello indeed built /gnu/store/59qdz41chhifidaq79iiiyx70m7lmyrp-debian-install-builder:1: FAIL = guix install hello /gnu/store/59qdz41chhifidaq79iiiyx70m7lmyrp-debian-install-builder:1: FAIL = user profile created /gnu/store/59qdz41chhifidaq79iiiyx70m7lmyrp-debian-install-builder:1: FAIL = hello PASS: guix install hello, unprivileged user PASS: user hello PASS: unprivileged user profile created /gnu/store/59qdz41chhifidaq79iiiyx70m7lmyrp-debian-install-builder:1: FAIL = store is read-only PASS: screenshot after # of expected passes 15 # of unexpected failures 4 --8<---------------cut here---------------end--------------->8--- Ludo=E2=80=99.
guix-patches@HIDDEN
:bug#75810
; Package guix-patches
.
Full text available.Received: (at 75810) by debbugs.gnu.org; 13 Mar 2025 06:04:54 +0000 From debbugs-submit-bounces <at> debbugs.gnu.org Thu Mar 13 02:04:54 2025 Received: from localhost ([127.0.0.1]:52999 helo=debbugs.gnu.org) by debbugs.gnu.org with esmtp (Exim 4.84_2) (envelope-from <debbugs-submit-bounces <at> debbugs.gnu.org>) id 1tsbgb-0005zs-P6 for submit <at> debbugs.gnu.org; Thu, 13 Mar 2025 02:04:54 -0400 Received: from mailout.russelstein.xyz ([2605:6400:20:11e::1]:37910) by debbugs.gnu.org with esmtps (TLS1.2:ECDHE_RSA_AES_256_GCM_SHA384:256) (Exim 4.84_2) (envelope-from <reepca@HIDDEN>) id 1tsbgY-0005zi-0q for 75810 <at> debbugs.gnu.org; Thu, 13 Mar 2025 02:04:51 -0400 DKIM-Signature: v=1; a=ed25519-sha256; q=dns/txt; c=relaxed/relaxed; d=russelstein.xyz; s=ed25519; h=Content-Type:MIME-Version:Message-ID:Date: References:In-Reply-To:Subject:Cc:To:From:Sender:Reply-To: Content-Transfer-Encoding:Content-ID:Content-Description:Resent-Date: Resent-From:Resent-Sender:Resent-To:Resent-Cc:Resent-Message-ID:List-Id: List-Help:List-Unsubscribe:List-Subscribe:List-Post:List-Owner:List-Archive; bh=5PXUtpEXOmb/rV3oRBecYxEL2EkTFWFs+YWRwPjHlZQ=; b=bvS7bFG+R+5yrKTjjRUT7uAE0I 0awMXWhnop8whL+caXxuObtPWPFqzqCTt7z5UBA9oLHwKeyqnGDrD8s7edBw==; DKIM-Signature: v=1; a=rsa-sha256; q=dns/txt; c=relaxed/relaxed; d=russelstein.xyz; s=rsa; h=Content-Type:MIME-Version:Message-ID:Date: References:In-Reply-To:Subject:Cc:To:From:Sender:Reply-To: Content-Transfer-Encoding:Content-ID:Content-Description:Resent-Date: Resent-From:Resent-Sender:Resent-To:Resent-Cc:Resent-Message-ID:List-Id: List-Help:List-Unsubscribe:List-Subscribe:List-Post:List-Owner:List-Archive; bh=5PXUtpEXOmb/rV3oRBecYxEL2EkTFWFs+YWRwPjHlZQ=; b=B89ZiyZ0MdgC04vVl+/QApbu/L YzLKvMmpd1d36j8tSXuN3Qntnj9B1jqb4S6ep286gTgEedLex2lu7f4/50fwXkpdzOdZFryNXJFtV 7aIt5vF1pVYiOvZh7R+VCBkarF61B5Z/XoLwpPh0kgnqui1MGnNrogvAPH1SEZdB36djEC/KKlORN Y37qi1Kv7/FxNPgHcTe3tT2jI50xAqs9Ixy/HSy2oAGA9oe/QQyJ5FRtMK/CvYzo6F3mzN7XXiUsf b3pXivQ3HPYlRriCZfa/S4xT94MP5Ye24SFThFhepcd7WsFT6cN0e3Bok0MmRkf/md9i/+9ZeAqc7 NX28yePWpkDWpK5OwwsL7Bw3L/nnpNBHdxLtvKTu4ziiM1HkYb2+4jd5SuIHikCoxy+3Ofg4gbj7J ZnnjT4FZWNvze+sitPlR06p9h8mW4j1DdecBufIeEq6gC8nFAfHgY89lGxdHzvOJGbBBqgYE7Z7OX bRQ3e+qLDv4z6RozxOTRSmphlURJoiDtprysq8zeoLraacwPeJZixNWZomH/LlbxtBTlmagbuZg4g D/FkcGUk4GGjuAeR2oUXzv7Psdmso2oG3zJ6bfaLOclVYxKqLQ7eNJpjbe+SBONsEzBEq6FqHpbkt 6gHtDKA5RHrF1RcmmI0MxA6fUWeCH3QaexDsPViQA=; Received: by russelstein.xyz with esmtpsa (TLS1.3:ECDHE_SECP256R1__RSA_PSS_RSAE_SHA256__AES_256_GCM:256) (Exim 4.98) (envelope-from <reepca@HIDDEN>) id 1tsbgT-000000003Yr-0UVs; Thu, 13 Mar 2025 01:04:46 -0500 From: Reepca Russelstein <reepca@HIDDEN> To: Ludovic =?utf-8?Q?Court=C3=A8s?= <ludo@HIDDEN> Subject: Re: bug#75810: [PATCH 0/6] Rootless guix-daemon In-Reply-To: <87h63xyjdh.fsf_-_@HIDDEN> ("Ludovic =?utf-8?Q?Court=C3=A8s?= =?utf-8?Q?=22's?= message of "Wed, 12 Mar 2025 23:27:54 +0100") References: <cover.1737738362.git.ludo@HIDDEN> <87r04qe7dj.fsf@HIDDEN> <87bjvshrk0.fsf@HIDDEN> <875xluehn7.fsf@HIDDEN> <877c5u2ct5.fsf@HIDDEN> <87jz9sc72o.fsf@HIDDEN> <87y0xbivsh.fsf_-_@HIDDEN> <87plin5j3u.fsf@HIDDEN> <87h63xyjdh.fsf_-_@HIDDEN> Date: Thu, 13 Mar 2025 01:04:09 -0500 Message-ID: <87ldt95uw6.fsf@HIDDEN> User-Agent: Gnus/5.13 (Gnus v5.13) MIME-Version: 1.0 Content-Type: multipart/signed; boundary="=-=-="; micalg=pgp-sha256; protocol="application/pgp-signature" X-Spam-Score: 0.5 X-Spam-Bar: / X-Spam-Score-Int: 5 X-Spam-Report: Spam detection software, running on the system "Sanctum", has NOT identified this incoming email as spam. The original message has been attached to this so you can view it or label similar future email. If you have any questions, see the administrator of that system for details. Content preview: Ludovic Courtès <ludo@HIDDEN> writes: > I tried running a build that sleeps and then joining its namespaces but > failed: > > $ pgrep -fa builder > 16091 guile --no-auto-compile -L /home/ludo/src/guix/test-tmp/store/ngrj4gl9lrbmbklcsbgcrq [...] Content analysis details: (0.5 points, 5.0 required) pts rule name description ---- ---------------------- -------------------------------------------------- -0.0 NO_RELAYS Informational: message was not relayed via SMTP 0.5 FROM_SUSPICIOUS_NTLD From abused NTLD X-Spam-Score: 1.2 (+) X-Spam-Report: Spam detection software, running on the system "debbugs.gnu.org", has NOT identified this incoming email as spam. The original message has been attached to this so you can view it or label similar future email. If you have any questions, see the administrator of that system for details. Content preview: Ludovic Courtès <ludo@HIDDEN> writes: > I tried running a build that sleeps and then joining its namespaces but > failed: > > $ pgrep -fa builder > 16091 guile --no-auto-compile -L /home/ludo/src/guix/test-tmp/store/ngrj4gl9lrbmbklcsbgcrq [...] Content analysis details: (1.2 points, 10.0 required) pts rule name description ---- ---------------------- -------------------------------------------------- 0.7 PDS_OTHER_BAD_TLD Untrustworthy TLDs [URI: russelstein.xyz (xyz)] 0.0 SPF_HELO_NONE SPF: HELO does not publish an SPF Record -0.0 SPF_PASS SPF: sender matches SPF record 0.5 FROM_SUSPICIOUS_NTLD From abused NTLD X-Debbugs-Envelope-To: 75810 Cc: 75810 <at> debbugs.gnu.org X-BeenThere: debbugs-submit <at> debbugs.gnu.org X-Mailman-Version: 2.1.18 Precedence: list List-Id: <debbugs-submit.debbugs.gnu.org> List-Unsubscribe: <https://debbugs.gnu.org/cgi-bin/mailman/options/debbugs-submit>, <mailto:debbugs-submit-request <at> debbugs.gnu.org?subject=unsubscribe> List-Archive: <https://debbugs.gnu.org/cgi-bin/mailman/private/debbugs-submit/> List-Post: <mailto:debbugs-submit <at> debbugs.gnu.org> List-Help: <mailto:debbugs-submit-request <at> debbugs.gnu.org?subject=help> List-Subscribe: <https://debbugs.gnu.org/cgi-bin/mailman/listinfo/debbugs-submit>, <mailto:debbugs-submit-request <at> debbugs.gnu.org?subject=subscribe> Errors-To: debbugs-submit-bounces <at> debbugs.gnu.org Sender: "Debbugs-submit" <debbugs-submit-bounces <at> debbugs.gnu.org> X-Spam-Score: 1.2 (+) X-Spam-Report: Spam detection software, running on the system "debbugs.gnu.org", has NOT identified this incoming email as spam. The original message has been attached to this so you can view it or label similar future email. If you have any questions, see the administrator of that system for details. Content preview: Ludovic Courtès <ludo@HIDDEN> writes: > I tried running a build that sleeps and then joining its namespaces but > failed: > > $ pgrep -fa builder > 16091 guile --no-auto-compile -L /home/ludo/src/guix/test-tmp/store/ngrj4gl9lrbmbklcsbgcrq [...] Content analysis details: (1.2 points, 10.0 required) pts rule name description ---- ---------------------- -------------------------------------------------- 0.7 PDS_OTHER_BAD_TLD Untrustworthy TLDs [URI: russelstein.xyz (xyz)] 0.0 SPF_HELO_NONE SPF: HELO does not publish an SPF Record -0.0 SPF_PASS SPF: sender matches SPF record 0.5 FROM_SUSPICIOUS_NTLD From abused NTLD 1.0 BULK_RE_SUSP_NTLD Precedence bulk and RE: from a suspicious TLD -1.0 MAILING_LIST_MULTI Multiple indicators imply a widely-seen list manager --=-=-= Content-Type: text/plain; charset=utf-8 Content-Transfer-Encoding: quoted-printable Ludovic Court=C3=A8s <ludo@HIDDEN> writes: > I tried running a build that sleeps and then joining its namespaces but > failed: > > $ pgrep -fa builder > 16091 guile --no-auto-compile -L /home/ludo/src/guix/test-tmp/store/ngrj4= gl9lrbmbklcsbgcrq622n9nf0jw-module-import -C /home/ludo/src/guix/test-tmp/s= tore/cskis66zjnhk28h11lbaxkd3j9lyzz6a-module-import-compiled /home/ludo/src= /guix/test-tmp/store/akndbdx1lmnigf8bi29dr0vd3c8dbdrg-attempt-to-unmount-in= put-builder > $ nsenter -m -u -i -n -p -U -t 16091=20 > nsenter: reassociate to namespace 'ns/ipc' failed: Operation not permitted > $ guix container exec 16091 /bin/sh > guix container: error: setns: 7 0: Operation not permitted > guix container: error: process exited with status 1 I failed to take into account that the setns sequence needs to start by joining the user namespace that owns all the other namespaces, so as to gain the necessary capabilities for joining them. But after unshare creates the second user namespace, that first user namespace no longer has a process in it; it only still exists due to indirect references. Without a process to reference it by, we can't join it. Trying to join the user namespace of the builder instead joins the inner user namespace, then tries to use the acquired credentials to join the namespaces owned by the outer user namespace, which naturally fails. > If you can think of ways to do that, I=E2=80=99m all ears. :-) It looks like the only easy way to test this - aside from something like scripted gdb playthroughs - might legitimately be to include a test inside the daemon itself. > You can try from the =E2=80=98wip-rootless-daemon=E2=80=99 at > <https://codeberg.org/civodul/guix> and apply the patch I sent earlier. > > (Incidentally, I don=E2=80=99t think we could write an automated test for= that; > in theory we could use (guix scripts processes) to determine the PID of > the build process but that would be too brittle, especially when running > =E2=80=9Cmake check -j123=E2=80=9D where it could pick the wrong guix-dae= mon process.) If we included a randomly-generated string in the command line or environment of something in the build environment, and then went looking through /proc for the matching process, it could work. But it's moot if we put this particular test inside the daemon. =2D reepca --=-=-= Content-Type: application/pgp-signature; name="signature.asc" -----BEGIN PGP SIGNATURE----- iQFLBAEBCAA1FiEEdNapMPRLm4SepVYGwWaqSV9/GJwFAmfSdVoXHHJlZXBjYUBy dXNzZWxzdGVpbi54eXoACgkQwWaqSV9/GJy2xggAgu2EedTltMnb4uCddN+SkvDU LcZj2WRsVkFmP+fSbJwbJh7VgrAwNHGFPKi+MD1dmvvu1nEMgGnvD/05SRfod8za 078uNIF3+0/W3rXHm4U7SqqfbpwG0pSylSLBET9QYeqTpPQvypE6p5GzQMkKJAgp /oMXrArSQB6i7NOZgUz8/azYbnAx/OIBjnVpA4Pbl55kRLSoDfyUeJkHkphqHgc2 uxRCx71rzpvJacnEk7e4hyU6j+mKrd/d7DyRdGQXPR/6lqMdLOX0SVLIKxA62CWu TMq0sIQiMOJuyXuuJa+/dVtVt/qSLJa3TwaPz/ZWsp5tm7l9quEfGnR+UaP5bA== =MZlY -----END PGP SIGNATURE----- --=-=-=--
guix-patches@HIDDEN
:bug#75810
; Package guix-patches
.
Full text available.Received: (at 75810) by debbugs.gnu.org; 12 Mar 2025 22:28:10 +0000 From debbugs-submit-bounces <at> debbugs.gnu.org Wed Mar 12 18:28:10 2025 Received: from localhost ([127.0.0.1]:52134 helo=debbugs.gnu.org) by debbugs.gnu.org with esmtp (Exim 4.84_2) (envelope-from <debbugs-submit-bounces <at> debbugs.gnu.org>) id 1tsUYc-00036K-7i for submit <at> debbugs.gnu.org; Wed, 12 Mar 2025 18:28:10 -0400 Received: from hera.aquilenet.fr ([185.233.100.1]:59042) by debbugs.gnu.org with esmtps (TLS1.2:ECDHE_RSA_AES_256_GCM_SHA384:256) (Exim 4.84_2) (envelope-from <ludo@HIDDEN>) id 1tsUYZ-00035l-Nl for 75810 <at> debbugs.gnu.org; Wed, 12 Mar 2025 18:28:08 -0400 Received: from localhost (localhost [127.0.0.1]) by hera.aquilenet.fr (Postfix) with ESMTP id 960CB3B3; Wed, 12 Mar 2025 23:28:00 +0100 (CET) Authentication-Results: hera.aquilenet.fr; none X-Virus-Scanned: Debian amavis at hera.aquilenet.fr Received: from hera.aquilenet.fr ([127.0.0.1]) by localhost (hera.aquilenet.fr [127.0.0.1]) (amavis, port 10024) with ESMTP id gJdJDbryLUP9; Wed, 12 Mar 2025 23:27:59 +0100 (CET) Received: from ribbon (unknown [83.118.207.42]) by hera.aquilenet.fr (Postfix) with ESMTPSA id 551C726D; Wed, 12 Mar 2025 23:27:59 +0100 (CET) From: =?utf-8?Q?Ludovic_Court=C3=A8s?= <ludo@HIDDEN> To: Reepca Russelstein <reepca@HIDDEN> Subject: Re: bug#75810: [PATCH 0/6] Rootless guix-daemon In-Reply-To: <87plin5j3u.fsf@HIDDEN> (Reepca Russelstein's message of "Tue, 11 Mar 2025 16:54:13 -0500") References: <cover.1737738362.git.ludo@HIDDEN> <87r04qe7dj.fsf@HIDDEN> <87bjvshrk0.fsf@HIDDEN> <875xluehn7.fsf@HIDDEN> <877c5u2ct5.fsf@HIDDEN> <87jz9sc72o.fsf@HIDDEN> <87y0xbivsh.fsf_-_@HIDDEN> <87plin5j3u.fsf@HIDDEN> User-Agent: Gnus/5.13 (Gnus v5.13) Date: Wed, 12 Mar 2025 23:27:54 +0100 Message-ID: <87h63xyjdh.fsf_-_@HIDDEN> MIME-Version: 1.0 Content-Type: text/plain; charset=utf-8 Content-Transfer-Encoding: quoted-printable X-Rspamd-Server: hera X-Rspamd-Queue-Id: 960CB3B3 X-Spamd-Result: default: False [4.90 / 15.00]; SPAM_FLAG(5.00)[]; BAYES_HAM(-3.00)[100.00%]; NEURAL_SPAM(3.00)[1.000]; MIME_GOOD(-0.10)[text/plain]; RCVD_COUNT_TWO(0.00)[2]; FROM_EQ_ENVFROM(0.00)[]; MIME_TRACE(0.00)[0:+]; RCPT_COUNT_TWO(0.00)[2]; ARC_NA(0.00)[]; TO_MATCH_ENVRCPT_ALL(0.00)[]; RCVD_VIA_SMTP_AUTH(0.00)[]; RCVD_TLS_ALL(0.00)[]; FROM_HAS_DN(0.00)[]; TO_DN_SOME(0.00)[]; MID_RHS_MATCH_FROM(0.00)[] X-Spamd-Bar: ++++ X-Rspamd-Action: no action X-Spam-Level: **** X-Spam-Score: 1.7 (+) X-Spam-Report: Spam detection software, running on the system "debbugs.gnu.org", has NOT identified this incoming email as spam. The original message has been attached to this so you can view it or label similar future email. If you have any questions, see the administrator of that system for details. Content preview: Hi, Reepca Russelstein <reepca@HIDDEN> skribis: >> For some reason, it’s not working as advertised: mounts are seemingly >> not locked together and umount(2) on one of them returns EPERM (instead >> of EINVAL). I suspect chroot, pivot_root, & co. [...] Content analysis details: (1.7 points, 10.0 required) pts rule name description ---- ---------------------- -------------------------------------------------- 0.0 RCVD_IN_VALIDITY_SAFE_BLOCKED RBL: ADMINISTRATOR NOTICE: The query to Validity was blocked. See https://knowledge.validity.com/hc/en-us/articles/20961730681243 for more information. [185.233.100.1 listed in sa-accredit.habeas.com] 0.0 RCVD_IN_VALIDITY_RPBL_BLOCKED RBL: ADMINISTRATOR NOTICE: The query to Validity was blocked. See https://knowledge.validity.com/hc/en-us/articles/20961730681243 for more information. [185.233.100.1 listed in bl.score.senderscore.com] -0.0 SPF_HELO_PASS SPF: HELO matches SPF record 0.7 PDS_OTHER_BAD_TLD Untrustworthy TLDs [URI: russelstein.xyz (xyz)] 1.0 SPF_SOFTFAIL SPF: sender does not match SPF record (softfail) X-Debbugs-Envelope-To: 75810 Cc: 75810 <at> debbugs.gnu.org X-BeenThere: debbugs-submit <at> debbugs.gnu.org X-Mailman-Version: 2.1.18 Precedence: list List-Id: <debbugs-submit.debbugs.gnu.org> List-Unsubscribe: <https://debbugs.gnu.org/cgi-bin/mailman/options/debbugs-submit>, <mailto:debbugs-submit-request <at> debbugs.gnu.org?subject=unsubscribe> List-Archive: <https://debbugs.gnu.org/cgi-bin/mailman/private/debbugs-submit/> List-Post: <mailto:debbugs-submit <at> debbugs.gnu.org> List-Help: <mailto:debbugs-submit-request <at> debbugs.gnu.org?subject=help> List-Subscribe: <https://debbugs.gnu.org/cgi-bin/mailman/listinfo/debbugs-submit>, <mailto:debbugs-submit-request <at> debbugs.gnu.org?subject=subscribe> Errors-To: debbugs-submit-bounces <at> debbugs.gnu.org Sender: "Debbugs-submit" <debbugs-submit-bounces <at> debbugs.gnu.org> X-Spam-Score: 0.7 (/) Hi, Reepca Russelstein <reepca@HIDDEN> skribis: >> For some reason, it=E2=80=99s not working as advertised: mounts are seem= ingly >> not locked together and umount(2) on one of them returns EPERM (instead >> of EINVAL). I suspect chroot, pivot_root, & co. spoil it all. > > What this shows is that we're not currently testing the mount-locking > because the builder lacks the necessary capability in its user namespace > (this capability was removed from the effective set when the builder was > exec'ed). That is, the kernel doesn't get as far as checking whether > the mount is locked because the caller wouldn't have the permission to > unmount it even if it weren't locked. Oh my. These clumsy semantics just can=E2=80=99t fit in my head. > One way to test this would be to use setns (perhaps via > container-excursion) to enter the namespaces of the builder, which > will cause you to start out with a full set of effective capabilities > in its user namespace, then try umount. Or a test could be done > within the daemon shortly prior to exec. I tried running a build that sleeps and then joining its namespaces but failed: --8<---------------cut here---------------start------------->8--- $ pgrep -fa builder 16091 guile --no-auto-compile -L /home/ludo/src/guix/test-tmp/store/ngrj4gl= 9lrbmbklcsbgcrq622n9nf0jw-module-import -C /home/ludo/src/guix/test-tmp/sto= re/cskis66zjnhk28h11lbaxkd3j9lyzz6a-module-import-compiled /home/ludo/src/g= uix/test-tmp/store/akndbdx1lmnigf8bi29dr0vd3c8dbdrg-attempt-to-unmount-inpu= t-builder $ nsenter -m -u -i -n -p -U -t 16091=20 nsenter: reassociate to namespace 'ns/ipc' failed: Operation not permitted $ guix container exec 16091 /bin/sh guix container: error: setns: 7 0: Operation not permitted guix container: error: process exited with status 1 --8<---------------cut here---------------end--------------->8--- If you can think of ways to do that, I=E2=80=99m all ears. :-) You can try from the =E2=80=98wip-rootless-daemon=E2=80=99 at <https://codeberg.org/civodul/guix> and apply the patch I sent earlier. (Incidentally, I don=E2=80=99t think we could write an automated test for t= hat; in theory we could use (guix scripts processes) to determine the PID of the build process but that would be too brittle, especially when running =E2=80=9Cmake check -j123=E2=80=9D where it could pick the wrong guix-daemo= n process.) > Note that we still need to initialize /proc/self/uid_map and friends for > the new user namespace, if I understand correctly. Yes, I left that for later (it triggers a test failure anyway, so we won=E2=80=99t forget.) > My reading of user_namespaces(7) is that it should be possible to do > this from within the new user namespace. Oh, interesting. > I hadn't heard of that restriction on unshare and clone. Thinking about > it, I suppose the reason could be that merely creating a user namespace > grants CAP_SYS_CHROOT, and because the current root directory is a > per-process property whose setting isn't limited by any namespace, it > would be possible to undo a chroot someone had tried to set as a > restriction on the current process by just calling chroot("/"). But if > we use pivot_root in conjunction with it, like we do in the daemon, it > should work. Interesting. Thanks for your guidance, as always! Ludo=E2=80=99.
guix-patches@HIDDEN
:bug#75810
; Package guix-patches
.
Full text available.Received: (at 75810) by debbugs.gnu.org; 11 Mar 2025 21:55:05 +0000 From debbugs-submit-bounces <at> debbugs.gnu.org Tue Mar 11 17:55:05 2025 Received: from localhost ([127.0.0.1]:46153 helo=debbugs.gnu.org) by debbugs.gnu.org with esmtp (Exim 4.84_2) (envelope-from <debbugs-submit-bounces <at> debbugs.gnu.org>) id 1ts7Z2-0005NT-Qi for submit <at> debbugs.gnu.org; Tue, 11 Mar 2025 17:55:05 -0400 Received: from mailout.russelstein.xyz ([2605:6400:20:11e::1]:41612) by debbugs.gnu.org with esmtps (TLS1.2:ECDHE_RSA_AES_256_GCM_SHA384:256) (Exim 4.84_2) (envelope-from <reepca@HIDDEN>) id 1ts7Yz-0005LH-LA for 75810 <at> debbugs.gnu.org; Tue, 11 Mar 2025 17:55:03 -0400 DKIM-Signature: v=1; a=ed25519-sha256; q=dns/txt; c=relaxed/relaxed; d=russelstein.xyz; s=ed25519; h=Content-Type:MIME-Version:Message-ID:Date: References:In-Reply-To:Subject:Cc:To:From:Sender:Reply-To: Content-Transfer-Encoding:Content-ID:Content-Description:Resent-Date: Resent-From:Resent-Sender:Resent-To:Resent-Cc:Resent-Message-ID:List-Id: List-Help:List-Unsubscribe:List-Subscribe:List-Post:List-Owner:List-Archive; bh=Tww7v3t80TrTb0dJeblC2JZ7T08c5ffrURyQ9YdEbUM=; b=h5p7HAvlfq3w2eLu8/XnsTSvsF 7igRsE8Pn+I69DeVOzPIJDt4N7lNmyMhybqOSawWyaeEriBnFviHGGzEPwBg==; DKIM-Signature: v=1; a=rsa-sha256; q=dns/txt; c=relaxed/relaxed; d=russelstein.xyz; s=rsa; h=Content-Type:MIME-Version:Message-ID:Date: References:In-Reply-To:Subject:Cc:To:From:Sender:Reply-To: Content-Transfer-Encoding:Content-ID:Content-Description:Resent-Date: Resent-From:Resent-Sender:Resent-To:Resent-Cc:Resent-Message-ID:List-Id: List-Help:List-Unsubscribe:List-Subscribe:List-Post:List-Owner:List-Archive; bh=Tww7v3t80TrTb0dJeblC2JZ7T08c5ffrURyQ9YdEbUM=; b=kdCIiyV8/ByPzUJ3B/7TayG0C8 5hjPVASxCNtfj9HLP4/p4qRip5sTdG1QV4eIAAqsq1ry895t27ZEuk9Oj3VjpzgJCUtsz89b8LrRT cP51HPQa/a8FGbnpxfLRLvvtZXWSIbR0VPe5J5v+hqjODSClrczpHxXOX/5y/V7nwKMgp66jRlNZE yZgx1WcchEf2iqlNS5AApIF8f1NpsQf80wrMwFQlGtlB7JltsKtouwUQZRv9yvknNqyc0h19qrHy8 RODo49Jxl6U8QIz1ia45aRo3LcStvUZANY5oPe4xYg5U6gOu4cVEiFbtvUqQd8W+xdckiAEXWiBQ2 5XGr/H7V4Otvaw908zALrZWQFG/flNgwvOtQ8RLe+xVgN5bWXTZ8TLawJnjfRTFGzWNHBzHCpgirP FMwphrNmITm5c/k6J+jJ/6mv/CLj5wOJ85y/LMKsa7JfuoctdO9qgfmrwjxcpoERsarQizPgmEE7U qTZcoKCKqTIczB/RFBL8a2wMkWBLQgXC4oxQDMuDGyzPtlORD049jOa07hsK+iIn1yFQe5l+QF5Tz htWabERcwdosD9d7Ig+1yTACDiMYGiTK/469sL8PmUC8mxFpXj8vh0OmTKWqz5V3maURXSReUDJ9z LaUFJdwG7iECjF0wOnnSDidkcY7+sEBvkfYpaVe8s=; Received: by russelstein.xyz with esmtpsa (TLS1.3:ECDHE_SECP256R1__RSA_PSS_RSAE_SHA256__AES_256_GCM:256) (Exim 4.98) (envelope-from <reepca@HIDDEN>) id 1ts7Yt-000000007cf-2q0B; Tue, 11 Mar 2025 16:54:57 -0500 From: Reepca Russelstein <reepca@HIDDEN> To: Ludovic =?utf-8?Q?Court=C3=A8s?= <ludo@HIDDEN> Subject: Re: Locked mounts In-Reply-To: <87y0xbivsh.fsf_-_@HIDDEN> ("Ludovic =?utf-8?Q?Court=C3=A8s?= =?utf-8?Q?=22's?= message of "Tue, 11 Mar 2025 13:41:50 +0100") References: <cover.1737738362.git.ludo@HIDDEN> <87r04qe7dj.fsf@HIDDEN> <87bjvshrk0.fsf@HIDDEN> <875xluehn7.fsf@HIDDEN> <877c5u2ct5.fsf@HIDDEN> <87jz9sc72o.fsf@HIDDEN> <87y0xbivsh.fsf_-_@HIDDEN> Date: Tue, 11 Mar 2025 16:54:13 -0500 Message-ID: <87plin5j3u.fsf@HIDDEN> User-Agent: Gnus/5.13 (Gnus v5.13) MIME-Version: 1.0 Content-Type: multipart/signed; boundary="=-=-="; micalg=pgp-sha256; protocol="application/pgp-signature" X-Spam-Score: 0.5 X-Spam-Bar: / X-Spam-Score-Int: 5 X-Spam-Report: Spam detection software, running on the system "Sanctum", has NOT identified this incoming email as spam. The original message has been attached to this so you can view it or label similar future email. If you have any questions, see the administrator of that system for details. Content preview: Ludovic Courtès <ludo@HIDDEN> writes: >> I still think it would be a good idea to call unshare to create an extra >> user and mount namespace just before executing the builder in the >> unprivileged case, just to be sure that the mount-lo [...] Content analysis details: (0.5 points, 5.0 required) pts rule name description ---- ---------------------- -------------------------------------------------- -0.0 NO_RELAYS Informational: message was not relayed via SMTP 0.5 FROM_SUSPICIOUS_NTLD From abused NTLD X-Spam-Score: 0.9 (/) X-Debbugs-Envelope-To: 75810 Cc: 75810 <at> debbugs.gnu.org X-BeenThere: debbugs-submit <at> debbugs.gnu.org X-Mailman-Version: 2.1.18 Precedence: list List-Id: <debbugs-submit.debbugs.gnu.org> List-Unsubscribe: <https://debbugs.gnu.org/cgi-bin/mailman/options/debbugs-submit>, <mailto:debbugs-submit-request <at> debbugs.gnu.org?subject=unsubscribe> List-Archive: <https://debbugs.gnu.org/cgi-bin/mailman/private/debbugs-submit/> List-Post: <mailto:debbugs-submit <at> debbugs.gnu.org> List-Help: <mailto:debbugs-submit-request <at> debbugs.gnu.org?subject=help> List-Subscribe: <https://debbugs.gnu.org/cgi-bin/mailman/listinfo/debbugs-submit>, <mailto:debbugs-submit-request <at> debbugs.gnu.org?subject=subscribe> Errors-To: debbugs-submit-bounces <at> debbugs.gnu.org Sender: "Debbugs-submit" <debbugs-submit-bounces <at> debbugs.gnu.org> X-Spam-Score: 0.9 (/) --=-=-= Content-Type: text/plain; charset=utf-8 Content-Transfer-Encoding: quoted-printable Ludovic Court=C3=A8s <ludo@HIDDEN> writes: >> I still think it would be a good idea to call unshare to create an extra >> user and mount namespace just before executing the builder in the >> unprivileged case, just to be sure that the mount-locking behavior is >> triggered in a way that is documented. > > For some reason, it=E2=80=99s not working as advertised: mounts are seemi= ngly > not locked together and umount(2) on one of them returns EPERM (instead > of EINVAL). I suspect chroot, pivot_root, & co. spoil it all. What this shows is that we're not currently testing the mount-locking because the builder lacks the necessary capability in its user namespace (this capability was removed from the effective set when the builder was exec'ed). That is, the kernel doesn't get as far as checking whether the mount is locked because the caller wouldn't have the permission to unmount it even if it weren't locked. One way to test this would be to use setns (perhaps via container-excursion) to enter the namespaces of the builder, which will cause you to start out with a full set of effective capabilities in its user namespace, then try umount. Or a test could be done within the daemon shortly prior to exec. > Attached is a patch and test case. [...] > diff --git a/nix/libstore/build.cc b/nix/libstore/build.cc > index 057a15ccd0..6a6a960a1c 100644 > --- a/nix/libstore/build.cc > +++ b/nix/libstore/build.cc > @@ -2244,6 +2244,13 @@ void DerivationGoal::runChild() > /* Remount root as read-only. */ > if (mount("/", "/", 0, MS_BIND | MS_REMOUNT | MS_RDONLY, 0) = =3D=3D -1) > throw SysError(format("read-only remount of build root '= %1%' failed") % chrootRootDir); > + > + if (getuid() !=3D 0) { > + /* Create a new mount namespace to "lock" previous mounts. > + See mount_namespaces(7). */ > + if (unshare(CLONE_NEWNS | CLONE_NEWUSER) =3D=3D -1) > + throw SysError(format("creating new user and mount namespaces")); > + } > } > #endif Note that we still need to initialize /proc/self/uid_map and friends for the new user namespace, if I understand correctly. My reading of user_namespaces(7) is that it should be possible to do this from within the new user namespace. > To be sure, I wrote a minimal C program: umount returns EINVAL as > expected. However, when compiling it with -DWITH_CHROOT, unshare(2) > fails with EPERM because =E2=80=9Cthe caller's root directory does not ma= tch the > root directory of the mount namespace in which it resides=E2=80=9D (quoti= ng > unshare(2)). > > So I now get the idea of =E2=80=9Clocked mounts=E2=80=9D but I=E2=80=99m = at loss as to how this > is supposed to interact with chroots. I hadn't heard of that restriction on unshare and clone. Thinking about it, I suppose the reason could be that merely creating a user namespace grants CAP_SYS_CHROOT, and because the current root directory is a per-process property whose setting isn't limited by any namespace, it would be possible to undo a chroot someone had tried to set as a restriction on the current process by just calling chroot("/"). But if we use pivot_root in conjunction with it, like we do in the daemon, it should work. =2D reepca --=-=-= Content-Type: application/pgp-signature; name="signature.asc" -----BEGIN PGP SIGNATURE----- iQFLBAEBCAA1FiEEdNapMPRLm4SepVYGwWaqSV9/GJwFAmfQsQUXHHJlZXBjYUBy dXNzZWxzdGVpbi54eXoACgkQwWaqSV9/GJwI/gf/VU39xMV5XNF1/gGoUyScZOS/ oZ1o6htatQElE+jiCcLs4RCCgCZDXeUc47byMljmQPTpY1NUw1IYB9jnjFxw1/Q3 qvYnE1+O91QZwd1b05nIm0QSOcNHdE+LDJm66ZWluIgtgLtDojBeem02+MlkHWxy Gvmu7YbBMUqLC0wqBIuzBmxsV8+X46Vu+YeuYYJP+09Ir04LFlamCCHJt+MaFjES nHD7rIsUrbQJg5coX0Lkguqhy2HNW/G1aPIlgDI+7PHD+2leR3cWWg9B0cTuwrc+ 53bpmNdeLJoPc7CUG01exQBHnA+SlrO99k1Ts/YFe5I8N0jCTcYQaSHb2BXx+w== =9uMu -----END PGP SIGNATURE----- --=-=-=--
guix-patches@HIDDEN
:bug#75810
; Package guix-patches
.
Full text available.Received: (at 75810) by debbugs.gnu.org; 11 Mar 2025 12:42:14 +0000 From debbugs-submit-bounces <at> debbugs.gnu.org Tue Mar 11 08:42:14 2025 Received: from localhost ([127.0.0.1]:42107 helo=debbugs.gnu.org) by debbugs.gnu.org with esmtp (Exim 4.84_2) (envelope-from <debbugs-submit-bounces <at> debbugs.gnu.org>) id 1tryvy-0005M0-Je for submit <at> debbugs.gnu.org; Tue, 11 Mar 2025 08:42:14 -0400 Received: from hera.aquilenet.fr ([185.233.100.1]:36596) by debbugs.gnu.org with esmtps (TLS1.2:ECDHE_RSA_AES_256_GCM_SHA384:256) (Exim 4.84_2) (envelope-from <ludo@HIDDEN>) id 1tryvr-0005LN-5L for 75810 <at> debbugs.gnu.org; Tue, 11 Mar 2025 08:42:07 -0400 Received: from localhost (localhost [127.0.0.1]) by hera.aquilenet.fr (Postfix) with ESMTP id 7D4C035A; Tue, 11 Mar 2025 13:41:55 +0100 (CET) Authentication-Results: hera.aquilenet.fr; none X-Virus-Scanned: Debian amavis at hera.aquilenet.fr Received: from hera.aquilenet.fr ([127.0.0.1]) by localhost (hera.aquilenet.fr [127.0.0.1]) (amavis, port 10024) with ESMTP id uHLQ3eloNKrI; Tue, 11 Mar 2025 13:41:53 +0100 (CET) Received: from ribbon (91-160-117-201.subs.proxad.net [91.160.117.201]) by hera.aquilenet.fr (Postfix) with ESMTPSA id 57DF22B0; Tue, 11 Mar 2025 13:41:53 +0100 (CET) From: =?utf-8?Q?Ludovic_Court=C3=A8s?= <ludo@HIDDEN> To: Reepca Russelstein <reepca@HIDDEN> Subject: Locked mounts In-Reply-To: <87jz9sc72o.fsf@HIDDEN> (Reepca Russelstein's message of "Fri, 14 Feb 2025 19:47:27 -0600") References: <cover.1737738362.git.ludo@HIDDEN> <87r04qe7dj.fsf@HIDDEN> <87bjvshrk0.fsf@HIDDEN> <875xluehn7.fsf@HIDDEN> <877c5u2ct5.fsf@HIDDEN> <87jz9sc72o.fsf@HIDDEN> Date: Tue, 11 Mar 2025 13:41:50 +0100 Message-ID: <87y0xbivsh.fsf_-_@HIDDEN> User-Agent: Gnus/5.13 (Gnus v5.13) MIME-Version: 1.0 Content-Type: multipart/mixed; boundary="=-=-=" X-Rspamd-Server: hera X-Rspamd-Queue-Id: 7D4C035A X-Spamd-Result: default: False [-4.84 / 15.00]; BAYES_HAM(-3.00)[100.00%]; NEURAL_HAM(-2.99)[-0.998]; R_MIXED_CHARSET(1.25)[subject]; MIME_GOOD(-0.10)[multipart/mixed,text/plain,text/x-patch]; MIME_TRACE(0.00)[0:+,1:+,2:+,3:+]; RCVD_COUNT_TWO(0.00)[2]; FROM_EQ_ENVFROM(0.00)[]; RCPT_COUNT_TWO(0.00)[2]; ARC_NA(0.00)[]; HAS_ATTACHMENT(0.00)[]; RCVD_VIA_SMTP_AUTH(0.00)[]; RCVD_TLS_ALL(0.00)[]; FROM_HAS_DN(0.00)[]; TO_MATCH_ENVRCPT_ALL(0.00)[]; TO_DN_SOME(0.00)[]; MID_RHS_MATCH_FROM(0.00)[] X-Spamd-Bar: ---- X-Rspamd-Action: no action X-Spam-Score: 1.4 (+) X-Spam-Report: Spam detection software, running on the system "debbugs.gnu.org", has NOT identified this incoming email as spam. The original message has been attached to this so you can view it or label similar future email. If you have any questions, see the administrator of that system for details. Content preview: Hi Reepca, Reepca Russelstein <reepca@HIDDEN> skribis: > I still think it would be a good idea to call unshare to create an extra > user and mount namespace just before executing the builder in the > unprivileged case, just to be sure that the mount-locki [...] Content analysis details: (1.4 points, 10.0 required) pts rule name description ---- ---------------------- -------------------------------------------------- 1.0 SPF_SOFTFAIL SPF: sender does not match SPF record (softfail) 0.0 RCVD_IN_VALIDITY_RPBL_BLOCKED RBL: ADMINISTRATOR NOTICE: The query to Validity was blocked. See https://knowledge.validity.com/hc/en-us/articles/20961730681243 for more information. [185.233.100.1 listed in bl.score.senderscore.com] 0.0 RCVD_IN_VALIDITY_SAFE_BLOCKED RBL: ADMINISTRATOR NOTICE: The query to Validity was blocked. See https://knowledge.validity.com/hc/en-us/articles/20961730681243 for more information. [185.233.100.1 listed in sa-trusted.bondedsender.org] 0.5 PDS_OTHER_BAD_TLD Untrustworthy TLDs [URI: russelstein.xyz (xyz)] -0.0 SPF_HELO_PASS SPF: HELO matches SPF record X-Debbugs-Envelope-To: 75810 Cc: 75810 <at> debbugs.gnu.org X-BeenThere: debbugs-submit <at> debbugs.gnu.org X-Mailman-Version: 2.1.18 Precedence: list List-Id: <debbugs-submit.debbugs.gnu.org> List-Unsubscribe: <https://debbugs.gnu.org/cgi-bin/mailman/options/debbugs-submit>, <mailto:debbugs-submit-request <at> debbugs.gnu.org?subject=unsubscribe> List-Archive: <https://debbugs.gnu.org/cgi-bin/mailman/private/debbugs-submit/> List-Post: <mailto:debbugs-submit <at> debbugs.gnu.org> List-Help: <mailto:debbugs-submit-request <at> debbugs.gnu.org?subject=help> List-Subscribe: <https://debbugs.gnu.org/cgi-bin/mailman/listinfo/debbugs-submit>, <mailto:debbugs-submit-request <at> debbugs.gnu.org?subject=subscribe> Errors-To: debbugs-submit-bounces <at> debbugs.gnu.org Sender: "Debbugs-submit" <debbugs-submit-bounces <at> debbugs.gnu.org> X-Spam-Score: 0.4 (/) --=-=-= Content-Type: text/plain; charset=utf-8 Content-Transfer-Encoding: quoted-printable Hi Reepca, Reepca Russelstein <reepca@HIDDEN> skribis: > I still think it would be a good idea to call unshare to create an extra > user and mount namespace just before executing the builder in the > unprivileged case, just to be sure that the mount-locking behavior is > triggered in a way that is documented. For some reason, it=E2=80=99s not working as advertised: mounts are seeming= ly not locked together and umount(2) on one of them returns EPERM (instead of EINVAL). I suspect chroot, pivot_root, & co. spoil it all. Attached is a patch and test case. To be sure, I wrote a minimal C program: umount returns EINVAL as expected. However, when compiling it with -DWITH_CHROOT, unshare(2) fails with EPERM because =E2=80=9Cthe caller's root directory does not matc= h the root directory of the mount namespace in which it resides=E2=80=9D (quoting unshare(2)). So I now get the idea of =E2=80=9Clocked mounts=E2=80=9D but I=E2=80=99m at= loss as to how this is supposed to interact with chroots. Thoughts? Ludo=E2=80=99. --=-=-= Content-Type: text/x-patch Content-Disposition: inline diff --git a/nix/libstore/build.cc b/nix/libstore/build.cc index 057a15ccd0..6a6a960a1c 100644 --- a/nix/libstore/build.cc +++ b/nix/libstore/build.cc @@ -2244,6 +2244,13 @@ void DerivationGoal::runChild() /* Remount root as read-only. */ if (mount("/", "/", 0, MS_BIND | MS_REMOUNT | MS_RDONLY, 0) == -1) throw SysError(format("read-only remount of build root '%1%' failed") % chrootRootDir); + + if (getuid() != 0) { + /* Create a new mount namespace to "lock" previous mounts. + See mount_namespaces(7). */ + if (unshare(CLONE_NEWNS | CLONE_NEWUSER) == -1) + throw SysError(format("creating new user and mount namespaces")); + } } #endif diff --git a/tests/store.scm b/tests/store.scm index c22739afe6..9da9345dd0 100644 --- a/tests/store.scm +++ b/tests/store.scm @@ -37,6 +37,8 @@ (define-module (test-store) #:use-module (guix gexp) #:use-module (gnu packages) #:use-module (gnu packages bootstrap) + #:use-module ((gnu packages make-bootstrap) + #:select (%guile-static-stripped)) #:use-module (ice-9 match) #:use-module (ice-9 regex) #:use-module (rnrs bytevectors) @@ -59,6 +61,8 @@ (define %shell (test-begin "store") +(test-skip 25) + (test-assert "open-connection with file:// URI" (let ((store (open-connection (string-append "file://" (%daemon-socket-uri))))) @@ -455,7 +459,7 @@ (define %shell (drv (run-with-store %store (gexp->derivation - "attempt-to-remount-input-read-write" + "attempt-to-write-to-input" (with-imported-modules (source-module-closure '((guix build syscalls))) #~(begin @@ -496,6 +500,58 @@ (define %shell (build-derivations %store (list drv)) #f))) +(let ((guile (with-external-store external-store + (and external-store + (run-with-store external-store + (mlet %store-monad ((drv (lower-object %guile-static-stripped))) + (mbegin %store-monad + (built-derivations (list drv)) + (return (derivation->output-path (pk 'GDRV drv)))))))))) + + (unless (and guile (unprivileged-user-namespace-supported?)) + (test-skip 1)) + (test-equal "input mount is locked" + EINVAL + ;; Check that mounts within the build environment are "locked" together and + ;; cannot be separated from within the build environment namespace--see + ;; mount_namespaces(7). + ;; + ;; Since guile-bootstrap@HIDDEN lacks 'umount', resort to the hack below to + ;; get a statically-linked Guile with 'umount'. + (let* ((guile (computed-file "guile-with-umount" + ;; The #:guile-for-build argument must be a + ;; derivation, hence this silly thing. + #~(symlink #$(local-file guile "guile-with-umount" + #:recursive? #t) + #$output) + #:guile %bootstrap-guile)) + (drv + (run-with-store %store + (mlet %store-monad ((guile (lower-object guile))) + (gexp->derivation + "attempt-to-unmount-input" + (with-imported-modules (source-module-closure + '((guix build syscalls))) + #~(begin + (use-modules (guix build syscalls)) + + (let ((input #$(plain-file "input-that-might-be-unmounted" + (random-text)))) + (catch 'system-error + (lambda () + ;; umount(2) returns EINVAL when the target is locked. + (umount input)) + (lambda args + (call-with-output-file #$output + (lambda (port) + (write (system-error-errno args) port)))))))) + #:guile-for-build guile))))) + (build-derivations %store (list (pk 'UMDRV drv))) + (call-with-input-file (derivation->output-path drv) + read)))) + +(test-skip 100) + (unless (unprivileged-user-namespace-supported?) (test-skip 1)) (test-assert "build root cannot be made world-readable" --=-=-= Content-Type: text/plain Content-Disposition: attachment; filename=mount-namespace-locking.c #define _GNU_SOURCE 1 #include <stdio.h> #include <stdlib.h> #include <unistd.h> #include <sys/mount.h> #include <sys/stat.h> #include <sched.h> #include <signal.h> #include <stdint.h> #include <string.h> #include <assert.h> #include <error.h> #include <errno.h> #undef NDEBUG static char child_stack[8192]; static int sync_pipe[2]; static int child (void *arg) { close (sync_pipe[1]); char str[123]; read (sync_pipe[0], str, sizeof str); assert (strcmp (str, "go!\n") == 0); close (sync_pipe[0]); printf ("child process: %d\n", getpid ()); mkdir ("/tmp/t", 0700); errno = 0; mount ("none", "/tmp/t", "tmpfs", 0, NULL); assert_perror (errno); #ifdef WITH_CHROOT chroot ("/tmp"); assert_perror (errno); #endif unshare (CLONE_NEWNS | CLONE_NEWUSER); assert_perror (errno); #ifdef WITH_CHROOT umount ("/t"); #else umount ("/tmp/t"); #endif int err = errno; printf ("umount errno: %s\n", strerror (err)); assert (err == EINVAL); return EXIT_FAILURE; } static void initialize_namespace (pid_t pid) { close (sync_pipe[0]); char name[1024]; FILE *file; sprintf (name, "/proc/%d/uid_map", pid); file = fopen (name, "w"); fprintf (file, "42 %d 1", getuid ()); fclose (file); sprintf (name, "/proc/%d/setgroups", pid); file = fopen (name, "w"); fprintf (file, "deny"); fclose (file); sprintf (name, "/proc/%d/gid_map", pid); file = fopen (name, "w"); fprintf (file, "42 %d 1", getgid ()); fclose (file); errno = 0; write (sync_pipe[1], "go!\n", 5); assert_perror (errno); close (sync_pipe[1]); } int main () { errno = 0; pipe2 (sync_pipe, O_CLOEXEC); assert_perror (errno); int pid = clone (child, (char *) (((intptr_t) child_stack + sizeof child_stack - sizeof (void *)) & ~0xfULL), CLONE_NEWNS | CLONE_NEWUSER | SIGCHLD, NULL); assert_perror (errno); initialize_namespace (pid); return EXIT_SUCCESS; } /* unshare -mrf sh -c 'mount -t tmpfs none /tmp; exec unshare -mr strace -e umount2 umount /tmp' */ --=-=-=--
guix-patches@HIDDEN
:bug#75810
; Package guix-patches
.
Full text available.Received: (at 75810) by debbugs.gnu.org; 4 Mar 2025 00:26:04 +0000 From debbugs-submit-bounces <at> debbugs.gnu.org Mon Mar 03 19:26:04 2025 Received: from localhost ([127.0.0.1]:53020 helo=debbugs.gnu.org) by debbugs.gnu.org with esmtp (Exim 4.84_2) (envelope-from <debbugs-submit-bounces <at> debbugs.gnu.org>) id 1tpG6l-00089A-Rv for submit <at> debbugs.gnu.org; Mon, 03 Mar 2025 19:26:04 -0500 Received: from mail-pl1-x636.google.com ([2607:f8b0:4864:20::636]:51699) by debbugs.gnu.org with esmtps (TLS1.2:ECDHE_RSA_AES_128_GCM_SHA256:128) (Exim 4.84_2) (envelope-from <maxim.cournoyer@HIDDEN>) id 1tpG6j-00088b-BY for 75810 <at> debbugs.gnu.org; Mon, 03 Mar 2025 19:26:01 -0500 Received: by mail-pl1-x636.google.com with SMTP id d9443c01a7336-2239aa5da08so33523805ad.3 for <75810 <at> debbugs.gnu.org>; Mon, 03 Mar 2025 16:26:01 -0800 (PST) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=gmail.com; s=20230601; t=1741047955; x=1741652755; darn=debbugs.gnu.org; h=content-transfer-encoding:mime-version:user-agent:message-id:date :references:in-reply-to:subject:cc:to:from:from:to:cc:subject:date :message-id:reply-to; bh=7+fUUXi1IBLrF40vjPFM/L76jRl8A5QqXYv9qCoMF4Q=; b=Tcr8M0SnJooAocORuxDYPzPF1G60lwkWIG7pYnBtrNpIgVrOlcDo9r26qO5k4UBJkW a/f1/d7JLNMMpn1iaoE7L3vVnI3oeejH2AxdBFlmYvVXr1P7PenSMG3cyTbAYQzA14oo DXVdzvYPEfZyI/eIgWCvNO4Mkf1Ovgpot4JiPA/djSTVwVSiiqhQvbw0a9KrioYWrH4G ZyYE0zmgqQ8j1AzP7T9mFHN2gqheK2yBOdcgmF9eouQAxEdDPCOgiWKxmDAz2azjvD8U PRWbRQy3oQwM3s0qZaXE7i+j22gAwbBtdXPqw6WzO0kWOsnXo2ODhsejs5u42Y6CXoy2 5g7w== X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20230601; t=1741047955; x=1741652755; h=content-transfer-encoding:mime-version:user-agent:message-id:date :references:in-reply-to:subject:cc:to:from:x-gm-message-state:from :to:cc:subject:date:message-id:reply-to; bh=7+fUUXi1IBLrF40vjPFM/L76jRl8A5QqXYv9qCoMF4Q=; b=YH2mCvNHhKSZTMk8DRptAdTHsqcl5PYDmVXJcROzoTZKSOqIoozBEfTRWOCQkMdndu AfUYzPFin+tUVcP93Hd+EunHSLqYzaSAHX7IIKo4gZQTvFc1Ke/dMpVw44vkY0mQyxo2 27ufDpJ5EpzOAPqcJRoIh8Ha8xPDiOQhExkOnc+s6GDTTI9tk7ozw/a1TRS9T0GuMdw8 ykgurfJnSf3BPXEJ1oqLRlFt7Z7VWb++yDO6rCoowXq9T6KDEthXRzwr+RMIgDfhf6bg P47SmZFxqAdI1TVY9BKh0A0A0yPXDLFaywv4JxLfT+Br674Qrl4qt6ja030tgcF6495I +kAA== X-Gm-Message-State: AOJu0Yyf2LGcRbVMv8fqzjCssrp+3ZIH34s3y8kbZKTCY+UJj5RqFIgA rJj5hchjdksiW3EvhnQ8rJmSuCa9+xhkoJcoBe0XBumnVwv28prR X-Gm-Gg: ASbGncunBUXvQ+dxLz6uAAmn2No9BfugMyKR3S8ItohPu7BE8ymkFeXsghMFYC3cLBd mBs0tD4VFztgu+nIcnlGTB2rmTMxGz0ef8oiuaLP2Kba3DK0CWMv88hE81YFkdfN6O0A2HzhpBm hvunP11PZ7cXeL+LCjSqYvBoIkUamjAS11xRdZ+gdp8Uw3WDLlAJF94/XcNhJMTq16k3DThmoCl 4xiB2fflie6wLpJDak3mKHCvar8wfSwRQ99kxccJLSpUuYsgX3eBpR89JxL2Jk7rWS2mPQOGvDH SEDryA5cju2XaX/qCjLOOVDAGjb3+GkthV6JSPPHMEY= X-Google-Smtp-Source: AGHT+IHfV6rXlLdlaQ3WWHiBWMkIhwezUfNo0RNus7y4Oi+HVSFUB1Wkc8yUnkBndmYnBcJUU2bSxA== X-Received: by 2002:a17:902:cec1:b0:220:e924:99dd with SMTP id d9443c01a7336-2236920baafmr236088065ad.34.1741047955209; Mon, 03 Mar 2025 16:25:55 -0800 (PST) Received: from terra ([2405:6586:be0:0:83c8:d31d:2cec:f542]) by smtp.gmail.com with ESMTPSA id d9443c01a7336-223501f9d7fsm84158695ad.70.2025.03.03.16.25.52 (version=TLS1_3 cipher=TLS_AES_256_GCM_SHA384 bits=256/256); Mon, 03 Mar 2025 16:25:54 -0800 (PST) From: Maxim Cournoyer <maxim.cournoyer@HIDDEN> To: Ludovic =?utf-8?Q?Court=C3=A8s?= <ludo@HIDDEN> Subject: Re: [bug#75810] [PATCH v4 06/14] daemon: Allow running as non-root with unprivileged user namespaces. In-Reply-To: <87o6yido2w.fsf@HIDDEN> ("Ludovic =?utf-8?Q?Court=C3=A8s=22'?= =?utf-8?Q?s?= message of "Mon, 03 Mar 2025 18:24:39 +0100") References: <cover.1740752774.git.ludo@HIDDEN> <10c042b5dfa44688c5e4aa0e72bd4f7d1ebf6eb5.1740752774.git.ludo@HIDDEN> <87senwezge.fsf@HIDDEN> <87o6yido2w.fsf@HIDDEN> Date: Tue, 04 Mar 2025 09:25:41 +0900 Message-ID: <87plixej5m.fsf@HIDDEN> User-Agent: Gnus/5.13 (Gnus v5.13) MIME-Version: 1.0 Content-Type: text/plain; charset=utf-8 Content-Transfer-Encoding: quoted-printable X-Spam-Score: 0.0 (/) X-Debbugs-Envelope-To: 75810 Cc: Josselin Poiret <dev@HIDDEN>, Simon Tournier <zimon.toutoune@HIDDEN>, Mathieu Othacehe <othacehe@HIDDEN>, Tobias Geerinckx-Rice <me@HIDDEN>, Christopher Baines <guix@HIDDEN>, 75810 <at> debbugs.gnu.org X-BeenThere: debbugs-submit <at> debbugs.gnu.org X-Mailman-Version: 2.1.18 Precedence: list List-Id: <debbugs-submit.debbugs.gnu.org> List-Unsubscribe: <https://debbugs.gnu.org/cgi-bin/mailman/options/debbugs-submit>, <mailto:debbugs-submit-request <at> debbugs.gnu.org?subject=unsubscribe> List-Archive: <https://debbugs.gnu.org/cgi-bin/mailman/private/debbugs-submit/> List-Post: <mailto:debbugs-submit <at> debbugs.gnu.org> List-Help: <mailto:debbugs-submit-request <at> debbugs.gnu.org?subject=help> List-Subscribe: <https://debbugs.gnu.org/cgi-bin/mailman/listinfo/debbugs-submit>, <mailto:debbugs-submit-request <at> debbugs.gnu.org?subject=subscribe> Errors-To: debbugs-submit-bounces <at> debbugs.gnu.org Sender: "Debbugs-submit" <debbugs-submit-bounces <at> debbugs.gnu.org> X-Spam-Score: -1.0 (-) Hi Ludovic, Ludovic Court=C3=A8s <ludo@HIDDEN> writes: [...] >>> - if (chown(chrootRootDir.c_str(), 0, buildUser.getGID()) =3D=3D= -1) >>> + if (buildUser.enabled() && chown(chrootRootDir.c_str(), 0, bui= ldUser.getGID()) =3D=3D -1) > >> I think adding the new check for buildUser.enabled() in the above ifs >> should be split into a distinct commit since it's not relevant to this >> specific new feature. > > It=E2=80=99s in fact related: previously you could not run guix-daemon wi= th > useChroot =3D=3D true unless running as root, and buildUser.enabled() was > implied in this case. > > With this change, you can end up in the =E2=80=9Cif (useChroot)=E2=80=9D = block without > running as root, which is why this distinction needs to be made. Oh, I see (and for the other instance as well). Thanks for explaining! Reviewed-by: Maxim Cournoyer <maxim.cournoyer@gmail> --=20 Thanks, Maxim
guix-patches@HIDDEN
:bug#75810
; Package guix-patches
.
Full text available.Received: (at 75810) by debbugs.gnu.org; 3 Mar 2025 17:25:34 +0000 From debbugs-submit-bounces <at> debbugs.gnu.org Mon Mar 03 12:25:34 2025 Received: from localhost ([127.0.0.1]:51132 helo=debbugs.gnu.org) by debbugs.gnu.org with esmtp (Exim 4.84_2) (envelope-from <debbugs-submit-bounces <at> debbugs.gnu.org>) id 1tp9Xq-0005Pe-BH for submit <at> debbugs.gnu.org; Mon, 03 Mar 2025 12:25:34 -0500 Received: from eggs.gnu.org ([2001:470:142:3::10]:54746) by debbugs.gnu.org with esmtps (TLS1.2:ECDHE_RSA_AES_256_GCM_SHA384:256) (Exim 4.84_2) (envelope-from <ludo@HIDDEN>) id 1tp9Xn-0005P1-Jl for 75810 <at> debbugs.gnu.org; Mon, 03 Mar 2025 12:25:32 -0500 Received: from fencepost.gnu.org ([2001:470:142:3::e]) by eggs.gnu.org with esmtps (TLS1.2:ECDHE_RSA_AES_256_GCM_SHA384:256) (Exim 4.90_1) (envelope-from <ludo@HIDDEN>) id 1tp9Xe-0003s4-Rk; Mon, 03 Mar 2025 12:25:22 -0500 DKIM-Signature: v=1; a=rsa-sha256; q=dns/txt; c=relaxed/relaxed; d=gnu.org; s=fencepost-gnu-org; h=MIME-Version:Date:References:In-Reply-To:Subject:To: From; bh=T5wYx0i8M00PhVCdiUZbDTr3fFvdR+1ei8t2DlDHc4s=; b=YNxoXkRXfmIot4eR6MoS Wq4+WCmcIVJifGSIqwKjar2gt14YKRQHXS4vHmGGSFlHnsr/jsxRCowokdE7GG93naxJu2FPsaZ8v roa5vzud+DWYkqBfX66jGMC+AxZl9sbtHmr7VSgJZ9X2KaMXz251NxjgEHWF+kNGnPgmf0G6jBvlv 209z8SDSA/XXWZsVgPL4fiJZhczFwR/Uo7PiPuu/s215eB/5lmKDPI0crayZRtQXoBo0YVwlX5zqy M2oCMeJbBr0gCA5tOB+bjYd3KShyke9anyreY+5210dqDgC26HJrbW2uuvVcggSJy3zMJ3JqOUJX3 SQQC/wuRW6gTow==; From: =?utf-8?Q?Ludovic_Court=C3=A8s?= <ludo@HIDDEN> To: Maxim Cournoyer <maxim.cournoyer@HIDDEN> Subject: Re: [bug#75810] [PATCH v4 06/14] daemon: Allow running as non-root with unprivileged user namespaces. In-Reply-To: <87senwezge.fsf@HIDDEN> (Maxim Cournoyer's message of "Sun, 02 Mar 2025 15:09:05 +0900") References: <cover.1740752774.git.ludo@HIDDEN> <10c042b5dfa44688c5e4aa0e72bd4f7d1ebf6eb5.1740752774.git.ludo@HIDDEN> <87senwezge.fsf@HIDDEN> X-URL: http://www.fdn.fr/~lcourtes/ X-Revolutionary-Date: Tridi 13 =?utf-8?Q?Vent=C3=B4se?= an 233 de la =?utf-8?Q?R=C3=A9volution=2C?= jour de la Fumeterre X-PGP-Key-ID: 0x090B11993D9AEBB5 X-PGP-Key: http://www.fdn.fr/~lcourtes/ludovic.asc X-PGP-Fingerprint: 3CE4 6455 8A84 FDC6 9DB4 0CFB 090B 1199 3D9A EBB5 X-OS: x86_64-pc-linux-gnu Date: Mon, 03 Mar 2025 18:24:39 +0100 Message-ID: <87o6yido2w.fsf@HIDDEN> User-Agent: Gnus/5.13 (Gnus v5.13) MIME-Version: 1.0 Content-Type: text/plain; charset=utf-8 Content-Transfer-Encoding: quoted-printable X-Spam-Score: -2.3 (--) X-Debbugs-Envelope-To: 75810 Cc: Josselin Poiret <dev@HIDDEN>, Simon Tournier <zimon.toutoune@HIDDEN>, Mathieu Othacehe <othacehe@HIDDEN>, Tobias Geerinckx-Rice <me@HIDDEN>, Christopher Baines <guix@HIDDEN>, 75810 <at> debbugs.gnu.org X-BeenThere: debbugs-submit <at> debbugs.gnu.org X-Mailman-Version: 2.1.18 Precedence: list List-Id: <debbugs-submit.debbugs.gnu.org> List-Unsubscribe: <https://debbugs.gnu.org/cgi-bin/mailman/options/debbugs-submit>, <mailto:debbugs-submit-request <at> debbugs.gnu.org?subject=unsubscribe> List-Archive: <https://debbugs.gnu.org/cgi-bin/mailman/private/debbugs-submit/> List-Post: <mailto:debbugs-submit <at> debbugs.gnu.org> List-Help: <mailto:debbugs-submit-request <at> debbugs.gnu.org?subject=help> List-Subscribe: <https://debbugs.gnu.org/cgi-bin/mailman/listinfo/debbugs-submit>, <mailto:debbugs-submit-request <at> debbugs.gnu.org?subject=subscribe> Errors-To: debbugs-submit-bounces <at> debbugs.gnu.org Sender: "Debbugs-submit" <debbugs-submit-bounces <at> debbugs.gnu.org> X-Spam-Score: -3.3 (---) Hello, Maxim Cournoyer <maxim.cournoyer@HIDDEN> skribis: > Similarly to what Simon pointed in their comments, I'd drop time-related > 'recently' wording, as it won't age well, and is already made obvious by > the above being mentioned as the 'historical' approach. Alright, noted for the next revision. >> - if (chown(chrootRootDir.c_str(), 0, buildUser.getGID()) =3D=3D = -1) >> + if (buildUser.enabled() && chown(chrootRootDir.c_str(), 0, buil= dUser.getGID()) =3D=3D -1) > I think adding the new check for buildUser.enabled() in the above ifs > should be split into a distinct commit since it's not relevant to this > specific new feature. It=E2=80=99s in fact related: previously you could not run guix-daemon with useChroot =3D=3D true unless running as root, and buildUser.enabled() was implied in this case. With this change, you can end up in the =E2=80=9Cif (useChroot)=E2=80=9D bl= ock without running as root, which is why this distinction needs to be made. >> #if CHROOT_ENABLED >> if (useChroot) { >> - /* Initialise the loopback interface. */ >> - AutoCloseFD fd(socket(PF_INET, SOCK_DGRAM, IPPROTO_IP)); >> - if (fd =3D=3D -1) throw SysError("cannot open IP socket"); >> + if (!fixedOutput) { >> + /* Initialise the loopback interface. */ >> + AutoCloseFD fd(socket(PF_INET, SOCK_DGRAM, IPPROTO_IP)); >> + if (fd =3D=3D -1) throw SysError("cannot open IP socket"); >>=20=20 >> - struct ifreq ifr; >> - strcpy(ifr.ifr_name, "lo"); >> - ifr.ifr_flags =3D IFF_UP | IFF_LOOPBACK | IFF_RUNNING; >> - if (ioctl(fd, SIOCSIFFLAGS, &ifr) =3D=3D -1) >> - throw SysError("cannot set loopback interface flags"); >> + struct ifreq ifr; >> + strcpy(ifr.ifr_name, "lo"); >> + ifr.ifr_flags =3D IFF_UP | IFF_LOOPBACK | IFF_RUNNING; >> + if (ioctl(fd, SIOCSIFFLAGS, &ifr) =3D=3D -1) >> + throw SysError("cannot set loopback interface flags"); >>=20=20 >> - fd.close(); >> + fd.close(); >> + } > > That hunk above is also orthogonal to this feature AFAICS, should be > split into a different commit to keep its diff focused. It=E2=80=99s also related: setting up =E2=80=98lo=E2=80=99 would always wor= k before, because we were running as root, but now it only works when running in a separate net namespace. Thanks for your feedback! Ludo=E2=80=99.
guix-patches@HIDDEN
:bug#75810
; Package guix-patches
.
Full text available.Received: (at 75810) by debbugs.gnu.org; 3 Mar 2025 17:16:53 +0000 From debbugs-submit-bounces <at> debbugs.gnu.org Mon Mar 03 12:16:53 2025 Received: from localhost ([127.0.0.1]:51087 helo=debbugs.gnu.org) by debbugs.gnu.org with esmtp (Exim 4.84_2) (envelope-from <debbugs-submit-bounces <at> debbugs.gnu.org>) id 1tp9PR-0004h7-Cb for submit <at> debbugs.gnu.org; Mon, 03 Mar 2025 12:16:53 -0500 Received: from eggs.gnu.org ([2001:470:142:3::10]:40158) by debbugs.gnu.org with esmtps (TLS1.2:ECDHE_RSA_AES_256_GCM_SHA384:256) (Exim 4.84_2) (envelope-from <ludo@HIDDEN>) id 1tp9PO-0004gp-Iv for 75810 <at> debbugs.gnu.org; Mon, 03 Mar 2025 12:16:51 -0500 Received: from fencepost.gnu.org ([2001:470:142:3::e]) by eggs.gnu.org with esmtps (TLS1.2:ECDHE_RSA_AES_256_GCM_SHA384:256) (Exim 4.90_1) (envelope-from <ludo@HIDDEN>) id 1tp9PD-00025F-0W; Mon, 03 Mar 2025 12:16:40 -0500 DKIM-Signature: v=1; a=rsa-sha256; q=dns/txt; c=relaxed/relaxed; d=gnu.org; s=fencepost-gnu-org; h=MIME-Version:Date:References:In-Reply-To:Subject:To: From; bh=IFZSrMS6mqDNuLJgR5r8TcyDiQBo4UgRMwcJlSPZr8w=; b=Uc8iz0k49+105UakYzaA WKduZGsnd3MxqOsanNW6JQPz6LeRPacBkRcDkuV2Cxot3o9TCZLxpJ7lypB2CmlDc+lWcULoMNpsh q7dytwagqNArpmNhbjgxt/7MPGXmlbwUk+t4kIOl36WOPkXfYyx7b14d6nNarnuwmWEbfMAmBg7cX CQhtzGvd26ZQliwUv1gZo6mGiFl7ecJMn734K0Kv5W6iUBLSPbjJrHvBqqF/8UJZsUXc2ysWlZJCC mwVsYQx7bdoJ3Kah96kJ5SxVwZ2ZTGYl3V0j4Bd5S+q1N7JrBGqcAM107pCuP6BZoK8NnbsqnXCf+ IKQziRBq9jxCAw==; From: =?utf-8?Q?Ludovic_Court=C3=A8s?= <ludo@HIDDEN> To: Simon Tournier <zimon.toutoune@HIDDEN> Subject: Re: [bug#75810] [PATCH v4 06/14] daemon: Allow running as non-root with unprivileged user namespaces. In-Reply-To: <87senyggjy.fsf@HIDDEN> (Simon Tournier's message of "Fri, 28 Feb 2025 17:49:53 +0100") References: <cover.1740752774.git.ludo@HIDDEN> <10c042b5dfa44688c5e4aa0e72bd4f7d1ebf6eb5.1740752774.git.ludo@HIDDEN> <87senyggjy.fsf@HIDDEN> X-URL: http://www.fdn.fr/~lcourtes/ X-Revolutionary-Date: Tridi 13 =?utf-8?Q?Vent=C3=B4se?= an 233 de la =?utf-8?Q?R=C3=A9volution=2C?= jour de la Fumeterre X-PGP-Key-ID: 0x090B11993D9AEBB5 X-PGP-Key: http://www.fdn.fr/~lcourtes/ludovic.asc X-PGP-Fingerprint: 3CE4 6455 8A84 FDC6 9DB4 0CFB 090B 1199 3D9A EBB5 X-OS: x86_64-pc-linux-gnu Date: Mon, 03 Mar 2025 18:16:18 +0100 Message-ID: <87zfi2dogt.fsf@HIDDEN> User-Agent: Gnus/5.13 (Gnus v5.13) MIME-Version: 1.0 Content-Type: text/plain; charset=utf-8 Content-Transfer-Encoding: quoted-printable X-Spam-Score: -2.3 (--) X-Debbugs-Envelope-To: 75810 Cc: Josselin Poiret <dev@HIDDEN>, Maxim Cournoyer <maxim.cournoyer@HIDDEN>, Mathieu Othacehe <othacehe@HIDDEN>, Tobias Geerinckx-Rice <me@HIDDEN>, Christopher Baines <guix@HIDDEN>, 75810 <at> debbugs.gnu.org X-BeenThere: debbugs-submit <at> debbugs.gnu.org X-Mailman-Version: 2.1.18 Precedence: list List-Id: <debbugs-submit.debbugs.gnu.org> List-Unsubscribe: <https://debbugs.gnu.org/cgi-bin/mailman/options/debbugs-submit>, <mailto:debbugs-submit-request <at> debbugs.gnu.org?subject=unsubscribe> List-Archive: <https://debbugs.gnu.org/cgi-bin/mailman/private/debbugs-submit/> List-Post: <mailto:debbugs-submit <at> debbugs.gnu.org> List-Help: <mailto:debbugs-submit-request <at> debbugs.gnu.org?subject=help> List-Subscribe: <https://debbugs.gnu.org/cgi-bin/mailman/listinfo/debbugs-submit>, <mailto:debbugs-submit-request <at> debbugs.gnu.org?subject=subscribe> Errors-To: debbugs-submit-bounces <at> debbugs.gnu.org Sender: "Debbugs-submit" <debbugs-submit-bounces <at> debbugs.gnu.org> X-Spam-Score: -3.3 (---) Hi, Simon Tournier <zimon.toutoune@HIDDEN> skribis: >> +There are currently two ways to set up and run the build daemon: >> + >> +@enumerate >> +@item >> +running @command{guix-daemon} as ``root'', letting it run build >> +processes as unprivileged users taken from a pool of build users---this >> +is the historical approach; >> + >> +@item >> +running @command{guix-daemon} as a separate unprivileged user, relying >> +on Linux's @dfn{unprivileged user namespace} functionality to set up >> +isolated environments---this option only appeared recently. >> +@end enumerate >> + >> +The sections below describe each of these two configurations in more >> +detail and summarize the kind of build isolation they provide. > > The paragraph above could give the impression that there is a choice > between two options =E2=80=93 well it was my understand when reading. On > foreign distro, there is no option, IIUC. The installation script chooses one of these two options for you, but the choice is still available. Since this section talks about guix-daemon in general, I thought we should maintain that generality here, but you=E2=80=99re probably right that it should stress that the installation script and Guix System config make choices. I=E2=80=99ll chan= ge that in the next revision. >> +@unnumberedsubsubsec Daemon Running Without Privileges >> + >> +@cindex rootless build daemon >> +@cindex unprivileged build daemon >> +@cindex build daemon, unprivileged >> +The second option, which is new, is to run @command{guix-daemon} > > I would remove =E2=80=9Cwhich is new=E2=80=9D. Or =E2=80=9Cmore recent=E2=80=9D maybe? The idea was to clarify why there = are two options at all. >> The >> +installation script automatically determines whether this option is >> +available on your system (@pxref{Binary Installation}). > > I would write: When using the installation script, it automatically > determines whether =E2=80=A6 Hmm I think that would be grammatically incorrect. Thanks for your feedback! Ludo=E2=80=99.
guix-patches@HIDDEN
:bug#75810
; Package guix-patches
.
Full text available.Received: (at 75810) by debbugs.gnu.org; 2 Mar 2025 06:09:29 +0000 From debbugs-submit-bounces <at> debbugs.gnu.org Sun Mar 02 01:09:29 2025 Received: from localhost ([127.0.0.1]:51210 helo=debbugs.gnu.org) by debbugs.gnu.org with esmtp (Exim 4.84_2) (envelope-from <debbugs-submit-bounces <at> debbugs.gnu.org>) id 1tocW0-0000Xe-Jf for submit <at> debbugs.gnu.org; Sun, 02 Mar 2025 01:09:29 -0500 Received: from mail-pl1-x635.google.com ([2607:f8b0:4864:20::635]:52429) by debbugs.gnu.org with esmtps (TLS1.2:ECDHE_RSA_AES_128_GCM_SHA256:128) (Exim 4.84_2) (envelope-from <maxim.cournoyer@HIDDEN>) id 1tocVw-0000WW-Kn for 75810 <at> debbugs.gnu.org; Sun, 02 Mar 2025 01:09:26 -0500 Received: by mail-pl1-x635.google.com with SMTP id d9443c01a7336-22349bb8605so66930145ad.0 for <75810 <at> debbugs.gnu.org>; Sat, 01 Mar 2025 22:09:24 -0800 (PST) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=gmail.com; s=20230601; t=1740895758; x=1741500558; darn=debbugs.gnu.org; h=content-transfer-encoding:mime-version:user-agent:message-id:date :references:in-reply-to:subject:cc:to:from:from:to:cc:subject:date :message-id:reply-to; bh=FlVaNutW3R0qPrMeQhcskKRiiP9Hnl2GXZVjTUdDRTY=; b=S3i7wMx8KBW6Tqajecj4gMEoG4/BYFERkULdea0r4UI048f63L2QxNlS2v4Wz+vt8g GLk3tChch0H+SAUwHtmYp4flOFqNgPuz98dsidX/sOQaAKllK6tQEAUPRWfVpLdhJrDd MD2aHBOB7SnT7ghfUMK0kfmqldGiFHcpHIDjhXUZauN2Gn9CYyE6ruJyzNCZE28qCduR gyQ2pv7XkvlWwSFMhfpNQXnEraVUCgd8+fHIMaHGJlYG41bn0y206bnRK4T7yWnXDUc/ TmKH5Pmdb2o/qtINAHKSadhTAJGdmH7FOzjDzWyx0FqdIZSG6jSe/kYCW8eOOhZAu+81 KCKg== X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20230601; t=1740895758; x=1741500558; h=content-transfer-encoding:mime-version:user-agent:message-id:date :references:in-reply-to:subject:cc:to:from:x-gm-message-state:from :to:cc:subject:date:message-id:reply-to; bh=FlVaNutW3R0qPrMeQhcskKRiiP9Hnl2GXZVjTUdDRTY=; b=mPpcsNa6/UELxI1N49diNnwiF5u8CFokmJIZKiyLxyhHyTH3dqnugtTEvacclWoGg6 qRso0Y7USNrnjgYC0A1RTQXxPpYbjMvM6lJRXdRiqDCnMWwTmlLwfAteixvkujzS+EcB GoDf72GJR/+NA8LKsBrHosvrY7FDPVgAXiT9RfkB7TeCMP+xpHFSgmaQKyixNicOJQS2 KuCvE0gSXpBM5oFI+sbO0egobvyDvXwk1B1vBiKgmeONJn4zEzUCrVUnTkTtYm4QDJ3R XsngsjmNFKPALYQh9r4DDW4QILXJm7bC/jvI4dBPFPsXHinO3x8dcVnUGtImJOcFKmRv AGSQ== X-Gm-Message-State: AOJu0Yz2FJRbmnYOtduYPIx8UBu88tOSYN+ccPZY1PUya08jfhRqjdDW vZFjh54Ceel4eJYfgfbkEIt4l/z6iDe+gIhk+a3znj5WJeBRfPY4 X-Gm-Gg: ASbGnctXny5U69umZYPgMtLUgGrFwzkzex0WkUjSEGTTy+GFpP1/XPsr9n3IWRABDEx 0/PBrMEQBMYm9PfQsrT5vhw1Hdg1FBSgnz1PIqNmIvdZ4uoY2jIfJhNcfKTjHULgmfRNmnOb0fo sU19Jedy/u+ewCEzTR+iMZXSycKXhLUqnYoXTsD9G4f4+fYceEd9NUB8iILYSDH+lKdCEhsvttG gEM5xmR+6ZZ7r7ssHVMOUTLpLJtVZvO5cJEENoxRjwUjMY17RDNMsWsaEEg7UJRjHbOjfDmzAjX Cfv89Jw0C0cmWioVJGbYQlf7EvrfdKCv6YJ8KMIGEfk= X-Google-Smtp-Source: AGHT+IH7N2rFDY1qdmg2M0MqzwQKQAKrQzrXA6pdjbNK9mWuzkasu9ZWO1TNGG4Mr11/4QmBv8fq9g== X-Received: by 2002:a17:902:e54e:b0:215:8809:b3b7 with SMTP id d9443c01a7336-22368f61b12mr130847715ad.7.1740895758287; Sat, 01 Mar 2025 22:09:18 -0800 (PST) Received: from terra ([2405:6586:be0:0:83c8:d31d:2cec:f542]) by smtp.gmail.com with ESMTPSA id d9443c01a7336-223504dc6desm56776805ad.168.2025.03.01.22.09.15 (version=TLS1_3 cipher=TLS_AES_256_GCM_SHA384 bits=256/256); Sat, 01 Mar 2025 22:09:17 -0800 (PST) From: Maxim Cournoyer <maxim.cournoyer@HIDDEN> To: Ludovic =?utf-8?Q?Court=C3=A8s?= <ludo@HIDDEN> Subject: Re: [bug#75810] [PATCH v4 06/14] daemon: Allow running as non-root with unprivileged user namespaces. In-Reply-To: <10c042b5dfa44688c5e4aa0e72bd4f7d1ebf6eb5.1740752774.git.ludo@HIDDEN> ("Ludovic =?utf-8?Q?Court=C3=A8s=22's?= message of "Fri, 28 Feb 2025 15:29:25 +0100") References: <cover.1740752774.git.ludo@HIDDEN> <10c042b5dfa44688c5e4aa0e72bd4f7d1ebf6eb5.1740752774.git.ludo@HIDDEN> Date: Sun, 02 Mar 2025 15:09:05 +0900 Message-ID: <87senwezge.fsf@HIDDEN> User-Agent: Gnus/5.13 (Gnus v5.13) MIME-Version: 1.0 Content-Type: text/plain; charset=utf-8 Content-Transfer-Encoding: quoted-printable X-Spam-Score: 0.0 (/) X-Debbugs-Envelope-To: 75810 Cc: Josselin Poiret <dev@HIDDEN>, Simon Tournier <zimon.toutoune@HIDDEN>, Mathieu Othacehe <othacehe@HIDDEN>, Tobias Geerinckx-Rice <me@HIDDEN>, Ludovic =?utf-8?Q?Court=C3=A8s?= <ludovic.courtes@HIDDEN>, Christopher Baines <guix@HIDDEN>, 75810 <at> debbugs.gnu.org X-BeenThere: debbugs-submit <at> debbugs.gnu.org X-Mailman-Version: 2.1.18 Precedence: list List-Id: <debbugs-submit.debbugs.gnu.org> List-Unsubscribe: <https://debbugs.gnu.org/cgi-bin/mailman/options/debbugs-submit>, <mailto:debbugs-submit-request <at> debbugs.gnu.org?subject=unsubscribe> List-Archive: <https://debbugs.gnu.org/cgi-bin/mailman/private/debbugs-submit/> List-Post: <mailto:debbugs-submit <at> debbugs.gnu.org> List-Help: <mailto:debbugs-submit-request <at> debbugs.gnu.org?subject=help> List-Subscribe: <https://debbugs.gnu.org/cgi-bin/mailman/listinfo/debbugs-submit>, <mailto:debbugs-submit-request <at> debbugs.gnu.org?subject=subscribe> Errors-To: debbugs-submit-bounces <at> debbugs.gnu.org Sender: "Debbugs-submit" <debbugs-submit-bounces <at> debbugs.gnu.org> X-Spam-Score: -1.0 (-) Hi Ludo, Ludovic Court=C3=A8s <ludo@HIDDEN> writes: > From: Ludovic Court=C3=A8s <ludovic.courtes@HIDDEN> > > * nix/libstore/build.cc (guestUID, guestGID): New variables. > (DerivationGoal)[readiness]: New field. > (initializeUserNamespace): New function. > (DerivationGoal::runChild): When =E2=80=98readiness.readSide=E2=80=99 is = positive, read > from it. > (DerivationGoal::startBuilder): Call =E2=80=98chown=E2=80=99 > only when =E2=80=98buildUser.enabled()=E2=80=99 is true. Pass CLONE_NEWU= SER to =E2=80=98clone=E2=80=99 > when =E2=80=98buildUser.enabled()=E2=80=99 is false or not running as roo= t. Retry > =E2=80=98clone=E2=80=99 without CLONE_NEWUSER upon EPERM. > (DerivationGoal::registerOutputs): Make =E2=80=98actualPath=E2=80=99 writ= able before > =E2=80=98rename=E2=80=99. > (DerivationGoal::deleteTmpDir): Catch =E2=80=98SysError=E2=80=99 around = =E2=80=98_chown=E2=80=99 call. > * nix/libstore/local-store.cc (LocalStore::createUser): Do nothing if > =E2=80=98dirs=E2=80=99 already exists. Warn instead of failing when fail= ing to chown > =E2=80=98dir=E2=80=99. > * guix/substitutes.scm (%narinfo-cache-directory): Check for > =E2=80=98_NIX_OPTIONS=E2=80=99 rather than getuid() =3D=3D 0 to determine= the cache > location. > * doc/guix.texi (Build Environment Setup): Reorganize a bit. Add > section headings =E2=80=9CDaemon Running as Root=E2=80=9D and =E2=80=9CTh= e Isolated Build > Environment=E2=80=9D. Add =E2=80=9CDaemon Running Without Privileges=E2= =80=9D subsection. > Remove paragraph about =E2=80=98--disable-chroot=E2=80=99. > (Invoking guix-daemon): Warn against =E2=80=98--disable-chroot=E2=80=99 a= nd explain why. That's a nice improvement! [...] > +There are currently two ways to set up and run the build daemon: > + > +@enumerate > +@item > +running @command{guix-daemon} as ``root'', letting it run build > +processes as unprivileged users taken from a pool of build users---this > +is the historical approach; > + > +@item > +running @command{guix-daemon} as a separate unprivileged user, relying > +on Linux's @dfn{unprivileged user namespace} functionality to set up > +isolated environments---this option only appeared recently. > +@end enumerate Similarly to what Simon pointed in their comments, I'd drop time-related 'recently' wording, as it won't age well, and is already made obvious by the above being mentioned as the 'historical' approach. > + > +The sections below describe each of these two configurations in more > +detail and summarize the kind of build isolation they provide. > + > +@unnumberedsubsubsec Daemon Running as Root >=20=20 > @cindex build users > When @command{guix-daemon} runs as @code{root}, you may not want package > build processes themselves to run as @code{root} too, for obvious > security reasons. To avoid that, a special pool of @dfn{build users} > should be created for use by build processes started by the daemon. > -These build users need not have a shell and a home directory: they will > -just be used when the daemon drops @code{root} privileges in build > -processes. Having several such users allows the daemon to launch > +Having several such users allows the daemon to launch > distinct build processes under separate UIDs, which guarantees that they > do not interfere with each other---an essential feature since builds are > regarded as pure functions (@pxref{Introduction}). > @@ -977,11 +994,45 @@ Build Environment Setup > # guix-daemon --build-users-group=3Dguixbuild > @end example >=20=20 > +In this setup, @file{/gnu/store} is owned by @code{root}. > + > +@unnumberedsubsubsec Daemon Running Without Privileges > + > +@cindex rootless build daemon > +@cindex unprivileged build daemon > +@cindex build daemon, unprivileged > +The second option, which is new, is to run @command{guix-daemon} s/, which is new,// as Simon pointed. [...] > void DerivationGoal::startBuilder() > { > auto f =3D format( > @@ -1682,7 +1705,7 @@ void DerivationGoal::startBuilder() > then an attacker could create in it a hardlink to a root-owned file > such as /etc/shadow. If 'keepFailed' is true, the daemon would > then chown that hardlink to the user, giving them write access to > - that file. */ > + that file. See CVE-2021-27851. */ > tmpDir +=3D "/top"; > if (mkdir(tmpDir.c_str(), 0700) =3D=3D 1) > throw SysError("creating top-level build directory"); > @@ -1799,7 +1822,7 @@ void DerivationGoal::startBuilder() > if (mkdir(chrootRootDir.c_str(), 0750) =3D=3D -1) > throw SysError(format("cannot create =E2=80=98%1%=E2=80=99")= % chrootRootDir); >=20=20 > - if (chown(chrootRootDir.c_str(), 0, buildUser.getGID()) =3D=3D -= 1) > + if (buildUser.enabled() && chown(chrootRootDir.c_str(), 0, build= User.getGID()) =3D=3D -1) > throw SysError(format("cannot change ownership of =E2=80=98%= 1%=E2=80=99") % chrootRootDir); >=20=20 > /* Create a writable /tmp in the chroot. Many builders need > @@ -1818,8 +1841,8 @@ void DerivationGoal::startBuilder() > (format( > "nixbld:x:%1%:%2%:Nix build user:/:/noshell\n" > "nobody:x:65534:65534:Nobody:/:/noshell\n") > - % (buildUser.enabled() ? buildUser.getUID() : getuid()) > - % (buildUser.enabled() ? buildUser.getGID() : getgid()))= .str()); > + % (buildUser.enabled() ? buildUser.getUID() : guestUID) > + % (buildUser.enabled() ? buildUser.getGID() : guestGID))= .str()); >=20=20 > /* Declare the build user's group so that programs get a consist= ent > view of the system (e.g., "id -gn"). */ > @@ -1854,7 +1877,7 @@ void DerivationGoal::startBuilder() > createDirs(chrootStoreDir); > chmod_(chrootStoreDir, 01775); >=20=20 > - if (chown(chrootStoreDir.c_str(), 0, buildUser.getGID()) =3D=3D = -1) > + if (buildUser.enabled() && chown(chrootStoreDir.c_str(), 0, buil= dUser.getGID()) =3D=3D -1) > throw SysError(format("cannot change ownership of =E2=80=98%= 1%=E2=80=99") % chrootStoreDir); I think adding the new check for buildUser.enabled() in the above ifs should be split into a distinct commit since it's not relevant to this specific new feature. [...] > #if CHROOT_ENABLED > if (useChroot) { > - /* Initialise the loopback interface. */ > - AutoCloseFD fd(socket(PF_INET, SOCK_DGRAM, IPPROTO_IP)); > - if (fd =3D=3D -1) throw SysError("cannot open IP socket"); > + if (!fixedOutput) { > + /* Initialise the loopback interface. */ > + AutoCloseFD fd(socket(PF_INET, SOCK_DGRAM, IPPROTO_IP)); > + if (fd =3D=3D -1) throw SysError("cannot open IP socket"); >=20=20 > - struct ifreq ifr; > - strcpy(ifr.ifr_name, "lo"); > - ifr.ifr_flags =3D IFF_UP | IFF_LOOPBACK | IFF_RUNNING; > - if (ioctl(fd, SIOCSIFFLAGS, &ifr) =3D=3D -1) > - throw SysError("cannot set loopback interface flags"); > + struct ifreq ifr; > + strcpy(ifr.ifr_name, "lo"); > + ifr.ifr_flags =3D IFF_UP | IFF_LOOPBACK | IFF_RUNNING; > + if (ioctl(fd, SIOCSIFFLAGS, &ifr) =3D=3D -1) > + throw SysError("cannot set loopback interface flags"); >=20=20 > - fd.close(); > + fd.close(); > + } That hunk above is also orthogonal to this feature AFAICS, should be split into a different commit to keep its diff focused. The rest LGTM. C++ is not that hard to parse after all; it seems the daemon is written in a style close to that of C. Reviewed-by: Maxim Cournoyer <maxim.cournoyer@gmail> --=20 Thanks, Maxim
guix-patches@HIDDEN
:bug#75810
; Package guix-patches
.
Full text available.Received: (at 75810) by debbugs.gnu.org; 1 Mar 2025 13:53:26 +0000 From debbugs-submit-bounces <at> debbugs.gnu.org Sat Mar 01 08:53:26 2025 Received: from localhost ([127.0.0.1]:35842 helo=debbugs.gnu.org) by debbugs.gnu.org with esmtp (Exim 4.84_2) (envelope-from <debbugs-submit-bounces <at> debbugs.gnu.org>) id 1toNHR-000204-96 for submit <at> debbugs.gnu.org; Sat, 01 Mar 2025 08:53:26 -0500 Received: from mailout.russelstein.xyz ([2605:6400:20:11e::1]:33662) by debbugs.gnu.org with esmtps (TLS1.2:ECDHE_RSA_AES_256_GCM_SHA384:256) (Exim 4.84_2) (envelope-from <reepca@HIDDEN>) id 1toNHN-0001zK-R2 for 75810 <at> debbugs.gnu.org; Sat, 01 Mar 2025 08:53:23 -0500 DKIM-Signature: v=1; a=ed25519-sha256; q=dns/txt; c=relaxed/relaxed; d=russelstein.xyz; s=ed25519; h=Content-Type:MIME-Version:Message-ID:Date: References:In-Reply-To:Subject:Cc:To:From:Sender:Reply-To: Content-Transfer-Encoding:Content-ID:Content-Description:Resent-Date: Resent-From:Resent-Sender:Resent-To:Resent-Cc:Resent-Message-ID:List-Id: List-Help:List-Unsubscribe:List-Subscribe:List-Post:List-Owner:List-Archive; bh=MJeSS+RrKigy1SFtox81x+j03k0jEgI15PJBnwY9dj8=; b=q3hlw4BUo/Shu9TILYdWcjOPvw tCqZJMMi24ONJih07lOEnNoyIOStUUhuQw7glk9BfpY9miwKt4mU3UYlcHAQ==; DKIM-Signature: v=1; a=rsa-sha256; q=dns/txt; c=relaxed/relaxed; d=russelstein.xyz; s=rsa; h=Content-Type:MIME-Version:Message-ID:Date: References:In-Reply-To:Subject:Cc:To:From:Sender:Reply-To: Content-Transfer-Encoding:Content-ID:Content-Description:Resent-Date: Resent-From:Resent-Sender:Resent-To:Resent-Cc:Resent-Message-ID:List-Id: List-Help:List-Unsubscribe:List-Subscribe:List-Post:List-Owner:List-Archive; bh=MJeSS+RrKigy1SFtox81x+j03k0jEgI15PJBnwY9dj8=; b=M4DlmGluDxmhyf3RVGaM+FaKd/ d4PT1K7Lb68B+0ypAfGBvS5hwgYayN60wJkIQlEjtXAknG93BVFQPvBvnsLEBrJX0rA4jfq7rLmt0 YsH9EFZIqbXqiPJFLtkElRBPmbAxka98U2nWdwQEbwYVVXx6EyJdSuzNoTP7YCC3d6h6dqYcyIEWK xGZtuOaVC3NOpg8TyMx4Gaf555u6spyJlXBtgKuQUVpFwFEFhxezAvRT0oAJ25qOjgc8itQ0NwQJ6 XVHUvCwo2hjmoqo7P0huDmCzDeHr8auih5VD0YHfZKE8fvkQp/RC5QXZKh0LmXSX5NW3Upnmlnnj1 LD7dwMJsbcxAF1PF8+3zEJgHutF/skm/2BDljeGqxPPEfq7a59GiS9aFk0d+WBYtgdvTXLPWqEIix ZnnpVGSr9Zb9aKEYqV2x0/ab5k7yz+hlnr3lBkWsx4t2BNxtDutSKmENOKdF/8920ZcjfqQHS2SI1 0JRYgvJiAbuau3Ugs/6YXlr+lcL2Xx7W71rITJMuFc1sp+y6hSGfGUpYnIqnP9fbqd3mGHUBU6W5G X44gjKtQal1xNMtXez1ZFr+by2PMudQiALl/wHLgn1urks/DrGgreAZJkCoSfYj1E3KBhl83FxueP zFBWsdIt75/9ixOOcJ6OaoGjHKCQDbMT7V2jvc85k=; Received: by russelstein.xyz with esmtpsa (TLS1.3:ECDHE_SECP256R1__RSA_PSS_RSAE_SHA256__AES_256_GCM:256) (Exim 4.98) (envelope-from <reepca@HIDDEN>) id 1toNHH-0000000070e-2fQq; Sat, 01 Mar 2025 07:53:17 -0600 From: Reepca Russelstein <reepca@HIDDEN> To: Ludovic =?utf-8?Q?Court=C3=A8s?= <ludo@HIDDEN> Subject: Re: [PATCH v4 00/14] Rootless guix-daemon In-Reply-To: <cover.1740752774.git.ludo@HIDDEN> ("Ludovic =?utf-8?Q?Court?= =?utf-8?Q?=C3=A8s=22's?= message of "Fri, 28 Feb 2025 15:29:19 +0100") References: <cover.1740752774.git.ludo@HIDDEN> Date: Sat, 01 Mar 2025 07:52:40 -0600 Message-ID: <8734fw7t93.fsf@HIDDEN> User-Agent: Gnus/5.13 (Gnus v5.13) MIME-Version: 1.0 Content-Type: multipart/signed; boundary="=-=-="; micalg=pgp-sha256; protocol="application/pgp-signature" X-Spam-Score: 0.5 X-Spam-Bar: / X-Spam-Score-Int: 5 X-Spam-Report: Spam detection software, running on the system "Sanctum", has NOT identified this incoming email as spam. The original message has been attached to this so you can view it or label similar future email. If you have any questions, see the administrator of that system for details. Content preview: Ludovic Courtès <ludo@HIDDEN> writes: > Hello Guix! > > Changes in v4, hopefully the last revision of this patch set: > > • For ‘deleteTmpDir’, go back to v2, but add ‘secureFilePerms’ call and > define ‘reown’ variable to d [...] Content analysis details: (0.5 points, 5.0 required) pts rule name description ---- ---------------------- -------------------------------------------------- -0.0 NO_RELAYS Informational: message was not relayed via SMTP 0.5 FROM_SUSPICIOUS_NTLD From abused NTLD X-Spam-Score: 1.3 (+) X-Spam-Report: Spam detection software, running on the system "debbugs.gnu.org", has NOT identified this incoming email as spam. The original message has been attached to this so you can view it or label similar future email. If you have any questions, see the administrator of that system for details. Content preview: Ludovic Courtès <ludo@HIDDEN> writes: > Hello Guix! > > Changes in v4, hopefully the last revision of this patch set: > > • For ‘deleteTmpDir’, go back to v2, but add ‘secureFilePerms’ call and > define ‘reown’ variable to d [...] Content analysis details: (1.3 points, 10.0 required) pts rule name description ---- ---------------------- -------------------------------------------------- 0.8 PDS_OTHER_BAD_TLD Untrustworthy TLDs [URI: russelstein.xyz (xyz)] -0.0 SPF_PASS SPF: sender matches SPF record 0.0 SPF_HELO_NONE SPF: HELO does not publish an SPF Record 0.5 FROM_SUSPICIOUS_NTLD From abused NTLD X-Debbugs-Envelope-To: 75810 Cc: 75810 <at> debbugs.gnu.org X-BeenThere: debbugs-submit <at> debbugs.gnu.org X-Mailman-Version: 2.1.18 Precedence: list List-Id: <debbugs-submit.debbugs.gnu.org> List-Unsubscribe: <https://debbugs.gnu.org/cgi-bin/mailman/options/debbugs-submit>, <mailto:debbugs-submit-request <at> debbugs.gnu.org?subject=unsubscribe> List-Archive: <https://debbugs.gnu.org/cgi-bin/mailman/private/debbugs-submit/> List-Post: <mailto:debbugs-submit <at> debbugs.gnu.org> List-Help: <mailto:debbugs-submit-request <at> debbugs.gnu.org?subject=help> List-Subscribe: <https://debbugs.gnu.org/cgi-bin/mailman/listinfo/debbugs-submit>, <mailto:debbugs-submit-request <at> debbugs.gnu.org?subject=subscribe> Errors-To: debbugs-submit-bounces <at> debbugs.gnu.org Sender: "Debbugs-submit" <debbugs-submit-bounces <at> debbugs.gnu.org> X-Spam-Score: 1.3 (+) X-Spam-Report: Spam detection software, running on the system "debbugs.gnu.org", has NOT identified this incoming email as spam. The original message has been attached to this so you can view it or label similar future email. If you have any questions, see the administrator of that system for details. Content preview: Ludovic Courtès <ludo@HIDDEN> writes: > Hello Guix! > > Changes in v4, hopefully the last revision of this patch set: > > • For ‘deleteTmpDir’, go back to v2, but add ‘secureFilePerms’ call and > define ‘reown’ variable to d [...] Content analysis details: (1.3 points, 10.0 required) pts rule name description ---- ---------------------- -------------------------------------------------- 0.8 PDS_OTHER_BAD_TLD Untrustworthy TLDs [URI: russelstein.xyz (xyz)] -0.0 SPF_PASS SPF: sender matches SPF record 0.0 SPF_HELO_NONE SPF: HELO does not publish an SPF Record 1.0 BULK_RE_SUSP_NTLD Precedence bulk and RE: from a suspicious TLD 0.5 FROM_SUSPICIOUS_NTLD From abused NTLD -1.0 MAILING_LIST_MULTI Multiple indicators imply a widely-seen list manager --=-=-= Content-Type: text/plain; charset=utf-8 Content-Transfer-Encoding: quoted-printable Ludovic Court=C3=A8s <ludo@HIDDEN> writes: > Hello Guix! > > Changes in v4, hopefully the last revision of this patch set: > > =E2=80=A2 For =E2=80=98deleteTmpDir=E2=80=99, go back to v2, but add = =E2=80=98secureFilePerms=E2=80=99 call and > define =E2=80=98reown=E2=80=99 variable to determine whether to re-ch= own after pivoting > (suggested by Reepca). After re-reading the v4 patch for this I've noticed one minor nitpick: since it's technically possible (though unlikely) to both have CAP_CHOWN and have (top =3D=3D tmpdir), for example if --disable-chroot is given, it is possible that it will unnecessarily chown tmpDir and then never re-chown it back. The diff in question, for clarity: > @@ -2736,8 +2798,32 @@ void DerivationGoal::deleteTmpDir(bool force) > // Change the ownership if clientUid is set. Never change the > // ownership or the group to "root" for security reasons. > if (settings.clientUid !=3D (uid_t) -1 && settings.clientUid= !=3D 0) { > - _chown(tmpDir, settings.clientUid, > - settings.clientGid !=3D 0 ? settings.clientGid : = -1); > + uid_t uid =3D settings.clientUid; > + gid_t gid =3D settings.clientGid !=3D 0 ? settings.clientGid : -1; > + bool reown =3D false; > + > + /* First remove setuid/setgid bits. */ > + secureFilePerms(tmpDir); > + > + try { > + _chown(tmpDir, uid, gid); > + > + if (getuid() !=3D 0) { > + /* If, without being root, the '_chown' call above > + succeeded, then it means we have CAP_CHOWN. Retake > + ownership of tmpDir itself so it can be renamed > + below. */ > + chown(tmpDir.c_str(), getuid(), getgid()); > + reown =3D true; > + } > + > + } catch (SysError & e) { > + /* When running as an unprivileged user and without > + CAP_CHOWN, we cannot chown the build tree. Print a > + message and keep going. */ > + printMsg(lvlInfo, format("cannot change ownership of build directo= ry '%1%': %2%") > + % tmpDir % strerror(e.errNo)); > + } >=20=20 > if (top !=3D tmpDir) { > // Rename tmpDir to its parent, with an intermediate step. > @@ -2746,6 +2832,11 @@ void DerivationGoal::deleteTmpDir(bool force) > throw SysError("pivoting failed build tree"); > if (rename((pivot + "/top").c_str(), top.c_str()) =3D=3D -1) > throw SysError("renaming failed build tree"); > + > + if (reown) > + /* Running unprivileged but with CAP_CHOWN. */ > + chown(top.c_str(), uid, gid); > + > rmdir(pivot.c_str()); > } > } This can be remedied by moving chown(tmpDir.c_str(), getuid(), getgid()); to inside the if (top !=3D tmpDir) block, and adding a test for 'reown', like so: if (top !=3D tmpDir) { if (reown) chown(tmpDir.c_str(), getuid(), getgid()); // Rename tmpDir to its parent, with an intermediate step. ... } The extra symmetry should also make this section a bit clearer overall. > The tests try to MS_REMOUNT the inputs, which is exactly what we want to > prevent; we could test the low-level semantics you describe, but it=E2=80= =99s > quite obscure and maybe unnecessary given that we test MS_REMOUNT? My concern is that it may be possible, now or in the future, for the builder to gain the necessary capability within its user namespace... somehow. This concern comes from reading the capabilities(7) manual page, where it says: Per-user-namespace "set-user-ID-root" programs A set-user-ID program whose UID matches the UID that created a u= ser namespace will confer capabilities in the process's permitted and = ef=E2=80=90 fective sets when executed by any process inside that namespace or = any descendant user namespace. The rules about the transformation of the process's capabilities dur= ing the execve(2) are exactly as described in Transformation of capabi= li=E2=80=90 ties during execve() and Capabilities and execution of programs by r= oot above, with the difference that, in the latter subsection, "root"= is the UID of the creator of the user namespace. Even with no effective capabilities whatsoever, nothing is stopping root from making a setuid program and executing it, and I don't see what would stop the builder from doing likewise. If it works as described ("whose UID matches the UID that created a user namespace"), this should cause the builder to gain full capabilities within its user namespace. Now, experimentally, this doesn't /seem/ to work as described, but if it's in the manual, it may be unwise to bet against it ever happening. Additionally, even if it never is implemented as described, this text's presence makes it less clear how security within a user namespace (not just between user namespaces) is intended to work. That's why I would like for the security against remounting to not depend on the capabilities that the builder has in its user namespace. =2D reepca --=-=-= Content-Type: application/pgp-signature; name="signature.asc" -----BEGIN PGP SIGNATURE----- iQFLBAEBCAA1FiEEdNapMPRLm4SepVYGwWaqSV9/GJwFAmfDESkXHHJlZXBjYUBy dXNzZWxzdGVpbi54eXoACgkQwWaqSV9/GJzjmQgAon0XOWbS7jwlulptpAiXIkXA V1q/837h5N/qLH6goZ7YAoikyQ/DuooCmU7Y8PrIF80y1y6Vi7mPD32Cx9/pKsXG ktHTM9skGqvntzozqUHHzjzZm8V5zNSANdnBb+luZvnKsZHQdxh0dzN5hokK8y1x 7CIj1pGS0sSb6lhiFm1RSuCw3FegxltZeKPb+OJrjfSXZWtN14nvQqdRTLLX01zj 6Yh8k5tJetYs4FWOwjsa8BzsqIGnoOtjb11KOiBfsHcgSoWgGRyGEDhYbnLbXpw4 0wG03p8ble2YGqMbRiJ2zOSt+cVcdpf3OQ7Mgd34XL8WVSCxBG1hf5YoJrim2A== =DRJH -----END PGP SIGNATURE----- --=-=-=--
guix-patches@HIDDEN
:bug#75810
; Package guix-patches
.
Full text available.Received: (at 75810) by debbugs.gnu.org; 28 Feb 2025 17:57:46 +0000 From debbugs-submit-bounces <at> debbugs.gnu.org Fri Feb 28 12:57:46 2025 Received: from localhost ([127.0.0.1]:52343 helo=debbugs.gnu.org) by debbugs.gnu.org with esmtp (Exim 4.84_2) (envelope-from <debbugs-submit-bounces <at> debbugs.gnu.org>) id 1to4cL-0003Sm-Ol for submit <at> debbugs.gnu.org; Fri, 28 Feb 2025 12:57:46 -0500 Received: from mail-wm1-x331.google.com ([2a00:1450:4864:20::331]:51710) by debbugs.gnu.org with esmtps (TLS1.2:ECDHE_RSA_AES_128_GCM_SHA256:128) (Exim 4.84_2) (envelope-from <zimon.toutoune@HIDDEN>) id 1to4cI-0003S3-KU for 75810 <at> debbugs.gnu.org; Fri, 28 Feb 2025 12:57:43 -0500 Received: by mail-wm1-x331.google.com with SMTP id 5b1f17b1804b1-43995b907cfso16043975e9.3 for <75810 <at> debbugs.gnu.org>; Fri, 28 Feb 2025 09:57:42 -0800 (PST) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=gmail.com; s=20230601; t=1740765456; x=1741370256; darn=debbugs.gnu.org; h=content-transfer-encoding:mime-version:message-id:date:references :in-reply-to:subject:cc:to:from:from:to:cc:subject:date:message-id :reply-to; bh=G730h75f+XzVw2NwaWvNsyb4w/sCtk+sVyAd/9JdWOk=; b=aqkhBSPCDVqGTVuU0UZI6fSjQsyiiOqliYAIQk3RsuY4q/jRlFPD2D+xceZnzpXg8C A3outzTsuzr07/cv4O+wM4CXFs1NrZvC+Xf6WrGOtW8yq1KC7zgD0qhgeNU8Akpy3Odu VcS/uf7FzY6yY+cu/I58xF0bJpGUTU93Z1I2QLE61dIGVUnsUFz3KqwMp3ZyQikeaMJ0 b1P6AfUYmQ6qHAtrw7qvawsavTFG/5R2iTmITokZSOZaWRWLSicJ1KOgZhcviBaQXw+y KIHFpdYYIROrHXWF3LHc3XIYmJ94Oerh4OtISY05W+SCpbyUk/AQ5kYTQRtY77wx47bp PJUQ== X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20230601; t=1740765456; x=1741370256; h=content-transfer-encoding:mime-version:message-id:date:references :in-reply-to:subject:cc:to:from:x-gm-message-state:from:to:cc :subject:date:message-id:reply-to; bh=G730h75f+XzVw2NwaWvNsyb4w/sCtk+sVyAd/9JdWOk=; b=uwbxUkmVw+kbFAO87fzev/WSZtPoI6hbKifVSU4chzH6zs7Cz4FhUjYw82PQJTfe9u h2f/7+5S9VKY5/mA03pYfSh7LlFe1lMsNaezV/YT22E29ZfeIIp5/lLdfEEV+yE0SSDd wX4DvGZhnBKB/2Rt4N+KUlgj67eoozoaiS4aod3BvftQfE81kzGC0rnadiSki8/fPaNh CFbTdqc9f00lzzOOP7Ff2Uqw/ZgVcKWCHNkz3VdBbP38caEzw6Estg8QpcyO8Z3p/CNM w3VqPs4D88S3rXCk7x/EPaG5wvtgAqo95iERUgnu6TaXT+ZPxD/h/Fdz3OkDQ2v6aAlv v1eA== X-Forwarded-Encrypted: i=1; AJvYcCVWFJ9wKLxD8SZMAa870VG0wwYgxlzcvnTNiJIGedKbQ683Q7FT4MLqjgIkips+A7BPUP6rDg==@debbugs.gnu.org X-Gm-Message-State: AOJu0YyNHz3mbfjisla2NrhN4RcmDLHXrkcfOZSnbK8QaA0SEiwn5NF0 7Rv25wciJ1shQQYpRLi8SAb/k0FC5C5YPIEcuujiJ4cQi2utvxF8 X-Gm-Gg: ASbGncvYE1mcxoHzMYxzLaCAoJKU4Epqh3ByagOuqPKk0KQsGEBFQP+bEFIimIQI998 VcnbDyrN4MwenrILZzzFsoE7yf6+WhEp2KyxGR6pB+57+OQPYJc0kHxDJFSx71fAFRusxTfcUWM olFGpcRE8Gah5cmRHfhHRPIIcKy6BFPMN2spxy2XY4IM3H4vUwfNnlS/q+NQv8ns8dUErfaqaIU nrN98r0LI6GWvt9wq6QiddDYWthZFLvlX7hJLseNhK+i3mWofXocOmDS/K7RmRrutdQWOzavtHx M7D24sOEyV+4SnAhA4ojsGIDeskBoSVN57pBTKNLT9ypvphpB3tbxV/0DZUHKSCEH7ZW+poG2XE hGm7aj68qlcg= X-Google-Smtp-Source: AGHT+IE9UR+usArpRXkN74a8ZtRsCktnlIh+cC6fKOkMxlh38T2Lr8yQvz5CxnnIIwVUWKsS7hSUBg== X-Received: by 2002:a05:6000:1f88:b0:38b:f44b:8663 with SMTP id ffacd0b85a97d-390eca38bfdmr4498965f8f.55.1740765456175; Fri, 28 Feb 2025 09:57:36 -0800 (PST) Received: from lili (roam-nat-fw-prg-194-254-61-45.net.univ-paris-diderot.fr. [194.254.61.45]) by smtp.gmail.com with ESMTPSA id 5b1f17b1804b1-43aba53942fsm95163385e9.24.2025.02.28.09.57.35 (version=TLS1_3 cipher=TLS_AES_256_GCM_SHA384 bits=256/256); Fri, 28 Feb 2025 09:57:35 -0800 (PST) From: Simon Tournier <zimon.toutoune@HIDDEN> To: Ludovic =?utf-8?Q?Court=C3=A8s?= <ludo@HIDDEN>, 75810 <at> debbugs.gnu.org Subject: Re: [bug#75810] [PATCH v4 06/14] daemon: Allow running as non-root with unprivileged user namespaces. In-Reply-To: <10c042b5dfa44688c5e4aa0e72bd4f7d1ebf6eb5.1740752774.git.ludo@HIDDEN> References: <cover.1740752774.git.ludo@HIDDEN> <10c042b5dfa44688c5e4aa0e72bd4f7d1ebf6eb5.1740752774.git.ludo@HIDDEN> Date: Fri, 28 Feb 2025 17:49:53 +0100 Message-ID: <87senyggjy.fsf@HIDDEN> MIME-Version: 1.0 Content-Type: text/plain; charset=utf-8 Content-Transfer-Encoding: quoted-printable X-Spam-Score: 0.0 (/) X-Debbugs-Envelope-To: 75810 Cc: Josselin Poiret <dev@HIDDEN>, Maxim Cournoyer <maxim.cournoyer@HIDDEN>, Mathieu Othacehe <othacehe@HIDDEN>, Ludovic =?utf-8?Q?Court=C3=A8s?= <ludo@HIDDEN>, Tobias Geerinckx-Rice <me@HIDDEN>, Ludovic =?utf-8?Q?Court=C3=A8s?= <ludovic.courtes@HIDDEN>, Christopher Baines <guix@HIDDEN> X-BeenThere: debbugs-submit <at> debbugs.gnu.org X-Mailman-Version: 2.1.18 Precedence: list List-Id: <debbugs-submit.debbugs.gnu.org> List-Unsubscribe: <https://debbugs.gnu.org/cgi-bin/mailman/options/debbugs-submit>, <mailto:debbugs-submit-request <at> debbugs.gnu.org?subject=unsubscribe> List-Archive: <https://debbugs.gnu.org/cgi-bin/mailman/private/debbugs-submit/> List-Post: <mailto:debbugs-submit <at> debbugs.gnu.org> List-Help: <mailto:debbugs-submit-request <at> debbugs.gnu.org?subject=help> List-Subscribe: <https://debbugs.gnu.org/cgi-bin/mailman/listinfo/debbugs-submit>, <mailto:debbugs-submit-request <at> debbugs.gnu.org?subject=subscribe> Errors-To: debbugs-submit-bounces <at> debbugs.gnu.org Sender: "Debbugs-submit" <debbugs-submit-bounces <at> debbugs.gnu.org> X-Spam-Score: -1.0 (-) Hi, On Fri, 28 Feb 2025 at 15:29, Ludovic Court=C3=A8s <ludo@HIDDEN> wrote: > * doc/guix.texi (Build Environment Setup): Reorganize a bit. Add > section headings =E2=80=9CDaemon Running as Root=E2=80=9D and =E2=80=9CTh= e Isolated Build > Environment=E2=80=9D. Add =E2=80=9CDaemon Running Without Privileges=E2= =80=9D subsection. > Remove paragraph about =E2=80=98--disable-chroot=E2=80=99. > (Invoking guix-daemon): Warn against =E2=80=98--disable-chroot=E2=80=99 a= nd explain why. > --- > doc/guix.texi | 100 +++++++++++++++++++------- [...] > diff --git a/doc/guix.texi b/doc/guix.texi > index 93380dc30d4..a2b65299e9f 100644 > --- a/doc/guix.texi > +++ b/doc/guix.texi > @@ -877,6 +877,7 @@ Setting Up the Daemon > @section Setting Up the Daemon [...] > +There are currently two ways to set up and run the build daemon: > + > +@enumerate > +@item > +running @command{guix-daemon} as ``root'', letting it run build > +processes as unprivileged users taken from a pool of build users---this > +is the historical approach; > + > +@item > +running @command{guix-daemon} as a separate unprivileged user, relying > +on Linux's @dfn{unprivileged user namespace} functionality to set up > +isolated environments---this option only appeared recently. > +@end enumerate > + > +The sections below describe each of these two configurations in more > +detail and summarize the kind of build isolation they provide. The paragraph above could give the impression that there is a choice between two options =E2=80=93 well it was my understand when reading. On foreign distro, there is no option, IIUC. Therefore, I would clarify, something like: Depending on your situation, the build daemon can set up and run in different ways: @enumerate @item=20=20=20=20=20=20=20=20 running @command{guix-daemon} as ``root'', letting it run build processes as unprivileged users taken from a pool of build users---this is the historical approach; @item=20=20=20=20=20=20=20 running @command{guix-daemon} as a separate unprivileged user, relying on Linux's @dfn{unprivileged user namespace} functionality to set up isolated environments---this option is recently become mandatory on foreign distribution.=20=20=20=20=20= =20=20=20 @end enumerate The sections below describe each of these two configurations in more detail and summarize the kind of build isolation they provide. Somehow, I would explicitly mention here what are my options when using Guix System and what is my option when using foreign distro. > +@unnumberedsubsubsec Daemon Running Without Privileges > + > +@cindex rootless build daemon > +@cindex unprivileged build daemon > +@cindex build daemon, unprivileged > +The second option, which is new, is to run @command{guix-daemon} I would remove =E2=80=9Cwhich is new=E2=80=9D. > +@emph{as an unprivileged user}. It has the advantage of reducing the > +harm that can be done should a build process manage to exploit a > +vulnerability in the daemon. This option requires the user of Linux's > +unprivileged user namespace mechanism; today it is available and enabled > +by most GNU/Linux distributions but can still be disabled. > The > +installation script automatically determines whether this option is > +available on your system (@pxref{Binary Installation}). I would write: When using the installation script, it automatically determines whether =E2=80=A6 > -If you are installing Guix as an unprivileged user, it is still possible > -to run @command{guix-daemon} provided you pass @option{--disable-chroot}. > -However, build processes will not be isolated from one another, and not > -from the rest of the system. Thus, build processes may interfere with > -each other, and may access programs, libraries, and other files > -available on the system---making it much harder to view them as > -@emph{pure} functions. > - Yeah, good removal! :-) Cheers, simon
guix-patches@HIDDEN
:bug#75810
; Package guix-patches
.
Full text available.Received: (at 75810) by debbugs.gnu.org; 28 Feb 2025 14:31:12 +0000 From debbugs-submit-bounces <at> debbugs.gnu.org Fri Feb 28 09:31:12 2025 Received: from localhost ([127.0.0.1]:47880 helo=debbugs.gnu.org) by debbugs.gnu.org with esmtp (Exim 4.84_2) (envelope-from <debbugs-submit-bounces <at> debbugs.gnu.org>) id 1to1OO-0004eR-Np for submit <at> debbugs.gnu.org; Fri, 28 Feb 2025 09:31:12 -0500 Received: from eggs.gnu.org ([2001:470:142:3::10]:45372) by debbugs.gnu.org with esmtps (TLS1.2:ECDHE_RSA_AES_256_GCM_SHA384:256) (Exim 4.84_2) (envelope-from <ludo@HIDDEN>) id 1to1NP-0004QB-HX for 75810 <at> debbugs.gnu.org; Fri, 28 Feb 2025 09:30:17 -0500 Received: from fencepost.gnu.org ([2001:470:142:3::e]) by eggs.gnu.org with esmtps (TLS1.2:ECDHE_RSA_AES_256_GCM_SHA384:256) (Exim 4.90_1) (envelope-from <ludo@HIDDEN>) id 1to1NI-0002Et-Gj; Fri, 28 Feb 2025 09:30:00 -0500 DKIM-Signature: v=1; a=rsa-sha256; q=dns/txt; c=relaxed/relaxed; d=gnu.org; s=fencepost-gnu-org; h=MIME-Version:References:In-Reply-To:Date:Subject:To: From; bh=cdZxe51hOaEFBGak7Gjws9ptWs0pjfB3xteJ+QyhK4A=; b=ARKPu0CEFgVYNBzVSuBa LcDpbsmcKt24Qlli3boFWLb0F6uhjRulY/H9jeKpiVQUZnPA2DHT+qcx6y2oBEUgF+HtEf7Pagbta 2um4+NRfKiSO8oOEcijEgnW2OhrEwLoenJwSioRhq7X5pq30QkG8rwMVjD65G0XnRYJ712lEH+E5U kNLZ4CMxSv1A3wEOgbkudHp3aXWPP7r79zTs5QSUpo9Q+DOP3sZU0KWkWrL/cgD5lxv2ytNTzT+7f WiaQhZRrAAnBdPw1exXYp91Pv7H1c/6wvngbSmeJ7c/hBTE/vQqYgAcSo9PK2vei/raduRlalLXL1 iIwpXNHMq6pW/w==; From: =?UTF-8?q?Ludovic=20Court=C3=A8s?= <ludo@HIDDEN> To: 75810 <at> debbugs.gnu.org Subject: [PATCH v4 06/14] daemon: Allow running as non-root with unprivileged user namespaces. Date: Fri, 28 Feb 2025 15:29:25 +0100 Message-ID: <10c042b5dfa44688c5e4aa0e72bd4f7d1ebf6eb5.1740752774.git.ludo@HIDDEN> X-Mailer: git-send-email 2.48.1 In-Reply-To: <cover.1740752774.git.ludo@HIDDEN> References: <cover.1740752774.git.ludo@HIDDEN> MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 X-Debbugs-Cc: Christopher Baines <guix@HIDDEN>, Josselin Poiret <dev@HIDDEN>, Ludovic Courtès <ludo@HIDDEN>, Mathieu Othacehe <othacehe@HIDDEN>, Maxim Cournoyer <maxim.cournoyer@HIDDEN>, Simon Tournier <zimon.toutoune@HIDDEN>, Tobias Geerinckx-Rice <me@HIDDEN> Content-Transfer-Encoding: 8bit X-Spam-Score: -2.3 (--) X-Debbugs-Envelope-To: 75810 Cc: =?UTF-8?q?Ludovic=20Court=C3=A8s?= <ludovic.courtes@HIDDEN> X-BeenThere: debbugs-submit <at> debbugs.gnu.org X-Mailman-Version: 2.1.18 Precedence: list List-Id: <debbugs-submit.debbugs.gnu.org> List-Unsubscribe: <https://debbugs.gnu.org/cgi-bin/mailman/options/debbugs-submit>, <mailto:debbugs-submit-request <at> debbugs.gnu.org?subject=unsubscribe> List-Archive: <https://debbugs.gnu.org/cgi-bin/mailman/private/debbugs-submit/> List-Post: <mailto:debbugs-submit <at> debbugs.gnu.org> List-Help: <mailto:debbugs-submit-request <at> debbugs.gnu.org?subject=help> List-Subscribe: <https://debbugs.gnu.org/cgi-bin/mailman/listinfo/debbugs-submit>, <mailto:debbugs-submit-request <at> debbugs.gnu.org?subject=subscribe> Errors-To: debbugs-submit-bounces <at> debbugs.gnu.org Sender: "Debbugs-submit" <debbugs-submit-bounces <at> debbugs.gnu.org> X-Spam-Score: -3.3 (---) From: Ludovic Courtès <ludovic.courtes@HIDDEN> * nix/libstore/build.cc (guestUID, guestGID): New variables. (DerivationGoal)[readiness]: New field. (initializeUserNamespace): New function. (DerivationGoal::runChild): When ‘readiness.readSide’ is positive, read from it. (DerivationGoal::startBuilder): Call ‘chown’ only when ‘buildUser.enabled()’ is true. Pass CLONE_NEWUSER to ‘clone’ when ‘buildUser.enabled()’ is false or not running as root. Retry ‘clone’ without CLONE_NEWUSER upon EPERM. (DerivationGoal::registerOutputs): Make ‘actualPath’ writable before ‘rename’. (DerivationGoal::deleteTmpDir): Catch ‘SysError’ around ‘_chown’ call. * nix/libstore/local-store.cc (LocalStore::createUser): Do nothing if ‘dirs’ already exists. Warn instead of failing when failing to chown ‘dir’. * guix/substitutes.scm (%narinfo-cache-directory): Check for ‘_NIX_OPTIONS’ rather than getuid() == 0 to determine the cache location. * doc/guix.texi (Build Environment Setup): Reorganize a bit. Add section headings “Daemon Running as Root” and “The Isolated Build Environment”. Add “Daemon Running Without Privileges” subsection. Remove paragraph about ‘--disable-chroot’. (Invoking guix-daemon): Warn against ‘--disable-chroot’ and explain why. --- doc/guix.texi | 100 +++++++++++++++++++------- guix/substitutes.scm | 4 +- nix/libstore/build.cc | 135 ++++++++++++++++++++++++++++++------ nix/libstore/local-store.cc | 18 +++-- 4 files changed, 203 insertions(+), 54 deletions(-) diff --git a/doc/guix.texi b/doc/guix.texi index 93380dc30d4..a2b65299e9f 100644 --- a/doc/guix.texi +++ b/doc/guix.texi @@ -877,6 +877,7 @@ Setting Up the Daemon @section Setting Up the Daemon @cindex daemon +@cindex build daemon During installation, the @dfn{build daemon} that must be running to use Guix has already been set up and you can run @command{guix} commands in your terminal program, @pxref{Getting Started}: @@ -921,20 +922,36 @@ Build Environment Setup @cindex build environment In a standard multi-user setup, Guix and its daemon---the @command{guix-daemon} program---are installed by the system -administrator; @file{/gnu/store} is owned by @code{root} and -@command{guix-daemon} runs as @code{root}. Unprivileged users may use -Guix tools to build packages or otherwise access the store, and the -daemon will do it on their behalf, ensuring that the store is kept in a -consistent state, and allowing built packages to be shared among users. +administrator. Unprivileged users may use Guix tools to build packages +or otherwise access the store, and the daemon will do it on their +behalf, ensuring that the store is kept in a consistent state, and +allowing built packages to be shared among users. + +There are currently two ways to set up and run the build daemon: + +@enumerate +@item +running @command{guix-daemon} as ``root'', letting it run build +processes as unprivileged users taken from a pool of build users---this +is the historical approach; + +@item +running @command{guix-daemon} as a separate unprivileged user, relying +on Linux's @dfn{unprivileged user namespace} functionality to set up +isolated environments---this option only appeared recently. +@end enumerate + +The sections below describe each of these two configurations in more +detail and summarize the kind of build isolation they provide. + +@unnumberedsubsubsec Daemon Running as Root @cindex build users When @command{guix-daemon} runs as @code{root}, you may not want package build processes themselves to run as @code{root} too, for obvious security reasons. To avoid that, a special pool of @dfn{build users} should be created for use by build processes started by the daemon. -These build users need not have a shell and a home directory: they will -just be used when the daemon drops @code{root} privileges in build -processes. Having several such users allows the daemon to launch +Having several such users allows the daemon to launch distinct build processes under separate UIDs, which guarantees that they do not interfere with each other---an essential feature since builds are regarded as pure functions (@pxref{Introduction}). @@ -977,11 +994,45 @@ Build Environment Setup # guix-daemon --build-users-group=guixbuild @end example +In this setup, @file{/gnu/store} is owned by @code{root}. + +@unnumberedsubsubsec Daemon Running Without Privileges + +@cindex rootless build daemon +@cindex unprivileged build daemon +@cindex build daemon, unprivileged +The second option, which is new, is to run @command{guix-daemon} +@emph{as an unprivileged user}. It has the advantage of reducing the +harm that can be done should a build process manage to exploit a +vulnerability in the daemon. This option requires the user of Linux's +unprivileged user namespace mechanism; today it is available and enabled +by most GNU/Linux distributions but can still be disabled. The +installation script automatically determines whether this option is +available on your system (@pxref{Binary Installation}). + +When using this option, you only need to create one user account, and +@command{guix-daemon} will run with the authority of that account: + +@example +# groupadd --system guix-daemon +# useradd -g guix-daemon -G guix-daemon \ + -d /var/empty -s $(which nologin) \ + -c "Guix daemon privilege separation user" \ + --system guix-daemon +@end example + +In this configuration, @file{/gnu/store} is owned by the +@code{guix-daemon} user. + +@unnumberedsubsubsec The Isolated Build Environment + @cindex chroot -@noindent -This way, the daemon starts build processes in a chroot, under one of -the @code{guixbuilder} users. On GNU/Linux, by default, the chroot -environment contains nothing but: +@cindex build environment isolation +@cindex isolated build environment +@cindex hermetic build environment +In both cases, the daemon starts build processes without privileges in +an @emph{isolated} or @emph{hermetic} build environment---a ``chroot''. +On GNU/Linux, by default, the build environment contains nothing but: @c Keep this list in sync with libstore/build.cc! ----------------------- @itemize @@ -1015,7 +1066,7 @@ Build Environment Setup @file{/homeless-shelter}. This helps to highlight inappropriate uses of @env{HOME} in the build scripts of packages. -All this usually enough to ensure details of the environment do not +All this is usually enough to ensure details of the environment do not influence build processes. In some exceptional cases where more control is needed---typically over the date, kernel, or CPU---you can resort to a virtual build machine (@pxref{build-vm, virtual build machines}). @@ -1035,14 +1086,6 @@ Build Environment Setup for fixed-output derivations (@pxref{Derivations}) or for substitutes (@pxref{Substitutes}). -If you are installing Guix as an unprivileged user, it is still possible -to run @command{guix-daemon} provided you pass @option{--disable-chroot}. -However, build processes will not be isolated from one another, and not -from the rest of the system. Thus, build processes may interfere with -each other, and may access programs, libraries, and other files -available on the system---making it much harder to view them as -@emph{pure} functions. - @node Daemon Offload Setup @subsection Using the Offload Facility @@ -1567,10 +1610,17 @@ Invoking guix-daemon @item --disable-chroot Disable chroot builds. -Using this option is not recommended since, again, it would allow build -processes to gain access to undeclared dependencies. It is necessary, -though, when @command{guix-daemon} is running under an unprivileged user -account. +@quotation Warning +Using this option is not recommended since it allows build processes to +gain access to undeclared dependencies, to interfere with one another, +and more generally to do anything that can be done with the authority of +the daemon---which includes at least the ability to tamper with any file +in the store! + +You may find it necessary, though, when support for Linux unprivileged +user namespaces is missing (@pxref{Build Environment Setup}). Use at +your own risk! +@end quotation @item --log-compression=@var{type} Compress build logs according to @var{type}, one of @code{gzip}, diff --git a/guix/substitutes.scm b/guix/substitutes.scm index e31b3940203..2761a3dafb4 100644 --- a/guix/substitutes.scm +++ b/guix/substitutes.scm @@ -1,5 +1,5 @@ ;;; GNU Guix --- Functional package management for GNU -;;; Copyright © 2013-2021, 2023-2024 Ludovic Courtès <ludo@HIDDEN> +;;; Copyright © 2013-2021, 2023-2025 Ludovic Courtès <ludo@HIDDEN> ;;; Copyright © 2014 Nikita Karetnikov <nikita@HIDDEN> ;;; Copyright © 2018 Kyle Meyer <kyle@HIDDEN> ;;; Copyright © 2020 Christopher Baines <mail@HIDDEN> @@ -76,7 +76,7 @@ (define %narinfo-cache-directory ;; time, 'guix substitute' is called by guix-daemon as root and stores its ;; cached data in /var/guix/…. However, when invoked from 'guix challenge' ;; as a user, it stores its cache in ~/.cache. - (if (zero? (getuid)) + (if (getenv "_NIX_OPTIONS") ;invoked by guix-daemon (or (and=> (getenv "XDG_CACHE_HOME") (cut string-append <> "/guix/substitute")) (string-append %state-directory "/substitute/cache")) diff --git a/nix/libstore/build.cc b/nix/libstore/build.cc index c8b778362ac..961894454f3 100644 --- a/nix/libstore/build.cc +++ b/nix/libstore/build.cc @@ -744,6 +744,10 @@ private: friend int childEntry(void *); + /* Pipe to notify readiness to the child process when using unprivileged + user namespaces. */ + Pipe readiness; + /* Check that the derivation outputs all exist and register them as valid. */ void registerOutputs(); @@ -1619,6 +1623,25 @@ int childEntry(void * arg) } +/* UID and GID of the build user inside its own user namespace. */ +static const uid_t guestUID = 30001; +static const gid_t guestGID = 30000; + +/* Initialize the user namespace of CHILD. */ +static void initializeUserNamespace(pid_t child) +{ + auto hostUID = getuid(); + auto hostGID = getgid(); + + writeFile("/proc/" + std::to_string(child) + "/uid_map", + (format("%d %d 1") % guestUID % hostUID).str()); + + writeFile("/proc/" + std::to_string(child) + "/setgroups", "deny"); + + writeFile("/proc/" + std::to_string(child) + "/gid_map", + (format("%d %d 1") % guestGID % hostGID).str()); +} + void DerivationGoal::startBuilder() { auto f = format( @@ -1682,7 +1705,7 @@ void DerivationGoal::startBuilder() then an attacker could create in it a hardlink to a root-owned file such as /etc/shadow. If 'keepFailed' is true, the daemon would then chown that hardlink to the user, giving them write access to - that file. */ + that file. See CVE-2021-27851. */ tmpDir += "/top"; if (mkdir(tmpDir.c_str(), 0700) == 1) throw SysError("creating top-level build directory"); @@ -1799,7 +1822,7 @@ void DerivationGoal::startBuilder() if (mkdir(chrootRootDir.c_str(), 0750) == -1) throw SysError(format("cannot create ‘%1%’") % chrootRootDir); - if (chown(chrootRootDir.c_str(), 0, buildUser.getGID()) == -1) + if (buildUser.enabled() && chown(chrootRootDir.c_str(), 0, buildUser.getGID()) == -1) throw SysError(format("cannot change ownership of ‘%1%’") % chrootRootDir); /* Create a writable /tmp in the chroot. Many builders need @@ -1818,8 +1841,8 @@ void DerivationGoal::startBuilder() (format( "nixbld:x:%1%:%2%:Nix build user:/:/noshell\n" "nobody:x:65534:65534:Nobody:/:/noshell\n") - % (buildUser.enabled() ? buildUser.getUID() : getuid()) - % (buildUser.enabled() ? buildUser.getGID() : getgid())).str()); + % (buildUser.enabled() ? buildUser.getUID() : guestUID) + % (buildUser.enabled() ? buildUser.getGID() : guestGID)).str()); /* Declare the build user's group so that programs get a consistent view of the system (e.g., "id -gn"). */ @@ -1854,7 +1877,7 @@ void DerivationGoal::startBuilder() createDirs(chrootStoreDir); chmod_(chrootStoreDir, 01775); - if (chown(chrootStoreDir.c_str(), 0, buildUser.getGID()) == -1) + if (buildUser.enabled() && chown(chrootStoreDir.c_str(), 0, buildUser.getGID()) == -1) throw SysError(format("cannot change ownership of ‘%1%’") % chrootStoreDir); foreach (PathSet::iterator, i, inputPaths) { @@ -1960,14 +1983,34 @@ void DerivationGoal::startBuilder() if (useChroot) { char stack[32 * 1024]; int flags = CLONE_NEWPID | CLONE_NEWNS | CLONE_NEWIPC | CLONE_NEWUTS | SIGCHLD; - if (!fixedOutput) flags |= CLONE_NEWNET; + if (!fixedOutput) { + flags |= CLONE_NEWNET; + } + if (!buildUser.enabled() || getuid() != 0) { + flags |= CLONE_NEWUSER; + readiness.create(); + } + /* Ensure proper alignment on the stack. On aarch64, it has to be 16 bytes. */ - pid = clone(childEntry, + pid = clone(childEntry, (char *)(((uintptr_t)stack + sizeof(stack) - 8) & ~(uintptr_t)0xf), flags, this); - if (pid == -1) - throw SysError("cloning builder process"); + if (pid == -1) { + if ((flags & CLONE_NEWUSER) != 0 && getuid() != 0) + /* 'clone' fails with EPERM on distros where unprivileged user + namespaces are disabled. Error out instead of giving up on + isolation. */ + throw SysError("cannot create process in unprivileged user namespace"); + else + throw SysError("cloning builder process"); + } + + if ((flags & CLONE_NEWUSER) != 0) { + /* Initialize the UID/GID mapping of the child process. */ + initializeUserNamespace(pid); + writeFull(readiness.writeSide, (unsigned char*)"go\n", 3); + } } else #endif { @@ -2013,23 +2056,34 @@ void DerivationGoal::runChild() _writeToStderr = 0; + if (readiness.readSide > 0) { + /* Wait for the parent process to initialize the UID/GID mapping + of our user namespace. */ + char str[20] = { '\0' }; + readFull(readiness.readSide, (unsigned char*)str, 3); + if (strcmp(str, "go\n") != 0) + throw Error("failed to initialize process in unprivileged user namespace"); + } + restoreAffinity(); commonChildInit(builderOut); #if CHROOT_ENABLED if (useChroot) { - /* Initialise the loopback interface. */ - AutoCloseFD fd(socket(PF_INET, SOCK_DGRAM, IPPROTO_IP)); - if (fd == -1) throw SysError("cannot open IP socket"); + if (!fixedOutput) { + /* Initialise the loopback interface. */ + AutoCloseFD fd(socket(PF_INET, SOCK_DGRAM, IPPROTO_IP)); + if (fd == -1) throw SysError("cannot open IP socket"); - struct ifreq ifr; - strcpy(ifr.ifr_name, "lo"); - ifr.ifr_flags = IFF_UP | IFF_LOOPBACK | IFF_RUNNING; - if (ioctl(fd, SIOCSIFFLAGS, &ifr) == -1) - throw SysError("cannot set loopback interface flags"); + struct ifreq ifr; + strcpy(ifr.ifr_name, "lo"); + ifr.ifr_flags = IFF_UP | IFF_LOOPBACK | IFF_RUNNING; + if (ioctl(fd, SIOCSIFFLAGS, &ifr) == -1) + throw SysError("cannot set loopback interface flags"); - fd.close(); + fd.close(); + } /* Set the hostname etc. to fixed values. */ char hostname[] = "localhost"; @@ -2476,8 +2530,16 @@ void DerivationGoal::registerOutputs() 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) { + if (S_ISDIR(st.st_mode)) + /* Change mode on the directory to allow for + rename(2). */ + chmod(actualPath.c_str(), st.st_mode | 0700); + if (rename(actualPath.c_str(), path.c_str()) == -1) + throw SysError(format("moving build output `%1%' from the chroot to the store") % path); + if (S_ISDIR(st.st_mode) && chmod(path.c_str(), st.st_mode) == -1) + throw SysError(format("restoring permissions on directory `%1%'") % actualPath); + } } if (buildMode != bmCheck) actualPath = path; } @@ -2736,8 +2798,32 @@ void DerivationGoal::deleteTmpDir(bool force) // Change the ownership if clientUid is set. Never change the // ownership or the group to "root" for security reasons. if (settings.clientUid != (uid_t) -1 && settings.clientUid != 0) { - _chown(tmpDir, settings.clientUid, - settings.clientGid != 0 ? settings.clientGid : -1); + uid_t uid = settings.clientUid; + gid_t gid = settings.clientGid != 0 ? settings.clientGid : -1; + bool reown = false; + + /* First remove setuid/setgid bits. */ + secureFilePerms(tmpDir); + + try { + _chown(tmpDir, uid, gid); + + if (getuid() != 0) { + /* If, without being root, the '_chown' call above + succeeded, then it means we have CAP_CHOWN. Retake + ownership of tmpDir itself so it can be renamed + below. */ + chown(tmpDir.c_str(), getuid(), getgid()); + reown = true; + } + + } catch (SysError & e) { + /* When running as an unprivileged user and without + CAP_CHOWN, we cannot chown the build tree. Print a + message and keep going. */ + printMsg(lvlInfo, format("cannot change ownership of build directory '%1%': %2%") + % tmpDir % strerror(e.errNo)); + } if (top != tmpDir) { // Rename tmpDir to its parent, with an intermediate step. @@ -2746,6 +2832,11 @@ void DerivationGoal::deleteTmpDir(bool force) throw SysError("pivoting failed build tree"); if (rename((pivot + "/top").c_str(), top.c_str()) == -1) throw SysError("renaming failed build tree"); + + if (reown) + /* Running unprivileged but with CAP_CHOWN. */ + chown(top.c_str(), uid, gid); + rmdir(pivot.c_str()); } } diff --git a/nix/libstore/local-store.cc b/nix/libstore/local-store.cc index 0883a4bbcee..83e6c3e16ec 100644 --- a/nix/libstore/local-store.cc +++ b/nix/libstore/local-store.cc @@ -1614,11 +1614,19 @@ void LocalStore::createUser(const std::string & userName, uid_t userId) { auto dir = settings.nixStateDir + "/profiles/per-user/" + userName; - createDirs(dir); - if (chmod(dir.c_str(), 0755) == -1) - throw SysError(format("changing permissions of directory '%s'") % dir); - if (chown(dir.c_str(), userId, -1) == -1) - throw SysError(format("changing owner of directory '%s'") % dir); + auto created = createDirs(dir); + if (!created.empty()) { + if (chmod(dir.c_str(), 0755) == -1) + throw SysError(format("changing permissions of directory '%s'") % dir); + + /* The following operation requires CAP_CHOWN or can be handled + manually by a user with CAP_CHOWN. */ + if (chown(dir.c_str(), userId, -1) == -1) { + rmdir(dir.c_str()); + string message = strerror(errno); + printMsg(lvlInfo, format("failed to change owner of directory '%1%' to %2%: %3%") % dir % userId % message); + } + } } -- 2.48.1
guix@HIDDEN, dev@HIDDEN, ludo@HIDDEN, othacehe@HIDDEN, maxim.cournoyer@HIDDEN, zimon.toutoune@HIDDEN, me@HIDDEN, guix-patches@HIDDEN
:bug#75810
; Package guix-patches
.
Full text available.Received: (at 75810) by debbugs.gnu.org; 28 Feb 2025 14:31:09 +0000 From debbugs-submit-bounces <at> debbugs.gnu.org Fri Feb 28 09:31:08 2025 Received: from localhost ([127.0.0.1]:47877 helo=debbugs.gnu.org) by debbugs.gnu.org with esmtp (Exim 4.84_2) (envelope-from <debbugs-submit-bounces <at> debbugs.gnu.org>) id 1to1ON-0004e8-Az for submit <at> debbugs.gnu.org; Fri, 28 Feb 2025 09:31:08 -0500 Received: from eggs.gnu.org ([2001:470:142:3::10]:45438) by debbugs.gnu.org with esmtps (TLS1.2:ECDHE_RSA_AES_256_GCM_SHA384:256) (Exim 4.84_2) (envelope-from <ludo@HIDDEN>) id 1to1NV-0004RE-DP for 75810 <at> debbugs.gnu.org; Fri, 28 Feb 2025 09:30:17 -0500 Received: from fencepost.gnu.org ([2001:470:142:3::e]) by eggs.gnu.org with esmtps (TLS1.2:ECDHE_RSA_AES_256_GCM_SHA384:256) (Exim 4.90_1) (envelope-from <ludo@HIDDEN>) id 1to1NP-0002SR-Pn; Fri, 28 Feb 2025 09:30:08 -0500 DKIM-Signature: v=1; a=rsa-sha256; q=dns/txt; c=relaxed/relaxed; d=gnu.org; s=fencepost-gnu-org; h=MIME-Version:References:In-Reply-To:Date:Subject:To: From; bh=sVGXaLW10Ms4hxe95q1BQtEJs+WHY2eek+mEc17o+M8=; b=lkhd++w498JhSpZk+A/m Ll81iljrjgxlq9TKljCcBiCJ0X4fTD3ce9v9e7DPrWRtIF7j6uHA7Djizit+cqI0KKV+oOELWxDB0 loUAKfDFffPeKqC7pQFVdqGoB7rQbzKv4XBMXmTCiOYo6eTKC2GPdBJpRFvU7XQrTjqiEjHpHiOXm vZMLJvdUGXeuTGtd7nH/Q4UVSZcBySmRCWglQxtZMbwelFFMG+8aA4YOKjCZAyhZbqudgd3KyUI3c sUuSZVHaf6sSuc33LlHhudCp/u616ZNHy78Ta5OWD3LqRlOZrXZaLGSlgtbHxkDRZxwDn0552UadT 1nF22++7aLtNtA==; From: =?UTF-8?q?Ludovic=20Court=C3=A8s?= <ludo@HIDDEN> To: 75810 <at> debbugs.gnu.org Subject: [PATCH v4 13/14] guix-install.sh: Support the unprivileged daemon where possible. Date: Fri, 28 Feb 2025 15:29:32 +0100 Message-ID: <26dd92508755f40dbca161e81f801b3c212e1c86.1740752774.git.ludo@HIDDEN> X-Mailer: git-send-email 2.48.1 In-Reply-To: <cover.1740752774.git.ludo@HIDDEN> References: <cover.1740752774.git.ludo@HIDDEN> MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit X-Spam-Score: -2.3 (--) X-Debbugs-Envelope-To: 75810 Cc: =?UTF-8?q?Ludovic=20Court=C3=A8s?= <ludo@HIDDEN> X-BeenThere: debbugs-submit <at> debbugs.gnu.org X-Mailman-Version: 2.1.18 Precedence: list List-Id: <debbugs-submit.debbugs.gnu.org> List-Unsubscribe: <https://debbugs.gnu.org/cgi-bin/mailman/options/debbugs-submit>, <mailto:debbugs-submit-request <at> debbugs.gnu.org?subject=unsubscribe> List-Archive: <https://debbugs.gnu.org/cgi-bin/mailman/private/debbugs-submit/> List-Post: <mailto:debbugs-submit <at> debbugs.gnu.org> List-Help: <mailto:debbugs-submit-request <at> debbugs.gnu.org?subject=help> List-Subscribe: <https://debbugs.gnu.org/cgi-bin/mailman/listinfo/debbugs-submit>, <mailto:debbugs-submit-request <at> debbugs.gnu.org?subject=subscribe> Errors-To: debbugs-submit-bounces <at> debbugs.gnu.org Sender: "Debbugs-submit" <debbugs-submit-bounces <at> debbugs.gnu.org> X-Spam-Score: -3.3 (---) * etc/guix-install.sh (create_account): New function. (sys_create_build_user): Use it. When ‘guix-daemon.service’ contains “User=guix-daemon” only create the ‘guix-daemon’ user and group. (sys_delete_build_user): Delete the ‘guix-daemon’ user and group. (can_install_unprivileged_daemon): New function. (sys_create_store): When installing the unprivileged daemon, change ownership of /gnu and /var/guix, and create /var/log/guix. (sys_authorize_build_farms): When the ‘guix-daemon’ account exists, change ownership of /etc/guix. Change-Id: I73e573f1cc5c0cb3794aaaa6b576616b66e0c5e9 --- etc/guix-install.sh | 106 ++++++++++++++++++++++++++++++++++---------- 1 file changed, 82 insertions(+), 24 deletions(-) diff --git a/etc/guix-install.sh b/etc/guix-install.sh index 8887204df41..b0b0ee84ba5 100755 --- a/etc/guix-install.sh +++ b/etc/guix-install.sh @@ -414,6 +414,11 @@ sys_create_store() cd "$tmp_path" _msg_info "Installing /var/guix and /gnu..." # Strip (skip) the leading ‘.’ component, which fails on read-only ‘/’. + # + # TODO: Eventually extract with ‘--owner=guix-daemon’ when installing + # and unprivileged guix-daemon service; for now, this script may install + # from both an old release that does not support unprivileged guix-daemon + # and a new release that does, so ‘chown -R’ later if needed. tar --extract --strip-components=1 --file "$pkg" -C / _msg_info "Linking the root user's profile" @@ -441,38 +446,80 @@ sys_delete_store() rm -rf ~root/.config/guix } +create_account() +{ + local user="$1" + local group="$2" + local supplementary_groups="$3" + local comment="$4" + + if id "$user" &>/dev/null; then + _msg_info "user '$user' is already in the system, reset" + usermod -g "$group" -G "$supplementary_groups" \ + -d /var/empty -s "$(which nologin)" \ + -c "$comment" "$user" + else + useradd -g "$group" -G "$supplementary_groups" \ + -d /var/empty -s "$(which nologin)" \ + -c "$comment" --system "$user" + _msg_pass "user added <$user>" + fi +} + +can_install_unprivileged_daemon() +{ # Return true if we can install guix-daemon running without privileges. + [ "$INIT_SYS" = systemd ] && \ + grep -q "User=guix-daemon" \ + ~root/.config/guix/current/lib/systemd/system/guix-daemon.service \ + && ([ ! -f /proc/sys/kernel/unprivileged_userns_clone ] \ + || [ "$(cat /proc/sys/kernel/unprivileged_userns_clone)" -eq 1 ]) +} + sys_create_build_user() { # Create the group and user accounts for build users. _debug "--- [ ${FUNCNAME[0]} ] ---" - if getent group guixbuild > /dev/null; then - _msg_info "group guixbuild exists" - else - groupadd --system guixbuild - _msg_pass "group <guixbuild> created" - fi - if getent group kvm > /dev/null; then _msg_info "group kvm exists and build users will be added to it" local KVMGROUP=,kvm fi - for i in $(seq -w 1 10); do - if id "guixbuilder${i}" &>/dev/null; then - _msg_info "user is already in the system, reset" - usermod -g guixbuild -G guixbuild"$KVMGROUP" \ - -d /var/empty -s "$(which nologin)" \ - -c "Guix build user $i" \ - "guixbuilder${i}"; - else - useradd -g guixbuild -G guixbuild"$KVMGROUP" \ - -d /var/empty -s "$(which nologin)" \ - -c "Guix build user $i" --system \ - "guixbuilder${i}"; - _msg_pass "user added <guixbuilder${i}>" - fi - done + if can_install_unprivileged_daemon + then + if getent group guix-daemon > /dev/null; then + _msg_info "group guix-daemon exists" + else + groupadd --system guix-daemon + _msg_pass "group guix-daemon created" + fi + + create_account guix-daemon guix-daemon \ + guix-daemon$KVMGROUP \ + "Unprivileged Guix Daemon User" + + # ‘tar xf’ creates root:root files. Change that. + chown -R guix-daemon:guix-daemon \ + /gnu /var/guix + + # The unprivileged cannot create the log directory by itself. + mkdir /var/log/guix + chown guix-daemon:guix-daemon /var/log/guix + chmod 755 /var/log/guix + else + if getent group guixbuild > /dev/null; then + _msg_info "group guixbuild exists" + else + groupadd --system guixbuild + _msg_pass "group <guixbuild> created" + fi + + for i in $(seq -w 1 10); do + create_account "guixbuilder${i}" "guixbuild" \ + "guixbuild${KVMGROUP}" \ + "Guix build user $i" + done + fi } sys_delete_build_user() @@ -487,6 +534,14 @@ sys_delete_build_user() if getent group guixbuild &>/dev/null; then groupdel -f guixbuild fi + + _msg_info "remove guix-daemon user" + if id guix-daemon &>/dev/null; then + userdel -f guix-daemon + fi + if getent group guix-daemon &>/dev/null; then + groupdel -f guix-daemon + fi } sys_enable_guix_daemon() @@ -529,8 +584,7 @@ sys_enable_guix_daemon() # Install after guix-daemon.service to avoid a harmless warning. # systemd .mount units must be named after the target directory. - # Here we assume a hard-coded name of /gnu/store. - install_unit gnu-store.mount + install_unit gnu-store.mount systemctl daemon-reload && systemctl start guix-daemon; } && @@ -654,6 +708,10 @@ project's build farms?"; then && guix archive --authorize < "$key" \ && _msg_pass "Authorized public key for $host" done + if id guix-daemon &>/dev/null; then + # /etc/guix/acl must be readable by the unprivileged guix-daemon. + chown -R guix-daemon:guix-daemon /etc/guix + fi else _msg_info "Skipped authorizing build farm public keys" fi -- 2.48.1
guix-patches@HIDDEN
:bug#75810
; Package guix-patches
.
Full text available.Received: (at 75810) by debbugs.gnu.org; 28 Feb 2025 14:31:07 +0000 From debbugs-submit-bounces <at> debbugs.gnu.org Fri Feb 28 09:31:07 2025 Received: from localhost ([127.0.0.1]:47870 helo=debbugs.gnu.org) by debbugs.gnu.org with esmtp (Exim 4.84_2) (envelope-from <debbugs-submit-bounces <at> debbugs.gnu.org>) id 1to1OL-0004di-95 for submit <at> debbugs.gnu.org; Fri, 28 Feb 2025 09:31:07 -0500 Received: from eggs.gnu.org ([2001:470:142:3::10]:45414) by debbugs.gnu.org with esmtps (TLS1.2:ECDHE_RSA_AES_256_GCM_SHA384:256) (Exim 4.84_2) (envelope-from <ludo@HIDDEN>) id 1to1NT-0004Qx-0E for 75810 <at> debbugs.gnu.org; Fri, 28 Feb 2025 09:30:16 -0500 Received: from fencepost.gnu.org ([2001:470:142:3::e]) by eggs.gnu.org with esmtps (TLS1.2:ECDHE_RSA_AES_256_GCM_SHA384:256) (Exim 4.90_1) (envelope-from <ludo@HIDDEN>) id 1to1NN-0002Rp-Jy; Fri, 28 Feb 2025 09:30:05 -0500 DKIM-Signature: v=1; a=rsa-sha256; q=dns/txt; c=relaxed/relaxed; d=gnu.org; s=fencepost-gnu-org; h=MIME-Version:References:In-Reply-To:Date:Subject:To: From; bh=HxNGlymvq52OsSNSV0ItDLPmN67Gwid6SJgWevq4+BM=; b=ATqLc+mxKQqNSEUz4ctQ Zxd5nMkFikqj3GVXHJgWPpmastyZvzGB/nx7wyN1p9DSs84Tf66HvxXOi82sW9/Ul1JjeFkZHn0MJ tmyISa6zwC1JDDJ2rq6VD2Okf7+Zxpw2WphdOjy83K7vCWCAjs/Irr9icneR6it2m9qiHNJrtl1iQ L7EFKx0kJJbnQooSdnWAD0UbktKSpM94ImbbKnqw41VnOTVJFeMAmaRBVL9RAKfRETOLBEBsJkqUw OmMg3IL31tZncXsT4Mi3KP3+Dnge4mJ7lpT8u1B4n6zSOO2GfAyJsnAc9eu1ShytHPs6a1MfWtN7p agXzi1dWirW52A==; From: =?UTF-8?q?Ludovic=20Court=C3=A8s?= <ludo@HIDDEN> To: 75810 <at> debbugs.gnu.org Subject: [PATCH v4 11/14] tests: Run in a chroot and unprivileged user namespaces. Date: Fri, 28 Feb 2025 15:29:30 +0100 Message-ID: <fd153e1ba1a543e35561649d7b3e9d472d4f9ef5.1740752774.git.ludo@HIDDEN> X-Mailer: git-send-email 2.48.1 In-Reply-To: <cover.1740752774.git.ludo@HIDDEN> References: <cover.1740752774.git.ludo@HIDDEN> MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit X-Spam-Score: -2.3 (--) X-Debbugs-Envelope-To: 75810 Cc: =?UTF-8?q?Ludovic=20Court=C3=A8s?= <ludo@HIDDEN> X-BeenThere: debbugs-submit <at> debbugs.gnu.org X-Mailman-Version: 2.1.18 Precedence: list List-Id: <debbugs-submit.debbugs.gnu.org> List-Unsubscribe: <https://debbugs.gnu.org/cgi-bin/mailman/options/debbugs-submit>, <mailto:debbugs-submit-request <at> debbugs.gnu.org?subject=unsubscribe> List-Archive: <https://debbugs.gnu.org/cgi-bin/mailman/private/debbugs-submit/> List-Post: <mailto:debbugs-submit <at> debbugs.gnu.org> List-Help: <mailto:debbugs-submit-request <at> debbugs.gnu.org?subject=help> List-Subscribe: <https://debbugs.gnu.org/cgi-bin/mailman/listinfo/debbugs-submit>, <mailto:debbugs-submit-request <at> debbugs.gnu.org?subject=subscribe> Errors-To: debbugs-submit-bounces <at> debbugs.gnu.org Sender: "Debbugs-submit" <debbugs-submit-bounces <at> debbugs.gnu.org> X-Spam-Score: -3.3 (---) * build-aux/test-env.in: Pass ‘--disable-chroot’ only when unprivileged user namespace support is lacking and warn in that case. * tests/store.scm ("build-things, check mode"): Use ‘gettimeofday’ rather than a shared file as a source of entropy. ("symlink is symlink") ("isolated environment", "inputs are read-only") ("inputs cannot be remounted read-write") ("build root cannot be made world-readable") ("/tmp, store, and /dev/{null,full} are writable") ("network is unreachable"): New tests. * tests/processes.scm ("client + lock"): Skip when ‘unprivileged-user-namespace-supported?’ returns true. Change-Id: I3b3c3ebdf6db5fd36ee70251d07b893c17ca1b84 --- build-aux/test-env.in | 16 ++- tests/processes.scm | 9 +- tests/store.scm | 250 ++++++++++++++++++++++++++++++++++++------ 3 files changed, 237 insertions(+), 38 deletions(-) diff --git a/build-aux/test-env.in b/build-aux/test-env.in index 9caa29da581..a3f225582df 100644 --- a/build-aux/test-env.in +++ b/build-aux/test-env.in @@ -1,7 +1,7 @@ #!/bin/sh # GNU Guix --- Functional package management for GNU -# Copyright © 2012, 2013, 2014, 2015, 2016, 2017, 2018, 2019, 2021 Ludovic Courtès <ludo@HIDDEN> +# Copyright © 2012-2019, 2021, 2025 Ludovic Courtès <ludo@HIDDEN> # # This file is part of GNU Guix. # @@ -102,10 +102,22 @@ then rm -rf "$GUIX_STATE_DIRECTORY/daemon-socket" mkdir -m 0700 "$GUIX_STATE_DIRECTORY/daemon-socket" + # If unprivileged user namespaces are not supported, pass + # '--disable-chroot'. + if [ ! -f /proc/sys/kernel/unprivileged_userns_clone ] \ + || [ "$(cat /proc/sys/kernel/unprivileged_userns_clone)" -eq 1 ]; then + extra_options="" + else + extra_options="--disable-chroot" + echo "unprivileged user namespaces not supported; \ +running 'guix-daemon $extra_options'" >&2 + fi + # Launch the daemon without chroot support because is may be # unavailable, for instance if we're not running as root. "@abs_top_builddir@/pre-inst-env" \ - "@abs_top_builddir@/guix-daemon" --disable-chroot \ + "@abs_top_builddir@/guix-daemon" \ + $extra_options \ --substitute-urls="$GUIX_BINARY_SUBSTITUTE_URL" & daemon_pid=$! diff --git a/tests/processes.scm b/tests/processes.scm index ba518f2d9e3..a72ba16f587 100644 --- a/tests/processes.scm +++ b/tests/processes.scm @@ -1,5 +1,5 @@ ;;; GNU Guix --- Functional package management for GNU -;;; Copyright © 2018 Ludovic Courtès <ludo@HIDDEN> +;;; Copyright © 2018, 2025 Ludovic Courtès <ludo@HIDDEN> ;;; Copyright © 2019 Mathieu Othacehe <m.othacehe@HIDDEN> ;;; ;;; This file is part of GNU Guix. @@ -25,6 +25,8 @@ (define-module (test-processes) #:use-module (guix gexp) #:use-module ((guix utils) #:select (call-with-temporary-directory)) #:use-module (gnu packages bootstrap) + #:use-module ((gnu build linux-container) + #:select (unprivileged-user-namespace-supported?)) #:use-module (guix tests) #:use-module (srfi srfi-1) #:use-module (srfi srfi-64) @@ -84,6 +86,11 @@ (define-syntax-rule (test-assert* description exp) (and (kill (process-id daemon) 0) (string-suffix? "guix-daemon" (first (process-command daemon))))))) +(when (unprivileged-user-namespace-supported?) + ;; The test below assumes the build process can communicate with the outside + ;; world via the TOKEN1 and TOKEN2 files, which is impossible when + ;; guix-daemon is set up to build in separate namespaces. + (test-skip 1)) (test-assert* "client + lock" (with-store store (call-with-temporary-directory diff --git a/tests/store.scm b/tests/store.scm index 45948f4f433..c22739afe6b 100644 --- a/tests/store.scm +++ b/tests/store.scm @@ -1,5 +1,5 @@ ;;; GNU Guix --- Functional package management for GNU -;;; Copyright © 2012-2021, 2023 Ludovic Courtès <ludo@HIDDEN> +;;; Copyright © 2012-2021, 2023, 2025 Ludovic Courtès <ludo@HIDDEN> ;;; ;;; This file is part of GNU Guix. ;;; @@ -28,8 +28,12 @@ (define-module (test-store) #:use-module (guix base32) #:use-module (guix packages) #:use-module (guix derivations) + #:use-module ((guix modules) + #:select (source-module-closure)) #:use-module (guix serialization) #:use-module (guix build utils) + #:use-module ((gnu build linux-container) + #:select (unprivileged-user-namespace-supported?)) #:use-module (guix gexp) #:use-module (gnu packages) #:use-module (gnu packages bootstrap) @@ -391,6 +395,191 @@ (define %shell (equal? (valid-derivers %store o) (list (derivation-file-name d)))))) +(test-assert "symlink is symlink" + (let* ((a (add-text-to-store %store "hello.txt" (random-text))) + (b (build-expression->derivation + %store "symlink" + '(symlink (assoc-ref %build-inputs "a") %output) + #:inputs `(("a" ,a)))) + (c (build-expression->derivation + %store "symlink-reference" + `(call-with-output-file %output + (lambda (port) + ;; Check that B is indeed visible as a symlink. This should + ;; always be the case, both in the '--disable-chroot' and in + ;; the user namespace setups. + (pk 'stat (lstat (assoc-ref %build-inputs "b"))) + (display (readlink (assoc-ref %build-inputs "b")) + port))) + #:inputs `(("b" ,b))))) + (and (build-derivations %store (list c)) + (string=? (call-with-input-file (derivation->output-path c) + get-string-all) + a)))) + +(unless (unprivileged-user-namespace-supported?) + (test-skip 1)) +(test-equal "isolated environment" + (string-join (append + '("PID: 1" "UID: 30001") + (delete-duplicates + (sort (list "/dev" "/tmp" "/proc" "/etc" + (match (string-tokenize (%store-prefix) + (char-set-complement + (char-set #\/))) + ((top _ ...) (string-append "/" top)))) + string<?)) + '("/etc/group" "/etc/hosts" "/etc/passwd"))) + (let* ((b (add-text-to-store %store "build.sh" + "echo -n PID: $$ UID: $UID /* /etc/* > $out")) + (s (add-to-store %store "bash" #t "sha256" + (search-bootstrap-binary "bash" + (%current-system)))) + (d (derivation %store "the-thing" + s `("-e" ,b) + #:env-vars `(("foo" . ,(random-text))) + #:sources (list b s))) + (o (derivation->output-path d))) + (and (build-derivations %store (list d)) + (call-with-input-file o get-string-all)))) + +(unless (unprivileged-user-namespace-supported?) + (test-skip 1)) +(test-equal "inputs are read-only" + "All good!" + (let* ((input (plain-file (string-append "might-be-tampered-with-" + (number->string + (car (gettimeofday)) + 16)) + "All good!")) + (drv + (run-with-store %store + (gexp->derivation + "attempt-to-remount-input-read-write" + (with-imported-modules (source-module-closure + '((guix build syscalls))) + #~(begin + (use-modules (guix build syscalls)) + + (let ((input #$input)) + (chmod input #o666) + (call-with-output-file input + (lambda (port) + (display "BAD!" port))) + (mkdir #$output)))))))) + (and (guard (c ((store-protocol-error? c) #t)) + (build-derivations %store (list drv))) + (call-with-input-file (run-with-store %store + (lower-object input)) + get-string-all)))) + +(unless (unprivileged-user-namespace-supported?) + (test-skip 1)) +(test-assert "inputs cannot be remounted read-write" + (let ((drv + (run-with-store %store + (gexp->derivation + "attempt-to-remount-input-read-write" + (with-imported-modules (source-module-closure + '((guix build syscalls))) + #~(begin + (use-modules (guix build syscalls)) + + (let ((input #$(plain-file "input-that-might-be-tampered-with" + "All good!"))) + (mount "none" input "none" (logior MS_BIND MS_REMOUNT)) + (call-with-output-file input + (lambda (port) + (display "BAD!" port))) + (mkdir #$output)))))))) + (guard (c ((store-protocol-error? c) #t)) + (build-derivations %store (list drv)) + #f))) + +(unless (unprivileged-user-namespace-supported?) + (test-skip 1)) +(test-assert "build root cannot be made world-readable" + (let ((drv + (run-with-store %store + (gexp->derivation + "attempt-to-make-root-world-readable" + (with-imported-modules (source-module-closure + '((guix build syscalls))) + #~(begin + (use-modules (guix build syscalls)) + + (let ((guile (string-append (assoc-ref %guile-build-info + 'bindir) + "/guile"))) + (catch 'system-error + (lambda () + (chmod "/" #o777)) + (lambda args + (format #t "failed to make root writable: ~a~%" + (strerror (system-error-errno args))) + (format #t "attempting read-write remount~%") + (mount "none" "/" "/" (logior MS_BIND MS_REMOUNT)) + (chmod "/" #o777))) + (copy-file guile "/guile") + (chmod "/guile" #o6755) + ;; At this point, there's a world-readable setuid 'guile' + ;; binary in the store that remains visible until this + ;; build completes. + (list #$output)))))))) + (guard (c ((store-protocol-error? c) #t)) + (build-derivations %store (list drv)) + #f))) + +(unless (unprivileged-user-namespace-supported?) + (test-skip 1)) +(test-assert "/tmp, store, and /dev/{null,full} are writable" + ;; All of /tmp and all of the store must be writable (the store is writable + ;; so that derivation outputs can be written to it, but in practice it's + ;; always been wide open). Things like /dev/null must be writable too. + (let ((drv (run-with-store %store + (gexp->derivation + "check-tmp-and-store-are-writable" + #~(begin + (mkdir "/tmp/something") + (mkdir (in-vicinity (getenv "NIX_STORE") + "some-other-thing")) + (call-with-output-file "/dev/null" + (lambda (port) + (display "Welcome to the void." port))) + (catch 'system-error + (lambda () + (call-with-output-file "/dev/full" + (lambda (port) + (display "No space left!" port))) + (error "Should have thrown!")) + (lambda args + (unless (= ENOSPC (system-error-errno args)) + (apply throw args)))) + (mkdir #$output)))))) + (build-derivations %store (list drv)))) + +(unless (unprivileged-user-namespace-supported?) + (test-skip 1)) +(test-assert "network is unreachable" + (let ((drv (run-with-store %store + (gexp->derivation + "check-network-unreachable" + #~(let ((check-connection-failure + (lambda (address expected-code) + (let ((s (socket AF_INET SOCK_STREAM 0))) + (catch 'system-error + (lambda () + (connect s AF_INET (inet-pton AF_INET address) 80)) + (lambda args + (let ((errno (system-error-errno args))) + (unless (= expected-code errno) + (error "wrong error code" + errno (strerror errno)))))))))) + (check-connection-failure "127.0.0.1" ECONNREFUSED) + (check-connection-failure "9.9.9.9" ENETUNREACH) + (mkdir #$output)))))) + (build-derivations %store (list drv)))) + (test-equal "with-build-handler" 'success (let* ((b (add-text-to-store %store "build" "echo $foo > $out" '())) @@ -1333,40 +1522,31 @@ (define %shell (test-assert "build-things, check mode" (with-store store - (call-with-temporary-output-file - (lambda (entropy entropy-port) - (write (random-text) entropy-port) - (force-output entropy-port) - (let* ((drv (build-expression->derivation - store "non-deterministic" - `(begin - (use-modules (rnrs io ports)) - (let ((out (assoc-ref %outputs "out"))) - (call-with-output-file out - (lambda (port) - ;; Rely on the fact that tests do not use the - ;; chroot, and thus ENTROPY is readable. - (display (call-with-input-file ,entropy - get-string-all) - port))) - #t)) - #:guile-for-build - (package-derivation store %bootstrap-guile (%current-system)))) - (file (derivation->output-path drv))) - (and (build-things store (list (derivation-file-name drv))) - (begin - (write (random-text) entropy-port) - (force-output entropy-port) - (guard (c ((store-protocol-error? c) - (pk 'determinism-exception c) - (and (not (zero? (store-protocol-error-status c))) - (string-contains (store-protocol-error-message c) - "deterministic")))) - ;; This one will produce a different result. Since we're in - ;; 'check' mode, this must fail. - (build-things store (list (derivation-file-name drv)) - (build-mode check)) - #f)))))))) + (let* ((drv (build-expression->derivation + store "non-deterministic" + `(begin + (use-modules (rnrs io ports)) + (let ((out (assoc-ref %outputs "out"))) + (call-with-output-file out + (lambda (port) + (let ((now (gettimeofday))) + (display (+ (car now) (cdr now)) port)))) + #t)) + #:guile-for-build + (package-derivation store %bootstrap-guile (%current-system)))) + (file (derivation->output-path drv))) + (and (build-things store (list (derivation-file-name drv))) + (begin + (guard (c ((store-protocol-error? c) + (pk 'determinism-exception c) + (and (not (zero? (store-protocol-error-status c))) + (string-contains (store-protocol-error-message c) + "deterministic")))) + ;; This one will produce a different result. Since we're in + ;; 'check' mode, this must fail. + (build-things store (list (derivation-file-name drv)) + (build-mode check)) + #f)))))) (test-assert "build-succeeded trace in check mode" (string-contains -- 2.48.1
guix-patches@HIDDEN
:bug#75810
; Package guix-patches
.
Full text available.Received: (at 75810) by debbugs.gnu.org; 28 Feb 2025 14:31:05 +0000 From debbugs-submit-bounces <at> debbugs.gnu.org Fri Feb 28 09:31:05 2025 Received: from localhost ([127.0.0.1]:47864 helo=debbugs.gnu.org) by debbugs.gnu.org with esmtp (Exim 4.84_2) (envelope-from <debbugs-submit-bounces <at> debbugs.gnu.org>) id 1to1OK-0004dN-4G for submit <at> debbugs.gnu.org; Fri, 28 Feb 2025 09:31:05 -0500 Received: from eggs.gnu.org ([2001:470:142:3::10]:36542) by debbugs.gnu.org with esmtps (TLS1.2:ECDHE_RSA_AES_256_GCM_SHA384:256) (Exim 4.84_2) (envelope-from <ludo@HIDDEN>) id 1to1NM-0004PO-8i for 75810 <at> debbugs.gnu.org; Fri, 28 Feb 2025 09:30:08 -0500 Received: from fencepost.gnu.org ([2001:470:142:3::e]) by eggs.gnu.org with esmtps (TLS1.2:ECDHE_RSA_AES_256_GCM_SHA384:256) (Exim 4.90_1) (envelope-from <ludo@HIDDEN>) id 1to1NG-0002EY-Dg; Fri, 28 Feb 2025 09:29:58 -0500 DKIM-Signature: v=1; a=rsa-sha256; q=dns/txt; c=relaxed/relaxed; d=gnu.org; s=fencepost-gnu-org; h=MIME-Version:References:In-Reply-To:Date:Subject:To: From; bh=WLW6IffmqGQ4nvr5FusvR17usLyG/jdfaM2u5a/nHO8=; b=fCdINh4nYA5jv3NNQVmE 5U+uvgrqowjCXuKjkFXjFYNuoCkwzoby2ivC8IjiA9mLYQzXTWyYqioQ5ERKd20Yn5Mfy7ae3kPaY k4BsDQIRaOSORzHVp5tYOCVW2Ia1I4ni98xSajw+iSmARggOMWq/awTyZbgImNmNlJlKs9k9mj/7R 8AnXIz/Gt3gbV27gmM39MYna/m+/k8dL42aBYM2CUhLOqhpfpJuKh/AbSy0l+kAAf27nTUeki3DT0 LmdAe06GzFQivuIFETRngDiTIUi1UfcgCC9MBFUk1WzyU94DnTAFuea6L/vgORuSG3cS2P4MEYE2H FsQuOBvfDhRoWQ==; From: =?UTF-8?q?Ludovic=20Court=C3=A8s?= <ludo@HIDDEN> To: 75810 <at> debbugs.gnu.org Subject: [PATCH v4 04/14] daemon: Remount inputs as read-only. Date: Fri, 28 Feb 2025 15:29:23 +0100 Message-ID: <2c64a81a3bcd1ea6e79d24dea82ea6bf28af6aac.1740752774.git.ludo@HIDDEN> X-Mailer: git-send-email 2.48.1 In-Reply-To: <cover.1740752774.git.ludo@HIDDEN> References: <cover.1740752774.git.ludo@HIDDEN> MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit X-Spam-Score: -1.5 (-) X-Debbugs-Envelope-To: 75810 Cc: =?UTF-8?q?Ludovic=20Court=C3=A8s?= <ludo@HIDDEN>, Reepca Russelstein <reepca@HIDDEN> X-BeenThere: debbugs-submit <at> debbugs.gnu.org X-Mailman-Version: 2.1.18 Precedence: list List-Id: <debbugs-submit.debbugs.gnu.org> List-Unsubscribe: <https://debbugs.gnu.org/cgi-bin/mailman/options/debbugs-submit>, <mailto:debbugs-submit-request <at> debbugs.gnu.org?subject=unsubscribe> List-Archive: <https://debbugs.gnu.org/cgi-bin/mailman/private/debbugs-submit/> List-Post: <mailto:debbugs-submit <at> debbugs.gnu.org> List-Help: <mailto:debbugs-submit-request <at> debbugs.gnu.org?subject=help> List-Subscribe: <https://debbugs.gnu.org/cgi-bin/mailman/listinfo/debbugs-submit>, <mailto:debbugs-submit-request <at> debbugs.gnu.org?subject=subscribe> Errors-To: debbugs-submit-bounces <at> debbugs.gnu.org Sender: "Debbugs-submit" <debbugs-submit-bounces <at> debbugs.gnu.org> X-Spam-Score: -2.5 (--) * nix/libstore/build.cc (DerivationGoal::runChild): Remount ‘target’ as read-only. Reported-by: Reepca Russelstein <reepca@HIDDEN> Change-Id: Ib7201bcf4363be566f205d23d17fe2f55d3ad666 --- nix/libstore/build.cc | 7 +++++++ 1 file changed, 7 insertions(+) diff --git a/nix/libstore/build.cc b/nix/libstore/build.cc index 193b279b88a..3861a1ffd90 100644 --- a/nix/libstore/build.cc +++ b/nix/libstore/build.cc @@ -2107,8 +2107,15 @@ void DerivationGoal::runChild() createDirs(dirOf(target)); writeFile(target, ""); } + + /* Extra flags passed with MS_BIND are ignored, hence the + extra MS_REMOUNT. */ if (mount(source.c_str(), target.c_str(), "", MS_BIND, 0) == -1) throw SysError(format("bind mount from `%1%' to `%2%' failed") % source % target); + if (source.compare(0, settings.nixStore.length(), settings.nixStore) == 0) { + if (mount(source.c_str(), target.c_str(), "", MS_BIND | MS_REMOUNT | MS_RDONLY, 0) == -1) + throw SysError(format("read-only remount of `%1%' failed") % target); + } } /* Bind a new instance of procfs on /proc to reflect our -- 2.48.1
guix-patches@HIDDEN
:bug#75810
; Package guix-patches
.
Full text available.Received: (at 75810) by debbugs.gnu.org; 28 Feb 2025 14:31:04 +0000 From debbugs-submit-bounces <at> debbugs.gnu.org Fri Feb 28 09:31:04 2025 Received: from localhost ([127.0.0.1]:47862 helo=debbugs.gnu.org) by debbugs.gnu.org with esmtp (Exim 4.84_2) (envelope-from <debbugs-submit-bounces <at> debbugs.gnu.org>) id 1to1OJ-0004dA-CW for submit <at> debbugs.gnu.org; Fri, 28 Feb 2025 09:31:04 -0500 Received: from eggs.gnu.org ([2001:470:142:3::10]:45430) by debbugs.gnu.org with esmtps (TLS1.2:ECDHE_RSA_AES_256_GCM_SHA384:256) (Exim 4.84_2) (envelope-from <ludo@HIDDEN>) id 1to1NU-0004R4-AZ for 75810 <at> debbugs.gnu.org; Fri, 28 Feb 2025 09:30:16 -0500 Received: from fencepost.gnu.org ([2001:470:142:3::e]) by eggs.gnu.org with esmtps (TLS1.2:ECDHE_RSA_AES_256_GCM_SHA384:256) (Exim 4.90_1) (envelope-from <ludo@HIDDEN>) id 1to1NO-0002SA-T6; Fri, 28 Feb 2025 09:30:06 -0500 DKIM-Signature: v=1; a=rsa-sha256; q=dns/txt; c=relaxed/relaxed; d=gnu.org; s=fencepost-gnu-org; h=MIME-Version:References:In-Reply-To:Date:Subject:To: From; bh=fWWXPGKmocenmkwm2NuKznHSEy4eXcjP6Tuf4/xJCg8=; b=OFFALB3RGHuqz5U14ckP 3EwEwpVKFXNZUg90zz+4f52Y4Ovz0Wqh06DCtBRfefpous+hsvbbzEElDMPV2/XpHmmHPPp1yrHhb ybJx6lUkFQuOGpO6z312OKAeyfI4kqD3bJcSSZo4GJRe7+oPNvREuo0aIBycHKxpszf3i2hkkXXiq NS/nz9QetzKVkamU6R3YtDcNKafzJh339lE+d+aR/9TuX/uRV1sRB+lSwHl5nnoloHb+qUVjkzqWp MfXLcz15vnmMVvaBgHbGSWPkG4F1v/B3TJTZFA3yMl0UKptPLYQc30d0R6gBCpUCOVd6LELDyz3B7 k5wnfj5UJQ+/pA==; From: =?UTF-8?q?Ludovic=20Court=C3=A8s?= <ludo@HIDDEN> To: 75810 <at> debbugs.gnu.org Subject: [PATCH v4 12/14] =?UTF-8?q?etc:=20systemd=20services:=20Run=20?= =?UTF-8?q?=E2=80=98guix-daemon=E2=80=99=20as=20an=20unprivileged=20user.?= Date: Fri, 28 Feb 2025 15:29:31 +0100 Message-ID: <ad43a913694738760d5e4f77af620af19d228801.1740752774.git.ludo@HIDDEN> X-Mailer: git-send-email 2.48.1 In-Reply-To: <cover.1740752774.git.ludo@HIDDEN> References: <cover.1740752774.git.ludo@HIDDEN> MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit X-Spam-Score: -2.3 (--) X-Debbugs-Envelope-To: 75810 Cc: =?UTF-8?q?Ludovic=20Court=C3=A8s?= <ludo@HIDDEN> X-BeenThere: debbugs-submit <at> debbugs.gnu.org X-Mailman-Version: 2.1.18 Precedence: list List-Id: <debbugs-submit.debbugs.gnu.org> List-Unsubscribe: <https://debbugs.gnu.org/cgi-bin/mailman/options/debbugs-submit>, <mailto:debbugs-submit-request <at> debbugs.gnu.org?subject=unsubscribe> List-Archive: <https://debbugs.gnu.org/cgi-bin/mailman/private/debbugs-submit/> List-Post: <mailto:debbugs-submit <at> debbugs.gnu.org> List-Help: <mailto:debbugs-submit-request <at> debbugs.gnu.org?subject=help> List-Subscribe: <https://debbugs.gnu.org/cgi-bin/mailman/listinfo/debbugs-submit>, <mailto:debbugs-submit-request <at> debbugs.gnu.org?subject=subscribe> Errors-To: debbugs-submit-bounces <at> debbugs.gnu.org Sender: "Debbugs-submit" <debbugs-submit-bounces <at> debbugs.gnu.org> X-Spam-Score: -3.3 (---) * etc/guix-daemon.service.in (ExecStart): Remove ‘--build-users-group’. (Before, User, AmbientCapabilities, PrivateMounts, BindPaths): New fields. * etc/gnu-store.mount.in (Before): Remove. (WantedBy): Change to ‘multi-user.target’. Change-Id: Id826b8ab535844b6024d777f6bd15fd49db6d65e --- etc/gnu-store.mount.in | 3 +-- etc/guix-daemon.service.in | 20 +++++++++++++++++++- 2 files changed, 20 insertions(+), 3 deletions(-) diff --git a/etc/gnu-store.mount.in b/etc/gnu-store.mount.in index c94f2db72be..f9918c9e52e 100644 --- a/etc/gnu-store.mount.in +++ b/etc/gnu-store.mount.in @@ -2,10 +2,9 @@ Description=Read-only @storedir@ for GNU Guix DefaultDependencies=no ConditionPathExists=@storedir@ -Before=guix-daemon.service [Install] -WantedBy=guix-daemon.service +WantedBy=multi-user.target [Mount] What=@storedir@ diff --git a/etc/guix-daemon.service.in b/etc/guix-daemon.service.in index 5c43d9b7f1b..a04cf1f2f0f 100644 --- a/etc/guix-daemon.service.in +++ b/etc/guix-daemon.service.in @@ -5,11 +5,29 @@ [Unit] Description=Build daemon for GNU Guix +# Start before 'gnu-store.mount' to get a writable view of the store. +Before=gnu-store.mount + [Service] ExecStart=@localstatedir@/guix/profiles/per-user/root/current-guix/bin/guix-daemon \ - --build-users-group=guixbuild --discover=no \ + --discover=no \ --substitute-urls='@GUIX_SUBSTITUTE_URLS@' Environment='GUIX_LOCPATH=@localstatedir@/guix/profiles/per-user/root/guix-profile/lib/locale' LC_ALL=en_US.utf8 + +# Run under a dedicated unprivileged user account. +User=guix-daemon + +# Bind-mount the store read-write in a private namespace, to counter the +# effect of 'gnu-store.mount'. +PrivateMounts=true +BindPaths=@storedir@ + +# Provide the CAP_CHOWN capability so that guix-daemon cran create and chown +# /var/guix/profiles/per-user/$USER and also chown failed build directories +# when using '--keep-failed'. Note that guix-daemon explicitly drops ambient +# capabilities before executing build processes so they don't inherit them. +AmbientCapabilities=CAP_CHOWN + StandardOutput=journal StandardError=journal -- 2.48.1
guix-patches@HIDDEN
:bug#75810
; Package guix-patches
.
Full text available.Received: (at 75810) by debbugs.gnu.org; 28 Feb 2025 14:31:03 +0000 From debbugs-submit-bounces <at> debbugs.gnu.org Fri Feb 28 09:31:03 2025 Received: from localhost ([127.0.0.1]:47859 helo=debbugs.gnu.org) by debbugs.gnu.org with esmtp (Exim 4.84_2) (envelope-from <debbugs-submit-bounces <at> debbugs.gnu.org>) id 1to1OI-0004d0-Rk for submit <at> debbugs.gnu.org; Fri, 28 Feb 2025 09:31:03 -0500 Received: from eggs.gnu.org ([2001:470:142:3::10]:45452) by debbugs.gnu.org with esmtps (TLS1.2:ECDHE_RSA_AES_256_GCM_SHA384:256) (Exim 4.84_2) (envelope-from <ludo@HIDDEN>) id 1to1NW-0004RY-7N for 75810 <at> debbugs.gnu.org; Fri, 28 Feb 2025 09:30:16 -0500 Received: from fencepost.gnu.org ([2001:470:142:3::e]) by eggs.gnu.org with esmtps (TLS1.2:ECDHE_RSA_AES_256_GCM_SHA384:256) (Exim 4.90_1) (envelope-from <ludo@HIDDEN>) id 1to1NQ-0002Sb-PA; Fri, 28 Feb 2025 09:30:08 -0500 DKIM-Signature: v=1; a=rsa-sha256; q=dns/txt; c=relaxed/relaxed; d=gnu.org; s=fencepost-gnu-org; h=MIME-Version:References:In-Reply-To:Date:Subject:To: From; bh=aclAN4I3us6dIXC6MTr5TCJIgd9trnsuFHdiamwNBz8=; b=o3/dfnYyq/pNKyolW8VG jVo+vDs+Sed+GZGVxSI/MuKtJYEFxVJlWRRdtbjmJQnC+bRzbOm1noST12fY+Qh0pcngbMVx7elKM U3sCCaew1ZJ5UKDaDqWWBpg8Ra1UpzOukU8a3s2aFrh/HYq6Uur+iwS2thjSLUeVmNeH/lEr2M16p AXE466hrBPLi2CbZgFhUKpw5PFawfkI3SiiAn/2IeTsaIpdClf2Y8n4NmBIGJ6UQRGcrlH+QQUESg kgeLaDsncZQAEdBBOAfUla6pcGgiStccVuMYaRiCuBPOODnkYQyyGVbKZ58S8TzFfhiHtP962JXT1 ZWkFydyeB7px2g==; From: =?UTF-8?q?Ludovic=20Court=C3=A8s?= <ludo@HIDDEN> To: 75810 <at> debbugs.gnu.org Subject: [PATCH v4 14/14] =?UTF-8?q?DRAFT=20gexp:=20No=20symlinks=20for=20?= =?UTF-8?q?=E2=80=98imported-files/derivation=E2=80=99.?= Date: Fri, 28 Feb 2025 15:29:33 +0100 Message-ID: <4f4dfe6ff53cb4ff0832a0f02640735c0e3fa52a.1740752774.git.ludo@HIDDEN> X-Mailer: git-send-email 2.48.1 In-Reply-To: <cover.1740752774.git.ludo@HIDDEN> References: <cover.1740752774.git.ludo@HIDDEN> MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 X-Debbugs-Cc: Christopher Baines <guix@HIDDEN>, Josselin Poiret <dev@HIDDEN>, Ludovic Courtès <ludo@HIDDEN>, Mathieu Othacehe <othacehe@HIDDEN>, Simon Tournier <zimon.toutoune@HIDDEN>, Tobias Geerinckx-Rice <me@HIDDEN> Content-Transfer-Encoding: 8bit X-Spam-Score: -2.3 (--) X-Debbugs-Envelope-To: 75810 Cc: =?UTF-8?q?Ludovic=20Court=C3=A8s?= <ludo@HIDDEN> X-BeenThere: debbugs-submit <at> debbugs.gnu.org X-Mailman-Version: 2.1.18 Precedence: list List-Id: <debbugs-submit.debbugs.gnu.org> List-Unsubscribe: <https://debbugs.gnu.org/cgi-bin/mailman/options/debbugs-submit>, <mailto:debbugs-submit-request <at> debbugs.gnu.org?subject=unsubscribe> List-Archive: <https://debbugs.gnu.org/cgi-bin/mailman/private/debbugs-submit/> List-Post: <mailto:debbugs-submit <at> debbugs.gnu.org> List-Help: <mailto:debbugs-submit-request <at> debbugs.gnu.org?subject=help> List-Subscribe: <https://debbugs.gnu.org/cgi-bin/mailman/listinfo/debbugs-submit>, <mailto:debbugs-submit-request <at> debbugs.gnu.org?subject=subscribe> Errors-To: debbugs-submit-bounces <at> debbugs.gnu.org Sender: "Debbugs-submit" <debbugs-submit-bounces <at> debbugs.gnu.org> X-Spam-Score: -3.3 (---) DRAFT: Wait for <https://issues.guix.gnu.org/76376>. * guix/gexp.scm (imported-files/derivation): Pass #:recursive? #f to ‘interned-file’ and call ‘readlink*’ on ‘file-name’. Change-Id: Idc5b59cd8f0c1217e84c7cbfba64d97d5999429f --- guix/gexp.scm | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/guix/gexp.scm b/guix/gexp.scm index ad51bc55b78..ddd2e1a0812 100644 --- a/guix/gexp.scm +++ b/guix/gexp.scm @@ -1584,8 +1584,9 @@ (define* (imported-files/derivation files (define file-pair (match-lambda ((final-path . (? string? file-name)) - (mlet %store-monad ((file (interned-file file-name - (basename final-path)))) + (mlet %store-monad ((file (interned-file (readlink* file-name) + (basename final-path) + #:recursive? #f))) (return (list final-path file)))) ((final-path . file-like) (mlet %store-monad ((file (lower-object file-like system))) -- 2.48.1
guix@HIDDEN, dev@HIDDEN, ludo@HIDDEN, othacehe@HIDDEN, zimon.toutoune@HIDDEN, me@HIDDEN, guix-patches@HIDDEN
:bug#75810
; Package guix-patches
.
Full text available.Received: (at 75810) by debbugs.gnu.org; 28 Feb 2025 14:31:02 +0000 From debbugs-submit-bounces <at> debbugs.gnu.org Fri Feb 28 09:31:02 2025 Received: from localhost ([127.0.0.1]:47857 helo=debbugs.gnu.org) by debbugs.gnu.org with esmtp (Exim 4.84_2) (envelope-from <debbugs-submit-bounces <at> debbugs.gnu.org>) id 1to1OG-0004cX-Uv for submit <at> debbugs.gnu.org; Fri, 28 Feb 2025 09:31:02 -0500 Received: from eggs.gnu.org ([2001:470:142:3::10]:45406) by debbugs.gnu.org with esmtps (TLS1.2:ECDHE_RSA_AES_256_GCM_SHA384:256) (Exim 4.84_2) (envelope-from <ludo@HIDDEN>) id 1to1NR-0004Qm-VN for 75810 <at> debbugs.gnu.org; Fri, 28 Feb 2025 09:30:13 -0500 Received: from fencepost.gnu.org ([2001:470:142:3::e]) by eggs.gnu.org with esmtps (TLS1.2:ECDHE_RSA_AES_256_GCM_SHA384:256) (Exim 4.90_1) (envelope-from <ludo@HIDDEN>) id 1to1NM-0002Ra-G3; Fri, 28 Feb 2025 09:30:04 -0500 DKIM-Signature: v=1; a=rsa-sha256; q=dns/txt; c=relaxed/relaxed; d=gnu.org; s=fencepost-gnu-org; h=MIME-Version:References:In-Reply-To:Date:Subject:To: From; bh=MrAPisSjnu47SdKFbk6IPhnOUMkhBCPYlfMXNLE80zk=; b=YeafyD386Cwipu2fPfAD GyKHsuFtjCbiEimQMqh2Mkxx+vnsSYCU8p4qbLZ2mnUzjbRBOcRwmpZOttVAbrPw3ZyQ++BaDtO6X RIeMuwYZOdWzX3mG3AUEWsxUtjuTxYULFfqE9JGzC+H51IPUQEv1Gc9ZaV94cN5pX/bHqS1Itk7/U TlO9v0o2lOTT5VfzgCLXOYtccWnoBuTSYnjSEnPaWCAGDkXZeoD0XSDfaMxO7lTcA9YfuLRdxR+bJ EOisKjZSB9JNg9FYS4yEPC/DHXV9Ti8K5+OMHPjp0odcCZRYSnfwkTpEbhA8xS50ywDV9Wg2Qs+cc iY2rko7R5i1Vtg==; From: =?UTF-8?q?Ludovic=20Court=C3=A8s?= <ludo@HIDDEN> To: 75810 <at> debbugs.gnu.org Subject: [PATCH v4 10/14] tests: Add missing derivation inputs. Date: Fri, 28 Feb 2025 15:29:29 +0100 Message-ID: <f32d600f0b63651c64531ff5df0dbedd4152bcc4.1740752774.git.ludo@HIDDEN> X-Mailer: git-send-email 2.48.1 In-Reply-To: <cover.1740752774.git.ludo@HIDDEN> References: <cover.1740752774.git.ludo@HIDDEN> MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit X-Spam-Score: -2.3 (--) X-Debbugs-Envelope-To: 75810 Cc: =?UTF-8?q?Ludovic=20Court=C3=A8s?= <ludo@HIDDEN> X-BeenThere: debbugs-submit <at> debbugs.gnu.org X-Mailman-Version: 2.1.18 Precedence: list List-Id: <debbugs-submit.debbugs.gnu.org> List-Unsubscribe: <https://debbugs.gnu.org/cgi-bin/mailman/options/debbugs-submit>, <mailto:debbugs-submit-request <at> debbugs.gnu.org?subject=unsubscribe> List-Archive: <https://debbugs.gnu.org/cgi-bin/mailman/private/debbugs-submit/> List-Post: <mailto:debbugs-submit <at> debbugs.gnu.org> List-Help: <mailto:debbugs-submit-request <at> debbugs.gnu.org?subject=help> List-Subscribe: <https://debbugs.gnu.org/cgi-bin/mailman/listinfo/debbugs-submit>, <mailto:debbugs-submit-request <at> debbugs.gnu.org?subject=subscribe> Errors-To: debbugs-submit-bounces <at> debbugs.gnu.org Sender: "Debbugs-submit" <debbugs-submit-bounces <at> debbugs.gnu.org> X-Spam-Score: -3.3 (---) These missing inputs go unnoticed when running ‘guix-daemon --disable-chroot’ but are immediately visible otherwise. * tests/derivations.scm ("fixed-output derivation"): Add %BASH to #:sources. ("fixed-output derivation: output paths are equal"): ("fixed-output derivation, recursive"): ("derivation with a fixed-output input"): ("derivation with duplicate fixed-output inputs"): ("derivation with equivalent fixed-output inputs"): ("build derivation with coreutils"): Likewise. * tests/packages.scm (bootstrap-binary): New procedure. ("package-source-derivation, origin, sha512"): Use it instead of ‘search-bootstrap-binary’ and add BASH to #:sources. ("package-source-derivation, origin, sha3-512"): Likewise. Change-Id: I4c9087df23c47729a3aff15e9e1435b7266e36e2 --- tests/derivations.scm | 24 +++++++++++++++--------- tests/packages.scm | 13 +++++++++---- 2 files changed, 24 insertions(+), 13 deletions(-) diff --git a/tests/derivations.scm b/tests/derivations.scm index 72ea9aa9ccb..f30f05474e3 100644 --- a/tests/derivations.scm +++ b/tests/derivations.scm @@ -1,5 +1,5 @@ ;;; GNU Guix --- Functional package management for GNU -;;; Copyright © 2012-2024 Ludovic Courtès <ludo@HIDDEN> +;;; Copyright © 2012-2025 Ludovic Courtès <ludo@HIDDEN> ;;; ;;; This file is part of GNU Guix. ;;; @@ -443,7 +443,7 @@ (define* (directory-contents dir #:optional (slurp get-bytevector-all)) (string-append "fixed-" (symbol->string hash-algorithm)) %bash `(,builder) - #:sources `(,builder) ;optional + #:sources (list %bash builder) #:hash hash #:hash-algo hash-algorithm))) (build-derivations %store (list drv)) @@ -462,9 +462,11 @@ (define* (directory-contents dir #:optional (slurp get-bytevector-all)) (hash (gcrypt:sha256 (string->utf8 "hello"))) (drv1 (derivation %store "fixed" %bash `(,builder1) + #:sources (list %bash builder1) #:hash hash #:hash-algo 'sha256)) (drv2 (derivation %store "fixed" %bash `(,builder2) + #:sources (list %bash builder2) #:hash hash #:hash-algo 'sha256)) (succeeded? (build-derivations %store (list drv1 drv2)))) (and succeeded? @@ -477,7 +479,7 @@ (define* (directory-contents dir #:optional (slurp get-bytevector-all)) (hash (gcrypt:sha256 (string->utf8 "hello"))) (drv (derivation %store "fixed-rec" %bash `(,builder) - #:sources (list builder) + #:sources (list %bash builder) #:hash (base32 "0sg9f58l1jj88w6pdrfdpj5x9b1zrwszk84j81zvby36q9whhhqa") #:hash-algo 'sha256 #:recursive? #t)) @@ -511,9 +513,11 @@ (define* (directory-contents dir #:optional (slurp get-bytevector-all)) (hash (gcrypt:sha256 (string->utf8 "hello"))) (fixed1 (derivation %store "fixed" %bash `(,builder1) + #:sources (list %bash builder1) #:hash hash #:hash-algo 'sha256)) (fixed2 (derivation %store "fixed" %bash `(,builder2) + #:sources (list %bash builder2) #:hash hash #:hash-algo 'sha256)) (fixed-out (derivation->output-path fixed1)) (builder3 (add-text-to-store @@ -548,9 +552,11 @@ (define* (directory-contents dir #:optional (slurp get-bytevector-all)) (hash (gcrypt:sha256 (string->utf8 "hello"))) (fixed1 (derivation %store "fixed" %bash `(,builder1) + #:sources (list %bash builder1) #:hash hash #:hash-algo 'sha256)) (fixed2 (derivation %store "fixed" %bash `(,builder2) + #:sources (list %bash builder2) #:hash hash #:hash-algo 'sha256)) (builder3 (add-text-to-store %store "builder.sh" "echo fake builder")) @@ -580,21 +586,21 @@ (define* (directory-contents dir #:optional (slurp get-bytevector-all)) '())) (hash (gcrypt:sha256 (string->utf8 "hello"))) (drv1 (derivation %store "fixed" %bash (list builder1) - #:sources (list builder1) + #:sources (list %bash builder1) #:hash hash #:hash-algo 'sha256)) (drv2 (derivation %store "fixed" %bash (list builder2) - #:sources (list builder2) + #:sources (list %bash builder2) #:hash hash #:hash-algo 'sha256)) (drv3a (derivation %store "fixed-user" %bash (list builder3) #:outputs '("one" "two") - #:sources (list builder3) + #:sources (list %bash builder3) #:inputs (list (derivation-input drv1)))) (drv3b (derivation %store "fixed-user" %bash (list builder3) #:outputs '("one" "two") - #:sources (list builder3) + #:sources (list %bash builder3) #:inputs (list (derivation-input drv2)))) (drv4 (derivation %store "fixed-user-user" %bash (list builder1) - #:sources (list builder1) + #:sources (list %bash builder1) #:inputs (list (derivation-input drv3a '("one")) (derivation-input drv3b '("two")))))) (match (derivation-inputs drv4) @@ -878,7 +884,7 @@ (define %coreutils ,(string-append (derivation->output-path %coreutils) "/bin"))) - #:sources (list builder) + #:sources (list %bash builder) #:inputs (list (derivation-input %coreutils)))) (succeeded? (build-derivations %store (list drv)))) diff --git a/tests/packages.scm b/tests/packages.scm index 2863fb5991e..701bcd4a333 100644 --- a/tests/packages.scm +++ b/tests/packages.scm @@ -79,6 +79,11 @@ (define %store ;; When grafting, do not add dependency on 'glibc-utf8-locales'. (%graft-with-utf8-locale? #f) +(define (bootstrap-binary name) + (let ((bin (search-bootstrap-binary name (%current-system)))) + (and %store + (add-to-store %store name #t "sha256" bin)))) + (test-begin "packages") @@ -608,14 +613,14 @@ (define %store (test-equal "package-source-derivation, origin, sha512" "hello" - (let* ((bash (search-bootstrap-binary "bash" (%current-system))) + (let* ((bash (bootstrap-binary "bash")) (builder (add-text-to-store %store "my-fixed-builder.sh" "echo -n hello > $out" '())) (method (lambda* (url hash-algo hash #:optional name #:rest rest) (and (eq? hash-algo 'sha512) (raw-derivation name bash (list builder) - #:sources (list builder) + #:sources (list bash builder) #:hash hash #:hash-algo hash-algo)))) (source (origin @@ -634,14 +639,14 @@ (define %store (test-equal "package-source-derivation, origin, sha3-512" "hello, sha3" - (let* ((bash (search-bootstrap-binary "bash" (%current-system))) + (let* ((bash (bootstrap-binary "bash")) (builder (add-text-to-store %store "my-fixed-builder.sh" "echo -n hello, sha3 > $out" '())) (method (lambda* (url hash-algo hash #:optional name #:rest rest) (and (eq? hash-algo 'sha3-512) (raw-derivation name bash (list builder) - #:sources (list builder) + #:sources (list bash builder) #:hash hash #:hash-algo hash-algo)))) (source (origin -- 2.48.1
guix-patches@HIDDEN
:bug#75810
; Package guix-patches
.
Full text available.Received: (at 75810) by debbugs.gnu.org; 28 Feb 2025 14:31:01 +0000 From debbugs-submit-bounces <at> debbugs.gnu.org Fri Feb 28 09:31:01 2025 Received: from localhost ([127.0.0.1]:47855 helo=debbugs.gnu.org) by debbugs.gnu.org with esmtp (Exim 4.84_2) (envelope-from <debbugs-submit-bounces <at> debbugs.gnu.org>) id 1to1OG-0004cN-1X for submit <at> debbugs.gnu.org; Fri, 28 Feb 2025 09:31:00 -0500 Received: from eggs.gnu.org ([2001:470:142:3::10]:45384) by debbugs.gnu.org with esmtps (TLS1.2:ECDHE_RSA_AES_256_GCM_SHA384:256) (Exim 4.84_2) (envelope-from <ludo@HIDDEN>) id 1to1NP-0004QE-PV for 75810 <at> debbugs.gnu.org; Fri, 28 Feb 2025 09:30:11 -0500 Received: from fencepost.gnu.org ([2001:470:142:3::e]) by eggs.gnu.org with esmtps (TLS1.2:ECDHE_RSA_AES_256_GCM_SHA384:256) (Exim 4.90_1) (envelope-from <ludo@HIDDEN>) id 1to1NK-0002GH-EC; Fri, 28 Feb 2025 09:30:02 -0500 DKIM-Signature: v=1; a=rsa-sha256; q=dns/txt; c=relaxed/relaxed; d=gnu.org; s=fencepost-gnu-org; h=MIME-Version:References:In-Reply-To:Date:Subject:To: From; bh=JVfl/asypkCDUpbrB8bsnxtK7I5iWUTxJVun/LKjTyM=; b=diwFFV98p3ZTAUsqAtQH 5RT+3eLetvEcQKPhnJ6yEOmSh61Wzaw85orEqrAIigDCgdNahClIe2+6emudeFbnAAFGTIIHNvVUS 0IvvoAJkgA9oMhEW05JQWxPKmPI6ZxxkLzt6mT9R4AeIzDSp+3ubE36d7hZXjOhj9RE49gerwKSS1 hss3fjRPkVOrdqXZgdXXq0ZF9w68N6U90pz7PVPvmlYIp3Y88aYVU3PlNmXw0izO9zzKNKDjxWmX4 KOFuyuKhTHlWXgE8F003PHBRuj5YCXWFjYYelBggTQkEDt2Uq/nVOr8O5j6eQSqecO2zjhuHKpnc9 /+VuY4llPB/vqg==; From: =?UTF-8?q?Ludovic=20Court=C3=A8s?= <ludo@HIDDEN> To: 75810 <at> debbugs.gnu.org Subject: [PATCH v4 08/14] daemon: Drop Linux ambient capabilities before executing builder. Date: Fri, 28 Feb 2025 15:29:27 +0100 Message-ID: <ed036f6e200cadf86df275a91b768693c6579b06.1740752774.git.ludo@HIDDEN> X-Mailer: git-send-email 2.48.1 In-Reply-To: <cover.1740752774.git.ludo@HIDDEN> References: <cover.1740752774.git.ludo@HIDDEN> MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit X-Spam-Score: -2.3 (--) X-Debbugs-Envelope-To: 75810 Cc: =?UTF-8?q?Ludovic=20Court=C3=A8s?= <ludo@HIDDEN> X-BeenThere: debbugs-submit <at> debbugs.gnu.org X-Mailman-Version: 2.1.18 Precedence: list List-Id: <debbugs-submit.debbugs.gnu.org> List-Unsubscribe: <https://debbugs.gnu.org/cgi-bin/mailman/options/debbugs-submit>, <mailto:debbugs-submit-request <at> debbugs.gnu.org?subject=unsubscribe> List-Archive: <https://debbugs.gnu.org/cgi-bin/mailman/private/debbugs-submit/> List-Post: <mailto:debbugs-submit <at> debbugs.gnu.org> List-Help: <mailto:debbugs-submit-request <at> debbugs.gnu.org?subject=help> List-Subscribe: <https://debbugs.gnu.org/cgi-bin/mailman/listinfo/debbugs-submit>, <mailto:debbugs-submit-request <at> debbugs.gnu.org?subject=subscribe> Errors-To: debbugs-submit-bounces <at> debbugs.gnu.org Sender: "Debbugs-submit" <debbugs-submit-bounces <at> debbugs.gnu.org> X-Spam-Score: -3.3 (---) * config-daemon.ac: Check for <sys/prctl.h>. * nix/libstore/build.cc (DerivationGoal::runChild): When ‘useChroot’ is true, call ‘prctl’ to drop all ambient capabilities. Change-Id: If34637fc508e5fb6d278167f5df7802fc595284f --- config-daemon.ac | 2 +- nix/libstore/build.cc | 9 +++++++++ 2 files changed, 10 insertions(+), 1 deletion(-) diff --git a/config-daemon.ac b/config-daemon.ac index 4e949bc88a3..35d9c8cd56b 100644 --- a/config-daemon.ac +++ b/config-daemon.ac @@ -79,7 +79,7 @@ if test "x$guix_build_daemon" = "xyes"; then dnl Chroot support. AC_CHECK_FUNCS([chroot unshare]) AC_CHECK_HEADERS([sched.h sys/param.h sys/mount.h sys/syscall.h \ - linux/close_range.h]) + linux/close_range.h sys/prctl.h]) if test "x$ac_cv_func_chroot" != "xyes"; then AC_MSG_ERROR(['chroot' function missing, bailing out]) diff --git a/nix/libstore/build.cc b/nix/libstore/build.cc index 961894454f3..2145955c4bd 100644 --- a/nix/libstore/build.cc +++ b/nix/libstore/build.cc @@ -50,6 +50,9 @@ #if HAVE_SCHED_H #include <sched.h> #endif +#if HAVE_SYS_PRCTL_H +#include <sys/prctl.h> +#endif #define CHROOT_ENABLED HAVE_CHROOT && HAVE_SYS_MOUNT_H && defined(MS_BIND) && defined(MS_PRIVATE) @@ -2071,6 +2074,12 @@ void DerivationGoal::runChild() #if CHROOT_ENABLED if (useChroot) { +# if HAVE_SYS_PRCTL_H + /* Drop ambient capabilities such as CAP_CHOWN that might have + been granted when starting guix-daemon. */ + prctl(PR_CAP_AMBIENT, PR_CAP_AMBIENT_CLEAR_ALL, 0, 0, 0); +# endif + if (!fixedOutput) { /* Initialise the loopback interface. */ AutoCloseFD fd(socket(PF_INET, SOCK_DGRAM, IPPROTO_IP)); -- 2.48.1
guix-patches@HIDDEN
:bug#75810
; Package guix-patches
.
Full text available.Received: (at 75810) by debbugs.gnu.org; 28 Feb 2025 14:31:00 +0000 From debbugs-submit-bounces <at> debbugs.gnu.org Fri Feb 28 09:31:00 2025 Received: from localhost ([127.0.0.1]:47853 helo=debbugs.gnu.org) by debbugs.gnu.org with esmtp (Exim 4.84_2) (envelope-from <debbugs-submit-bounces <at> debbugs.gnu.org>) id 1to1OF-0004cG-Ir for submit <at> debbugs.gnu.org; Fri, 28 Feb 2025 09:30:59 -0500 Received: from eggs.gnu.org ([2001:470:142:3::10]:45396) by debbugs.gnu.org with esmtps (TLS1.2:ECDHE_RSA_AES_256_GCM_SHA384:256) (Exim 4.84_2) (envelope-from <ludo@HIDDEN>) id 1to1NR-0004Qc-5L for 75810 <at> debbugs.gnu.org; Fri, 28 Feb 2025 09:30:11 -0500 Received: from fencepost.gnu.org ([2001:470:142:3::e]) by eggs.gnu.org with esmtps (TLS1.2:ECDHE_RSA_AES_256_GCM_SHA384:256) (Exim 4.90_1) (envelope-from <ludo@HIDDEN>) id 1to1NL-0002MN-IX; Fri, 28 Feb 2025 09:30:03 -0500 DKIM-Signature: v=1; a=rsa-sha256; q=dns/txt; c=relaxed/relaxed; d=gnu.org; s=fencepost-gnu-org; h=MIME-Version:References:In-Reply-To:Date:Subject:To: From; bh=NLafqJZ6BIvCCekAS+MOlHmLkanbGr+JT2Q80td8JA8=; b=CIOclN1ZklQriqzRs5V6 meOM8ilPLCLDEax2ruoOxX4EnwQEbWMw5/faSWD2RkNvCaJrii6zMD5FeEQGV9aE9pxEoUrbAUzGc zdQX1Zap1lGYTFnOc6E2PGf6BCSL2m/I3u0cVj4GQ96RHRsDtlxphsJN0CR/Ng3pwMIlMY7CGXXik TQrjUlZQIR7RWuWwd13jVpprDA4OLiqdn34s8SdwHtXwt5gUof9HqdAbzvuZFjiuIB0+AtFUjrl1w 8fuc/bZUSdlCvAeKV2+4+I+4uLLi8zcKkia5AGt7PN4EmzR7Kpxr0HUfXQhtWhJnF2DjuILcsSfWu BjOwC+5hwOvWtg==; From: =?UTF-8?q?Ludovic=20Court=C3=A8s?= <ludo@HIDDEN> To: 75810 <at> debbugs.gnu.org Subject: [PATCH v4 09/14] daemon: Move comments where they belong. Date: Fri, 28 Feb 2025 15:29:28 +0100 Message-ID: <7f3478a0fd9d7e26d5c5abda46c2821900c8bff6.1740752774.git.ludo@HIDDEN> X-Mailer: git-send-email 2.48.1 In-Reply-To: <cover.1740752774.git.ludo@HIDDEN> References: <cover.1740752774.git.ludo@HIDDEN> MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit X-Spam-Score: -2.3 (--) X-Debbugs-Envelope-To: 75810 Cc: =?UTF-8?q?Ludovic=20Court=C3=A8s?= <ludo@HIDDEN> X-BeenThere: debbugs-submit <at> debbugs.gnu.org X-Mailman-Version: 2.1.18 Precedence: list List-Id: <debbugs-submit.debbugs.gnu.org> List-Unsubscribe: <https://debbugs.gnu.org/cgi-bin/mailman/options/debbugs-submit>, <mailto:debbugs-submit-request <at> debbugs.gnu.org?subject=unsubscribe> List-Archive: <https://debbugs.gnu.org/cgi-bin/mailman/private/debbugs-submit/> List-Post: <mailto:debbugs-submit <at> debbugs.gnu.org> List-Help: <mailto:debbugs-submit-request <at> debbugs.gnu.org?subject=help> List-Subscribe: <https://debbugs.gnu.org/cgi-bin/mailman/listinfo/debbugs-submit>, <mailto:debbugs-submit-request <at> debbugs.gnu.org?subject=subscribe> Errors-To: debbugs-submit-bounces <at> debbugs.gnu.org Sender: "Debbugs-submit" <debbugs-submit-bounces <at> debbugs.gnu.org> X-Spam-Score: -3.3 (---) * nix/libstore/build.cc (DerivationGoal::startBuilder): Shuffle comments for clarity. Change-Id: I6557c103ade4a3ab046354548ea193c68f8c9c05 --- nix/libstore/build.cc | 13 +++++++------ 1 file changed, 7 insertions(+), 6 deletions(-) diff --git a/nix/libstore/build.cc b/nix/libstore/build.cc index 2145955c4bd..47f73ac8d23 100644 --- a/nix/libstore/build.cc +++ b/nix/libstore/build.cc @@ -1871,18 +1871,19 @@ void DerivationGoal::startBuilder() } dirsInChroot[tmpDirInSandbox] = tmpDir; - /* Make the closure of the inputs available in the chroot, - rather than the whole store. This prevents any access - to undeclared dependencies. !!! As an extra security - precaution, make the fake store only writable by the - build user. */ + /* Create the fake store. */ Path chrootStoreDir = chrootRootDir + settings.nixStore; createDirs(chrootStoreDir); chmod_(chrootStoreDir, 01775); if (buildUser.enabled() && chown(chrootStoreDir.c_str(), 0, buildUser.getGID()) == -1) - throw SysError(format("cannot change ownership of ‘%1%’") % chrootStoreDir); + /* As an extra security precaution, make the fake store only + writable by the build user. */ + throw SysError(format("cannot change ownership of ‘%1%’") % chrootStoreDir); + /* Make the closure of the inputs available in the chroot, rather than + the whole store. This prevents any access to undeclared + dependencies. */ foreach (PathSet::iterator, i, inputPaths) { struct stat st; if (lstat(i->c_str(), &st)) -- 2.48.1
guix-patches@HIDDEN
:bug#75810
; Package guix-patches
.
Full text available.Received: (at 75810) by debbugs.gnu.org; 28 Feb 2025 14:30:59 +0000 From debbugs-submit-bounces <at> debbugs.gnu.org Fri Feb 28 09:30:59 2025 Received: from localhost ([127.0.0.1]:47851 helo=debbugs.gnu.org) by debbugs.gnu.org with esmtp (Exim 4.84_2) (envelope-from <debbugs-submit-bounces <at> debbugs.gnu.org>) id 1to1OF-0004c9-2W for submit <at> debbugs.gnu.org; Fri, 28 Feb 2025 09:30:59 -0500 Received: from eggs.gnu.org ([2001:470:142:3::10]:36544) by debbugs.gnu.org with esmtps (TLS1.2:ECDHE_RSA_AES_256_GCM_SHA384:256) (Exim 4.84_2) (envelope-from <ludo@HIDDEN>) id 1to1NM-0004PY-QQ for 75810 <at> debbugs.gnu.org; Fri, 28 Feb 2025 09:30:08 -0500 Received: from fencepost.gnu.org ([2001:470:142:3::e]) by eggs.gnu.org with esmtps (TLS1.2:ECDHE_RSA_AES_256_GCM_SHA384:256) (Exim 4.90_1) (envelope-from <ludo@HIDDEN>) id 1to1NH-0002Ej-FW; Fri, 28 Feb 2025 09:29:59 -0500 DKIM-Signature: v=1; a=rsa-sha256; q=dns/txt; c=relaxed/relaxed; d=gnu.org; s=fencepost-gnu-org; h=MIME-Version:References:In-Reply-To:Date:Subject:To: From; bh=3bB9WyIt0Vkk/qSchJHScluBVP5+vsBh/S+chQ+QsfI=; b=mun4SWk8Ria4UK9G89vt e5vRKPFE/s+hCmUfREPfA2wZg+PR7enaBcEXv8iyQuP2MO/HbRdmLIZIfEiVBmsqmgip9eUge9yKM 8PHTtwrNqk++m6KjgTdZyQV/ebhQrywpuvfmU86g0yyfGsfz8QnEL6FrS5tEyffRy1GaaWQ28cA7A 5Jxp+ZOwchU4F4WAB+0hj5SgEmiaPbXsXF9Au+l4fFrOmgXJaEtf+QA7zIMCWuBhTEgir55+cQTUG dhBOZ3QE/IvgHd2BMG84XDdqNNESU/Y76HLtA1tC467Vm5weiFGJmcS+5fl83+cEgJV3BOr3Y4DId 6PoPQllqvylILA==; From: =?UTF-8?q?Ludovic=20Court=C3=A8s?= <ludo@HIDDEN> To: 75810 <at> debbugs.gnu.org Subject: [PATCH v4 05/14] daemon: Remount root directory as read-only. Date: Fri, 28 Feb 2025 15:29:24 +0100 Message-ID: <f3474c5bb726b06503c9ccc1758019ba327b21cd.1740752774.git.ludo@HIDDEN> X-Mailer: git-send-email 2.48.1 In-Reply-To: <cover.1740752774.git.ludo@HIDDEN> References: <cover.1740752774.git.ludo@HIDDEN> MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit X-Spam-Score: -2.3 (--) X-Debbugs-Envelope-To: 75810 Cc: =?UTF-8?q?Ludovic=20Court=C3=A8s?= <ludo@HIDDEN> X-BeenThere: debbugs-submit <at> debbugs.gnu.org X-Mailman-Version: 2.1.18 Precedence: list List-Id: <debbugs-submit.debbugs.gnu.org> List-Unsubscribe: <https://debbugs.gnu.org/cgi-bin/mailman/options/debbugs-submit>, <mailto:debbugs-submit-request <at> debbugs.gnu.org?subject=unsubscribe> List-Archive: <https://debbugs.gnu.org/cgi-bin/mailman/private/debbugs-submit/> List-Post: <mailto:debbugs-submit <at> debbugs.gnu.org> List-Help: <mailto:debbugs-submit-request <at> debbugs.gnu.org?subject=help> List-Subscribe: <https://debbugs.gnu.org/cgi-bin/mailman/listinfo/debbugs-submit>, <mailto:debbugs-submit-request <at> debbugs.gnu.org?subject=subscribe> Errors-To: debbugs-submit-bounces <at> debbugs.gnu.org Sender: "Debbugs-submit" <debbugs-submit-bounces <at> debbugs.gnu.org> X-Spam-Score: -3.3 (---) * nix/libstore/build.cc (DerivationGoal::runChild): Bind-mount the store and /tmp under ‘chrootRootDir’ to themselves as read-write. Remount / as read-only. Change-Id: I79565094c8ec8448401897c720aad75304fd1948 --- nix/libstore/build.cc | 16 ++++++++++++++++ 1 file changed, 16 insertions(+) diff --git a/nix/libstore/build.cc b/nix/libstore/build.cc index 3861a1ffd90..c8b778362ac 100644 --- a/nix/libstore/build.cc +++ b/nix/libstore/build.cc @@ -2091,6 +2091,18 @@ void DerivationGoal::runChild() for (auto & i : ss) dirsInChroot[i] = i; + /* Make new mounts for the store and for /tmp. That way, when + 'chrootRootDir' is made read-only below, these two mounts will + remain writable (the store needs to be writable so derivation + outputs can be written to it, and /tmp is writable by + convention). */ + auto chrootStoreDir = chrootRootDir + settings.nixStore; + if (mount(chrootStoreDir.c_str(), chrootStoreDir.c_str(), 0, MS_BIND, 0) == -1) + throw SysError(format("read-write mount of store '%1%' failed") % chrootStoreDir); + auto chrootTmpDir = chrootRootDir + "/tmp"; + if (mount(chrootTmpDir.c_str(), chrootTmpDir.c_str(), 0, MS_BIND, 0) == -1) + throw SysError(format("read-write mount of temporary directory '%1%' failed") % chrootTmpDir); + /* Bind-mount all the directories from the "host" filesystem that we want in the chroot environment. */ @@ -2164,6 +2176,10 @@ void DerivationGoal::runChild() if (rmdir("real-root") == -1) throw SysError("cannot remove real-root directory"); + + /* Remount root as read-only. */ + if (mount("/", "/", 0, MS_BIND | MS_REMOUNT | MS_RDONLY, 0) == -1) + throw SysError(format("read-only remount of build root '%1%' failed") % chrootRootDir); } #endif -- 2.48.1
guix-patches@HIDDEN
:bug#75810
; Package guix-patches
.
Full text available.Received: (at 75810) by debbugs.gnu.org; 28 Feb 2025 14:30:59 +0000 From debbugs-submit-bounces <at> debbugs.gnu.org Fri Feb 28 09:30:58 2025 Received: from localhost ([127.0.0.1]:47849 helo=debbugs.gnu.org) by debbugs.gnu.org with esmtp (Exim 4.84_2) (envelope-from <debbugs-submit-bounces <at> debbugs.gnu.org>) id 1to1OE-0004c1-5n for submit <at> debbugs.gnu.org; Fri, 28 Feb 2025 09:30:58 -0500 Received: from eggs.gnu.org ([2001:470:142:3::10]:45362) by debbugs.gnu.org with esmtps (TLS1.2:ECDHE_RSA_AES_256_GCM_SHA384:256) (Exim 4.84_2) (envelope-from <ludo@HIDDEN>) id 1to1NP-0004Q5-2N for 75810 <at> debbugs.gnu.org; Fri, 28 Feb 2025 09:30:08 -0500 Received: from fencepost.gnu.org ([2001:470:142:3::e]) by eggs.gnu.org with esmtps (TLS1.2:ECDHE_RSA_AES_256_GCM_SHA384:256) (Exim 4.90_1) (envelope-from <ludo@HIDDEN>) id 1to1NJ-0002FA-Fq; Fri, 28 Feb 2025 09:30:01 -0500 DKIM-Signature: v=1; a=rsa-sha256; q=dns/txt; c=relaxed/relaxed; d=gnu.org; s=fencepost-gnu-org; h=MIME-Version:References:In-Reply-To:Date:Subject:To: From; bh=nqlzKMPZLgTl3mUC6Z2Zfd4XTH6zRZXHrXrdQzkm5pA=; b=ktfH5m1dab5qskP1QGwz FXhes6C7pJQ8idGndsfPnSMAha/wlTYX77qxCQ3CErdFXpNgxe3mf9ZOkFXKIJmZvTaWfoXVgzMvt BENl1CbTMNs5pz66x0AyHGTnsJCjkV2vmYM+qQWmAj12v1TapPaCzGTT92DgC2zO3/Rf/HaSNZoYD Bna62jyuucfYHYeftY/ErLjXlYe9iIsA7pXhBNTHgc4MY3pOWSCFoiYPyjoeb69G2htgoos68sIIN OQzZ8eWxvKznySmPWlkxoUWuVpTeTVnqJ3qXzaV4N0gJu+Q3fE9lJsJgkhkLcULbbCa8dT+dOVjz+ 19kCGFykZkR7hQ==; From: =?UTF-8?q?Ludovic=20Court=C3=A8s?= <ludo@HIDDEN> To: 75810 <at> debbugs.gnu.org Subject: [PATCH v4 07/14] daemon: Create /var/guix/profiles/per-user unconditionally. Date: Fri, 28 Feb 2025 15:29:26 +0100 Message-ID: <1ffc921092a6ef697f1ee1ded2c256afbd985723.1740752774.git.ludo@HIDDEN> X-Mailer: git-send-email 2.48.1 In-Reply-To: <cover.1740752774.git.ludo@HIDDEN> References: <cover.1740752774.git.ludo@HIDDEN> MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit X-Spam-Score: -2.3 (--) X-Debbugs-Envelope-To: 75810 Cc: =?UTF-8?q?Ludovic=20Court=C3=A8s?= <ludo@HIDDEN> X-BeenThere: debbugs-submit <at> debbugs.gnu.org X-Mailman-Version: 2.1.18 Precedence: list List-Id: <debbugs-submit.debbugs.gnu.org> List-Unsubscribe: <https://debbugs.gnu.org/cgi-bin/mailman/options/debbugs-submit>, <mailto:debbugs-submit-request <at> debbugs.gnu.org?subject=unsubscribe> List-Archive: <https://debbugs.gnu.org/cgi-bin/mailman/private/debbugs-submit/> List-Post: <mailto:debbugs-submit <at> debbugs.gnu.org> List-Help: <mailto:debbugs-submit-request <at> debbugs.gnu.org?subject=help> List-Subscribe: <https://debbugs.gnu.org/cgi-bin/mailman/listinfo/debbugs-submit>, <mailto:debbugs-submit-request <at> debbugs.gnu.org?subject=subscribe> Errors-To: debbugs-submit-bounces <at> debbugs.gnu.org Sender: "Debbugs-submit" <debbugs-submit-bounces <at> debbugs.gnu.org> X-Spam-Score: -3.3 (---) * nix/libstore/local-store.cc (LocalStore::LocalStore): Create ‘perUserDir’ unconditionally. Change-Id: I5188320f9630a81d16f79212d0fffabd55d94abe --- nix/libstore/local-store.cc | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/nix/libstore/local-store.cc b/nix/libstore/local-store.cc index 83e6c3e16ec..f6540c2117d 100644 --- a/nix/libstore/local-store.cc +++ b/nix/libstore/local-store.cc @@ -79,12 +79,12 @@ LocalStore::LocalStore(bool reserveSpace) createSymlink(profilesDir, gcRootsDir + "/profiles"); } - /* Optionally, create directories and set permissions for a - multi-user install. */ + Path perUserDir = profilesDir + "/per-user"; + createDirs(perUserDir); + + /* Optionally, set permissions for a multi-user install. */ if (getuid() == 0 && settings.buildUsersGroup != "") { - Path perUserDir = profilesDir + "/per-user"; - createDirs(perUserDir); if (chmod(perUserDir.c_str(), 0755) == -1) throw SysError(format("could not set permissions on '%1%' to 755") % perUserDir); -- 2.48.1
guix-patches@HIDDEN
:bug#75810
; Package guix-patches
.
Full text available.Received: (at 75810) by debbugs.gnu.org; 28 Feb 2025 14:30:14 +0000 From debbugs-submit-bounces <at> debbugs.gnu.org Fri Feb 28 09:30:13 2025 Received: from localhost ([127.0.0.1]:47823 helo=debbugs.gnu.org) by debbugs.gnu.org with esmtp (Exim 4.84_2) (envelope-from <debbugs-submit-bounces <at> debbugs.gnu.org>) id 1to1NT-0004Rm-3t for submit <at> debbugs.gnu.org; Fri, 28 Feb 2025 09:30:13 -0500 Received: from eggs.gnu.org ([2001:470:142:3::10]:36532) by debbugs.gnu.org with esmtps (TLS1.2:ECDHE_RSA_AES_256_GCM_SHA384:256) (Exim 4.84_2) (envelope-from <ludo@HIDDEN>) id 1to1NL-0004PA-1v for 75810 <at> debbugs.gnu.org; Fri, 28 Feb 2025 09:30:04 -0500 Received: from fencepost.gnu.org ([2001:470:142:3::e]) by eggs.gnu.org with esmtps (TLS1.2:ECDHE_RSA_AES_256_GCM_SHA384:256) (Exim 4.90_1) (envelope-from <ludo@HIDDEN>) id 1to1NF-0002EJ-8X; Fri, 28 Feb 2025 09:29:57 -0500 DKIM-Signature: v=1; a=rsa-sha256; q=dns/txt; c=relaxed/relaxed; d=gnu.org; s=fencepost-gnu-org; h=MIME-Version:References:In-Reply-To:Date:Subject:To: From; bh=NrqDWSBdaW+uq4Ctj1kouCXkp1v2g9wJcyVNHH7P7aA=; b=dyrHB4BIFdnYMdxsxjlr DCveUNT7LSnWLm+1tI+Nly75nKSb1VOKSNcxop5cswtBHbrG0RhuSq5iN05bNWNP+ppvqDkrv5VAE +XAfrhT+a/5QL8D5CCpBNfuTCFCNtY2VWQtGANbsfxZeZABtmrm/mbTe0gNGlm3MlACUG/xa+DR75 zuf8VdsthOuMc1Yaa72qMXLIiL86ynIZ8wQwZooO2lna/SKmk+zQ53ChgmgIbfNwVeC9/8HCBrFIj k1fKQ2gw0h3RQrZKw+9U6hcNlDziRwRdqORQw87XKU9QOWwQKAwBHIKRqLwtTx8/HyVazOtfBGs6X /xsLkpWopWe2wQ==; From: =?UTF-8?q?Ludovic=20Court=C3=A8s?= <ludo@HIDDEN> To: 75810 <at> debbugs.gnu.org Subject: [PATCH v4 03/14] daemon: Bind-mount all the inputs, not just directories. Date: Fri, 28 Feb 2025 15:29:22 +0100 Message-ID: <99aa9bb6ad2104a891536b2cc94db64cbe7ad0ba.1740752774.git.ludo@HIDDEN> X-Mailer: git-send-email 2.48.1 In-Reply-To: <cover.1740752774.git.ludo@HIDDEN> References: <cover.1740752774.git.ludo@HIDDEN> MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit X-Spam-Score: -1.5 (-) X-Debbugs-Envelope-To: 75810 Cc: =?UTF-8?q?Ludovic=20Court=C3=A8s?= <ludo@HIDDEN>, Reepca Russelstein <reepca@HIDDEN> X-BeenThere: debbugs-submit <at> debbugs.gnu.org X-Mailman-Version: 2.1.18 Precedence: list List-Id: <debbugs-submit.debbugs.gnu.org> List-Unsubscribe: <https://debbugs.gnu.org/cgi-bin/mailman/options/debbugs-submit>, <mailto:debbugs-submit-request <at> debbugs.gnu.org?subject=unsubscribe> List-Archive: <https://debbugs.gnu.org/cgi-bin/mailman/private/debbugs-submit/> List-Post: <mailto:debbugs-submit <at> debbugs.gnu.org> List-Help: <mailto:debbugs-submit-request <at> debbugs.gnu.org?subject=help> List-Subscribe: <https://debbugs.gnu.org/cgi-bin/mailman/listinfo/debbugs-submit>, <mailto:debbugs-submit-request <at> debbugs.gnu.org?subject=subscribe> Errors-To: debbugs-submit-bounces <at> debbugs.gnu.org Sender: "Debbugs-submit" <debbugs-submit-bounces <at> debbugs.gnu.org> X-Spam-Score: -2.5 (--) * nix/libstore/build.cc (DerivationGoal::startBuilder): Add all of ‘inputPaths’ to ‘dirsInChroot’ instead of hard-linking regular files. Special-case symlinks. (DerivationGoal)[regularInputPaths]: Remove. Reported-by: Reepca Russelstein <reepca@HIDDEN> Change-Id: I070987f92d73f187f7826a975bee9ee309d67f56 --- nix/libstore/build.cc | 39 ++++++++++++++------------------------- 1 file changed, 14 insertions(+), 25 deletions(-) diff --git a/nix/libstore/build.cc b/nix/libstore/build.cc index 8ca5e5b732c..193b279b88a 100644 --- a/nix/libstore/build.cc +++ b/nix/libstore/build.cc @@ -659,9 +659,6 @@ private: /* RAII object to delete the chroot directory. */ std::shared_ptr<AutoDelete> autoDelChroot; - /* All inputs that are regular files. */ - PathSet regularInputPaths; - /* Whether this is a fixed-output derivation. */ bool fixedOutput; @@ -1850,9 +1847,7 @@ void DerivationGoal::startBuilder() /* Make the closure of the inputs available in the chroot, rather than the whole store. This prevents any access - to undeclared dependencies. Directories are bind-mounted, - while other inputs are hard-linked (since only directories - can be bind-mounted). !!! As an extra security + to undeclared dependencies. !!! As an extra security precaution, make the fake store only writable by the build user. */ Path chrootStoreDir = chrootRootDir + settings.nixStore; @@ -1863,28 +1858,22 @@ void DerivationGoal::startBuilder() throw SysError(format("cannot change ownership of ‘%1%’") % chrootStoreDir); foreach (PathSet::iterator, i, inputPaths) { - struct stat st; + struct stat st; if (lstat(i->c_str(), &st)) throw SysError(format("getting attributes of path `%1%'") % *i); - if (S_ISDIR(st.st_mode)) - dirsInChroot[*i] = *i; - else { - Path p = chrootRootDir + *i; - if (link(i->c_str(), p.c_str()) == -1) { - /* Hard-linking fails if we exceed the maximum - link count on a file (e.g. 32000 of ext3), - which is quite possible after a `nix-store - --optimise'. */ - if (errno != EMLINK) - throw SysError(format("linking `%1%' to `%2%'") % p % *i); - StringSink sink; - dumpPath(*i, sink); - StringSource source(sink.s); - restorePath(p, source); - } - regularInputPaths.insert(*i); - } + if (S_ISLNK(st.st_mode)) { + /* Since bind-mounts follow symlinks, thus representing their + target and not the symlink itself, special-case + symlinks. XXX: When running unprivileged, TARGET can be + deleted by the build process. Use 'open_tree' & co. when + it's more widely available. */ + Path target = chrootRootDir + *i; + if (symlink(readLink(*i).c_str(), target.c_str()) == -1) + throw SysError(format("failed to create symlink '%1%' to '%2%'") % target % readLink(*i)); + } + else + dirsInChroot[*i] = *i; } /* If we're repairing, checking or rebuilding part of a -- 2.48.1
guix-patches@HIDDEN
:bug#75810
; Package guix-patches
.
Full text available.Received: (at 75810) by debbugs.gnu.org; 28 Feb 2025 14:30:11 +0000 From debbugs-submit-bounces <at> debbugs.gnu.org Fri Feb 28 09:30:11 2025 Received: from localhost ([127.0.0.1]:47815 helo=debbugs.gnu.org) by debbugs.gnu.org with esmtp (Exim 4.84_2) (envelope-from <debbugs-submit-bounces <at> debbugs.gnu.org>) id 1to1NQ-0004RM-KL for submit <at> debbugs.gnu.org; Fri, 28 Feb 2025 09:30:11 -0500 Received: from eggs.gnu.org ([2001:470:142:3::10]:36524) by debbugs.gnu.org with esmtps (TLS1.2:ECDHE_RSA_AES_256_GCM_SHA384:256) (Exim 4.84_2) (envelope-from <ludo@HIDDEN>) id 1to1NJ-0004P6-GE for 75810 <at> debbugs.gnu.org; Fri, 28 Feb 2025 09:30:02 -0500 Received: from fencepost.gnu.org ([2001:470:142:3::e]) by eggs.gnu.org with esmtps (TLS1.2:ECDHE_RSA_AES_256_GCM_SHA384:256) (Exim 4.90_1) (envelope-from <ludo@HIDDEN>) id 1to1NE-0002E0-1F; Fri, 28 Feb 2025 09:29:56 -0500 DKIM-Signature: v=1; a=rsa-sha256; q=dns/txt; c=relaxed/relaxed; d=gnu.org; s=fencepost-gnu-org; h=MIME-Version:References:In-Reply-To:Date:Subject:To: From; bh=GvrSaaobOA5tdGu0YyC/d2iS1wHrLGwDVV1qFej7o30=; b=ltrLOL0ivbxd+UOuEtbT T/sbdE03vVNyxQJwPQlLat/QUvxb+Nj4ghZNeI0EQji48T/mOwPw8UQq2/nSjHkeq0GtxuEXLXskO A4WnjKIuGl58EvYiifbt++/uj2ys52VbMNDyf+ji3ujhbRJtnE+ciCxwSepH+PmCOllKx/ds6k7tQ 4+4B6aVFxhmuMhMGK/JiWh0lWR0+vjEsJWX5zAE8uw9nfhH+mKLIgz+iGQXq/dPi31K/G2BG5eYde pw1Dft8o7l85SoiZAKOGuNbXZ/RAsSPHjZG3GApSuXUJcQrtre/xNvHZkfaiKQVSJvGIOHhwjpG7c fMyI37dBAspASw==; From: =?UTF-8?q?Ludovic=20Court=C3=A8s?= <ludo@HIDDEN> To: 75810 <at> debbugs.gnu.org Subject: [PATCH v4 02/14] daemon: Bind-mount /etc/nsswitch.conf & co. only if it exists. Date: Fri, 28 Feb 2025 15:29:21 +0100 Message-ID: <9c8ee0e95ead78ad6d34459f998097413e9f9bf8.1740752774.git.ludo@HIDDEN> X-Mailer: git-send-email 2.48.1 In-Reply-To: <cover.1740752774.git.ludo@HIDDEN> References: <cover.1740752774.git.ludo@HIDDEN> MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit X-Spam-Score: -2.3 (--) X-Debbugs-Envelope-To: 75810 Cc: =?UTF-8?q?Ludovic=20Court=C3=A8s?= <ludo@HIDDEN> X-BeenThere: debbugs-submit <at> debbugs.gnu.org X-Mailman-Version: 2.1.18 Precedence: list List-Id: <debbugs-submit.debbugs.gnu.org> List-Unsubscribe: <https://debbugs.gnu.org/cgi-bin/mailman/options/debbugs-submit>, <mailto:debbugs-submit-request <at> debbugs.gnu.org?subject=unsubscribe> List-Archive: <https://debbugs.gnu.org/cgi-bin/mailman/private/debbugs-submit/> List-Post: <mailto:debbugs-submit <at> debbugs.gnu.org> List-Help: <mailto:debbugs-submit-request <at> debbugs.gnu.org?subject=help> List-Subscribe: <https://debbugs.gnu.org/cgi-bin/mailman/listinfo/debbugs-submit>, <mailto:debbugs-submit-request <at> debbugs.gnu.org?subject=subscribe> Errors-To: debbugs-submit-bounces <at> debbugs.gnu.org Sender: "Debbugs-submit" <debbugs-submit-bounces <at> debbugs.gnu.org> X-Spam-Score: -3.3 (---) Those files may be missing in some contexts, for instance within the build environment. * nix/libstore/build.cc (DerivationGoal::runChild): Add /etc/resolv.conf and related files to ‘ss’ only if they exist. Change-Id: Ie19664a86c8101a1dc82cf39ad4b7abb10f8250a --- nix/libstore/build.cc | 9 +++++---- 1 file changed, 5 insertions(+), 4 deletions(-) diff --git a/nix/libstore/build.cc b/nix/libstore/build.cc index edd01bab34d..8ca5e5b732c 100644 --- a/nix/libstore/build.cc +++ b/nix/libstore/build.cc @@ -2093,10 +2093,11 @@ void DerivationGoal::runChild() network, so give them access to /etc/resolv.conf and so on. */ if (fixedOutput) { - ss.push_back("/etc/resolv.conf"); - ss.push_back("/etc/nsswitch.conf"); - ss.push_back("/etc/services"); - ss.push_back("/etc/hosts"); + auto files = { "/etc/resolv.conf", "/etc/nsswitch.conf", + "/etc/services", "/etc/hosts" }; + for (auto & file: files) { + if (pathExists(file)) ss.push_back(file); + } } for (auto & i : ss) dirsInChroot[i] = i; -- 2.48.1
guix-patches@HIDDEN
:bug#75810
; Package guix-patches
.
Full text available.Received: (at 75810) by debbugs.gnu.org; 28 Feb 2025 14:30:09 +0000 From debbugs-submit-bounces <at> debbugs.gnu.org Fri Feb 28 09:30:08 2025 Received: from localhost ([127.0.0.1]:47803 helo=debbugs.gnu.org) by debbugs.gnu.org with esmtp (Exim 4.84_2) (envelope-from <debbugs-submit-bounces <at> debbugs.gnu.org>) id 1to1NM-0004Qn-QF for submit <at> debbugs.gnu.org; Fri, 28 Feb 2025 09:30:08 -0500 Received: from eggs.gnu.org ([2001:470:142:3::10]:36516) by debbugs.gnu.org with esmtps (TLS1.2:ECDHE_RSA_AES_256_GCM_SHA384:256) (Exim 4.84_2) (envelope-from <ludo@HIDDEN>) id 1to1NH-0004P4-UD for 75810 <at> debbugs.gnu.org; Fri, 28 Feb 2025 09:30:01 -0500 Received: from fencepost.gnu.org ([2001:470:142:3::e]) by eggs.gnu.org with esmtps (TLS1.2:ECDHE_RSA_AES_256_GCM_SHA384:256) (Exim 4.90_1) (envelope-from <ludo@HIDDEN>) id 1to1NA-0002DT-20; Fri, 28 Feb 2025 09:29:53 -0500 DKIM-Signature: v=1; a=rsa-sha256; q=dns/txt; c=relaxed/relaxed; d=gnu.org; s=fencepost-gnu-org; h=MIME-Version:Date:Subject:To:From:in-reply-to: references; bh=3KoEV6d3IwZA+o9z6X2JwkW4pkj4V/mmt9sUhn53J9k=; b=eU2D7QWWfQpvDx SaE+cn6c86hSNN2G5Gi7IWh8UxM2zF2uD9b0I5aF8XGKXePR7YLIQqBJHayULXIX1H/RegboWLU1J uQ0nGHifP9lsPV80pCk+Vbq5DeRr6WHhvfTnkAu7NSaQillTwRiB9UmY+beIhpQPpoKeSPlwl87HL 6d6QshamSyTDhb7MaPosTgGEDB0TDf+SfGAzHR6ssxyzRXQhllyx1vkGs510JY8mSsgICnQczznaq ZwWDFK42vGf/TmDTQ4FUr9r0aMcuvIV2zAIzcQG7yxK+CPbqwavzpCnZ11SDcEF4hSlYf3jImaEWQ R67YarUDq4o8MIUTQjGw==; From: =?UTF-8?q?Ludovic=20Court=C3=A8s?= <ludo@HIDDEN> To: 75810 <at> debbugs.gnu.org Subject: [PATCH v4 00/14] Rootless guix-daemon Date: Fri, 28 Feb 2025 15:29:19 +0100 Message-ID: <cover.1740752774.git.ludo@HIDDEN> X-Mailer: git-send-email 2.48.1 MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 X-Debbugs-Cc: Christopher Baines <guix@HIDDEN>, Josselin Poiret <dev@HIDDEN>, Ludovic Courtès <ludo@HIDDEN>, Mathieu Othacehe <othacehe@HIDDEN>, Simon Tournier <zimon.toutoune@HIDDEN>, Tobias Geerinckx-Rice <me@HIDDEN> Content-Transfer-Encoding: 8bit X-Spam-Score: -1.4 (-) X-Debbugs-Envelope-To: 75810 Cc: =?UTF-8?q?Ludovic=20Court=C3=A8s?= <ludo@HIDDEN>, Reepca Russelstein <reepca@HIDDEN> X-BeenThere: debbugs-submit <at> debbugs.gnu.org X-Mailman-Version: 2.1.18 Precedence: list List-Id: <debbugs-submit.debbugs.gnu.org> List-Unsubscribe: <https://debbugs.gnu.org/cgi-bin/mailman/options/debbugs-submit>, <mailto:debbugs-submit-request <at> debbugs.gnu.org?subject=unsubscribe> List-Archive: <https://debbugs.gnu.org/cgi-bin/mailman/private/debbugs-submit/> List-Post: <mailto:debbugs-submit <at> debbugs.gnu.org> List-Help: <mailto:debbugs-submit-request <at> debbugs.gnu.org?subject=help> List-Subscribe: <https://debbugs.gnu.org/cgi-bin/mailman/listinfo/debbugs-submit>, <mailto:debbugs-submit-request <at> debbugs.gnu.org?subject=subscribe> Errors-To: debbugs-submit-bounces <at> debbugs.gnu.org Sender: "Debbugs-submit" <debbugs-submit-bounces <at> debbugs.gnu.org> X-Spam-Score: -2.4 (--) Hello Guix! Changes in v4, hopefully the last revision of this patch set: • For ‘deleteTmpDir’, go back to v2, but add ‘secureFilePerms’ call and define ‘reown’ variable to determine whether to re-chown after pivoting (suggested by Reepca). • For fixed outputs, bind-mount /etc/nsswitch.conf & co. only if they exist (necessary when running ‘guix build guix’, where these files are missing). • In ‘Derivationgoal::startBuilder’, when an input is a symlink, symlink it instead of bind-mounting it (bind mounts would reveal the symlink target, not the symlink itself.) Add a test for that. Consequently, an input that is a symlink may be deleted by a build process. This is a harmless (only the copy of the symlink in the temporary store is deleted) but observable change. • Fix several tests that were missing explicit inputs (discovered by running ‘guix build guix’; this had gone unnoticed when I first ran ‘make check’ because I was sharing ‘ac_cv_guix_test_root’ with my main Guix checkout, so these derivation results were already in store.) • Leave ‘makeStoreWritable’ unchanged compared to current ‘master’. • ‘guix-install.sh’ uses the ‘can_install_unprivileged_daemon’ function (it was defined but unused). • ‘./test-env’ warns when resorting to ‘--disable-chroot’. • Unprivileged daemon documented under “Build Environment Setup”. I would like to push the two guix-daemon tests before this series: https://issues.guix.gnu.org/76488 https://issues.guix.gnu.org/76636 Thoughts? Are we done? Ludo’. Ludovic Courtès (14): daemon: Use ‘close_range’ where available. daemon: Bind-mount /etc/nsswitch.conf & co. only if it exists. daemon: Bind-mount all the inputs, not just directories. daemon: Remount inputs as read-only. daemon: Remount root directory as read-only. daemon: Allow running as non-root with unprivileged user namespaces. daemon: Create /var/guix/profiles/per-user unconditionally. daemon: Drop Linux ambient capabilities before executing builder. daemon: Move comments where they belong. tests: Add missing derivation inputs. tests: Run in a chroot and unprivileged user namespaces. etc: systemd services: Run ‘guix-daemon’ as an unprivileged user. guix-install.sh: Support the unprivileged daemon where possible. DRAFT gexp: No symlinks for ‘imported-files/derivation’. build-aux/test-env.in | 16 ++- config-daemon.ac | 5 +- doc/guix.texi | 100 +++++++++++---- etc/gnu-store.mount.in | 3 +- etc/guix-daemon.service.in | 20 ++- etc/guix-install.sh | 106 +++++++++++---- guix/gexp.scm | 5 +- guix/substitutes.scm | 4 +- nix/libstore/build.cc | 226 ++++++++++++++++++++++++-------- nix/libstore/local-store.cc | 26 ++-- nix/libutil/util.cc | 23 +++- tests/derivations.scm | 24 ++-- tests/packages.scm | 13 +- tests/processes.scm | 9 +- tests/store.scm | 250 +++++++++++++++++++++++++++++++----- 15 files changed, 650 insertions(+), 180 deletions(-) base-commit: a76708a872e65230931f3c5c3b079d0a39d5cb84 -- 2.48.1
guix@HIDDEN, dev@HIDDEN, ludo@HIDDEN, othacehe@HIDDEN, zimon.toutoune@HIDDEN, me@HIDDEN, guix-patches@HIDDEN
:bug#75810
; Package guix-patches
.
Full text available.Received: (at 75810) by debbugs.gnu.org; 28 Feb 2025 14:30:05 +0000 From debbugs-submit-bounces <at> debbugs.gnu.org Fri Feb 28 09:30:04 2025 Received: from localhost ([127.0.0.1]:47799 helo=debbugs.gnu.org) by debbugs.gnu.org with esmtp (Exim 4.84_2) (envelope-from <debbugs-submit-bounces <at> debbugs.gnu.org>) id 1to1NL-0004QZ-Qd for submit <at> debbugs.gnu.org; Fri, 28 Feb 2025 09:30:04 -0500 Received: from eggs.gnu.org ([2001:470:142:3::10]:36512) by debbugs.gnu.org with esmtps (TLS1.2:ECDHE_RSA_AES_256_GCM_SHA384:256) (Exim 4.84_2) (envelope-from <ludo@HIDDEN>) id 1to1NH-0004P3-SZ for 75810 <at> debbugs.gnu.org; Fri, 28 Feb 2025 09:30:01 -0500 Received: from fencepost.gnu.org ([2001:470:142:3::e]) by eggs.gnu.org with esmtps (TLS1.2:ECDHE_RSA_AES_256_GCM_SHA384:256) (Exim 4.90_1) (envelope-from <ludo@HIDDEN>) id 1to1NB-0002Da-N0; Fri, 28 Feb 2025 09:29:53 -0500 DKIM-Signature: v=1; a=rsa-sha256; q=dns/txt; c=relaxed/relaxed; d=gnu.org; s=fencepost-gnu-org; h=MIME-Version:References:In-Reply-To:Date:Subject:To: From; bh=0izMrOHlIq4NgLJJUeAlULEe8K+llpxfq6yctCHxero=; b=pjJYlMH89ls2eK+OSh6X WFe9MaRzYMMv0gHZ1Y/3YalqMfbqk7kS94XEbh5wQaMOXfTYsdrStPjpk1qVmfbrDeCE2No8XDj+a QUKqiU7loyGLQeHDnP7L3y1L2skCByLnc4lylc3/jmJNCL0fOFzN7BJe++k83jyLSAFn+VG+sElyQ Re2wyHGeFatbKVYMizBBhq9Oxn6y3YsIfTwH86GPi/9CdZGfEQLOP2/8+hsMMiZsrzTMWlt49kDIc UvQjIFCLeCP5e7yHtO9+mjD49VfzjIkYY/0oxyD+7U4aDvI+FdgCxbWN0QmAKB5H3I88CQc9m/ueI 1ZCg6Ldd8eC6xQ==; From: =?UTF-8?q?Ludovic=20Court=C3=A8s?= <ludo@HIDDEN> To: 75810 <at> debbugs.gnu.org Subject: [PATCH v4 01/14] =?UTF-8?q?daemon:=20Use=20=E2=80=98close=5Frange?= =?UTF-8?q?=E2=80=99=20where=20available.?= Date: Fri, 28 Feb 2025 15:29:20 +0100 Message-ID: <a6cdda9b1569fa4211e08164af40f1f1ede5ac53.1740752774.git.ludo@HIDDEN> X-Mailer: git-send-email 2.48.1 In-Reply-To: <cover.1740752774.git.ludo@HIDDEN> References: <cover.1740752774.git.ludo@HIDDEN> MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit X-Spam-Score: -2.3 (--) X-Debbugs-Envelope-To: 75810 Cc: =?UTF-8?q?Ludovic=20Court=C3=A8s?= <ludo@HIDDEN> X-BeenThere: debbugs-submit <at> debbugs.gnu.org X-Mailman-Version: 2.1.18 Precedence: list List-Id: <debbugs-submit.debbugs.gnu.org> List-Unsubscribe: <https://debbugs.gnu.org/cgi-bin/mailman/options/debbugs-submit>, <mailto:debbugs-submit-request <at> debbugs.gnu.org?subject=unsubscribe> List-Archive: <https://debbugs.gnu.org/cgi-bin/mailman/private/debbugs-submit/> List-Post: <mailto:debbugs-submit <at> debbugs.gnu.org> List-Help: <mailto:debbugs-submit-request <at> debbugs.gnu.org?subject=help> List-Subscribe: <https://debbugs.gnu.org/cgi-bin/mailman/listinfo/debbugs-submit>, <mailto:debbugs-submit-request <at> debbugs.gnu.org?subject=subscribe> Errors-To: debbugs-submit-bounces <at> debbugs.gnu.org Sender: "Debbugs-submit" <debbugs-submit-bounces <at> debbugs.gnu.org> X-Spam-Score: -3.3 (---) * nix/libutil/util.cc (closeMostFDs) [HAVE_CLOSE_RANGE]: Use ‘close_range’ when ‘exceptions’ is empty. * config-daemon.ac: Check for <linux/close_range.h> and the ‘close_range’ symbol. Change-Id: I12fa3bde58b003fcce5ea5a1fee1dcf9a92c0359 --- config-daemon.ac | 5 +++-- nix/libutil/util.cc | 23 +++++++++++++++++------ 2 files changed, 20 insertions(+), 8 deletions(-) diff --git a/config-daemon.ac b/config-daemon.ac index 6731c68bc39..4e949bc88a3 100644 --- a/config-daemon.ac +++ b/config-daemon.ac @@ -78,7 +78,8 @@ if test "x$guix_build_daemon" = "xyes"; then dnl Chroot support. AC_CHECK_FUNCS([chroot unshare]) - AC_CHECK_HEADERS([sched.h sys/param.h sys/mount.h sys/syscall.h]) + AC_CHECK_HEADERS([sched.h sys/param.h sys/mount.h sys/syscall.h \ + linux/close_range.h]) if test "x$ac_cv_func_chroot" != "xyes"; then AC_MSG_ERROR(['chroot' function missing, bailing out]) @@ -95,7 +96,7 @@ if test "x$guix_build_daemon" = "xyes"; then dnl strsignal: for error reporting. dnl statx: fine-grain 'stat' call, new in glibc 2.28. AC_CHECK_FUNCS([lutimes lchown posix_fallocate sched_setaffinity \ - statvfs nanosleep strsignal statx]) + statvfs nanosleep strsignal statx close_range]) dnl Check for <locale>. AC_LANG_PUSH(C++) diff --git a/nix/libutil/util.cc b/nix/libutil/util.cc index 3206dea11b1..eb2d16e1cc3 100644 --- a/nix/libutil/util.cc +++ b/nix/libutil/util.cc @@ -23,6 +23,10 @@ #include <sys/prctl.h> #endif +#ifdef HAVE_LINUX_CLOSE_RANGE_H +# include <linux/close_range.h> +#endif + extern char * * environ; @@ -1087,12 +1091,19 @@ string runProgram(Path program, bool searchPath, const Strings & args) void closeMostFDs(const set<int> & exceptions) { - int maxFD = 0; - maxFD = sysconf(_SC_OPEN_MAX); - for (int fd = 0; fd < maxFD; ++fd) - if (fd != STDIN_FILENO && fd != STDOUT_FILENO && fd != STDERR_FILENO - && exceptions.find(fd) == exceptions.end()) - close(fd); /* ignore result */ +#ifdef HAVE_CLOSE_RANGE + if (exceptions.empty()) + close_range(3, ~0U, 0); + else +#endif + { + int maxFD = 0; + maxFD = sysconf(_SC_OPEN_MAX); + for (int fd = 0; fd < maxFD; ++fd) + if (fd != STDIN_FILENO && fd != STDOUT_FILENO && fd != STDERR_FILENO + && exceptions.find(fd) == exceptions.end()) + close(fd); /* ignore result */ + } } -- 2.48.1
guix-patches@HIDDEN
:bug#75810
; Package guix-patches
.
Full text available.Ludovic Courtès <ludo@HIDDEN>
to control <at> debbugs.gnu.org
.
Full text available.Received: (at 75810) by debbugs.gnu.org; 28 Feb 2025 09:43:38 +0000 From debbugs-submit-bounces <at> debbugs.gnu.org Fri Feb 28 04:43:38 2025 Received: from localhost ([127.0.0.1]:45191 helo=debbugs.gnu.org) by debbugs.gnu.org with esmtp (Exim 4.84_2) (envelope-from <debbugs-submit-bounces <at> debbugs.gnu.org>) id 1tnwu9-0004zl-CE for submit <at> debbugs.gnu.org; Fri, 28 Feb 2025 04:43:38 -0500 Received: from eggs.gnu.org ([2001:470:142:3::10]:39706) by debbugs.gnu.org with esmtps (TLS1.2:ECDHE_RSA_AES_256_GCM_SHA384:256) (Exim 4.84_2) (envelope-from <ludo@HIDDEN>) id 1tnwu5-0004yu-Pz for 75810 <at> debbugs.gnu.org; Fri, 28 Feb 2025 04:43:35 -0500 Received: from fencepost.gnu.org ([2001:470:142:3::e]) by eggs.gnu.org with esmtps (TLS1.2:ECDHE_RSA_AES_256_GCM_SHA384:256) (Exim 4.90_1) (envelope-from <ludo@HIDDEN>) id 1tnwtz-0005Qz-B5; Fri, 28 Feb 2025 04:43:27 -0500 DKIM-Signature: v=1; a=rsa-sha256; q=dns/txt; c=relaxed/relaxed; d=gnu.org; s=fencepost-gnu-org; h=MIME-Version:Date:References:In-Reply-To:Subject:To: From; bh=Tz6UceTIt5lV6ctIq7esttcu+BOSHIjEbnTFNIN4eSY=; b=AGnOvVLdZ88uiffQ3P4H bK8JdA0tCeo+daq3HK5YvJlze1BqJd7VX0EctXx6UuKhl8Qhl8860elB89p8tfJdnUMvA5CpkT0G1 BHVfFNm84svCjTXWwryMQn+M9T3P4ssSpDTnZ48Hjoj+W3C/rbO0Wat7SARdUBeiu6qFdFWVKJWi6 QKr69G4Fyip0d4SwFlr9d+DSDdg00dZ/ChJOCoDJSriOYWt+la7yQKXpahQHj3pva3ec+fs6KXAsr 0O4VOzF4p6yVbGk2hmqqKO9/LbtgQMSMouUwsi20Go8tfMUCTIFF7v6LtuaZlDQO/zWGGVjQMtnZa 7P5qNOFHP0/7Bg==; From: =?utf-8?Q?Ludovic_Court=C3=A8s?= <ludo@HIDDEN> To: Reepca Russelstein <reepca@HIDDEN> Subject: Re: [bug#75810] [PATCH v3 00/11] Rootless guix-daemon In-Reply-To: <877c5idit1.fsf@HIDDEN> (Reepca Russelstein's message of "Fri, 21 Feb 2025 16:39:06 -0600") References: <cover.1740142328.git.ludo@HIDDEN> <877c5idit1.fsf@HIDDEN> Date: Fri, 28 Feb 2025 10:43:24 +0100 Message-ID: <87wmdatner.fsf@HIDDEN> User-Agent: Gnus/5.13 (Gnus v5.13) MIME-Version: 1.0 Content-Type: text/plain; charset=utf-8 Content-Transfer-Encoding: quoted-printable X-Spam-Score: -1.5 (-) X-Debbugs-Envelope-To: 75810 Cc: 75810 <at> debbugs.gnu.org X-BeenThere: debbugs-submit <at> debbugs.gnu.org X-Mailman-Version: 2.1.18 Precedence: list List-Id: <debbugs-submit.debbugs.gnu.org> List-Unsubscribe: <https://debbugs.gnu.org/cgi-bin/mailman/options/debbugs-submit>, <mailto:debbugs-submit-request <at> debbugs.gnu.org?subject=unsubscribe> List-Archive: <https://debbugs.gnu.org/cgi-bin/mailman/private/debbugs-submit/> List-Post: <mailto:debbugs-submit <at> debbugs.gnu.org> List-Help: <mailto:debbugs-submit-request <at> debbugs.gnu.org?subject=help> List-Subscribe: <https://debbugs.gnu.org/cgi-bin/mailman/listinfo/debbugs-submit>, <mailto:debbugs-submit-request <at> debbugs.gnu.org?subject=subscribe> Errors-To: debbugs-submit-bounces <at> debbugs.gnu.org Sender: "Debbugs-submit" <debbugs-submit-bounces <at> debbugs.gnu.org> X-Spam-Score: -2.5 (--) Hi, Reepca Russelstein <reepca@HIDDEN> skribis: >> =E2=80=A2 Unit files for systemd tweaked so that (1) guix-daemon sees >> a private read-write mount of the store, and (2) gnu-store.mount >> actually remounts the store read-only after guix-daemon has >> started. > > I'm not familiar with how systemd does service dependencies, but does > this mean that the store becomes writable when the daemon is stopped? I had to check because it=E2=80=99s not crystal clear. =E2=80=98systemctl stop guix-daemon=E2=80=99 also stops =E2=80=98gnu-store.= mount=E2=80=99. But then you can do =E2=80=98systemctl start gnu-store.mount=E2=80=99, whic= h does *not* start guix-daemon; at that point, =E2=80=98systemctl start guix-daemon=E2= =80=99 spawns guix-daemon, but it cannot write to the store. It=E2=80=99s messy, but I don=E2=80=99t know how to do better. [...] > It may work well to use the v2 patch for this with a call to > secureFilePerms added right before the try block and a have_cap_chown > boolean flag being saved for later recall after the pivot instead of the > (getuid() !=3D 0) check. That way in the fully-unprivileged case it > doesn't successfully pivot the now-sanitized build directory only to > immediately fail to chown it. Actually, because that chown call doesn't > result in an exception on failure, it would also work to only add the > secureFilePerms call. I went back to v2 + =E2=80=98secureFilePerms=E2=80=99 call. > Also, I've discovered that while mount(2) uses EPERM for both a locked > mount point and insufficient privileges, umount(2) uses EINVAL for the > former and EPERM for the latter. This may be a good way to test that > we're triggering the mount-locking behavior as intended. The tests try to MS_REMOUNT the inputs, which is exactly what we want to prevent; we could test the low-level semantics you describe, but it=E2=80= =99s quite obscure and maybe unnecessary given that we test MS_REMOUNT? >> The one observable difference compared to current guix-daemon >> operational mode is that, in the build environment, writing to >> the root file system results in EROFS instead of EPERM, as you >> pointed out earlier. That=E2=80=99s not great but probably acceptable. >> We=E2=80=99ll only know whether this is a problem in practice once we=E2= =80=99ve >> run the test suites of tens of thousands of packages. > > Strictly speaking, it's also observable that the root file system, > store, /tmp, etc is not owned by uid 0, and that the input store items > are all mounted read-only. Right. I=E2=80=99ll send v4 shortly. Thanks again for your feedback! Ludo=E2=80=99.
guix-patches@HIDDEN
:bug#75810
; Package guix-patches
.
Full text available.Received: (at 75810) by debbugs.gnu.org; 22 Feb 2025 17:16:46 +0000 From debbugs-submit-bounces <at> debbugs.gnu.org Sat Feb 22 12:16:45 2025 Received: from localhost ([127.0.0.1]:57061 helo=debbugs.gnu.org) by debbugs.gnu.org with esmtp (Exim 4.84_2) (envelope-from <debbugs-submit-bounces <at> debbugs.gnu.org>) id 1tlt7N-0002Vj-Ig for submit <at> debbugs.gnu.org; Sat, 22 Feb 2025 12:16:45 -0500 Received: from eggs.gnu.org ([2001:470:142:3::10]:60024) by debbugs.gnu.org with esmtps (TLS1.2:ECDHE_RSA_AES_256_GCM_SHA384:256) (Exim 4.84_2) (envelope-from <ludo@HIDDEN>) id 1tlt7K-0002VP-It for 75810 <at> debbugs.gnu.org; Sat, 22 Feb 2025 12:16:43 -0500 Received: from fencepost.gnu.org ([2001:470:142:3::e]) by eggs.gnu.org with esmtps (TLS1.2:ECDHE_RSA_AES_256_GCM_SHA384:256) (Exim 4.90_1) (envelope-from <ludo@HIDDEN>) id 1tlt7C-0004y3-LW; Sat, 22 Feb 2025 12:16:35 -0500 DKIM-Signature: v=1; a=rsa-sha256; q=dns/txt; c=relaxed/relaxed; d=gnu.org; s=fencepost-gnu-org; h=MIME-Version:Date:References:In-Reply-To:Subject:To: From; bh=93p/wijZCltWRHsCv26oQzngS7PAiwmHE8iVY9MAJnw=; b=DPXv0GQV1q1+nlh5CrCw zjkKn+pL8Z3rAmIYrIGzo/gYsIfNRoHhIEVs3TS1JCGr5scigh1Z1HMpR7juMK2Mfbr3UIrOPZ6w9 +xrHugyRIJr+tUy2GtAlQOl7sUe+VPO1VPs/wuHm7TSuqHUC10D0K98y0gZSj6TBjvw4rpp5+Icv2 Y3e6XgDvUHwWtqQu3YG74NJfDf10kY2V8OdxjJvlS3oSe6YvkXOKhxmNnNznCuDGoiqmNtXQNdfDX juJ/4Lx1vMpA9p2gCryJlRyFbYz9Sei3VkY0BtE5LvnNrgphIrZklyvMzDJBdNRgy1b3xq6ataic/ yPyibXareiU78A==; From: =?utf-8?Q?Ludovic_Court=C3=A8s?= <ludo@HIDDEN> To: Simon Tournier <zimon.toutoune@HIDDEN> Subject: Re: [bug#75810] [PATCH v3 00/11] Rootless guix-daemon In-Reply-To: <87jz9jrzfo.fsf@HIDDEN> (Simon Tournier's message of "Fri, 21 Feb 2025 18:16:11 +0100") References: <cover.1737738362.git.ludo@HIDDEN> <cover.1740142328.git.ludo@HIDDEN> <87jz9jrzfo.fsf@HIDDEN> Date: Sat, 22 Feb 2025 18:16:17 +0100 Message-ID: <87y0xx528u.fsf@HIDDEN> User-Agent: Gnus/5.13 (Gnus v5.13) MIME-Version: 1.0 Content-Type: text/plain; charset=utf-8 Content-Transfer-Encoding: quoted-printable X-Spam-Score: -2.3 (--) X-Debbugs-Envelope-To: 75810 Cc: Reepca Russelstein <reepca@HIDDEN>, 75810 <at> debbugs.gnu.org X-BeenThere: debbugs-submit <at> debbugs.gnu.org X-Mailman-Version: 2.1.18 Precedence: list List-Id: <debbugs-submit.debbugs.gnu.org> List-Unsubscribe: <https://debbugs.gnu.org/cgi-bin/mailman/options/debbugs-submit>, <mailto:debbugs-submit-request <at> debbugs.gnu.org?subject=unsubscribe> List-Archive: <https://debbugs.gnu.org/cgi-bin/mailman/private/debbugs-submit/> List-Post: <mailto:debbugs-submit <at> debbugs.gnu.org> List-Help: <mailto:debbugs-submit-request <at> debbugs.gnu.org?subject=help> List-Subscribe: <https://debbugs.gnu.org/cgi-bin/mailman/listinfo/debbugs-submit>, <mailto:debbugs-submit-request <at> debbugs.gnu.org?subject=subscribe> Errors-To: debbugs-submit-bounces <at> debbugs.gnu.org Sender: "Debbugs-submit" <debbugs-submit-bounces <at> debbugs.gnu.org> X-Spam-Score: -3.3 (---) Hi, Simon Tournier <zimon.toutoune@HIDDEN> skribis: > Quoting Janneke [1]: > > I'm kind of afraid that having a writable /gnu/store, even if it'= s just > on foreign distributions, This problem is fixed in v3: the store will be remounted readonly as is currently the case. > Could you clarify the status about the store when running guix-daemon as > root on foreign distros? Or maybe now, will guix-daemon always run as a > regular user on foreign distros? As currently written, guix-daemon will always run as non-root on foreign distros (on systemd-based distros specifically.) >>From an user perspective, instead of running guix-daemon as root, now > guix-daemon will run as the regular user named =E2=80=99guix-daemon=E2=80= =99 without any > special privileges, right? Correct. > User still need root privileges once at guix-install.sh time but not > more. Therefore, for updating the guix-daemon, the user guix-daemon > needs to run =E2=80=9Cguix pull=E2=80=9C and restart the service, right? The upgrade procedure remains unchanged: you would run =E2=80=98guix pull= =E2=80=99 as root and restart the service=C2=B9 (the service itself runs as user =E2=80=98guix-daemon=E2=80=99). > If yes, cool! It=E2=80=99ll be a booster for cluster sysadmins. :-) Yup! Ludo=E2=80=99. =C2=B9 https://guix.gnu.org/manual/devel/en/html_node/Upgrading-Guix.html
guix-patches@HIDDEN
:bug#75810
; Package guix-patches
.
Full text available.Received: (at 75810) by debbugs.gnu.org; 22 Feb 2025 17:12:27 +0000 From debbugs-submit-bounces <at> debbugs.gnu.org Sat Feb 22 12:12:27 2025 Received: from localhost ([127.0.0.1]:57053 helo=debbugs.gnu.org) by debbugs.gnu.org with esmtp (Exim 4.84_2) (envelope-from <debbugs-submit-bounces <at> debbugs.gnu.org>) id 1tlt3D-0002HS-0x for submit <at> debbugs.gnu.org; Sat, 22 Feb 2025 12:12:27 -0500 Received: from eggs.gnu.org ([2001:470:142:3::10]:49484) by debbugs.gnu.org with esmtps (TLS1.2:ECDHE_RSA_AES_256_GCM_SHA384:256) (Exim 4.84_2) (envelope-from <ludo@HIDDEN>) id 1tlt3B-0002HE-Dh for 75810 <at> debbugs.gnu.org; Sat, 22 Feb 2025 12:12:25 -0500 Received: from fencepost.gnu.org ([2001:470:142:3::e]) by eggs.gnu.org with esmtps (TLS1.2:ECDHE_RSA_AES_256_GCM_SHA384:256) (Exim 4.90_1) (envelope-from <ludo@HIDDEN>) id 1tlt35-0004Rr-6M; Sat, 22 Feb 2025 12:12:19 -0500 DKIM-Signature: v=1; a=rsa-sha256; q=dns/txt; c=relaxed/relaxed; d=gnu.org; s=fencepost-gnu-org; h=MIME-Version:Date:References:In-Reply-To:Subject:To: From; bh=5cjo95l86nd1K4e4k9NumfJx11LJzndQq/hGA/b5JvU=; b=jcaHzHeZgpheHRTgYndC 2GSLogP9vBekiCs1/aMK91TOsfLRVtnwCRAxuODmuJm2oFDU2d3jSrtUJ5wdBjhRU9vXErajAn9Qo xEqTavOcPpcw/8EJjFCriLN/kI0xiJ5wmO8C6Lm8Z/dfb1Nq1A/5JiapIP1KE/YF5U//Rz9n7zqx5 nouoDIttk7e/6vnWtLdsJNns2aodJC7qOmDqe1eJojmfiq0KbZ2wG323Rmq1GWz3iR0N9HHVFg0TF RobiBNf7EE9ygYwtVCGv3cbhuK8oMXaFhQuzl+L49c4BS4+VWJ79icExEy3H6A8DHh5UbJIFl1YE1 3fh3+5Aj/CYEEA==; From: =?utf-8?Q?Ludovic_Court=C3=A8s?= <ludo@HIDDEN> To: 75810 <at> debbugs.gnu.org Subject: Re: [bug#75810] [PATCH v3 00/11] Rootless guix-daemon In-Reply-To: <cover.1740142328.git.ludo@HIDDEN> ("Ludovic =?utf-8?Q?Court?= =?utf-8?Q?=C3=A8s=22's?= message of "Fri, 21 Feb 2025 14:05:48 +0100") References: <cover.1737738362.git.ludo@HIDDEN> <cover.1740142328.git.ludo@HIDDEN> Date: Sat, 22 Feb 2025 18:12:02 +0100 Message-ID: <87bjut6h0d.fsf@HIDDEN> User-Agent: Gnus/5.13 (Gnus v5.13) MIME-Version: 1.0 Content-Type: text/plain; charset=utf-8 Content-Transfer-Encoding: quoted-printable X-Spam-Score: -2.3 (--) X-Debbugs-Envelope-To: 75810 Cc: Reepca Russelstein <reepca@HIDDEN> X-BeenThere: debbugs-submit <at> debbugs.gnu.org X-Mailman-Version: 2.1.18 Precedence: list List-Id: <debbugs-submit.debbugs.gnu.org> List-Unsubscribe: <https://debbugs.gnu.org/cgi-bin/mailman/options/debbugs-submit>, <mailto:debbugs-submit-request <at> debbugs.gnu.org?subject=unsubscribe> List-Archive: <https://debbugs.gnu.org/cgi-bin/mailman/private/debbugs-submit/> List-Post: <mailto:debbugs-submit <at> debbugs.gnu.org> List-Help: <mailto:debbugs-submit-request <at> debbugs.gnu.org?subject=help> List-Subscribe: <https://debbugs.gnu.org/cgi-bin/mailman/listinfo/debbugs-submit>, <mailto:debbugs-submit-request <at> debbugs.gnu.org?subject=subscribe> Errors-To: debbugs-submit-bounces <at> debbugs.gnu.org Sender: "Debbugs-submit" <debbugs-submit-bounces <at> debbugs.gnu.org> X-Spam-Score: -3.3 (---) Ludovic Court=C3=A8s <ludo@HIDDEN> skribis: > Next up: > > =E2=80=A2 automating =E2=80=98guix-install.sh=E2=80=99 VM tests; Done in <https://issues.guix.gnu.org/76488>. Ludo=E2=80=99.
guix-patches@HIDDEN
:bug#75810
; Package guix-patches
.
Full text available.Received: (at 75810) by debbugs.gnu.org; 21 Feb 2025 22:40:35 +0000 From debbugs-submit-bounces <at> debbugs.gnu.org Fri Feb 21 17:40:35 2025 Received: from localhost ([127.0.0.1]:39347 helo=debbugs.gnu.org) by debbugs.gnu.org with esmtp (Exim 4.84_2) (envelope-from <debbugs-submit-bounces <at> debbugs.gnu.org>) id 1tlbhC-0001Z4-Dg for submit <at> debbugs.gnu.org; Fri, 21 Feb 2025 17:40:35 -0500 Received: from mailout.russelstein.xyz ([2605:6400:20:11e::1]:57488) by debbugs.gnu.org with esmtps (TLS1.2:ECDHE_RSA_AES_256_GCM_SHA384:256) (Exim 4.84_2) (envelope-from <reepca@HIDDEN>) id 1tlbh7-0001YI-Th for 75810 <at> debbugs.gnu.org; Fri, 21 Feb 2025 17:40:32 -0500 DKIM-Signature: v=1; a=ed25519-sha256; q=dns/txt; c=relaxed/relaxed; d=russelstein.xyz; s=ed25519; h=Content-Type:MIME-Version:Message-ID:Date: References:In-Reply-To:Subject:Cc:To:From:Sender:Reply-To: Content-Transfer-Encoding:Content-ID:Content-Description:Resent-Date: Resent-From:Resent-Sender:Resent-To:Resent-Cc:Resent-Message-ID:List-Id: List-Help:List-Unsubscribe:List-Subscribe:List-Post:List-Owner:List-Archive; bh=SsnJXQ0ht6+cyqyTRUUPcTTDXlJZAsrADpoyaQny70M=; b=NIEt2dIj2EFmSa3aWOvu4/W+4H KtIf0VLY1avfHy4slAPxWlNK2yHKY7icf2XZRn59UmXuoH1P2BSdya7WmJCQ==; DKIM-Signature: v=1; a=rsa-sha256; q=dns/txt; c=relaxed/relaxed; d=russelstein.xyz; s=rsa; h=Content-Type:MIME-Version:Message-ID:Date: References:In-Reply-To:Subject:Cc:To:From:Sender:Reply-To: Content-Transfer-Encoding:Content-ID:Content-Description:Resent-Date: Resent-From:Resent-Sender:Resent-To:Resent-Cc:Resent-Message-ID:List-Id: List-Help:List-Unsubscribe:List-Subscribe:List-Post:List-Owner:List-Archive; bh=SsnJXQ0ht6+cyqyTRUUPcTTDXlJZAsrADpoyaQny70M=; b=irQ3vcwv7z6avneQPEpcL3evuY o/3csLTkyTEw29X1Otf6YKIH6/kGKZnbb+Wu66BC0m+BpvJiTpLXu2EBt+CY2+YpB3c46qO5wlRxA U21XYhzQy/zXjJcoc0pGYdZLDCiFKDgUJnec7xJSGPpXYGz71D2NqFgx6w66KxrRXIKlssWInzENw bgzguKZ6QPTbsoTk4ntufB1HOO/ZeP9qHE5t8sjEty17Sb6XOOTRGUS1c86d1kPX2FTP13d2bdEnn UT5WYF2dxLTOOhKgZ+axdH22fIe3Oj8zkr8hlpDvthxhXHKXFSdsWIaP1yL6EFYndfXd/yl4NZoSH W2N5Nd/cffJDPuEns0KmSTksY7hfbEMb2w4Id/HLJZ+EMHGC9d76da12ZEaGdd2MVQ24Of0ELkSVy OIX7uoFjclbIWIKl3nHaVCByLlj2w4lbgf3gxD9Sf+Y6o/PXcgrWEQs3+HZ0FQ8KWs++3yK9FgSU/ yi0vKLjpAAuX64JjSI+zOTOu3Q2Xo1Sxn6p6ERSHwTaD00m+4jaU7RfMpODirSryCk8E4/lMmB6yo peYXEzJWxLCtpG59dsXevCWdf15UQw5S0s7jgTFVK5LxFNcLxQWoe96CdfTLclcsgG9wKiNXpfga5 k0KI+qiyfz9dOPzKec8XRA5FhL0DwlkBdgXq29qz8=; Received: by russelstein.xyz with esmtpsa (TLS1.3:ECDHE_SECP256R1__RSA_PSS_RSAE_SHA256__AES_256_GCM:256) (Exim 4.98) (envelope-from <reepca@HIDDEN>) id 1tlbh0-000000002hm-40Xu; Fri, 21 Feb 2025 16:40:25 -0600 From: Reepca Russelstein <reepca@HIDDEN> To: Ludovic =?utf-8?Q?Court=C3=A8s?= <ludo@HIDDEN> Subject: Re: [PATCH v3 00/11] Rootless guix-daemon In-Reply-To: <cover.1740142328.git.ludo@HIDDEN> ("Ludovic =?utf-8?Q?Court?= =?utf-8?Q?=C3=A8s=22's?= message of "Fri, 21 Feb 2025 14:05:48 +0100") References: <cover.1740142328.git.ludo@HIDDEN> Date: Fri, 21 Feb 2025 16:39:06 -0600 Message-ID: <877c5idit1.fsf@HIDDEN> User-Agent: Gnus/5.13 (Gnus v5.13) MIME-Version: 1.0 Content-Type: multipart/signed; boundary="=-=-="; micalg=pgp-sha256; protocol="application/pgp-signature" X-Spam-Score: 0.5 X-Spam-Bar: / X-Spam-Score-Int: 5 X-Spam-Report: Spam detection software, running on the system "Sanctum", has NOT identified this incoming email as spam. The original message has been attached to this so you can view it or label similar future email. If you have any questions, see the administrator of that system for details. Content preview: Ludovic Courtès <ludo@HIDDEN> writes: > Hello! > > Here’s an updated version, addressing most issues brought up > by Reepca, also available from > <https://codeberg.org/civodul/guix/src/branch/wip-rootless-daemon>. > Main changes compar [...] Content analysis details: (0.5 points, 5.0 required) pts rule name description ---- ---------------------- -------------------------------------------------- -0.0 NO_RELAYS Informational: message was not relayed via SMTP 0.5 FROM_SUSPICIOUS_NTLD From abused NTLD X-Spam-Score: 0.5 (/) X-Debbugs-Envelope-To: 75810 Cc: 75810 <at> debbugs.gnu.org X-BeenThere: debbugs-submit <at> debbugs.gnu.org X-Mailman-Version: 2.1.18 Precedence: list List-Id: <debbugs-submit.debbugs.gnu.org> List-Unsubscribe: <https://debbugs.gnu.org/cgi-bin/mailman/options/debbugs-submit>, <mailto:debbugs-submit-request <at> debbugs.gnu.org?subject=unsubscribe> List-Archive: <https://debbugs.gnu.org/cgi-bin/mailman/private/debbugs-submit/> List-Post: <mailto:debbugs-submit <at> debbugs.gnu.org> List-Help: <mailto:debbugs-submit-request <at> debbugs.gnu.org?subject=help> List-Subscribe: <https://debbugs.gnu.org/cgi-bin/mailman/listinfo/debbugs-submit>, <mailto:debbugs-submit-request <at> debbugs.gnu.org?subject=subscribe> Errors-To: debbugs-submit-bounces <at> debbugs.gnu.org Sender: "Debbugs-submit" <debbugs-submit-bounces <at> debbugs.gnu.org> X-Spam-Score: 0.5 (/) --=-=-= Content-Type: text/plain; charset=utf-8 Content-Transfer-Encoding: quoted-printable Ludovic Court=C3=A8s <ludo@HIDDEN> writes: > Hello! > > Here=E2=80=99s an updated version, addressing most issues brought up > by Reepca, also available from > <https://codeberg.org/civodul/guix/src/branch/wip-rootless-daemon>. > Main changes compared to v2: > > =E2=80=A2 Derivation inputs and / are mounted read-only; additional > tests check the ability to write to these, to /tmp, to > /dev/{full,null}, and to remount any of these as read-write. > > =E2=80=A2 Unit files for systemd tweaked so that (1) guix-daemon sees > a private read-write mount of the store, and (2) gnu-store.mount > actually remounts the store read-only after guix-daemon has > started. I'm not familiar with how systemd does service dependencies, but does this mean that the store becomes writable when the daemon is stopped? > > =E2=80=A2 =E2=80=98DerivationGoal::deleteTmpDir=E2=80=99 bails out when= it fails to > chown =E2=80=98tmpDir=E2=80=99 (i.e., it does not try to =E2=80=9Cpiv= ot=E2=80=9D the /top > sub-directory). > > Did I forget anything, Reepca? I believe that if you try a "--keep-failed" build that fails in the CAP_CHOWN case, you'll find that only root or the guix-daemon user can delete the kept build directory, though the user that started the build can delete everything inside it. This is because in that case the build directory was chown'ed back to guix-daemon so that it could be moved, but wasn't chown'ed to the client user afterward. If I recall correctly there was code included to perform this extra chown in the (getuid() !=3D 0) case in the v2 series - was it accidentally forgotten? Also, there are potential issues with how wide the scope of the try block in DerivationGoal::deleteTmpDir is - _chown isn't the only place within it that can raise a SysError, and there are failure modes present that may merit more user attention than lvlInfo. For example, if rename((pivot + "/top").c_str(), top.c_str()) fails (which can be rather easily arranged by a local attacker), then the build directory path reported in the "note: keeping build directory" message remains up for grabs by anyone. If the user doesn't go out of their way to verify that the build directory isn't attacker-controlled, they could be rather easily tricked into executing malicious code. But currently the exception from this rename failing will be turned into a lvlInfo message, and I'm not sure how that interacts with the verbosity defaults in the various CLI programs. This does somewhat raise the question of why we're even doing the pivoting in a way that creates a window during which failure can be induced. For example, we could move the inner build directory to the pivot path, at which point the outer build directory should become empty, so it should work to then rename the pivot path to the outer build directory path, thereby atomically replacing it. Also, in the unprivileged case (non-root, no CAP_CHOWN), the build directory never gets pivoted out. This is better for security than the previous situation (which allowed setuid programs to be exposed), but it should be quite doable to simply secure the file permissions first and then carry on with the pivot. I believe I previously mentioned perhaps using secureFilePerms to do this? It may work well to use the v2 patch for this with a call to secureFilePerms added right before the try block and a have_cap_chown boolean flag being saved for later recall after the pivot instead of the (getuid() !=3D 0) check. That way in the fully-unprivileged case it doesn't successfully pivot the now-sanitized build directory only to immediately fail to chown it. Actually, because that chown call doesn't result in an exception on failure, it would also work to only add the secureFilePerms call. Also, I've discovered that while mount(2) uses EPERM for both a locked mount point and insufficient privileges, umount(2) uses EINVAL for the former and EPERM for the latter. This may be a good way to test that we're triggering the mount-locking behavior as intended. > The one observable difference compared to current guix-daemon > operational mode is that, in the build environment, writing to > the root file system results in EROFS instead of EPERM, as you > pointed out earlier. That=E2=80=99s not great but probably acceptable. > We=E2=80=99ll only know whether this is a problem in practice once we=E2= =80=99ve > run the test suites of tens of thousands of packages. Strictly speaking, it's also observable that the root file system, store, /tmp, etc is not owned by uid 0, and that the input store items are all mounted read-only. =2D reepca --=-=-= Content-Type: application/pgp-signature; name="signature.asc" -----BEGIN PGP SIGNATURE----- iQFLBAEBCAA1FiEEdNapMPRLm4SepVYGwWaqSV9/GJwFAme5AIoXHHJlZXBjYUBy dXNzZWxzdGVpbi54eXoACgkQwWaqSV9/GJxgYwgAhCMl0Qtku5lc4mEsPXe8b9pV +yE3q1BYWa3Wbo4Cy9M5gYUG9l7R5jk1wRD7g7BZJAcN7IwbUwBzXpHVaRgBn81P ZrduzqK4I42w5PxSc8VU274uWVrHAHu8P6kvV+EKlQL1ooiMi7DhTytFNXlaiPEI nAgZJKiKxEfkvgTiAWDySuM7EDQ+CZ5CDn7k9bOsYJjeDqCW7CSIt3jhNz/Sltg8 3pijCCCa6sFSdxUVJd9wPPK+AulN3oMHz0JfWKPotsjKM2nSt+jwWXZIZwUvOyVo 2VNQ+gOqA8acA4vKFMcm6fZ2YNko0y/TJOn/vcKXmxU4lvzJPdmaBFZvztpsEQ== =zez6 -----END PGP SIGNATURE----- --=-=-=--
guix-patches@HIDDEN
:bug#75810
; Package guix-patches
.
Full text available.Received: (at 75810) by debbugs.gnu.org; 21 Feb 2025 19:23:45 +0000 From debbugs-submit-bounces <at> debbugs.gnu.org Fri Feb 21 14:23:45 2025 Received: from localhost ([127.0.0.1]:36346 helo=debbugs.gnu.org) by debbugs.gnu.org with esmtp (Exim 4.84_2) (envelope-from <debbugs-submit-bounces <at> debbugs.gnu.org>) id 1tlYce-0000Ci-GK for submit <at> debbugs.gnu.org; Fri, 21 Feb 2025 14:23:44 -0500 Received: from mail-wm1-x32f.google.com ([2a00:1450:4864:20::32f]:44148) by debbugs.gnu.org with esmtps (TLS1.2:ECDHE_RSA_AES_128_GCM_SHA256:128) (Exim 4.84_2) (envelope-from <zimon.toutoune@HIDDEN>) id 1tlYca-0000B6-4H for 75810 <at> debbugs.gnu.org; Fri, 21 Feb 2025 14:23:37 -0500 Received: by mail-wm1-x32f.google.com with SMTP id 5b1f17b1804b1-4399deda4bfso17513175e9.0 for <75810 <at> debbugs.gnu.org>; Fri, 21 Feb 2025 11:23:36 -0800 (PST) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=gmail.com; s=20230601; t=1740165810; x=1740770610; darn=debbugs.gnu.org; h=content-transfer-encoding:mime-version:message-id:date:references :in-reply-to:subject:cc:to:from:from:to:cc:subject:date:message-id :reply-to; bh=JL0cUwZOmt0vmc5SLP2va36BjzZij+khGE1JMcEia7Y=; b=JJ1ArDu91x6bNTrd52zOW0tdFzZ8tfS/H0od8S+ws201hPIwm25xwsjSAgGAKC0TFx +WhdbfrMv2KRjO9peWny16qpY2jYtRvS2lpRoE4RRllLa27o+dTbcg2eVg2P7jvoCFBe nrFzzsrKEey7jW1UqWFiZmvN9pNe+S7J5rOUEESfYMCMu0cSdIe4MVeAV34TA+W6GkyJ d9cMDp98GYecomexNUlNkPNlZyxgDtJmRJOd9K/k9txdg5NUogBaLXKMigK0A89HSFW2 rqzUJ8Rq8nDq/93GEZ5jmtW8gMEFdw3oOP2kbnBtdg3qyagiQksHhAzqWUBLY7XtyV6f Dr1Q== X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20230601; t=1740165810; x=1740770610; h=content-transfer-encoding:mime-version:message-id:date:references :in-reply-to:subject:cc:to:from:x-gm-message-state:from:to:cc :subject:date:message-id:reply-to; bh=JL0cUwZOmt0vmc5SLP2va36BjzZij+khGE1JMcEia7Y=; b=D8ZAJeKKWJy5IDwY6+VuDO6r7s2CaI8dVT//NC5tRRtYJ6Xy+hFpT1cOjkCb6dXMk7 rEZB3NdLlWAkfLi3rjuhM+yv8Buw1E3ckQODpLeXjMR7FG08WUxfV9hREAVZUJMbjtBI hdGJnapJBPB4O1K7iHu+v8Dy/li403mLNSsJypoqXtiX3OPqHyi9bBmK5VkYr4dQGq5v QC64ff1K9pkTuAqBKH7Fu8ZrKVrZwAauvZo8oIbtoUXUC00r12DJLtOCPRkkCZKXDCcl DwmOI6B5PNc7BH14i/a1zf4cc2zpKHoHXRRezhSnagJciE8sWbgQeuctrfy88Azij+s9 DvhQ== X-Forwarded-Encrypted: i=1; AJvYcCVokn6B9xQlX3vCE6RRNyNE/DCRTithPlePMoBE5MJYlNw1NcFzWckOo5a8FTX1f9vDu0jtcg==@debbugs.gnu.org X-Gm-Message-State: AOJu0Yx0rDfvfn2nNRIsfCq/bXyAsQT9+W1NNy/OE+VTxjkLWgyAvA6r LriXrU/TWS2e1TaSWSplkR9l/mL+MBRsAWkEdXA1/V9LBD/GZiyL X-Gm-Gg: ASbGncvwIeHAXIl8CpKmfLgu8uU9MTE1jYWQEyybYFh7OOy1oWvRcPIS95m6MQ3udPh O2EQA5cLaRdN81l4E8L4+4FpounfxNeG4OfXt/xWJPppHB/fm3VzZlgAm4/OAmPq4CRca27rYt+ VTjhEjMi7R1P8pr5TrDObGwYeg/tHGJqf3pA2vFfqI6AlNQnUdatAtC9/9x6VDzJeUEHt6vq3XZ 7V3HPEuhL68Y3eARI+SrE2CDAyBABXu1wp/MjPP4NLAdO5P7oC2evTlEcSzCjKsoKGCM5UoxBwH ImuoYZruq4KUfGvmQ+sm8kClHbyYgu32G2VhHMCjPTN6rG2ZXLCIboiEClSKta9PxdSYbsqZlSP zxTNG4Skm/0Y= X-Google-Smtp-Source: AGHT+IFeFkXLRdKR+T/ekjxFkaEwVCzDwYwhVR16zJ1Cw2uVVC5MFicMuwysKcofLctq0l/ChfNDoA== X-Received: by 2002:a05:600c:3c90:b0:439:a202:86dd with SMTP id 5b1f17b1804b1-439b155b048mr28876815e9.26.1740165809655; Fri, 21 Feb 2025 11:23:29 -0800 (PST) Received: from lili (roam-nat-fw-prg-194-254-61-45.net.univ-paris-diderot.fr. [194.254.61.45]) by smtp.gmail.com with ESMTPSA id 5b1f17b1804b1-4399be7ccfesm48968095e9.0.2025.02.21.11.23.28 (version=TLS1_3 cipher=TLS_AES_256_GCM_SHA384 bits=256/256); Fri, 21 Feb 2025 11:23:29 -0800 (PST) From: Simon Tournier <zimon.toutoune@HIDDEN> To: Ludovic =?utf-8?Q?Court=C3=A8s?= <ludo@HIDDEN>, 75810 <at> debbugs.gnu.org Subject: Re: [bug#75810] [PATCH v3 00/11] Rootless guix-daemon In-Reply-To: <cover.1740142328.git.ludo@HIDDEN> References: <cover.1737738362.git.ludo@HIDDEN> <cover.1740142328.git.ludo@HIDDEN> Date: Fri, 21 Feb 2025 18:16:11 +0100 Message-ID: <87jz9jrzfo.fsf@HIDDEN> MIME-Version: 1.0 Content-Type: text/plain; charset=utf-8 Content-Transfer-Encoding: quoted-printable X-Spam-Score: 0.0 (/) X-Debbugs-Envelope-To: 75810 Cc: Ludovic =?utf-8?Q?Court=C3=A8s?= <ludo@HIDDEN>, Reepca Russelstein <reepca@HIDDEN> X-BeenThere: debbugs-submit <at> debbugs.gnu.org X-Mailman-Version: 2.1.18 Precedence: list List-Id: <debbugs-submit.debbugs.gnu.org> List-Unsubscribe: <https://debbugs.gnu.org/cgi-bin/mailman/options/debbugs-submit>, <mailto:debbugs-submit-request <at> debbugs.gnu.org?subject=unsubscribe> List-Archive: <https://debbugs.gnu.org/cgi-bin/mailman/private/debbugs-submit/> List-Post: <mailto:debbugs-submit <at> debbugs.gnu.org> List-Help: <mailto:debbugs-submit-request <at> debbugs.gnu.org?subject=help> List-Subscribe: <https://debbugs.gnu.org/cgi-bin/mailman/listinfo/debbugs-submit>, <mailto:debbugs-submit-request <at> debbugs.gnu.org?subject=subscribe> Errors-To: debbugs-submit-bounces <at> debbugs.gnu.org Sender: "Debbugs-submit" <debbugs-submit-bounces <at> debbugs.gnu.org> X-Spam-Score: -1.0 (-) Hi Ludo, On Fri, 21 Feb 2025 at 14:05, Ludovic Court=C3=A8s <ludo@HIDDEN> wrote: > The one observable difference compared to current guix-daemon > operational mode is that, in the build environment, writing to > the root file system results in EROFS instead of EPERM, as you > pointed out earlier. That=E2=80=99s not great but probably acceptable. > We=E2=80=99ll only know whether this is a problem in practice once we=E2= =80=99ve > run the test suites of tens of thousands of packages. Clearly, I do not fully understand all the deep details of all the series. Quoting Janneke [1]: I'm kind of afraid that having a writable /gnu/store, even if it's = just on foreign distributions, is going to cause a whole lot of problems= /bug reports with people changing files in the store. When I came to gu= ix I ran it on Debian for a couple of months and I certainly changed fil= es in the store, even with the read-only mount hurdle, to "get stuff to build". Only later to realise that by doing so I was making things= much more difficult for myself. Hopefully I'm either misunderstanding this patch set, or else too pessimistict, and maybe other people aren't as stupid as I was when= I first came to Guix? I=E2=80=99m not sure to get what=E2=80=99s the answer now with the v3? Esp= ecially when connected to this other question: Will there be an option for users to choose betw= een a non-root guix-daemon or a read-only store? Where the answer, IIUC, is no. Could you clarify the status about the store when running guix-daemon as root on foreign distros? Or maybe now, will guix-daemon always run as a regular user on foreign distros? From an user perspective, instead of running guix-daemon as root, now guix-daemon will run as the regular user named =E2=80=99guix-daemon=E2=80= =99 without any special privileges, right? User still need root privileges once at guix-install.sh time but not more. Therefore, for updating the guix-daemon, the user guix-daemon needs to run =E2=80=9Cguix pull=E2=80=9C and restart the service, right? If yes, cool! It=E2=80=99ll be a booster for cluster sysadmins. :-) Cheers, simon 1: [bug#75810] [PATCH 0/6] Rootless guix-daemon Janneke Nieuwenhuizen <janneke@HIDDEN> Fri, 24 Jan 2025 20:20:42 +0100 id:87ikq49fxx.fsf@HIDDEN https://issues.guix.gnu.org/75810 https://issues.guix.gnu.org/msgid/87ikq49fxx.fsf@HIDDEN https://yhetil.org/guix/87ikq49fxx.fsf@HIDDEN
guix-patches@HIDDEN
:bug#75810
; Package guix-patches
.
Full text available.Received: (at 75810) by debbugs.gnu.org; 21 Feb 2025 13:09:45 +0000 From debbugs-submit-bounces <at> debbugs.gnu.org Fri Feb 21 08:09:45 2025 Received: from localhost ([127.0.0.1]:56713 helo=debbugs.gnu.org) by debbugs.gnu.org with esmtp (Exim 4.84_2) (envelope-from <debbugs-submit-bounces <at> debbugs.gnu.org>) id 1tlSmk-0005tL-HY for submit <at> debbugs.gnu.org; Fri, 21 Feb 2025 08:09:44 -0500 Received: from eggs.gnu.org ([2001:470:142:3::10]:60040) by debbugs.gnu.org with esmtps (TLS1.2:ECDHE_RSA_AES_256_GCM_SHA384:256) (Exim 4.84_2) (envelope-from <ludo@HIDDEN>) id 1tlSjt-0005OD-RP for 75810 <at> debbugs.gnu.org; Fri, 21 Feb 2025 08:07:02 -0500 Received: from fencepost.gnu.org ([2001:470:142:3::e]) by eggs.gnu.org with esmtps (TLS1.2:ECDHE_RSA_AES_256_GCM_SHA384:256) (Exim 4.90_1) (envelope-from <ludo@HIDDEN>) id 1tlSjn-0004Yz-Ia; Fri, 21 Feb 2025 08:06:39 -0500 DKIM-Signature: v=1; a=rsa-sha256; q=dns/txt; c=relaxed/relaxed; d=gnu.org; s=fencepost-gnu-org; h=MIME-Version:References:In-Reply-To:Date:Subject:To: From; bh=idfaYvTmznhqv9+JO9+QiD13YMv5X4U5zH6e+nqsgOA=; b=R8mrQ4mlW7XQGnsEkwbQ 0s5fR0rOxQAZqcb3y9C2swDIloNT4IJ/S+Se16uHsQSTA4Qg2rrM6kcwB3hI6gEOdUwDCdiweD9dN inarbhDvq/IszdaORra1+Rv6U8EWKdJG1PKiktE4VcFFmPwZX9Z4oAHYyTqXiH5OkAdlPt2q8ugU6 3kcM+iG+WrrFnXh/JEzQyqLoIoW1O12krwoNAgYlSxcaCRU8yBWqIfOz4f2yo4UwSFEESoRVj9B7q LDybhvqvH56EPOK3dV3ufSy0aYFKVXUPSBzJUlWpn4U6+MPD18hXJDUpqhkKW5UXLSOE+L9TyAyVf 05ixn7KlXYlrxA==; From: =?UTF-8?q?Ludovic=20Court=C3=A8s?= <ludo@HIDDEN> To: 75810 <at> debbugs.gnu.org Subject: [PATCH v3 05/11] daemon: Allow running as non-root with unprivileged user namespaces. Date: Fri, 21 Feb 2025 14:05:53 +0100 Message-ID: <1f4adc1c09dde70b193e1571b250e6152f0b4ca2.1740142328.git.ludo@HIDDEN> X-Mailer: git-send-email 2.48.1 In-Reply-To: <cover.1740142328.git.ludo@HIDDEN> References: <cover.1740142328.git.ludo@HIDDEN> MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 X-Debbugs-Cc: Christopher Baines <guix@HIDDEN>, Josselin Poiret <dev@HIDDEN>, Ludovic Courtès <ludo@HIDDEN>, Mathieu Othacehe <othacehe@HIDDEN>, Simon Tournier <zimon.toutoune@HIDDEN>, Tobias Geerinckx-Rice <me@HIDDEN> Content-Transfer-Encoding: 8bit X-Spam-Score: -2.3 (--) X-Debbugs-Envelope-To: 75810 Cc: =?UTF-8?q?Ludovic=20Court=C3=A8s?= <ludovic.courtes@HIDDEN> X-BeenThere: debbugs-submit <at> debbugs.gnu.org X-Mailman-Version: 2.1.18 Precedence: list List-Id: <debbugs-submit.debbugs.gnu.org> List-Unsubscribe: <https://debbugs.gnu.org/cgi-bin/mailman/options/debbugs-submit>, <mailto:debbugs-submit-request <at> debbugs.gnu.org?subject=unsubscribe> List-Archive: <https://debbugs.gnu.org/cgi-bin/mailman/private/debbugs-submit/> List-Post: <mailto:debbugs-submit <at> debbugs.gnu.org> List-Help: <mailto:debbugs-submit-request <at> debbugs.gnu.org?subject=help> List-Subscribe: <https://debbugs.gnu.org/cgi-bin/mailman/listinfo/debbugs-submit>, <mailto:debbugs-submit-request <at> debbugs.gnu.org?subject=subscribe> Errors-To: debbugs-submit-bounces <at> debbugs.gnu.org Sender: "Debbugs-submit" <debbugs-submit-bounces <at> debbugs.gnu.org> X-Spam-Score: -3.3 (---) From: Ludovic Courtès <ludovic.courtes@HIDDEN> * nix/libstore/build.cc (guestUID, guestGID): New variables. (DerivationGoal)[readiness]: New field. (initializeUserNamespace): New function. (DerivationGoal::runChild): When ‘readiness.readSide’ is positive, read from it. (DerivationGoal::startBuilder): Call ‘chown’ only when ‘buildUser.enabled()’ is true. Pass CLONE_NEWUSER to ‘clone’ when ‘buildUser.enabled()’ is false or not running as root. Retry ‘clone’ without CLONE_NEWUSER upon EPERM. (DerivationGoal::registerOutputs): Make ‘actualPath’ writable before ‘rename’. (DerivationGoal::deleteTmpDir): Catch ‘SysError’ around ‘_chown’ call. * nix/libstore/local-store.cc (LocalStore::createUser): Do nothing if ‘dirs’ already exists. Warn instead of failing when failing to chown ‘dir’. * guix/substitutes.scm (%narinfo-cache-directory): Check for ‘_NIX_OPTIONS’ rather than getuid() == 0 to determine the cache location. Change-Id: I38fbe01f80fb45a99cd8a391e55a39a54d64fcb7 --- guix/substitutes.scm | 4 +- nix/libstore/build.cc | 149 ++++++++++++++++++++++++++++-------- nix/libstore/local-store.cc | 22 ++++-- 3 files changed, 135 insertions(+), 40 deletions(-) diff --git a/guix/substitutes.scm b/guix/substitutes.scm index e31b3940203..2761a3dafb4 100644 --- a/guix/substitutes.scm +++ b/guix/substitutes.scm @@ -1,5 +1,5 @@ ;;; GNU Guix --- Functional package management for GNU -;;; Copyright © 2013-2021, 2023-2024 Ludovic Courtès <ludo@HIDDEN> +;;; Copyright © 2013-2021, 2023-2025 Ludovic Courtès <ludo@HIDDEN> ;;; Copyright © 2014 Nikita Karetnikov <nikita@HIDDEN> ;;; Copyright © 2018 Kyle Meyer <kyle@HIDDEN> ;;; Copyright © 2020 Christopher Baines <mail@HIDDEN> @@ -76,7 +76,7 @@ (define %narinfo-cache-directory ;; time, 'guix substitute' is called by guix-daemon as root and stores its ;; cached data in /var/guix/…. However, when invoked from 'guix challenge' ;; as a user, it stores its cache in ~/.cache. - (if (zero? (getuid)) + (if (getenv "_NIX_OPTIONS") ;invoked by guix-daemon (or (and=> (getenv "XDG_CACHE_HOME") (cut string-append <> "/guix/substitute")) (string-append %state-directory "/substitute/cache")) diff --git a/nix/libstore/build.cc b/nix/libstore/build.cc index c87f4f767c5..107ffcfea06 100644 --- a/nix/libstore/build.cc +++ b/nix/libstore/build.cc @@ -747,6 +747,10 @@ private: friend int childEntry(void *); + /* Pipe to notify readiness to the child process when using unprivileged + user namespaces. */ + Pipe readiness; + /* Check that the derivation outputs all exist and register them as valid. */ void registerOutputs(); @@ -1622,6 +1626,25 @@ int childEntry(void * arg) } +/* UID and GID of the build user inside its own user namespace. */ +static const uid_t guestUID = 30001; +static const gid_t guestGID = 30000; + +/* Initialize the user namespace of CHILD. */ +static void initializeUserNamespace(pid_t child) +{ + auto hostUID = getuid(); + auto hostGID = getgid(); + + writeFile("/proc/" + std::to_string(child) + "/uid_map", + (format("%d %d 1") % guestUID % hostUID).str()); + + writeFile("/proc/" + std::to_string(child) + "/setgroups", "deny"); + + writeFile("/proc/" + std::to_string(child) + "/gid_map", + (format("%d %d 1") % guestGID % hostGID).str()); +} + void DerivationGoal::startBuilder() { auto f = format( @@ -1685,7 +1708,7 @@ void DerivationGoal::startBuilder() then an attacker could create in it a hardlink to a root-owned file such as /etc/shadow. If 'keepFailed' is true, the daemon would then chown that hardlink to the user, giving them write access to - that file. */ + that file. See CVE-2021-27851. */ tmpDir += "/top"; if (mkdir(tmpDir.c_str(), 0700) == 1) throw SysError("creating top-level build directory"); @@ -1802,7 +1825,7 @@ void DerivationGoal::startBuilder() if (mkdir(chrootRootDir.c_str(), 0750) == -1) throw SysError(format("cannot create ‘%1%’") % chrootRootDir); - if (chown(chrootRootDir.c_str(), 0, buildUser.getGID()) == -1) + if (buildUser.enabled() && chown(chrootRootDir.c_str(), 0, buildUser.getGID()) == -1) throw SysError(format("cannot change ownership of ‘%1%’") % chrootRootDir); /* Create a writable /tmp in the chroot. Many builders need @@ -1821,8 +1844,8 @@ void DerivationGoal::startBuilder() (format( "nixbld:x:%1%:%2%:Nix build user:/:/noshell\n" "nobody:x:65534:65534:Nobody:/:/noshell\n") - % (buildUser.enabled() ? buildUser.getUID() : getuid()) - % (buildUser.enabled() ? buildUser.getGID() : getgid())).str()); + % (buildUser.enabled() ? buildUser.getUID() : guestUID) + % (buildUser.enabled() ? buildUser.getGID() : guestGID)).str()); /* Declare the build user's group so that programs get a consistent view of the system (e.g., "id -gn"). */ @@ -1857,7 +1880,7 @@ void DerivationGoal::startBuilder() createDirs(chrootStoreDir); chmod_(chrootStoreDir, 01775); - if (chown(chrootStoreDir.c_str(), 0, buildUser.getGID()) == -1) + if (buildUser.enabled() && chown(chrootStoreDir.c_str(), 0, buildUser.getGID()) == -1) throw SysError(format("cannot change ownership of ‘%1%’") % chrootStoreDir); foreach (PathSet::iterator, i, inputPaths) { @@ -1948,14 +1971,34 @@ void DerivationGoal::startBuilder() if (useChroot) { char stack[32 * 1024]; int flags = CLONE_NEWPID | CLONE_NEWNS | CLONE_NEWIPC | CLONE_NEWUTS | SIGCHLD; - if (!fixedOutput) flags |= CLONE_NEWNET; + if (!fixedOutput) { + flags |= CLONE_NEWNET; + } + if (!buildUser.enabled() || getuid() != 0) { + flags |= CLONE_NEWUSER; + readiness.create(); + } + /* Ensure proper alignment on the stack. On aarch64, it has to be 16 bytes. */ - pid = clone(childEntry, + pid = clone(childEntry, (char *)(((uintptr_t)stack + sizeof(stack) - 8) & ~(uintptr_t)0xf), flags, this); - if (pid == -1) - throw SysError("cloning builder process"); + if (pid == -1) { + if ((flags & CLONE_NEWUSER) != 0 && getuid() != 0) + /* 'clone' fails with EPERM on distros where unprivileged user + namespaces are disabled. Error out instead of giving up on + isolation. */ + throw SysError("cannot create process in unprivileged user namespace"); + else + throw SysError("cloning builder process"); + } + + if ((flags & CLONE_NEWUSER) != 0) { + /* Initialize the UID/GID mapping of the child process. */ + initializeUserNamespace(pid); + writeFull(readiness.writeSide, (unsigned char*)"go\n", 3); + } } else #endif { @@ -2001,23 +2044,34 @@ void DerivationGoal::runChild() _writeToStderr = 0; + if (readiness.readSide > 0) { + /* Wait for the parent process to initialize the UID/GID mapping + of our user namespace. */ + char str[20] = { '\0' }; + readFull(readiness.readSide, (unsigned char*)str, 3); + if (strcmp(str, "go\n") != 0) + throw Error("failed to initialize process in unprivileged user namespace"); + } + restoreAffinity(); commonChildInit(builderOut); #if CHROOT_ENABLED if (useChroot) { - /* Initialise the loopback interface. */ - AutoCloseFD fd(socket(PF_INET, SOCK_DGRAM, IPPROTO_IP)); - if (fd == -1) throw SysError("cannot open IP socket"); + if (!fixedOutput) { + /* Initialise the loopback interface. */ + AutoCloseFD fd(socket(PF_INET, SOCK_DGRAM, IPPROTO_IP)); + if (fd == -1) throw SysError("cannot open IP socket"); - struct ifreq ifr; - strcpy(ifr.ifr_name, "lo"); - ifr.ifr_flags = IFF_UP | IFF_LOOPBACK | IFF_RUNNING; - if (ioctl(fd, SIOCSIFFLAGS, &ifr) == -1) - throw SysError("cannot set loopback interface flags"); + struct ifreq ifr; + strcpy(ifr.ifr_name, "lo"); + ifr.ifr_flags = IFF_UP | IFF_LOOPBACK | IFF_RUNNING; + if (ioctl(fd, SIOCSIFFLAGS, &ifr) == -1) + throw SysError("cannot set loopback interface flags"); - fd.close(); + fd.close(); + } /* Set the hostname etc. to fixed values. */ char hostname[] = "localhost"; @@ -2463,8 +2517,16 @@ void DerivationGoal::registerOutputs() 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) { + if (S_ISDIR(st.st_mode)) + /* Change mode on the directory to allow for + rename(2). */ + chmod(actualPath.c_str(), st.st_mode | 0700); + if (rename(actualPath.c_str(), path.c_str()) == -1) + throw SysError(format("moving build output `%1%' from the chroot to the store") % path); + if (S_ISDIR(st.st_mode) && chmod(path.c_str(), st.st_mode) == -1) + throw SysError(format("restoring permissions on directory `%1%'") % actualPath); + } } if (buildMode != bmCheck) actualPath = path; } @@ -2723,17 +2785,42 @@ void DerivationGoal::deleteTmpDir(bool force) // Change the ownership if clientUid is set. Never change the // ownership or the group to "root" for security reasons. if (settings.clientUid != (uid_t) -1 && settings.clientUid != 0) { - _chown(tmpDir, settings.clientUid, - settings.clientGid != 0 ? settings.clientGid : -1); - - if (top != tmpDir) { - // Rename tmpDir to its parent, with an intermediate step. - string pivot = top + ".pivot"; - if (rename(top.c_str(), pivot.c_str()) == -1) - throw SysError("pivoting failed build tree"); - if (rename((pivot + "/top").c_str(), top.c_str()) == -1) - throw SysError("renaming failed build tree"); - rmdir(pivot.c_str()); + uid_t uid = settings.clientUid; + gid_t gid = settings.clientGid != 0 ? settings.clientGid : -1; + try { + _chown(tmpDir, uid, gid); + + if (getuid() != 0) { + /* If, without being root, the '_chown' call above + succeeded, then it means we have CAP_CHOWN. Retake + ownership of tmpDir itself so it can be renamed + below. */ + chown(tmpDir.c_str(), getuid(), getgid()); + } + + if (top != tmpDir) { + /* Rename 'tmpDir' to its parent with an intermediate + step. Skip that if the '_chown' call above fails + since in that case the setuid bits are not + removed. */ + string pivot = top + ".pivot"; + if (rename(top.c_str(), pivot.c_str()) == -1) + throw SysError("pivoting failed build tree"); + if (rename((pivot + "/top").c_str(), top.c_str()) == -1) + throw SysError("renaming failed build tree"); + + if (getuid() != 0) + /* Running unprivileged but with CAP_CHOWN. */ + chown(top.c_str(), uid, gid); + + rmdir(pivot.c_str()); + } + } catch (SysError & e) { + /* When running as an unprivileged user and without + CAP_CHOWN, we cannot chown the build tree. Print a + message and keep going. */ + printMsg(lvlInfo, format("cannot change ownership of build directory '%1%': %2%") + % tmpDir % strerror(e.errNo)); } } } diff --git a/nix/libstore/local-store.cc b/nix/libstore/local-store.cc index 0883a4bbcee..4308264a4f3 100644 --- a/nix/libstore/local-store.cc +++ b/nix/libstore/local-store.cc @@ -306,14 +306,14 @@ void LocalStore::openDB(bool create) void LocalStore::makeStoreWritable() { #if HAVE_UNSHARE && HAVE_STATVFS && HAVE_SYS_MOUNT_H && defined(MS_BIND) && defined(MS_REMOUNT) - if (getuid() != 0) return; /* Check if /nix/store is on a read-only mount. */ struct statvfs stat; if (statvfs(settings.nixStore.c_str(), &stat) != 0) throw SysError("getting info about the store mount point"); if (stat.f_flag & ST_RDONLY) { - if (unshare(CLONE_NEWNS) == -1) + int flags = CLONE_NEWNS | (getpid() == 0 ? 0 : CLONE_NEWUSER); + if (unshare(flags) == -1) throw SysError("setting up a private mount namespace"); if (mount(0, settings.nixStore.c_str(), "none", MS_REMOUNT | MS_BIND, 0) == -1) @@ -1614,11 +1614,19 @@ void LocalStore::createUser(const std::string & userName, uid_t userId) { auto dir = settings.nixStateDir + "/profiles/per-user/" + userName; - createDirs(dir); - if (chmod(dir.c_str(), 0755) == -1) - throw SysError(format("changing permissions of directory '%s'") % dir); - if (chown(dir.c_str(), userId, -1) == -1) - throw SysError(format("changing owner of directory '%s'") % dir); + auto created = createDirs(dir); + if (!created.empty()) { + if (chmod(dir.c_str(), 0755) == -1) + throw SysError(format("changing permissions of directory '%s'") % dir); + + /* The following operation requires CAP_CHOWN or can be handled + manually by a user with CAP_CHOWN. */ + if (chown(dir.c_str(), userId, -1) == -1) { + rmdir(dir.c_str()); + string message = strerror(errno); + printMsg(lvlInfo, format("failed to change owner of directory '%1%' to %2%: %3%") % dir % userId % message); + } + } } -- 2.48.1
guix@HIDDEN, dev@HIDDEN, ludo@HIDDEN, othacehe@HIDDEN, zimon.toutoune@HIDDEN, me@HIDDEN, guix-patches@HIDDEN
:bug#75810
; Package guix-patches
.
Full text available.Received: (at 75810) by debbugs.gnu.org; 21 Feb 2025 13:09:42 +0000 From debbugs-submit-bounces <at> debbugs.gnu.org Fri Feb 21 08:09:42 2025 Received: from localhost ([127.0.0.1]:56710 helo=debbugs.gnu.org) by debbugs.gnu.org with esmtp (Exim 4.84_2) (envelope-from <debbugs-submit-bounces <at> debbugs.gnu.org>) id 1tlSmj-0005tC-Mq for submit <at> debbugs.gnu.org; Fri, 21 Feb 2025 08:09:42 -0500 Received: from eggs.gnu.org ([2001:470:142:3::10]:49138) by debbugs.gnu.org with esmtps (TLS1.2:ECDHE_RSA_AES_256_GCM_SHA384:256) (Exim 4.84_2) (envelope-from <ludo@HIDDEN>) id 1tlSmA-0005mF-77 for 75810 <at> debbugs.gnu.org; Fri, 21 Feb 2025 08:09:07 -0500 Received: from fencepost.gnu.org ([2001:470:142:3::e]) by eggs.gnu.org with esmtps (TLS1.2:ECDHE_RSA_AES_256_GCM_SHA384:256) (Exim 4.90_1) (envelope-from <ludo@HIDDEN>) id 1tlSm2-0004pv-Ap; Fri, 21 Feb 2025 08:08:59 -0500 DKIM-Signature: v=1; a=rsa-sha256; q=dns/txt; c=relaxed/relaxed; d=gnu.org; s=fencepost-gnu-org; h=MIME-Version:Date:References:In-Reply-To:Subject:To: From; bh=SM53dgQb3S15KqJEJPeKID9PBkjwc6++/HEHo6BgAm4=; b=cCgsrIgYo7ersm6W2csN VM8iHXeU0YvA6zLoGe7K5o0iGxYVfh5V8XTUw4Hf7I510Kj/cFcpUSZgk5E0iM/vpum73+uRzSVbf wQYPzsXbvI84DY2FZkLkv9C8vYacOxPG4A7uL1u2wfrZdkQOpm2xkcbp0rZuMCibHiZloOmbKoeYc 4sCPCnltk9Z3ITv7OsxTDToA0vT+z2xhQ0GchCz2zRwrkLDY2kWfUxq1hL1EyLsfldodBbIR69YIg 6huuTbwnAGRxuuQFdYN2Zvs5C5BiW1BQFzyJ6RDl6wG0K9NOz+TI+74KywJFCI4Ks1BwGOSN+9kWm lPgmWA4cDgC2Nw==; From: =?utf-8?Q?Ludovic_Court=C3=A8s?= <ludo@HIDDEN> To: Reepca Russelstein <reepca@HIDDEN> Subject: Re: [bug#75810] Remounting the store read-write for guix-daemon In-Reply-To: <87h64sldip.fsf_-_@HIDDEN> ("Ludovic =?utf-8?Q?Court=C3=A8s?= =?utf-8?Q?=22's?= message of "Mon, 17 Feb 2025 17:52:30 +0100") References: <cover.1737738362.git.ludo@HIDDEN> <87r04qe7dj.fsf@HIDDEN> <87bjvshrk0.fsf@HIDDEN> <87h64sldip.fsf_-_@HIDDEN> Date: Fri, 21 Feb 2025 14:08:50 +0100 Message-ID: <87ikp38mxp.fsf@HIDDEN> User-Agent: Gnus/5.13 (Gnus v5.13) MIME-Version: 1.0 Content-Type: text/plain; charset=utf-8 Content-Transfer-Encoding: quoted-printable X-Spam-Score: -2.3 (--) X-Debbugs-Envelope-To: 75810 Cc: 75810 <at> debbugs.gnu.org X-BeenThere: debbugs-submit <at> debbugs.gnu.org X-Mailman-Version: 2.1.18 Precedence: list List-Id: <debbugs-submit.debbugs.gnu.org> List-Unsubscribe: <https://debbugs.gnu.org/cgi-bin/mailman/options/debbugs-submit>, <mailto:debbugs-submit-request <at> debbugs.gnu.org?subject=unsubscribe> List-Archive: <https://debbugs.gnu.org/cgi-bin/mailman/private/debbugs-submit/> List-Post: <mailto:debbugs-submit <at> debbugs.gnu.org> List-Help: <mailto:debbugs-submit-request <at> debbugs.gnu.org?subject=help> List-Subscribe: <https://debbugs.gnu.org/cgi-bin/mailman/listinfo/debbugs-submit>, <mailto:debbugs-submit-request <at> debbugs.gnu.org?subject=subscribe> Errors-To: debbugs-submit-bounces <at> debbugs.gnu.org Sender: "Debbugs-submit" <debbugs-submit-bounces <at> debbugs.gnu.org> X-Spam-Score: -3.3 (---) Ludovic Court=C3=A8s <ludovic.courtes@HIDDEN> skribis: > Second option: > > BindPaths=3D/gnu/store > > =E2=80=A6 but that does essentially nothing, and we can=E2=80=99t specify= that we want > =E2=80=9Cremount,rw=E2=80=9D. Actually, adding =E2=80=9CBefore=3Dgnu-store.mount=E2=80=9D does the trick;= I implemented that in v3. Ludo=E2=80=99.
guix-patches@HIDDEN
:bug#75810
; Package guix-patches
.
Full text available.Received: (at 75810) by debbugs.gnu.org; 21 Feb 2025 13:09:41 +0000 From debbugs-submit-bounces <at> debbugs.gnu.org Fri Feb 21 08:09:41 2025 Received: from localhost ([127.0.0.1]:56708 helo=debbugs.gnu.org) by debbugs.gnu.org with esmtp (Exim 4.84_2) (envelope-from <debbugs-submit-bounces <at> debbugs.gnu.org>) id 1tlSmg-0005sj-9n for submit <at> debbugs.gnu.org; Fri, 21 Feb 2025 08:09:41 -0500 Received: from eggs.gnu.org ([2001:470:142:3::10]:43390) by debbugs.gnu.org with esmtps (TLS1.2:ECDHE_RSA_AES_256_GCM_SHA384:256) (Exim 4.84_2) (envelope-from <ludo@HIDDEN>) id 1tlSk3-0005QC-UL for 75810 <at> debbugs.gnu.org; Fri, 21 Feb 2025 08:07:09 -0500 Received: from fencepost.gnu.org ([2001:470:142:3::e]) by eggs.gnu.org with esmtps (TLS1.2:ECDHE_RSA_AES_256_GCM_SHA384:256) (Exim 4.90_1) (envelope-from <ludo@HIDDEN>) id 1tlSjy-0004a2-0g; Fri, 21 Feb 2025 08:06:50 -0500 DKIM-Signature: v=1; a=rsa-sha256; q=dns/txt; c=relaxed/relaxed; d=gnu.org; s=fencepost-gnu-org; h=MIME-Version:References:In-Reply-To:Date:Subject:To: From; bh=PwQDQer/23CkjUsQpvDtFSJfseycr+nkoov1zPm6lbc=; b=KV09Clz6tU49fox7TU4Y fngjYCoQngCKnFkWBQXee1JogmZsLLUSyhfhpXj0SaLXqKLeJjiJbak9Zssba2l6U9RyGnIsFuqVn 5IF2FD+FugWxeBqex8D7UWPJL2IWLDikHEf6Lbcevxc5tapwduVohls6vyCln7pq7Z1zzFSgTYBXN a+YpIoBQ6QV1Xmn5EKv67CG8zHmkxt+G9V6sCcWy1h64y1bnFpxzhFhcjraAvMk4FqIfstpxhe5pl L7Q+If3/g0gDKxMMOa2UHW1GCkt3hHBYo8bgwJ31LYIUkBSxy64xF1ogxfRh4GqIBT9KT/Q8o4OpR n4QcRxqM4Kuh5w==; From: =?UTF-8?q?Ludovic=20Court=C3=A8s?= <ludo@HIDDEN> To: 75810 <at> debbugs.gnu.org Subject: [PATCH v3 11/11] guix-install.sh: Support the unprivileged daemon where possible. Date: Fri, 21 Feb 2025 14:05:59 +0100 Message-ID: <bd7e1c6c599a505c4be0ee001f27bb6d9a973b5a.1740142328.git.ludo@HIDDEN> X-Mailer: git-send-email 2.48.1 In-Reply-To: <cover.1740142328.git.ludo@HIDDEN> References: <cover.1740142328.git.ludo@HIDDEN> MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit X-Spam-Score: -2.3 (--) X-Debbugs-Envelope-To: 75810 Cc: =?UTF-8?q?Ludovic=20Court=C3=A8s?= <ludo@HIDDEN> X-BeenThere: debbugs-submit <at> debbugs.gnu.org X-Mailman-Version: 2.1.18 Precedence: list List-Id: <debbugs-submit.debbugs.gnu.org> List-Unsubscribe: <https://debbugs.gnu.org/cgi-bin/mailman/options/debbugs-submit>, <mailto:debbugs-submit-request <at> debbugs.gnu.org?subject=unsubscribe> List-Archive: <https://debbugs.gnu.org/cgi-bin/mailman/private/debbugs-submit/> List-Post: <mailto:debbugs-submit <at> debbugs.gnu.org> List-Help: <mailto:debbugs-submit-request <at> debbugs.gnu.org?subject=help> List-Subscribe: <https://debbugs.gnu.org/cgi-bin/mailman/listinfo/debbugs-submit>, <mailto:debbugs-submit-request <at> debbugs.gnu.org?subject=subscribe> Errors-To: debbugs-submit-bounces <at> debbugs.gnu.org Sender: "Debbugs-submit" <debbugs-submit-bounces <at> debbugs.gnu.org> X-Spam-Score: -3.3 (---) * etc/guix-install.sh (create_account): New function. (sys_create_build_user): Use it. When ‘guix-daemon.service’ contains “User=guix-daemon” only create the ‘guix-daemon’ user and group. (sys_delete_build_user): Delete the ‘guix-daemon’ user and group. (can_install_unprivileged_daemon): New function. (sys_create_store): When installing the unprivileged daemon, change ownership of /gnu and /var/guix, and create /var/log/guix. (sys_authorize_build_farms): When the ‘guix-daemon’ account exists, change ownership of /etc/guix. Change-Id: I73e573f1cc5c0cb3794aaaa6b576616b66e0c5e9 --- etc/guix-install.sh | 108 ++++++++++++++++++++++++++++++++++---------- 1 file changed, 84 insertions(+), 24 deletions(-) diff --git a/etc/guix-install.sh b/etc/guix-install.sh index 22d54c0c832..c6f0812b5cf 100755 --- a/etc/guix-install.sh +++ b/etc/guix-install.sh @@ -390,6 +390,11 @@ sys_create_store() cd "$tmp_path" _msg "${INF}Installing /var/guix and /gnu..." # Strip (skip) the leading ‘.’ component, which fails on read-only ‘/’. + # + # TODO: Eventually extract with ‘--owner=guix-daemon’ when installing + # and unprivileged guix-daemon service; for now, this script may install + # from both an old release that does not support unprivileged guix-daemon + # and a new release that does, so ‘chown -R’ later if needed. tar --extract --strip-components=1 --file "$pkg" -C / _msg "${INF}Linking the root user's profile" @@ -415,38 +420,82 @@ sys_delete_store() rm -rf ~root/.config/guix } +create_account() +{ + local user="$1" + local group="$2" + local supplementary_groups="$3" + local comment="$4" + + if id "$user" &>/dev/null; then + _msg "${INF}user '$user' is already in the system, reset" + usermod -g "$group" -G "$supplementary_groups" \ + -d /var/empty -s "$(which nologin)" \ + -c "$comment" "$user" + else + useradd -g "$group" -G "$supplementary_groups" \ + -d /var/empty -s "$(which nologin)" \ + -c "$comment" --system "$user" + _msg "${PAS}user added <$user>" + fi +} + +can_install_unprivileged_daemon() +{ # Return true if we can install guix-daemon running without privileges. + [ "$INIT_SYS" = systemd ] && \ + grep -q "User=guix-daemon" \ + ~root/.config/guix/current/lib/systemd/system/guix-daemon.service \ + && ([ ! -f /proc/sys/kernel/unprivileged_userns_clone ] \ + || [ "$(cat /proc/sys/kernel/unprivileged_userns_clone)" -eq 1 ]) +} + sys_create_build_user() { # Create the group and user accounts for build users. _debug "--- [ ${FUNCNAME[0]} ] ---" - if getent group guixbuild > /dev/null; then - _msg "${INF}group guixbuild exists" - else - groupadd --system guixbuild - _msg "${PAS}group <guixbuild> created" - fi - if getent group kvm > /dev/null; then _msg "${INF}group kvm exists and build users will be added to it" local KVMGROUP=,kvm fi - for i in $(seq -w 1 10); do - if id "guixbuilder${i}" &>/dev/null; then - _msg "${INF}user is already in the system, reset" - usermod -g guixbuild -G guixbuild${KVMGROUP} \ - -d /var/empty -s "$(which nologin)" \ - -c "Guix build user $i" \ - "guixbuilder${i}"; - else - useradd -g guixbuild -G guixbuild${KVMGROUP} \ - -d /var/empty -s "$(which nologin)" \ - -c "Guix build user $i" --system \ - "guixbuilder${i}"; - _msg "${PAS}user added <guixbuilder${i}>" - fi - done + if [ "$INIT_SYS" = systemd ] && \ + grep -q "User=guix-daemon" \ + ~root/.config/guix/current/lib/systemd/system/guix-daemon.service + then + if getent group guix-daemon > /dev/null; then + _msg "${INF}group guix-daemon exists" + else + groupadd --system guix-daemon + _msg "${PAS}group guix-daemon created" + fi + + create_account guix-daemon guix-daemon \ + guix-daemon$KVMGROUP \ + "Unprivileged Guix Daemon User" + + # ‘tar xf’ creates root:root files. Change that. + chown -R guix-daemon:guix-daemon \ + /gnu /var/guix + + # The unprivileged cannot create the log directory by itself. + mkdir /var/log/guix + chown guix-daemon:guix-daemon /var/log/guix + chmod 755 /var/log/guix + else + if getent group guixbuild > /dev/null; then + _msg "${INF}group guixbuild exists" + else + groupadd --system guixbuild + _msg "${PAS}group <guixbuild> created" + fi + + for i in $(seq -w 1 10); do + create_account "guixbuilder${i}" "guixbuild" \ + "guixbuild${KVMGROUP}" \ + "Guix build user $i" + done + fi } sys_delete_build_user() @@ -461,6 +510,14 @@ sys_delete_build_user() if getent group guixbuild &>/dev/null; then groupdel -f guixbuild fi + + _msg "${INF}remove guix-daemon user" + if id guix-daemon &>/dev/null; then + userdel -f guix-daemon + fi + if getent group guix-daemon &>/dev/null; then + groupdel -f guix-daemon + fi } sys_enable_guix_daemon() @@ -503,8 +560,7 @@ sys_enable_guix_daemon() # Install after guix-daemon.service to avoid a harmless warning. # systemd .mount units must be named after the target directory. - # Here we assume a hard-coded name of /gnu/store. - install_unit gnu-store.mount + install_unit gnu-store.mount systemctl daemon-reload && systemctl start guix-daemon; } && @@ -628,6 +684,10 @@ project's build farms?"; then && guix archive --authorize < "$key" \ && _msg "${PAS}Authorized public key for $host" done + if id guix-daemon &>/dev/null; then + # /etc/guix/acl must be readable by the unprivileged guix-daemon. + chown -R guix-daemon:guix-daemon /etc/guix + fi else _msg "${INF}Skipped authorizing build farm public keys" fi -- 2.48.1
guix-patches@HIDDEN
:bug#75810
; Package guix-patches
.
Full text available.Received: (at 75810) by debbugs.gnu.org; 21 Feb 2025 13:09:13 +0000 From debbugs-submit-bounces <at> debbugs.gnu.org Fri Feb 21 08:09:13 2025 Received: from localhost ([127.0.0.1]:56701 helo=debbugs.gnu.org) by debbugs.gnu.org with esmtp (Exim 4.84_2) (envelope-from <debbugs-submit-bounces <at> debbugs.gnu.org>) id 1tlSmF-0005oS-1C for submit <at> debbugs.gnu.org; Fri, 21 Feb 2025 08:09:13 -0500 Received: from eggs.gnu.org ([2001:470:142:3::10]:60070) by debbugs.gnu.org with esmtps (TLS1.2:ECDHE_RSA_AES_256_GCM_SHA384:256) (Exim 4.84_2) (envelope-from <ludo@HIDDEN>) id 1tlSk1-0005PX-6T for 75810 <at> debbugs.gnu.org; Fri, 21 Feb 2025 08:07:06 -0500 Received: from fencepost.gnu.org ([2001:470:142:3::e]) by eggs.gnu.org with esmtps (TLS1.2:ECDHE_RSA_AES_256_GCM_SHA384:256) (Exim 4.90_1) (envelope-from <ludo@HIDDEN>) id 1tlSjv-0004Zn-Kv; Fri, 21 Feb 2025 08:06:47 -0500 DKIM-Signature: v=1; a=rsa-sha256; q=dns/txt; c=relaxed/relaxed; d=gnu.org; s=fencepost-gnu-org; h=MIME-Version:References:In-Reply-To:Date:Subject:To: From; bh=fWWXPGKmocenmkwm2NuKznHSEy4eXcjP6Tuf4/xJCg8=; b=auRDK2ruMfc5RD6arP5j uAoAGuI/i8HBtnCV1YMc+pHZhD50PWpZL0Cd+6NfC9sjY7+bE0PaTiHYa40V91ebluZPd+S1gEr+x 7nRLF0HGI3R/3fXmVz/KAId8u141GkMc850QccaCLIFCvh79glR+ufs+Wljfo+YBAkCroLLHckpaX emo25BEufl6UYHmRBeWyCMF6F2/GOKc8WCKf0SAd0mxOUlmozJUnTwFC+WrosnzpegcPgvfUDSGCJ zrTfrniVZJixMEvB4hMS0ptlaVUb2ENXOOdGkHvMarwP8HnsilQLz//bgq/oeSI8kjr0sNbLcGyCN 74i2NoInvcaevQ==; From: =?UTF-8?q?Ludovic=20Court=C3=A8s?= <ludo@HIDDEN> To: 75810 <at> debbugs.gnu.org Subject: [PATCH v3 10/11] =?UTF-8?q?etc:=20systemd=20services:=20Run=20?= =?UTF-8?q?=E2=80=98guix-daemon=E2=80=99=20as=20an=20unprivileged=20user.?= Date: Fri, 21 Feb 2025 14:05:58 +0100 Message-ID: <32992bd69bfc6c3ff386c67ccfc2edeeb9fe7fd4.1740142328.git.ludo@HIDDEN> X-Mailer: git-send-email 2.48.1 In-Reply-To: <cover.1740142328.git.ludo@HIDDEN> References: <cover.1740142328.git.ludo@HIDDEN> MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit X-Spam-Score: -2.3 (--) X-Debbugs-Envelope-To: 75810 Cc: =?UTF-8?q?Ludovic=20Court=C3=A8s?= <ludo@HIDDEN> X-BeenThere: debbugs-submit <at> debbugs.gnu.org X-Mailman-Version: 2.1.18 Precedence: list List-Id: <debbugs-submit.debbugs.gnu.org> List-Unsubscribe: <https://debbugs.gnu.org/cgi-bin/mailman/options/debbugs-submit>, <mailto:debbugs-submit-request <at> debbugs.gnu.org?subject=unsubscribe> List-Archive: <https://debbugs.gnu.org/cgi-bin/mailman/private/debbugs-submit/> List-Post: <mailto:debbugs-submit <at> debbugs.gnu.org> List-Help: <mailto:debbugs-submit-request <at> debbugs.gnu.org?subject=help> List-Subscribe: <https://debbugs.gnu.org/cgi-bin/mailman/listinfo/debbugs-submit>, <mailto:debbugs-submit-request <at> debbugs.gnu.org?subject=subscribe> Errors-To: debbugs-submit-bounces <at> debbugs.gnu.org Sender: "Debbugs-submit" <debbugs-submit-bounces <at> debbugs.gnu.org> X-Spam-Score: -3.3 (---) * etc/guix-daemon.service.in (ExecStart): Remove ‘--build-users-group’. (Before, User, AmbientCapabilities, PrivateMounts, BindPaths): New fields. * etc/gnu-store.mount.in (Before): Remove. (WantedBy): Change to ‘multi-user.target’. Change-Id: Id826b8ab535844b6024d777f6bd15fd49db6d65e --- etc/gnu-store.mount.in | 3 +-- etc/guix-daemon.service.in | 20 +++++++++++++++++++- 2 files changed, 20 insertions(+), 3 deletions(-) diff --git a/etc/gnu-store.mount.in b/etc/gnu-store.mount.in index c94f2db72be..f9918c9e52e 100644 --- a/etc/gnu-store.mount.in +++ b/etc/gnu-store.mount.in @@ -2,10 +2,9 @@ Description=Read-only @storedir@ for GNU Guix DefaultDependencies=no ConditionPathExists=@storedir@ -Before=guix-daemon.service [Install] -WantedBy=guix-daemon.service +WantedBy=multi-user.target [Mount] What=@storedir@ diff --git a/etc/guix-daemon.service.in b/etc/guix-daemon.service.in index 5c43d9b7f1b..a04cf1f2f0f 100644 --- a/etc/guix-daemon.service.in +++ b/etc/guix-daemon.service.in @@ -5,11 +5,29 @@ [Unit] Description=Build daemon for GNU Guix +# Start before 'gnu-store.mount' to get a writable view of the store. +Before=gnu-store.mount + [Service] ExecStart=@localstatedir@/guix/profiles/per-user/root/current-guix/bin/guix-daemon \ - --build-users-group=guixbuild --discover=no \ + --discover=no \ --substitute-urls='@GUIX_SUBSTITUTE_URLS@' Environment='GUIX_LOCPATH=@localstatedir@/guix/profiles/per-user/root/guix-profile/lib/locale' LC_ALL=en_US.utf8 + +# Run under a dedicated unprivileged user account. +User=guix-daemon + +# Bind-mount the store read-write in a private namespace, to counter the +# effect of 'gnu-store.mount'. +PrivateMounts=true +BindPaths=@storedir@ + +# Provide the CAP_CHOWN capability so that guix-daemon cran create and chown +# /var/guix/profiles/per-user/$USER and also chown failed build directories +# when using '--keep-failed'. Note that guix-daemon explicitly drops ambient +# capabilities before executing build processes so they don't inherit them. +AmbientCapabilities=CAP_CHOWN + StandardOutput=journal StandardError=journal -- 2.48.1
guix-patches@HIDDEN
:bug#75810
; Package guix-patches
.
Full text available.Received: (at 75810) by debbugs.gnu.org; 21 Feb 2025 13:09:11 +0000 From debbugs-submit-bounces <at> debbugs.gnu.org Fri Feb 21 08:09:11 2025 Received: from localhost ([127.0.0.1]:56699 helo=debbugs.gnu.org) by debbugs.gnu.org with esmtp (Exim 4.84_2) (envelope-from <debbugs-submit-bounces <at> debbugs.gnu.org>) id 1tlSmC-0005o8-UZ for submit <at> debbugs.gnu.org; Fri, 21 Feb 2025 08:09:10 -0500 Received: from eggs.gnu.org ([2001:470:142:3::10]:60064) by debbugs.gnu.org with esmtps (TLS1.2:ECDHE_RSA_AES_256_GCM_SHA384:256) (Exim 4.84_2) (envelope-from <ludo@HIDDEN>) id 1tlSjz-0005PH-Re for 75810 <at> debbugs.gnu.org; Fri, 21 Feb 2025 08:07:04 -0500 Received: from fencepost.gnu.org ([2001:470:142:3::e]) by eggs.gnu.org with esmtps (TLS1.2:ECDHE_RSA_AES_256_GCM_SHA384:256) (Exim 4.90_1) (envelope-from <ludo@HIDDEN>) id 1tlSju-0004Zc-7k; Fri, 21 Feb 2025 08:06:46 -0500 DKIM-Signature: v=1; a=rsa-sha256; q=dns/txt; c=relaxed/relaxed; d=gnu.org; s=fencepost-gnu-org; h=MIME-Version:References:In-Reply-To:Date:Subject:To: From; bh=O9Cnga7box/1rcpw3VHiKXPbujUc92KmLXmRuqngb6k=; b=Udu5iZBOsTuJRHw4R6qH ZDFS4h8FKfsU+cwOvU48gwqFjUYnhfw7Y67b854brijWZ8Ab80CPJyB1Z0jkeXLuX1k0+3ABEVZwc 7po5z8NrKtsJ9XeMy1qid1Ck/QfeJt6jDq6Plx7XaUCNCmYcmUPBqpcV+Z+9G80sRhBa7L/avyKde 0p90m6lUtYcW7UvDCW45kuNIJdaNobxe0EgcKXi3Wdbt9WGQ0Fu9DXrtjUwyYLxcslVXfrfnSmR0X UHBxv7wcerNqL5SavyCZxmcH7BNn1jYxsEjJHaFTx9WDqFDA72xwNOVjj6q1wqdmUm8fnPjXXRwud WlfxrVUapjKQPg==; From: =?UTF-8?q?Ludovic=20Court=C3=A8s?= <ludo@HIDDEN> To: 75810 <at> debbugs.gnu.org Subject: [PATCH v3 09/11] daemon: Move comments where they belong. Date: Fri, 21 Feb 2025 14:05:57 +0100 Message-ID: <ec4bc30e61d57621813fe5a4a3ec6c4036a805eb.1740142328.git.ludo@HIDDEN> X-Mailer: git-send-email 2.48.1 In-Reply-To: <cover.1740142328.git.ludo@HIDDEN> References: <cover.1740142328.git.ludo@HIDDEN> MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit X-Spam-Score: -2.3 (--) X-Debbugs-Envelope-To: 75810 Cc: =?UTF-8?q?Ludovic=20Court=C3=A8s?= <ludo@HIDDEN> X-BeenThere: debbugs-submit <at> debbugs.gnu.org X-Mailman-Version: 2.1.18 Precedence: list List-Id: <debbugs-submit.debbugs.gnu.org> List-Unsubscribe: <https://debbugs.gnu.org/cgi-bin/mailman/options/debbugs-submit>, <mailto:debbugs-submit-request <at> debbugs.gnu.org?subject=unsubscribe> List-Archive: <https://debbugs.gnu.org/cgi-bin/mailman/private/debbugs-submit/> List-Post: <mailto:debbugs-submit <at> debbugs.gnu.org> List-Help: <mailto:debbugs-submit-request <at> debbugs.gnu.org?subject=help> List-Subscribe: <https://debbugs.gnu.org/cgi-bin/mailman/listinfo/debbugs-submit>, <mailto:debbugs-submit-request <at> debbugs.gnu.org?subject=subscribe> Errors-To: debbugs-submit-bounces <at> debbugs.gnu.org Sender: "Debbugs-submit" <debbugs-submit-bounces <at> debbugs.gnu.org> X-Spam-Score: -3.3 (---) * nix/libstore/build.cc (DerivationGoal::startBuilder): Shuffle comments for clarity. Change-Id: I6557c103ade4a3ab046354548ea193c68f8c9c05 --- nix/libstore/build.cc | 13 +++++++------ 1 file changed, 7 insertions(+), 6 deletions(-) diff --git a/nix/libstore/build.cc b/nix/libstore/build.cc index 213ed635933..c8a0667c7b5 100644 --- a/nix/libstore/build.cc +++ b/nix/libstore/build.cc @@ -1874,18 +1874,19 @@ void DerivationGoal::startBuilder() } dirsInChroot[tmpDirInSandbox] = tmpDir; - /* Make the closure of the inputs available in the chroot, - rather than the whole store. This prevents any access - to undeclared dependencies. !!! As an extra security - precaution, make the fake store only writable by the - build user. */ + /* Create the fake store. */ Path chrootStoreDir = chrootRootDir + settings.nixStore; createDirs(chrootStoreDir); chmod_(chrootStoreDir, 01775); if (buildUser.enabled() && chown(chrootStoreDir.c_str(), 0, buildUser.getGID()) == -1) - throw SysError(format("cannot change ownership of ‘%1%’") % chrootStoreDir); + /* As an extra security precaution, make the fake store only + writable by the build user. */ + throw SysError(format("cannot change ownership of ‘%1%’") % chrootStoreDir); + /* Make the closure of the inputs available in the chroot, rather than + the whole store. This prevents any access to undeclared + dependencies. */ foreach (PathSet::iterator, i, inputPaths) { dirsInChroot[*i] = *i; } -- 2.48.1
guix-patches@HIDDEN
:bug#75810
; Package guix-patches
.
Full text available.Received: (at 75810) by debbugs.gnu.org; 21 Feb 2025 13:08:51 +0000 From debbugs-submit-bounces <at> debbugs.gnu.org Fri Feb 21 08:08:50 2025 Received: from localhost ([127.0.0.1]:56691 helo=debbugs.gnu.org) by debbugs.gnu.org with esmtp (Exim 4.84_2) (envelope-from <debbugs-submit-bounces <at> debbugs.gnu.org>) id 1tlSlt-0005kT-17 for submit <at> debbugs.gnu.org; Fri, 21 Feb 2025 08:08:50 -0500 Received: from eggs.gnu.org ([2001:470:142:3::10]:60044) by debbugs.gnu.org with esmtps (TLS1.2:ECDHE_RSA_AES_256_GCM_SHA384:256) (Exim 4.84_2) (envelope-from <ludo@HIDDEN>) id 1tlSju-0005OH-5o for 75810 <at> debbugs.gnu.org; Fri, 21 Feb 2025 08:07:01 -0500 Received: from fencepost.gnu.org ([2001:470:142:3::e]) by eggs.gnu.org with esmtps (TLS1.2:ECDHE_RSA_AES_256_GCM_SHA384:256) (Exim 4.90_1) (envelope-from <ludo@HIDDEN>) id 1tlSjo-0004Z7-PQ; Fri, 21 Feb 2025 08:06:40 -0500 DKIM-Signature: v=1; a=rsa-sha256; q=dns/txt; c=relaxed/relaxed; d=gnu.org; s=fencepost-gnu-org; h=MIME-Version:References:In-Reply-To:Date:Subject:To: From; bh=x4qLkh9hJTZ4TkZolyQcxkgbw8cbkZm5cnTUmctXty8=; b=ktDtittoYnlV9w3J0Qp3 wT+5TAOUna0q4SyqB2cco3M8nNwxjh6mda4Hvn0HHhuecw9xSxnQiW5jBY6BF8X4UCVT+LVzzXnFd cY2wagPXDspLQ5gRnJrEl1J/d9dAUrymx5ywGUlctAOZvFme4+x/nwCL1QAOWAwrFo8Wfhjs3Lt58 ypTJ7FaGOu42hdXhZlD9vPmZ+ZT+0+BsnhNxguByjci86/xOswSsl/lVOijFUGkC4QGFW3kP/0IwD pEI01vjKLjZzkwB1sdwhX7oIGyW9Hi9Mw//4CXeLCqXKgEWSfDSlJ/oPSzAX+4/5mC9k6tlO1G1kn X5+qtEolwvFMeg==; From: =?UTF-8?q?Ludovic=20Court=C3=A8s?= <ludo@HIDDEN> To: 75810 <at> debbugs.gnu.org Subject: [PATCH v3 06/11] tests: Run in a chroot and unprivileged user namespaces. Date: Fri, 21 Feb 2025 14:05:54 +0100 Message-ID: <b97bc2f5d1a408c0f1007166f8654c03f11ca2c4.1740142328.git.ludo@HIDDEN> X-Mailer: git-send-email 2.48.1 In-Reply-To: <cover.1740142328.git.ludo@HIDDEN> References: <cover.1740142328.git.ludo@HIDDEN> MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit X-Spam-Score: -2.3 (--) X-Debbugs-Envelope-To: 75810 Cc: =?UTF-8?q?Ludovic=20Court=C3=A8s?= <ludo@HIDDEN> X-BeenThere: debbugs-submit <at> debbugs.gnu.org X-Mailman-Version: 2.1.18 Precedence: list List-Id: <debbugs-submit.debbugs.gnu.org> List-Unsubscribe: <https://debbugs.gnu.org/cgi-bin/mailman/options/debbugs-submit>, <mailto:debbugs-submit-request <at> debbugs.gnu.org?subject=unsubscribe> List-Archive: <https://debbugs.gnu.org/cgi-bin/mailman/private/debbugs-submit/> List-Post: <mailto:debbugs-submit <at> debbugs.gnu.org> List-Help: <mailto:debbugs-submit-request <at> debbugs.gnu.org?subject=help> List-Subscribe: <https://debbugs.gnu.org/cgi-bin/mailman/listinfo/debbugs-submit>, <mailto:debbugs-submit-request <at> debbugs.gnu.org?subject=subscribe> Errors-To: debbugs-submit-bounces <at> debbugs.gnu.org Sender: "Debbugs-submit" <debbugs-submit-bounces <at> debbugs.gnu.org> X-Spam-Score: -3.3 (---) * build-aux/test-env.in: Pass ‘--disable-chroot’ only when unprivileged user namespace support is lacking. * tests/store.scm ("build-things, check mode"): Use ‘gettimeofday’ rather than a shared file as a source of entropy. ("isolated environment", "inputs are read-only") ("inputs cannot be remounted read-write") ("build root cannot be made world-readable") ("/tmp, store, and /dev/{null,full} are writable"): New tests. * tests/processes.scm ("client + lock"): Skip when ‘unprivileged-user-namespace-supported?’ returns true. Change-Id: I3b3c3ebdf6db5fd36ee70251d07b893c17ca1b84 --- build-aux/test-env.in | 14 ++- tests/processes.scm | 9 +- tests/store.scm | 206 +++++++++++++++++++++++++++++++++++------- 3 files changed, 191 insertions(+), 38 deletions(-) diff --git a/build-aux/test-env.in b/build-aux/test-env.in index 9caa29da581..5626152b346 100644 --- a/build-aux/test-env.in +++ b/build-aux/test-env.in @@ -1,7 +1,7 @@ #!/bin/sh # GNU Guix --- Functional package management for GNU -# Copyright © 2012, 2013, 2014, 2015, 2016, 2017, 2018, 2019, 2021 Ludovic Courtès <ludo@HIDDEN> +# Copyright © 2012-2019, 2021, 2025 Ludovic Courtès <ludo@HIDDEN> # # This file is part of GNU Guix. # @@ -102,10 +102,20 @@ then rm -rf "$GUIX_STATE_DIRECTORY/daemon-socket" mkdir -m 0700 "$GUIX_STATE_DIRECTORY/daemon-socket" + # If unprivileged user namespaces are not supported, pass + # '--disable-chroot'. + if [ ! -f /proc/sys/kernel/unprivileged_userns_clone ] \ + || [ "$(cat /proc/sys/kernel/unprivileged_userns_clone)" -eq 1 ]; then + extra_options="" + else + extra_options="--disable-chroot" + fi + # Launch the daemon without chroot support because is may be # unavailable, for instance if we're not running as root. "@abs_top_builddir@/pre-inst-env" \ - "@abs_top_builddir@/guix-daemon" --disable-chroot \ + "@abs_top_builddir@/guix-daemon" \ + $extra_options \ --substitute-urls="$GUIX_BINARY_SUBSTITUTE_URL" & daemon_pid=$! diff --git a/tests/processes.scm b/tests/processes.scm index ba518f2d9e3..a72ba16f587 100644 --- a/tests/processes.scm +++ b/tests/processes.scm @@ -1,5 +1,5 @@ ;;; GNU Guix --- Functional package management for GNU -;;; Copyright © 2018 Ludovic Courtès <ludo@HIDDEN> +;;; Copyright © 2018, 2025 Ludovic Courtès <ludo@HIDDEN> ;;; Copyright © 2019 Mathieu Othacehe <m.othacehe@HIDDEN> ;;; ;;; This file is part of GNU Guix. @@ -25,6 +25,8 @@ (define-module (test-processes) #:use-module (guix gexp) #:use-module ((guix utils) #:select (call-with-temporary-directory)) #:use-module (gnu packages bootstrap) + #:use-module ((gnu build linux-container) + #:select (unprivileged-user-namespace-supported?)) #:use-module (guix tests) #:use-module (srfi srfi-1) #:use-module (srfi srfi-64) @@ -84,6 +86,11 @@ (define-syntax-rule (test-assert* description exp) (and (kill (process-id daemon) 0) (string-suffix? "guix-daemon" (first (process-command daemon))))))) +(when (unprivileged-user-namespace-supported?) + ;; The test below assumes the build process can communicate with the outside + ;; world via the TOKEN1 and TOKEN2 files, which is impossible when + ;; guix-daemon is set up to build in separate namespaces. + (test-skip 1)) (test-assert* "client + lock" (with-store store (call-with-temporary-directory diff --git a/tests/store.scm b/tests/store.scm index 45948f4f433..4ba0916e3fe 100644 --- a/tests/store.scm +++ b/tests/store.scm @@ -1,5 +1,5 @@ ;;; GNU Guix --- Functional package management for GNU -;;; Copyright © 2012-2021, 2023 Ludovic Courtès <ludo@HIDDEN> +;;; Copyright © 2012-2021, 2023, 2025 Ludovic Courtès <ludo@HIDDEN> ;;; ;;; This file is part of GNU Guix. ;;; @@ -28,8 +28,12 @@ (define-module (test-store) #:use-module (guix base32) #:use-module (guix packages) #:use-module (guix derivations) + #:use-module ((guix modules) + #:select (source-module-closure)) #:use-module (guix serialization) #:use-module (guix build utils) + #:use-module ((gnu build linux-container) + #:select (unprivileged-user-namespace-supported?)) #:use-module (guix gexp) #:use-module (gnu packages) #:use-module (gnu packages bootstrap) @@ -391,6 +395,147 @@ (define %shell (equal? (valid-derivers %store o) (list (derivation-file-name d)))))) +(unless (unprivileged-user-namespace-supported?) + (test-skip 1)) +(test-equal "isolated environment" + (string-join (append + '("PID: 1" "UID: 30001") + (delete-duplicates + (sort (list "/dev" "/tmp" "/proc" "/etc" + (match (string-tokenize (%store-prefix) + (char-set-complement + (char-set #\/))) + ((top _ ...) (string-append "/" top)))) + string<?)) + '("/etc/group" "/etc/hosts" "/etc/passwd"))) + (let* ((b (add-text-to-store %store "build.sh" + "echo -n PID: $$ UID: $UID /* /etc/* > $out")) + (s (add-to-store %store "bash" #t "sha256" + (search-bootstrap-binary "bash" + (%current-system)))) + (d (derivation %store "the-thing" + s `("-e" ,b) + #:env-vars `(("foo" . ,(random-text))) + #:sources (list b s))) + (o (derivation->output-path d))) + (and (build-derivations %store (list d)) + (call-with-input-file o get-string-all)))) + +(unless (unprivileged-user-namespace-supported?) + (test-skip 1)) +(test-equal "inputs are read-only" + "All good!" + (let* ((input (plain-file (string-append "might-be-tampered-with-" + (number->string + (car (gettimeofday)) + 16)) + "All good!")) + (drv + (run-with-store %store + (gexp->derivation + "attempt-to-remount-input-read-write" + (with-imported-modules (source-module-closure + '((guix build syscalls))) + #~(begin + (use-modules (guix build syscalls)) + + (let ((input #$input)) + (chmod input #o666) + (call-with-output-file input + (lambda (port) + (display "BAD!" port))) + (mkdir #$output)))))))) + (and (guard (c ((store-protocol-error? c) #t)) + (build-derivations %store (list drv))) + (call-with-input-file (run-with-store %store + (lower-object input)) + get-string-all)))) + +(unless (unprivileged-user-namespace-supported?) + (test-skip 1)) +(test-assert "inputs cannot be remounted read-write" + (let ((drv + (run-with-store %store + (gexp->derivation + "attempt-to-remount-input-read-write" + (with-imported-modules (source-module-closure + '((guix build syscalls))) + #~(begin + (use-modules (guix build syscalls)) + + (let ((input #$(plain-file "input-that-might-be-tampered-with" + "All good!"))) + (mount "none" input "none" (logior MS_BIND MS_REMOUNT)) + (call-with-output-file input + (lambda (port) + (display "BAD!" port))) + (mkdir #$output)))))))) + (guard (c ((store-protocol-error? c) #t)) + (build-derivations %store (list drv)) + #f))) + +(unless (unprivileged-user-namespace-supported?) + (test-skip 1)) +(test-assert "build root cannot be made world-readable" + (let ((drv + (run-with-store %store + (gexp->derivation + "attempt-to-make-root-world-readable" + (with-imported-modules (source-module-closure + '((guix build syscalls))) + #~(begin + (use-modules (guix build syscalls)) + + (let ((guile (string-append (assoc-ref %guile-build-info + 'bindir) + "/guile"))) + (catch 'system-error + (lambda () + (chmod "/" #o777)) + (lambda args + (format #t "failed to make root writable: ~a~%" + (strerror (system-error-errno args))) + (format #t "attempting read-write remount~%") + (mount "none" "/" "/" (logior MS_BIND MS_REMOUNT)) + (chmod "/" #o777))) + (copy-file guile "/guile") + (chmod "/guile" #o6755) + ;; At this point, there's a world-readable setuid 'guile' + ;; binary in the store that remains visible until this + ;; build completes. + (list #$output)))))))) + (guard (c ((store-protocol-error? c) #t)) + (build-derivations %store (list drv)) + #f))) + +(unless (unprivileged-user-namespace-supported?) + (test-skip 1)) +(test-assert "/tmp, store, and /dev/{null,full} are writable" + ;; All of /tmp and all of the store must be writable (the store is writable + ;; so that derivation outputs can be written to it, but in practice it's + ;; always been wide open). Things like /dev/null must be writable too. + (let ((drv (run-with-store %store + (gexp->derivation + "check-tmp-and-store-are-writable" + #~(begin + (mkdir "/tmp/something") + (mkdir (in-vicinity (getenv "NIX_STORE") + "some-other-thing")) + (call-with-output-file "/dev/null" + (lambda (port) + (display "Welcome to the void." port))) + (catch 'system-error + (lambda () + (call-with-output-file "/dev/full" + (lambda (port) + (display "No space left!" port))) + (error "Should have thrown!")) + (lambda args + (unless (= ENOSPC (system-error-errno args)) + (apply throw args)))) + (mkdir #$output)))))) + (build-derivations %store (list drv)))) + (test-equal "with-build-handler" 'success (let* ((b (add-text-to-store %store "build" "echo $foo > $out" '())) @@ -1333,40 +1478,31 @@ (define %shell (test-assert "build-things, check mode" (with-store store - (call-with-temporary-output-file - (lambda (entropy entropy-port) - (write (random-text) entropy-port) - (force-output entropy-port) - (let* ((drv (build-expression->derivation - store "non-deterministic" - `(begin - (use-modules (rnrs io ports)) - (let ((out (assoc-ref %outputs "out"))) - (call-with-output-file out - (lambda (port) - ;; Rely on the fact that tests do not use the - ;; chroot, and thus ENTROPY is readable. - (display (call-with-input-file ,entropy - get-string-all) - port))) - #t)) - #:guile-for-build - (package-derivation store %bootstrap-guile (%current-system)))) - (file (derivation->output-path drv))) - (and (build-things store (list (derivation-file-name drv))) - (begin - (write (random-text) entropy-port) - (force-output entropy-port) - (guard (c ((store-protocol-error? c) - (pk 'determinism-exception c) - (and (not (zero? (store-protocol-error-status c))) - (string-contains (store-protocol-error-message c) - "deterministic")))) - ;; This one will produce a different result. Since we're in - ;; 'check' mode, this must fail. - (build-things store (list (derivation-file-name drv)) - (build-mode check)) - #f)))))))) + (let* ((drv (build-expression->derivation + store "non-deterministic" + `(begin + (use-modules (rnrs io ports)) + (let ((out (assoc-ref %outputs "out"))) + (call-with-output-file out + (lambda (port) + (let ((now (gettimeofday))) + (display (+ (car now) (cdr now)) port)))) + #t)) + #:guile-for-build + (package-derivation store %bootstrap-guile (%current-system)))) + (file (derivation->output-path drv))) + (and (build-things store (list (derivation-file-name drv))) + (begin + (guard (c ((store-protocol-error? c) + (pk 'determinism-exception c) + (and (not (zero? (store-protocol-error-status c))) + (string-contains (store-protocol-error-message c) + "deterministic")))) + ;; This one will produce a different result. Since we're in + ;; 'check' mode, this must fail. + (build-things store (list (derivation-file-name drv)) + (build-mode check)) + #f)))))) (test-assert "build-succeeded trace in check mode" (string-contains -- 2.48.1
guix-patches@HIDDEN
:bug#75810
; Package guix-patches
.
Full text available.Received: (at 75810) by debbugs.gnu.org; 21 Feb 2025 13:08:49 +0000 From debbugs-submit-bounces <at> debbugs.gnu.org Fri Feb 21 08:08:49 2025 Received: from localhost ([127.0.0.1]:56688 helo=debbugs.gnu.org) by debbugs.gnu.org with esmtp (Exim 4.84_2) (envelope-from <debbugs-submit-bounces <at> debbugs.gnu.org>) id 1tlSls-0005kN-E7 for submit <at> debbugs.gnu.org; Fri, 21 Feb 2025 08:08:48 -0500 Received: from eggs.gnu.org ([2001:470:142:3::10]:60062) by debbugs.gnu.org with esmtps (TLS1.2:ECDHE_RSA_AES_256_GCM_SHA384:256) (Exim 4.84_2) (envelope-from <ludo@HIDDEN>) id 1tlSjy-0005P7-H9 for 75810 <at> debbugs.gnu.org; Fri, 21 Feb 2025 08:06:55 -0500 Received: from fencepost.gnu.org ([2001:470:142:3::e]) by eggs.gnu.org with esmtps (TLS1.2:ECDHE_RSA_AES_256_GCM_SHA384:256) (Exim 4.90_1) (envelope-from <ludo@HIDDEN>) id 1tlSjs-0004ZV-TC; Fri, 21 Feb 2025 08:06:45 -0500 DKIM-Signature: v=1; a=rsa-sha256; q=dns/txt; c=relaxed/relaxed; d=gnu.org; s=fencepost-gnu-org; h=MIME-Version:References:In-Reply-To:Date:Subject:To: From; bh=Cq0kaUqqXvShQhQeK/4/6kl4yXtjDCBbINBs6TqgNTE=; b=qBy9fbjeeW40p79U/07I tihiZE0Kqhyn8pVPYYjilI4BpQy6soiuikg3/imWGzATcvSkTRXHaPKbaglmWchOsryj3gNxv4o+m WLS3gSR7mcG0LJhwswLOSOPstwlzmJt2pywuXSqjxmWxe3d2SlYyrOMyaA2d47G+ya0j9pou5XSka QKPTL4yvZQhgERVKT/inE6kUrTxJTCHyFv1jq/ib1MiooLuiKaY5zGyxuKCzPrKKntdiM3sOsoRkf a3uu7MnHrUhD17ZZIracP2ZlfGFTKg8yzT5fkpnBMlKe0jgtyALeJAAYTPiVl2DXrwTaJDBso0xPn am++1LFfStjnPA==; From: =?UTF-8?q?Ludovic=20Court=C3=A8s?= <ludo@HIDDEN> To: 75810 <at> debbugs.gnu.org Subject: [PATCH v3 08/11] daemon: Drop Linux ambient capabilities before executing builder. Date: Fri, 21 Feb 2025 14:05:56 +0100 Message-ID: <41e73aaabf721c22bfde3b0369a8e0d1a5694671.1740142328.git.ludo@HIDDEN> X-Mailer: git-send-email 2.48.1 In-Reply-To: <cover.1740142328.git.ludo@HIDDEN> References: <cover.1740142328.git.ludo@HIDDEN> MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit X-Spam-Score: -2.3 (--) X-Debbugs-Envelope-To: 75810 Cc: =?UTF-8?q?Ludovic=20Court=C3=A8s?= <ludo@HIDDEN> X-BeenThere: debbugs-submit <at> debbugs.gnu.org X-Mailman-Version: 2.1.18 Precedence: list List-Id: <debbugs-submit.debbugs.gnu.org> List-Unsubscribe: <https://debbugs.gnu.org/cgi-bin/mailman/options/debbugs-submit>, <mailto:debbugs-submit-request <at> debbugs.gnu.org?subject=unsubscribe> List-Archive: <https://debbugs.gnu.org/cgi-bin/mailman/private/debbugs-submit/> List-Post: <mailto:debbugs-submit <at> debbugs.gnu.org> List-Help: <mailto:debbugs-submit-request <at> debbugs.gnu.org?subject=help> List-Subscribe: <https://debbugs.gnu.org/cgi-bin/mailman/listinfo/debbugs-submit>, <mailto:debbugs-submit-request <at> debbugs.gnu.org?subject=subscribe> Errors-To: debbugs-submit-bounces <at> debbugs.gnu.org Sender: "Debbugs-submit" <debbugs-submit-bounces <at> debbugs.gnu.org> X-Spam-Score: -3.3 (---) * config-daemon.ac: Check for <sys/prctl.h>. * nix/libstore/build.cc (DerivationGoal::runChild): When ‘useChroot’ is true, call ‘prctl’ to drop all ambient capabilities. Change-Id: If34637fc508e5fb6d278167f5df7802fc595284f --- config-daemon.ac | 2 +- nix/libstore/build.cc | 9 +++++++++ 2 files changed, 10 insertions(+), 1 deletion(-) diff --git a/config-daemon.ac b/config-daemon.ac index 4e949bc88a3..35d9c8cd56b 100644 --- a/config-daemon.ac +++ b/config-daemon.ac @@ -79,7 +79,7 @@ if test "x$guix_build_daemon" = "xyes"; then dnl Chroot support. AC_CHECK_FUNCS([chroot unshare]) AC_CHECK_HEADERS([sched.h sys/param.h sys/mount.h sys/syscall.h \ - linux/close_range.h]) + linux/close_range.h sys/prctl.h]) if test "x$ac_cv_func_chroot" != "xyes"; then AC_MSG_ERROR(['chroot' function missing, bailing out]) diff --git a/nix/libstore/build.cc b/nix/libstore/build.cc index 107ffcfea06..213ed635933 100644 --- a/nix/libstore/build.cc +++ b/nix/libstore/build.cc @@ -50,6 +50,9 @@ #if HAVE_SCHED_H #include <sched.h> #endif +#if HAVE_SYS_PRCTL_H +#include <sys/prctl.h> +#endif #define CHROOT_ENABLED HAVE_CHROOT && HAVE_SYS_MOUNT_H && defined(MS_BIND) && defined(MS_PRIVATE) @@ -2059,6 +2062,12 @@ void DerivationGoal::runChild() #if CHROOT_ENABLED if (useChroot) { +# if HAVE_SYS_PRCTL_H + /* Drop ambient capabilities such as CAP_CHOWN that might have + been granted when starting guix-daemon. */ + prctl(PR_CAP_AMBIENT, PR_CAP_AMBIENT_CLEAR_ALL, 0, 0, 0); +# endif + if (!fixedOutput) { /* Initialise the loopback interface. */ AutoCloseFD fd(socket(PF_INET, SOCK_DGRAM, IPPROTO_IP)); -- 2.48.1
guix-patches@HIDDEN
:bug#75810
; Package guix-patches
.
Full text available.Received: (at 75810) by debbugs.gnu.org; 21 Feb 2025 13:07:50 +0000 From debbugs-submit-bounces <at> debbugs.gnu.org Fri Feb 21 08:07:49 2025 Received: from localhost ([127.0.0.1]:56677 helo=debbugs.gnu.org) by debbugs.gnu.org with esmtp (Exim 4.84_2) (envelope-from <debbugs-submit-bounces <at> debbugs.gnu.org>) id 1tlSks-0005Zh-Ta for submit <at> debbugs.gnu.org; Fri, 21 Feb 2025 08:07:49 -0500 Received: from eggs.gnu.org ([2001:470:142:3::10]:48278) by debbugs.gnu.org with esmtps (TLS1.2:ECDHE_RSA_AES_256_GCM_SHA384:256) (Exim 4.84_2) (envelope-from <ludo@HIDDEN>) id 1tlSjq-0005NX-NM for 75810 <at> debbugs.gnu.org; Fri, 21 Feb 2025 08:06:49 -0500 Received: from fencepost.gnu.org ([2001:470:142:3::e]) by eggs.gnu.org with esmtps (TLS1.2:ECDHE_RSA_AES_256_GCM_SHA384:256) (Exim 4.90_1) (envelope-from <ludo@HIDDEN>) id 1tlSjk-0004YS-E4; Fri, 21 Feb 2025 08:06:36 -0500 DKIM-Signature: v=1; a=rsa-sha256; q=dns/txt; c=relaxed/relaxed; d=gnu.org; s=fencepost-gnu-org; h=MIME-Version:References:In-Reply-To:Date:Subject:To: From; bh=udLBw4qw0envZeVnNl6X7JHSGVVjKh3qwYLpmJ5s2vI=; b=gqyslp3G9o2/wxdo48xj ihL0DR7t+TeRNoFxv/94wfW8uFgwpJxNVrGO5cb5HtR01wjLMFZcbK2+daFhJTHPHKUSEVIGKwLSs ZzyD4f+e/9huSej3FK03lDgaHXhS9K+xfmUF7a7A/b+mW6YDVjU6kariWxcyEwGOaWUwOda2wgpy6 2sgZAWngi194os2gNLxHWfPFru41IJt8/9zqgyctM67fRpsCNxYZ5rQL5349hBVWXNlENvUIZc67X HBX5oapz3vCrZEF9sNTAfkCCf1BqVe1X2HADq26cWmBA9qmveBuGWLHfaeu2zYG0g35OOseWNG2DT tGymk+kLsZEgfg==; From: =?UTF-8?q?Ludovic=20Court=C3=A8s?= <ludo@HIDDEN> To: 75810 <at> debbugs.gnu.org Subject: [PATCH v3 03/11] daemon: Remount inputs as read-only. Date: Fri, 21 Feb 2025 14:05:51 +0100 Message-ID: <e62cb42e65d821ec41f8394a49c28da693d78d77.1740142328.git.ludo@HIDDEN> X-Mailer: git-send-email 2.48.1 In-Reply-To: <cover.1740142328.git.ludo@HIDDEN> References: <cover.1740142328.git.ludo@HIDDEN> MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit X-Spam-Score: -2.3 (--) X-Debbugs-Envelope-To: 75810 Cc: =?UTF-8?q?Ludovic=20Court=C3=A8s?= <ludo@HIDDEN>, Reepca Russelstein <reepca@HIDDEN> X-BeenThere: debbugs-submit <at> debbugs.gnu.org X-Mailman-Version: 2.1.18 Precedence: list List-Id: <debbugs-submit.debbugs.gnu.org> List-Unsubscribe: <https://debbugs.gnu.org/cgi-bin/mailman/options/debbugs-submit>, <mailto:debbugs-submit-request <at> debbugs.gnu.org?subject=unsubscribe> List-Archive: <https://debbugs.gnu.org/cgi-bin/mailman/private/debbugs-submit/> List-Post: <mailto:debbugs-submit <at> debbugs.gnu.org> List-Help: <mailto:debbugs-submit-request <at> debbugs.gnu.org?subject=help> List-Subscribe: <https://debbugs.gnu.org/cgi-bin/mailman/listinfo/debbugs-submit>, <mailto:debbugs-submit-request <at> debbugs.gnu.org?subject=subscribe> Errors-To: debbugs-submit-bounces <at> debbugs.gnu.org Sender: "Debbugs-submit" <debbugs-submit-bounces <at> debbugs.gnu.org> X-Spam-Score: -3.3 (---) * nix/libstore/build.cc (DerivationGoal::runChild): Remount ‘target’ as read-only. Reported-by: Reepca Russelstein <reepca@HIDDEN> Change-Id: Ib7201bcf4363be566f205d23d17fe2f55d3ad666 --- nix/libstore/build.cc | 7 +++++++ 1 file changed, 7 insertions(+) diff --git a/nix/libstore/build.cc b/nix/libstore/build.cc index f4cd2131c84..6244c99e751 100644 --- a/nix/libstore/build.cc +++ b/nix/libstore/build.cc @@ -2094,8 +2094,15 @@ void DerivationGoal::runChild() createDirs(dirOf(target)); writeFile(target, ""); } + + /* Extra flags passed with MS_BIND are ignored, hence the + extra MS_REMOUNT. */ if (mount(source.c_str(), target.c_str(), "", MS_BIND, 0) == -1) throw SysError(format("bind mount from `%1%' to `%2%' failed") % source % target); + if (source.compare(0, settings.nixStore.length(), settings.nixStore) == 0) { + if (mount(source.c_str(), target.c_str(), "", MS_BIND | MS_REMOUNT | MS_RDONLY, 0) == -1) + throw SysError(format("read-only remount of `%1%' failed") % target); + } } /* Bind a new instance of procfs on /proc to reflect our -- 2.48.1
guix-patches@HIDDEN
:bug#75810
; Package guix-patches
.
Full text available.Received: (at 75810) by debbugs.gnu.org; 21 Feb 2025 13:07:47 +0000 From debbugs-submit-bounces <at> debbugs.gnu.org Fri Feb 21 08:07:47 2025 Received: from localhost ([127.0.0.1]:56675 helo=debbugs.gnu.org) by debbugs.gnu.org with esmtp (Exim 4.84_2) (envelope-from <debbugs-submit-bounces <at> debbugs.gnu.org>) id 1tlSkq-0005Z5-3e for submit <at> debbugs.gnu.org; Fri, 21 Feb 2025 08:07:46 -0500 Received: from eggs.gnu.org ([2001:470:142:3::10]:48282) by debbugs.gnu.org with esmtps (TLS1.2:ECDHE_RSA_AES_256_GCM_SHA384:256) (Exim 4.84_2) (envelope-from <ludo@HIDDEN>) id 1tlSjr-0005No-NE for 75810 <at> debbugs.gnu.org; Fri, 21 Feb 2025 08:06:49 -0500 Received: from fencepost.gnu.org ([2001:470:142:3::e]) by eggs.gnu.org with esmtps (TLS1.2:ECDHE_RSA_AES_256_GCM_SHA384:256) (Exim 4.90_1) (envelope-from <ludo@HIDDEN>) id 1tlSjm-0004Yp-7F; Fri, 21 Feb 2025 08:06:38 -0500 DKIM-Signature: v=1; a=rsa-sha256; q=dns/txt; c=relaxed/relaxed; d=gnu.org; s=fencepost-gnu-org; h=MIME-Version:References:In-Reply-To:Date:Subject:To: From; bh=VRbaQkpHuujQuVs9fnXsFpQvamzXpEoyOQmUI3kKkJU=; b=dKDJ0U0xZVmzw0RV3sTS HqTzTYj+DkTY3554MBgb90Yq2uCTFaKBNOmy1Fvk4IFlekW2tmzco+7ErZiynwIXeWLoxDVLUg1Zh 9iPDaaDy761EzYvHA95e3787leu9S33EnVUh8ReMbUVn6GK6Trm8dv/Q6hP7VUl0+qkvJlJ8kazp2 5XaxreDXZagCkWMUdW7ZljxXoEaZJVHLVsnYNIi3IL/9Syedc2DTLQQQQMA+eeAl3m4jClq/Xpe3s krjZGkfyhqf1VEjrgYL0TQXnF4u+qzLDsXZiZomdqyova8+HqPjLsvkAecFYuVFeRJrMySvjtRfOM NtFhRhNYhuWtfg==; From: =?UTF-8?q?Ludovic=20Court=C3=A8s?= <ludo@HIDDEN> To: 75810 <at> debbugs.gnu.org Subject: [PATCH v3 04/11] daemon: Remount root directory as read-only. Date: Fri, 21 Feb 2025 14:05:52 +0100 Message-ID: <6272a7109a276d4ffa5cdd8b218b3233aaade5f5.1740142328.git.ludo@HIDDEN> X-Mailer: git-send-email 2.48.1 In-Reply-To: <cover.1740142328.git.ludo@HIDDEN> References: <cover.1740142328.git.ludo@HIDDEN> MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit X-Spam-Score: -2.3 (--) X-Debbugs-Envelope-To: 75810 Cc: =?UTF-8?q?Ludovic=20Court=C3=A8s?= <ludo@HIDDEN> X-BeenThere: debbugs-submit <at> debbugs.gnu.org X-Mailman-Version: 2.1.18 Precedence: list List-Id: <debbugs-submit.debbugs.gnu.org> List-Unsubscribe: <https://debbugs.gnu.org/cgi-bin/mailman/options/debbugs-submit>, <mailto:debbugs-submit-request <at> debbugs.gnu.org?subject=unsubscribe> List-Archive: <https://debbugs.gnu.org/cgi-bin/mailman/private/debbugs-submit/> List-Post: <mailto:debbugs-submit <at> debbugs.gnu.org> List-Help: <mailto:debbugs-submit-request <at> debbugs.gnu.org?subject=help> List-Subscribe: <https://debbugs.gnu.org/cgi-bin/mailman/listinfo/debbugs-submit>, <mailto:debbugs-submit-request <at> debbugs.gnu.org?subject=subscribe> Errors-To: debbugs-submit-bounces <at> debbugs.gnu.org Sender: "Debbugs-submit" <debbugs-submit-bounces <at> debbugs.gnu.org> X-Spam-Score: -3.3 (---) * nix/libstore/build.cc (DerivationGoal::runChild): Bind-mount the store and /tmp under ‘chrootRootDir’ to themselves as read-write. Remount / as read-only. Change-Id: I79565094c8ec8448401897c720aad75304fd1948 --- nix/libstore/build.cc | 16 ++++++++++++++++ 1 file changed, 16 insertions(+) diff --git a/nix/libstore/build.cc b/nix/libstore/build.cc index 6244c99e751..c87f4f767c5 100644 --- a/nix/libstore/build.cc +++ b/nix/libstore/build.cc @@ -2078,6 +2078,18 @@ void DerivationGoal::runChild() for (auto & i : ss) dirsInChroot[i] = i; + /* Make new mounts for the store and for /tmp. That way, when + 'chrootRootDir' is made read-only below, these two mounts will + remain writable (the store needs to be writable so derivation + outputs can be written to it, and /tmp is writable by + convention). */ + auto chrootStoreDir = chrootRootDir + settings.nixStore; + if (mount(chrootStoreDir.c_str(), chrootStoreDir.c_str(), 0, MS_BIND, 0) == -1) + throw SysError(format("read-write mount of store '%1%' failed") % chrootStoreDir); + auto chrootTmpDir = chrootRootDir + "/tmp"; + if (mount(chrootTmpDir.c_str(), chrootTmpDir.c_str(), 0, MS_BIND, 0) == -1) + throw SysError(format("read-write mount of temporary directory '%1%' failed") % chrootTmpDir); + /* Bind-mount all the directories from the "host" filesystem that we want in the chroot environment. */ @@ -2151,6 +2163,10 @@ void DerivationGoal::runChild() if (rmdir("real-root") == -1) throw SysError("cannot remove real-root directory"); + + /* Remount root as read-only. */ + if (mount("/", "/", 0, MS_BIND | MS_REMOUNT | MS_RDONLY, 0) == -1) + throw SysError(format("read-only remount of build root '%1%' failed") % chrootRootDir); } #endif -- 2.48.1
guix-patches@HIDDEN
:bug#75810
; Package guix-patches
.
Full text available.Received: (at 75810) by debbugs.gnu.org; 21 Feb 2025 13:07:44 +0000 From debbugs-submit-bounces <at> debbugs.gnu.org Fri Feb 21 08:07:44 2025 Received: from localhost ([127.0.0.1]:56673 helo=debbugs.gnu.org) by debbugs.gnu.org with esmtp (Exim 4.84_2) (envelope-from <debbugs-submit-bounces <at> debbugs.gnu.org>) id 1tlSkn-0005Ye-QL for submit <at> debbugs.gnu.org; Fri, 21 Feb 2025 08:07:43 -0500 Received: from eggs.gnu.org ([2001:470:142:3::10]:48276) by debbugs.gnu.org with esmtps (TLS1.2:ECDHE_RSA_AES_256_GCM_SHA384:256) (Exim 4.84_2) (envelope-from <ludo@HIDDEN>) id 1tlSjp-0005NF-Ey for 75810 <at> debbugs.gnu.org; Fri, 21 Feb 2025 08:06:46 -0500 Received: from fencepost.gnu.org ([2001:470:142:3::e]) by eggs.gnu.org with esmtps (TLS1.2:ECDHE_RSA_AES_256_GCM_SHA384:256) (Exim 4.90_1) (envelope-from <ludo@HIDDEN>) id 1tlSjj-0004Y4-2y; Fri, 21 Feb 2025 08:06:35 -0500 DKIM-Signature: v=1; a=rsa-sha256; q=dns/txt; c=relaxed/relaxed; d=gnu.org; s=fencepost-gnu-org; h=MIME-Version:References:In-Reply-To:Date:Subject:To: From; bh=G7Jx1/74uyahpmNN6NOOyHz1Zj53iERfANavhA6dHdE=; b=aHpHVyGtVmH3uhPTi7qz tnA+Ktpn0x6MnFWexd6kGAfCOfj3YW5s9Vd40ulEX33pXEudpuPI4df1CyJc+oEujxhL6fplnIBL6 dqHYXvMO46Dom+VhYnXq7k5TS7t3JhNqyIZOFhHYprmnGRzIXngx7UKGi7JnKPB78Efjy+IBlDuEP 8Oa+44VDYw7pmoyW4Cn40Hcm5YPXPUS8o4Ny1sfttYx38Jl4matq13vXJw9tLM2QU11omhs8ZNy30 5VQL15slVibAWblv8xxh6TRRXLIRKF4NCeZxhw7nuunVapen/ssBsm5acstlBbM+f/MUiaCgViNtl CO5OjBuHyDdiDw==; From: =?UTF-8?q?Ludovic=20Court=C3=A8s?= <ludo@HIDDEN> To: 75810 <at> debbugs.gnu.org Subject: [PATCH v3 02/11] daemon: Bind-mount all the inputs, not just directories. Date: Fri, 21 Feb 2025 14:05:50 +0100 Message-ID: <9819a4edaacbd5ed8d56094d6bb602f90f535be6.1740142328.git.ludo@HIDDEN> X-Mailer: git-send-email 2.48.1 In-Reply-To: <cover.1740142328.git.ludo@HIDDEN> References: <cover.1740142328.git.ludo@HIDDEN> MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit X-Spam-Score: -2.3 (--) X-Debbugs-Envelope-To: 75810 Cc: =?UTF-8?q?Ludovic=20Court=C3=A8s?= <ludo@HIDDEN>, Reepca Russelstein <reepca@HIDDEN> X-BeenThere: debbugs-submit <at> debbugs.gnu.org X-Mailman-Version: 2.1.18 Precedence: list List-Id: <debbugs-submit.debbugs.gnu.org> List-Unsubscribe: <https://debbugs.gnu.org/cgi-bin/mailman/options/debbugs-submit>, <mailto:debbugs-submit-request <at> debbugs.gnu.org?subject=unsubscribe> List-Archive: <https://debbugs.gnu.org/cgi-bin/mailman/private/debbugs-submit/> List-Post: <mailto:debbugs-submit <at> debbugs.gnu.org> List-Help: <mailto:debbugs-submit-request <at> debbugs.gnu.org?subject=help> List-Subscribe: <https://debbugs.gnu.org/cgi-bin/mailman/listinfo/debbugs-submit>, <mailto:debbugs-submit-request <at> debbugs.gnu.org?subject=subscribe> Errors-To: debbugs-submit-bounces <at> debbugs.gnu.org Sender: "Debbugs-submit" <debbugs-submit-bounces <at> debbugs.gnu.org> X-Spam-Score: -3.3 (---) * nix/libstore/build.cc (DerivationGoal::startBuilder): Add all of ‘inputPaths’ to ‘dirsInChroot’ instead of hard-linking regular files. Reported-by: Reepca Russelstein <reepca@HIDDEN> Change-Id: I070987f92d73f187f7826a975bee9ee309d67f56 --- nix/libstore/build.cc | 27 ++------------------------- 1 file changed, 2 insertions(+), 25 deletions(-) diff --git a/nix/libstore/build.cc b/nix/libstore/build.cc index edd01bab34d..f4cd2131c84 100644 --- a/nix/libstore/build.cc +++ b/nix/libstore/build.cc @@ -1850,9 +1850,7 @@ void DerivationGoal::startBuilder() /* Make the closure of the inputs available in the chroot, rather than the whole store. This prevents any access - to undeclared dependencies. Directories are bind-mounted, - while other inputs are hard-linked (since only directories - can be bind-mounted). !!! As an extra security + to undeclared dependencies. !!! As an extra security precaution, make the fake store only writable by the build user. */ Path chrootStoreDir = chrootRootDir + settings.nixStore; @@ -1863,28 +1861,7 @@ void DerivationGoal::startBuilder() throw SysError(format("cannot change ownership of ‘%1%’") % chrootStoreDir); foreach (PathSet::iterator, i, inputPaths) { - struct stat st; - if (lstat(i->c_str(), &st)) - throw SysError(format("getting attributes of path `%1%'") % *i); - if (S_ISDIR(st.st_mode)) - dirsInChroot[*i] = *i; - else { - Path p = chrootRootDir + *i; - if (link(i->c_str(), p.c_str()) == -1) { - /* Hard-linking fails if we exceed the maximum - link count on a file (e.g. 32000 of ext3), - which is quite possible after a `nix-store - --optimise'. */ - if (errno != EMLINK) - throw SysError(format("linking `%1%' to `%2%'") % p % *i); - StringSink sink; - dumpPath(*i, sink); - StringSource source(sink.s); - restorePath(p, source); - } - - regularInputPaths.insert(*i); - } + dirsInChroot[*i] = *i; } /* If we're repairing, checking or rebuilding part of a -- 2.48.1
guix-patches@HIDDEN
:bug#75810
; Package guix-patches
.
Full text available.Received: (at 75810) by debbugs.gnu.org; 21 Feb 2025 13:07:42 +0000 From debbugs-submit-bounces <at> debbugs.gnu.org Fri Feb 21 08:07:41 2025 Received: from localhost ([127.0.0.1]:56671 helo=debbugs.gnu.org) by debbugs.gnu.org with esmtp (Exim 4.84_2) (envelope-from <debbugs-submit-bounces <at> debbugs.gnu.org>) id 1tlSkl-0005YG-JD for submit <at> debbugs.gnu.org; Fri, 21 Feb 2025 08:07:41 -0500 Received: from eggs.gnu.org ([2001:470:142:3::10]:60052) by debbugs.gnu.org with esmtps (TLS1.2:ECDHE_RSA_AES_256_GCM_SHA384:256) (Exim 4.84_2) (envelope-from <ludo@HIDDEN>) id 1tlSjx-0005Ov-DA for 75810 <at> debbugs.gnu.org; Fri, 21 Feb 2025 08:06:54 -0500 Received: from fencepost.gnu.org ([2001:470:142:3::e]) by eggs.gnu.org with esmtps (TLS1.2:ECDHE_RSA_AES_256_GCM_SHA384:256) (Exim 4.90_1) (envelope-from <ludo@HIDDEN>) id 1tlSjr-0004ZO-MD; Fri, 21 Feb 2025 08:06:43 -0500 DKIM-Signature: v=1; a=rsa-sha256; q=dns/txt; c=relaxed/relaxed; d=gnu.org; s=fencepost-gnu-org; h=MIME-Version:References:In-Reply-To:Date:Subject:To: From; bh=Zsh2zvgPChPdygWDGttbjWAWpTHmsPY3r3V/6RFHAxg=; b=CQm+Lb8jxciD4Z5quqVJ C5g/T4kY8MF9sUmMO1mZm7OLhFZOLaZZiG6+XdmfwxhUzEA41OXA10F+rPBQtMaXmMnB11J0QBuWx 1cGb2hTK0xivL3sTvuC8pxjw6SrknC4viATybu2ZkLmkkotZYgDtEpwpAVlj6zNv/qJzVvQ3rKKkX aUFrivFux6mCljxfZQZJPgRZhFINqoTmWoVcLJ3PuDuTQgiSCWWKmxZGUL9+J4YnJkDEYyWSSvtYc 2F7nxQtnkB4Fay8H9G+SedxO292WORQl89eAc2yDNagHILPq//YQF4HEPPmT2DgngaBp7dCvyo7FR c16JjungyqlYZg==; From: =?UTF-8?q?Ludovic=20Court=C3=A8s?= <ludo@HIDDEN> To: 75810 <at> debbugs.gnu.org Subject: [PATCH v3 07/11] daemon: Create /var/guix/profiles/per-user unconditionally. Date: Fri, 21 Feb 2025 14:05:55 +0100 Message-ID: <42766ef6f8486fd4e25a5f211883934a7bdb5256.1740142328.git.ludo@HIDDEN> X-Mailer: git-send-email 2.48.1 In-Reply-To: <cover.1740142328.git.ludo@HIDDEN> References: <cover.1740142328.git.ludo@HIDDEN> MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit X-Spam-Score: -2.3 (--) X-Debbugs-Envelope-To: 75810 Cc: =?UTF-8?q?Ludovic=20Court=C3=A8s?= <ludo@HIDDEN> X-BeenThere: debbugs-submit <at> debbugs.gnu.org X-Mailman-Version: 2.1.18 Precedence: list List-Id: <debbugs-submit.debbugs.gnu.org> List-Unsubscribe: <https://debbugs.gnu.org/cgi-bin/mailman/options/debbugs-submit>, <mailto:debbugs-submit-request <at> debbugs.gnu.org?subject=unsubscribe> List-Archive: <https://debbugs.gnu.org/cgi-bin/mailman/private/debbugs-submit/> List-Post: <mailto:debbugs-submit <at> debbugs.gnu.org> List-Help: <mailto:debbugs-submit-request <at> debbugs.gnu.org?subject=help> List-Subscribe: <https://debbugs.gnu.org/cgi-bin/mailman/listinfo/debbugs-submit>, <mailto:debbugs-submit-request <at> debbugs.gnu.org?subject=subscribe> Errors-To: debbugs-submit-bounces <at> debbugs.gnu.org Sender: "Debbugs-submit" <debbugs-submit-bounces <at> debbugs.gnu.org> X-Spam-Score: -3.3 (---) * nix/libstore/local-store.cc (LocalStore::LocalStore): Create ‘perUserDir’ unconditionally. Change-Id: I5188320f9630a81d16f79212d0fffabd55d94abe --- nix/libstore/local-store.cc | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/nix/libstore/local-store.cc b/nix/libstore/local-store.cc index 4308264a4f3..63846695194 100644 --- a/nix/libstore/local-store.cc +++ b/nix/libstore/local-store.cc @@ -79,12 +79,12 @@ LocalStore::LocalStore(bool reserveSpace) createSymlink(profilesDir, gcRootsDir + "/profiles"); } - /* Optionally, create directories and set permissions for a - multi-user install. */ + Path perUserDir = profilesDir + "/per-user"; + createDirs(perUserDir); + + /* Optionally, set permissions for a multi-user install. */ if (getuid() == 0 && settings.buildUsersGroup != "") { - Path perUserDir = profilesDir + "/per-user"; - createDirs(perUserDir); if (chmod(perUserDir.c_str(), 0755) == -1) throw SysError(format("could not set permissions on '%1%' to 755") % perUserDir); -- 2.48.1
guix-patches@HIDDEN
:bug#75810
; Package guix-patches
.
Full text available.Received: (at 75810) by debbugs.gnu.org; 21 Feb 2025 13:07:03 +0000 From debbugs-submit-bounces <at> debbugs.gnu.org Fri Feb 21 08:07:01 2025 Received: from localhost ([127.0.0.1]:56656 helo=debbugs.gnu.org) by debbugs.gnu.org with esmtp (Exim 4.84_2) (envelope-from <debbugs-submit-bounces <at> debbugs.gnu.org>) id 1tlSjw-0005Pg-Ns for submit <at> debbugs.gnu.org; Fri, 21 Feb 2025 08:07:01 -0500 Received: from eggs.gnu.org ([2001:470:142:3::10]:48260) by debbugs.gnu.org with esmtps (TLS1.2:ECDHE_RSA_AES_256_GCM_SHA384:256) (Exim 4.84_2) (envelope-from <ludo@HIDDEN>) id 1tlSjn-0005Mw-B5 for 75810 <at> debbugs.gnu.org; Fri, 21 Feb 2025 08:06:43 -0500 Received: from fencepost.gnu.org ([2001:470:142:3::e]) by eggs.gnu.org with esmtps (TLS1.2:ECDHE_RSA_AES_256_GCM_SHA384:256) (Exim 4.90_1) (envelope-from <ludo@HIDDEN>) id 1tlSjg-0004Xo-6E; Fri, 21 Feb 2025 08:06:32 -0500 DKIM-Signature: v=1; a=rsa-sha256; q=dns/txt; c=relaxed/relaxed; d=gnu.org; s=fencepost-gnu-org; h=MIME-Version:Date:Subject:To:From:in-reply-to: references; bh=FLgFZ91ZIbk+/ybIGvHytOF4LNHGgU0XyA12luQqJT8=; b=igemvpQq642Lm3 Z4vigLUyM2kfDBEpo1GIGyy9JhyEqcj9xpivy3fuWxQjYdSVlDR6j3tB8/IhjW9l/GE3rdhBP04cX QZKix/bSfW7iWWVn8Cr5PT/D5WT/5WPLN4PWdkzz1Ci6otfy2jV7tuhJltG1Kbh4tt0KdW43SryTV 3wBKpLOPUMHIK28Wv52gyr7bwNmXn3+9C5jTKsG6iPpkBEukmuNWIICe7YIQNHdWES7IzXpq7kim0 yyJ/fGIlvwDdd7U01t/n9qh9oIjbC+xNa6xhQFC+FJ4u6DOVWwbp4A43OQgqdiP8v4U+f64xr8Dwl q3jIadW+kUdJL1k0zbYQ==; From: =?UTF-8?q?Ludovic=20Court=C3=A8s?= <ludo@HIDDEN> To: 75810 <at> debbugs.gnu.org Subject: [PATCH v3 00/11] Rootless guix-daemon Date: Fri, 21 Feb 2025 14:05:48 +0100 Message-ID: <cover.1740142328.git.ludo@HIDDEN> X-Mailer: git-send-email 2.48.1 MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit X-Spam-Score: -2.3 (--) X-Debbugs-Envelope-To: 75810 Cc: =?UTF-8?q?Ludovic=20Court=C3=A8s?= <ludo@HIDDEN>, Reepca Russelstein <reepca@HIDDEN> X-BeenThere: debbugs-submit <at> debbugs.gnu.org X-Mailman-Version: 2.1.18 Precedence: list List-Id: <debbugs-submit.debbugs.gnu.org> List-Unsubscribe: <https://debbugs.gnu.org/cgi-bin/mailman/options/debbugs-submit>, <mailto:debbugs-submit-request <at> debbugs.gnu.org?subject=unsubscribe> List-Archive: <https://debbugs.gnu.org/cgi-bin/mailman/private/debbugs-submit/> List-Post: <mailto:debbugs-submit <at> debbugs.gnu.org> List-Help: <mailto:debbugs-submit-request <at> debbugs.gnu.org?subject=help> List-Subscribe: <https://debbugs.gnu.org/cgi-bin/mailman/listinfo/debbugs-submit>, <mailto:debbugs-submit-request <at> debbugs.gnu.org?subject=subscribe> Errors-To: debbugs-submit-bounces <at> debbugs.gnu.org Sender: "Debbugs-submit" <debbugs-submit-bounces <at> debbugs.gnu.org> X-Spam-Score: -3.3 (---) Hello! Here’s an updated version, addressing most issues brought up by Reepca, also available from <https://codeberg.org/civodul/guix/src/branch/wip-rootless-daemon>. Main changes compared to v2: • Derivation inputs and / are mounted read-only; additional tests check the ability to write to these, to /tmp, to /dev/{full,null}, and to remount any of these as read-write. • Unit files for systemd tweaked so that (1) guix-daemon sees a private read-write mount of the store, and (2) gnu-store.mount actually remounts the store read-only after guix-daemon has started. • ‘DerivationGoal::deleteTmpDir’ bails out when it fails to chown ‘tmpDir’ (i.e., it does not try to “pivot” the /top sub-directory). Did I forget anything, Reepca? The one observable difference compared to current guix-daemon operational mode is that, in the build environment, writing to the root file system results in EROFS instead of EPERM, as you pointed out earlier. That’s not great but probably acceptable. We’ll only know whether this is a problem in practice once we’ve run the test suites of tens of thousands of packages. I tested this patch series by: • running ‘make check’; • manually running ‘guix-install.sh’ in a Debian VM, as explained before. Next up: • automating ‘guix-install.sh’ VM tests; • updating ‘guix-service-type’ to optionally support unprivileged guix-daemon. I think these two bits can come later though. Thoughts? Ludo’. Ludovic Courtès (11): daemon: Use ‘close_range’ where available. daemon: Bind-mount all the inputs, not just directories. daemon: Remount inputs as read-only. daemon: Remount root directory as read-only. daemon: Allow running as non-root with unprivileged user namespaces. tests: Run in a chroot and unprivileged user namespaces. daemon: Create /var/guix/profiles/per-user unconditionally. daemon: Drop Linux ambient capabilities before executing builder. daemon: Move comments where they belong. etc: systemd services: Run ‘guix-daemon’ as an unprivileged user. guix-install.sh: Support the unprivileged daemon where possible. build-aux/test-env.in | 14 ++- config-daemon.ac | 5 +- etc/gnu-store.mount.in | 3 +- etc/guix-daemon.service.in | 20 +++- etc/guix-install.sh | 108 ++++++++++++++---- guix/substitutes.scm | 4 +- nix/libstore/build.cc | 219 ++++++++++++++++++++++++++---------- nix/libstore/local-store.cc | 30 +++-- nix/libutil/util.cc | 23 +++- tests/processes.scm | 9 +- tests/store.scm | 206 +++++++++++++++++++++++++++------ 11 files changed, 494 insertions(+), 147 deletions(-) base-commit: 00787cd61611d74d3e54b160e94176905d36ef39 -- 2.48.1
guix-patches@HIDDEN
:bug#75810
; Package guix-patches
.
Full text available.Received: (at 75810) by debbugs.gnu.org; 21 Feb 2025 13:06:49 +0000 From debbugs-submit-bounces <at> debbugs.gnu.org Fri Feb 21 08:06:48 2025 Received: from localhost ([127.0.0.1]:56650 helo=debbugs.gnu.org) by debbugs.gnu.org with esmtp (Exim 4.84_2) (envelope-from <debbugs-submit-bounces <at> debbugs.gnu.org>) id 1tlSjt-0005P9-Fb for submit <at> debbugs.gnu.org; Fri, 21 Feb 2025 08:06:48 -0500 Received: from eggs.gnu.org ([2001:470:142:3::10]:48270) by debbugs.gnu.org with esmtps (TLS1.2:ECDHE_RSA_AES_256_GCM_SHA384:256) (Exim 4.84_2) (envelope-from <ludo@HIDDEN>) id 1tlSjn-0005Mz-H4 for 75810 <at> debbugs.gnu.org; Fri, 21 Feb 2025 08:06:42 -0500 Received: from fencepost.gnu.org ([2001:470:142:3::e]) by eggs.gnu.org with esmtps (TLS1.2:ECDHE_RSA_AES_256_GCM_SHA384:256) (Exim 4.90_1) (envelope-from <ludo@HIDDEN>) id 1tlSji-0004Xu-48; Fri, 21 Feb 2025 08:06:34 -0500 DKIM-Signature: v=1; a=rsa-sha256; q=dns/txt; c=relaxed/relaxed; d=gnu.org; s=fencepost-gnu-org; h=MIME-Version:References:In-Reply-To:Date:Subject:To: From; bh=0izMrOHlIq4NgLJJUeAlULEe8K+llpxfq6yctCHxero=; b=Fa8qHsdqYlC7tXaei7fh HJkYfqgSo7cMjdX9ShO89w2HV6D7Or4tuijB4swhy5hb2as9sTlJtlqmf7wyvZh4hhHtKtFXfWru0 gsY8dZYRqK/ebFoVzFWKyvwseHIl/pUnwkMQkRc3fVRPGG6NPHtA7lSO7d55QPqvEOzv1P5AZAojX 3qHiRnL4hSjZnAoBIrZYfkdoFLOyNaZ/athRYxgP17f57Cv7M1ynLqW0wuDplLeXDfLrkjbfgZlBE 0xfvAthaO3TQPkzCzYWvayQFtC5YH5iOQtQfYl7Q9LJu4APMrnmUr6ZaoFEOIO0z3c99ACU/gpBRF x12HDkMz/EeGBw==; From: =?UTF-8?q?Ludovic=20Court=C3=A8s?= <ludo@HIDDEN> To: 75810 <at> debbugs.gnu.org Subject: [PATCH v3 01/11] =?UTF-8?q?daemon:=20Use=20=E2=80=98close=5Frange?= =?UTF-8?q?=E2=80=99=20where=20available.?= Date: Fri, 21 Feb 2025 14:05:49 +0100 Message-ID: <47cd29cc645e87a85536da2d6edc676744c58cd5.1740142328.git.ludo@HIDDEN> X-Mailer: git-send-email 2.48.1 In-Reply-To: <cover.1740142328.git.ludo@HIDDEN> References: <cover.1740142328.git.ludo@HIDDEN> MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit X-Spam-Score: -2.3 (--) X-Debbugs-Envelope-To: 75810 Cc: =?UTF-8?q?Ludovic=20Court=C3=A8s?= <ludo@HIDDEN> X-BeenThere: debbugs-submit <at> debbugs.gnu.org X-Mailman-Version: 2.1.18 Precedence: list List-Id: <debbugs-submit.debbugs.gnu.org> List-Unsubscribe: <https://debbugs.gnu.org/cgi-bin/mailman/options/debbugs-submit>, <mailto:debbugs-submit-request <at> debbugs.gnu.org?subject=unsubscribe> List-Archive: <https://debbugs.gnu.org/cgi-bin/mailman/private/debbugs-submit/> List-Post: <mailto:debbugs-submit <at> debbugs.gnu.org> List-Help: <mailto:debbugs-submit-request <at> debbugs.gnu.org?subject=help> List-Subscribe: <https://debbugs.gnu.org/cgi-bin/mailman/listinfo/debbugs-submit>, <mailto:debbugs-submit-request <at> debbugs.gnu.org?subject=subscribe> Errors-To: debbugs-submit-bounces <at> debbugs.gnu.org Sender: "Debbugs-submit" <debbugs-submit-bounces <at> debbugs.gnu.org> X-Spam-Score: -3.3 (---) * nix/libutil/util.cc (closeMostFDs) [HAVE_CLOSE_RANGE]: Use ‘close_range’ when ‘exceptions’ is empty. * config-daemon.ac: Check for <linux/close_range.h> and the ‘close_range’ symbol. Change-Id: I12fa3bde58b003fcce5ea5a1fee1dcf9a92c0359 --- config-daemon.ac | 5 +++-- nix/libutil/util.cc | 23 +++++++++++++++++------ 2 files changed, 20 insertions(+), 8 deletions(-) diff --git a/config-daemon.ac b/config-daemon.ac index 6731c68bc39..4e949bc88a3 100644 --- a/config-daemon.ac +++ b/config-daemon.ac @@ -78,7 +78,8 @@ if test "x$guix_build_daemon" = "xyes"; then dnl Chroot support. AC_CHECK_FUNCS([chroot unshare]) - AC_CHECK_HEADERS([sched.h sys/param.h sys/mount.h sys/syscall.h]) + AC_CHECK_HEADERS([sched.h sys/param.h sys/mount.h sys/syscall.h \ + linux/close_range.h]) if test "x$ac_cv_func_chroot" != "xyes"; then AC_MSG_ERROR(['chroot' function missing, bailing out]) @@ -95,7 +96,7 @@ if test "x$guix_build_daemon" = "xyes"; then dnl strsignal: for error reporting. dnl statx: fine-grain 'stat' call, new in glibc 2.28. AC_CHECK_FUNCS([lutimes lchown posix_fallocate sched_setaffinity \ - statvfs nanosleep strsignal statx]) + statvfs nanosleep strsignal statx close_range]) dnl Check for <locale>. AC_LANG_PUSH(C++) diff --git a/nix/libutil/util.cc b/nix/libutil/util.cc index 3206dea11b1..eb2d16e1cc3 100644 --- a/nix/libutil/util.cc +++ b/nix/libutil/util.cc @@ -23,6 +23,10 @@ #include <sys/prctl.h> #endif +#ifdef HAVE_LINUX_CLOSE_RANGE_H +# include <linux/close_range.h> +#endif + extern char * * environ; @@ -1087,12 +1091,19 @@ string runProgram(Path program, bool searchPath, const Strings & args) void closeMostFDs(const set<int> & exceptions) { - int maxFD = 0; - maxFD = sysconf(_SC_OPEN_MAX); - for (int fd = 0; fd < maxFD; ++fd) - if (fd != STDIN_FILENO && fd != STDOUT_FILENO && fd != STDERR_FILENO - && exceptions.find(fd) == exceptions.end()) - close(fd); /* ignore result */ +#ifdef HAVE_CLOSE_RANGE + if (exceptions.empty()) + close_range(3, ~0U, 0); + else +#endif + { + int maxFD = 0; + maxFD = sysconf(_SC_OPEN_MAX); + for (int fd = 0; fd < maxFD; ++fd) + if (fd != STDIN_FILENO && fd != STDOUT_FILENO && fd != STDERR_FILENO + && exceptions.find(fd) == exceptions.end()) + close(fd); /* ignore result */ + } } -- 2.48.1
guix-patches@HIDDEN
:bug#75810
; Package guix-patches
.
Full text available.Received: (at 75810) by debbugs.gnu.org; 17 Feb 2025 16:52:45 +0000 From debbugs-submit-bounces <at> debbugs.gnu.org Mon Feb 17 11:52:44 2025 Received: from localhost ([127.0.0.1]:48149 helo=debbugs.gnu.org) by debbugs.gnu.org with esmtp (Exim 4.84_2) (envelope-from <debbugs-submit-bounces <at> debbugs.gnu.org>) id 1tk4MO-0003sU-Do for submit <at> debbugs.gnu.org; Mon, 17 Feb 2025 11:52:44 -0500 Received: from mail2-relais-roc.national.inria.fr ([192.134.164.83]:55934) by debbugs.gnu.org with esmtps (TLS1.2:ECDHE_RSA_AES_256_GCM_SHA384:256) (Exim 4.84_2) (envelope-from <ludovic.courtes@HIDDEN>) id 1tk4MH-0003rZ-Ih for 75810 <at> debbugs.gnu.org; Mon, 17 Feb 2025 11:52:42 -0500 DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=inria.fr; s=dc; h=from:to:cc:subject:in-reply-to:references:date: message-id:mime-version:content-transfer-encoding; bh=ReWBDVaBWZ3y9KLImKHX5d3/NUY4RSq/owzKRsKB/5s=; b=hnnOoS0zdrcawcAJnTCAmMSNL51hy0yuO9G6/VdYgoJh0qWA135HkLrM CSOjaZ9Foj3GhM0LMsKSRL5L7GMdKr0y5ZooNe61oTcUkCk9DH7dYulNn h5li1OPBI5lvxm17isxbWlRykRclZ0UKTi+VuUHFrzes/Q8sOsBh6ZVwT Y=; Authentication-Results: mail2-relais-roc.national.inria.fr; dkim=none (message not signed) header.i=none; spf=SoftFail smtp.mailfrom=ludovic.courtes@HIDDEN; dmarc=fail (p=none dis=none) d=inria.fr X-IronPort-AV: E=Sophos;i="6.13,293,1732575600"; d="scan'208";a="208678154" Received: from unknown (HELO ribbon) ([193.50.110.84]) by mail2-relais-roc.national.inria.fr with ESMTP/TLS/ECDHE-RSA-AES256-GCM-SHA384; 17 Feb 2025 17:52:30 +0100 From: =?utf-8?Q?Ludovic_Court=C3=A8s?= <ludovic.courtes@HIDDEN> To: Reepca Russelstein <reepca@HIDDEN> Subject: Remounting the store read-write for guix-daemon In-Reply-To: <87bjvshrk0.fsf@HIDDEN> ("Ludovic =?utf-8?Q?Court=C3=A8s=22'?= =?utf-8?Q?s?= message of "Mon, 27 Jan 2025 22:31:43 +0100") References: <cover.1737738362.git.ludo@HIDDEN> <87r04qe7dj.fsf@HIDDEN> <87bjvshrk0.fsf@HIDDEN> Date: Mon, 17 Feb 2025 17:52:30 +0100 Message-ID: <87h64sldip.fsf_-_@HIDDEN> User-Agent: Gnus/5.13 (Gnus v5.13) MIME-Version: 1.0 Content-Type: text/plain; charset=utf-8 Content-Transfer-Encoding: quoted-printable X-Spam-Score: -2.3 (--) X-Debbugs-Envelope-To: 75810 Cc: 75810 <at> debbugs.gnu.org X-BeenThere: debbugs-submit <at> debbugs.gnu.org X-Mailman-Version: 2.1.18 Precedence: list List-Id: <debbugs-submit.debbugs.gnu.org> List-Unsubscribe: <https://debbugs.gnu.org/cgi-bin/mailman/options/debbugs-submit>, <mailto:debbugs-submit-request <at> debbugs.gnu.org?subject=unsubscribe> List-Archive: <https://debbugs.gnu.org/cgi-bin/mailman/private/debbugs-submit/> List-Post: <mailto:debbugs-submit <at> debbugs.gnu.org> List-Help: <mailto:debbugs-submit-request <at> debbugs.gnu.org?subject=help> List-Subscribe: <https://debbugs.gnu.org/cgi-bin/mailman/listinfo/debbugs-submit>, <mailto:debbugs-submit-request <at> debbugs.gnu.org?subject=subscribe> Errors-To: debbugs-submit-bounces <at> debbugs.gnu.org Sender: "Debbugs-submit" <debbugs-submit-bounces <at> debbugs.gnu.org> X-Spam-Score: -3.3 (---) Hi, Ludovic Court=C3=A8s <ludo@HIDDEN> skribis: > I think I=E2=80=99d prefer to have a systemd (or other) service make a > read-write bind-mount at /gnu/store/.rw-store, and then we=E2=80=99d run > =E2=80=98guix-daemon --backing-store=3D/gnu/store/.rw-store=E2=80=99. For a moment, I thought we could just do nothing on our side and instead take advantage of what systemd (and shepherd) have to offer. On the systemd side, there are several things that looked promising=C2=B9. First option: PrivateMounts=3Dtrue PrivateUsers=3Dtrue ReadWritePaths=3D/gnu/store But that doesn=E2=80=99t work: the doc says that files in =E2=80=98ReadWrit= ePaths=E2=80=99 =E2=80=9Care accessible from within the namespace with the same access modes as from outside of it=E2=80=9D (so read-only in our case). Second option: BindPaths=3D/gnu/store =E2=80=A6 but that does essentially nothing, and we can=E2=80=99t specify t= hat we want =E2=80=9Cremount,rw=E2=80=9D. Third option: ExecStartPre=3Dmount --bind -o rw,remount /gnu/store =E2=80=A6 but the doc for =E2=80=98PrivateMounts=E2=80=99 says that =E2=80= =9C[m]ounts established in the namespace of the process created by ExecStartPre=3D will hence be cleaned up automatically as soon as that process exits and will not be available to subsequent processes forked off for ExecStart=3D=E2=80=9D. If anyone familiar with systemd has other ideas, I=E2=80=99m all ears! Otherwise I think we=E2=80=99ll have to have that =E2=80=98--backing-store= =E2=80=99 option (which would be useful in other contexts anyway). Thanks, Ludo=E2=80=99. =C2=B9 https://www.freedesktop.org/software/systemd/man/latest/systemd.exec= .html#
guix-patches@HIDDEN
:bug#75810
; Package guix-patches
.
Full text available.Received: (at 75810) by debbugs.gnu.org; 16 Feb 2025 02:40:55 +0000 From debbugs-submit-bounces <at> debbugs.gnu.org Sat Feb 15 21:40:54 2025 Received: from localhost ([127.0.0.1]:59265 helo=debbugs.gnu.org) by debbugs.gnu.org with esmtp (Exim 4.84_2) (envelope-from <debbugs-submit-bounces <at> debbugs.gnu.org>) id 1tjUaU-0001nw-0y for submit <at> debbugs.gnu.org; Sat, 15 Feb 2025 21:40:54 -0500 Received: from mailout.russelstein.xyz ([2605:6400:20:11e::1]:46760) by debbugs.gnu.org with esmtps (TLS1.2:ECDHE_RSA_AES_256_GCM_SHA384:256) (Exim 4.84_2) (envelope-from <reepca@HIDDEN>) id 1tjUaP-0001nf-95 for 75810 <at> debbugs.gnu.org; Sat, 15 Feb 2025 21:40:51 -0500 DKIM-Signature: v=1; a=ed25519-sha256; q=dns/txt; c=relaxed/relaxed; d=russelstein.xyz; s=ed25519; h=Content-Type:MIME-Version:Message-ID:Date: References:In-Reply-To:Subject:Cc:To:From:Sender:Reply-To: Content-Transfer-Encoding:Content-ID:Content-Description:Resent-Date: Resent-From:Resent-Sender:Resent-To:Resent-Cc:Resent-Message-ID:List-Id: List-Help:List-Unsubscribe:List-Subscribe:List-Post:List-Owner:List-Archive; bh=iDgY32vaZYp+aWrvFSDUa2KsPFczRIcrw1ibTQAw27E=; b=5LfWx6g8E5gmZJzg7wWjtExzcv C7meu0zXn+OAmysBoNIj/RKxMRxoah/2CnjshTZlAdPlkXoKS4+JdAo+ayCQ==; DKIM-Signature: v=1; a=rsa-sha256; q=dns/txt; c=relaxed/relaxed; d=russelstein.xyz; s=rsa; h=Content-Type:MIME-Version:Message-ID:Date: References:In-Reply-To:Subject:Cc:To:From:Sender:Reply-To: Content-Transfer-Encoding:Content-ID:Content-Description:Resent-Date: Resent-From:Resent-Sender:Resent-To:Resent-Cc:Resent-Message-ID:List-Id: List-Help:List-Unsubscribe:List-Subscribe:List-Post:List-Owner:List-Archive; bh=iDgY32vaZYp+aWrvFSDUa2KsPFczRIcrw1ibTQAw27E=; b=dGLEC0VbGO4hc9ViyUIB6y7r3x ahqdYg96Od3UWO1WeNterF16Ei7SQZqUiRbZX9iNJAYu5WtidxPVrJgrbUg331h2CVW5nXVk4LRAu FjC7M0G0eWS7WONVdONrOqVlQtZqZtmIF00IntFqIDks4jNbu9VNkTQpcfBepUkVGJrpTyMBkiaXi nwL79rptaDeYrIjFNCHYNzSaGaxcJCW+Y5dqX2GYOWK+TaH/EbYFNG2RBLv0fEWt4eMWL11UtqN+G NV8r2QaeLbTukmvgXqG1rZAFV8OlMLQVLE19fPhzee69XI4xjvDLAMN0oVtlPKAiNgPWziWz2L/3f F+kdW/5zFPy9y8rjJNmJZFaWP8XAgLVrp/W25cE0FMZO+ikDM8Yl7M3Dj0AIhD+NZWOTFOOFPCwjv h9GzlgTJjd3w0/qPXIMGz4+0/AJ3VTa2eR3nXYIZ50b2sFJri4cTo6C+9pw+LmAK0kTi2CMdn38nH u3DQvixZ+E7oviFuZfxYJ+O+M+Hg/Ib2xOGxvw6eKKlRRRxKOQa58mjexqhakfgxx23OIOmbVo0cv wMbXC5JD3l9EL/gI/0aTdeTNcuQaHKi+Tp7+VmSDn+gCFZIXQ53UNKUXTbqGJXWFTFP9klPTe4GHO RxMlerU8YOhA9a4cFWdJmbIME7e7BJI+taLJQikCc=; Received: by russelstein.xyz with esmtpsa (TLS1.3:ECDHE_SECP256R1__RSA_PSS_RSAE_SHA256__AES_256_GCM:256) (Exim 4.98) (envelope-from <reepca@HIDDEN>) id 1tjUaK-000000006Xd-2omK; Sat, 15 Feb 2025 20:40:46 -0600 From: Reepca Russelstein <reepca@HIDDEN> To: Ludovic =?utf-8?Q?Court=C3=A8s?= <ludo@HIDDEN> Subject: Re: [bug#75810] [PATCH 0/6] Rootless guix-daemon In-Reply-To: <87o6z2vqnt.fsf@HIDDEN> ("Ludovic =?utf-8?Q?Court=C3=A8s=22'?= =?utf-8?Q?s?= message of "Sat, 15 Feb 2025 22:33:58 +0100") References: <cover.1737738362.git.ludo@HIDDEN> <87r04qe7dj.fsf@HIDDEN> <87bjvshrk0.fsf@HIDDEN> <875xluehn7.fsf@HIDDEN> <877c5u2ct5.fsf@HIDDEN> <87jz9sc72o.fsf@HIDDEN> <87o6z2vqnt.fsf@HIDDEN> Date: Sat, 15 Feb 2025 20:40:04 -0600 Message-ID: <87cyfid33v.fsf@HIDDEN> User-Agent: Gnus/5.13 (Gnus v5.13) MIME-Version: 1.0 Content-Type: multipart/signed; boundary="=-=-="; micalg=pgp-sha256; protocol="application/pgp-signature" X-Spam-Score: 0.5 X-Spam-Bar: / X-Spam-Score-Int: 5 X-Spam-Report: Spam detection software, running on the system "Sanctum", has NOT identified this incoming email as spam. The original message has been attached to this so you can view it or label similar future email. If you have any questions, see the administrator of that system for details. Content preview: Ludovic Courtès <ludo@HIDDEN> writes: >> We seem to be relying entirely on the Linux behavior of chown to reset >> setuid / setgid bits. > > Yes, and I think chown(2) is quite clear: > > When the owner or group of an executable file is ch [...] Content analysis details: (0.5 points, 5.0 required) pts rule name description ---- ---------------------- -------------------------------------------------- -0.0 NO_RELAYS Informational: message was not relayed via SMTP 0.5 FROM_SUSPICIOUS_NTLD From abused NTLD X-Spam-Score: 2.5 (++) X-Spam-Report: Spam detection software, running on the system "debbugs.gnu.org", has NOT identified this incoming email as spam. The original message has been attached to this so you can view it or label similar future email. If you have any questions, see the administrator of that system for details. Content preview: Ludovic Courtès <ludo@HIDDEN> writes: >> We seem to be relying entirely on the Linux behavior of chown to reset >> setuid / setgid bits. > > Yes, and I think chown(2) is quite clear: > > When the owner or group of an executable file is ch [...] Content analysis details: (2.5 points, 10.0 required) pts rule name description ---- ---------------------- -------------------------------------------------- 0.0 SPF_HELO_NONE SPF: HELO does not publish an SPF Record -0.0 SPF_PASS SPF: sender matches SPF record 2.0 PDS_OTHER_BAD_TLD Untrustworthy TLDs [URI: russelstein.xyz (xyz)] 0.5 FROM_SUSPICIOUS_NTLD From abused NTLD X-Debbugs-Envelope-To: 75810 Cc: 75810 <at> debbugs.gnu.org X-BeenThere: debbugs-submit <at> debbugs.gnu.org X-Mailman-Version: 2.1.18 Precedence: list List-Id: <debbugs-submit.debbugs.gnu.org> List-Unsubscribe: <https://debbugs.gnu.org/cgi-bin/mailman/options/debbugs-submit>, <mailto:debbugs-submit-request <at> debbugs.gnu.org?subject=unsubscribe> List-Archive: <https://debbugs.gnu.org/cgi-bin/mailman/private/debbugs-submit/> List-Post: <mailto:debbugs-submit <at> debbugs.gnu.org> List-Help: <mailto:debbugs-submit-request <at> debbugs.gnu.org?subject=help> List-Subscribe: <https://debbugs.gnu.org/cgi-bin/mailman/listinfo/debbugs-submit>, <mailto:debbugs-submit-request <at> debbugs.gnu.org?subject=subscribe> Errors-To: debbugs-submit-bounces <at> debbugs.gnu.org Sender: "Debbugs-submit" <debbugs-submit-bounces <at> debbugs.gnu.org> X-Spam-Score: 2.5 (++) X-Spam-Report: Spam detection software, running on the system "debbugs.gnu.org", has NOT identified this incoming email as spam. The original message has been attached to this so you can view it or label similar future email. If you have any questions, see the administrator of that system for details. Content preview: Ludovic Courtès <ludo@HIDDEN> writes: >> We seem to be relying entirely on the Linux behavior of chown to reset >> setuid / setgid bits. > > Yes, and I think chown(2) is quite clear: > > When the owner or group of an executable file is ch [...] Content analysis details: (2.5 points, 10.0 required) pts rule name description ---- ---------------------- -------------------------------------------------- 0.0 SPF_HELO_NONE SPF: HELO does not publish an SPF Record -0.0 SPF_PASS SPF: sender matches SPF record 2.0 PDS_OTHER_BAD_TLD Untrustworthy TLDs [URI: russelstein.xyz (xyz)] 1.0 BULK_RE_SUSP_NTLD Precedence bulk and RE: from a suspicious TLD 0.5 FROM_SUSPICIOUS_NTLD From abused NTLD -1.0 MAILING_LIST_MULTI Multiple indicators imply a widely-seen list manager --=-=-= Content-Type: text/plain; charset=utf-8 Content-Transfer-Encoding: quoted-printable Ludovic Court=C3=A8s <ludo@HIDDEN> writes: >> We seem to be relying entirely on the Linux behavior of chown to reset >> setuid / setgid bits. > > Yes, and I think chown(2) is quite clear: > > When the owner or group of an executable file is changed by an > unprivileged user, the S_ISUID and S_ISGID mode bits are cleared. > [=E2=80=A6] since Linux 2.2.13, root is treated like other users. Ah, I misread it as "changed by an unprivileged process", not "changed by an unprivileged user". That clears things up. >> Now, for the non-pedantic, significant issue that I came across while >> writing all that: previously, it was not possible for the >> tmpDir-exposing code to be reached without doing the _chown that also >> reset setuid and setgid bits. But with this patch, in the non-root, >> non-CAP_CHOWN case (which is what is currently proposed for Guix >> System), it can be reached through the catch clause. In that case it >> will expose tmpDir without changing any permission bits of files beneath >> it, allowing anybody who can access a setuid program in tmpDir (which, >> due to that 0755 chmod, is "everybody") to take control of the build >> user (which in this case would be guix-daemon). > > I=E2=80=99m not sure I understand what you mean by =E2=80=9Cthe tmpDir-ex= posing code=E2=80=9D; > are you talking about =E2=80=98DerivationGoal::deleteTmpDir=E2=80=99? by "the tmpDir-exposing code" I mean this section inside of DerivationGoal::deleteTmpDir, starting at nix/libstore/build.cc line 2818 in commit e6c588: =2D-8<---------------cut here---------------start------------->8--- if (top !=3D tmpDir) { // Rename tmpDir to its parent, with an intermediate step. string pivot =3D top + ".pivot"; if (rename(top.c_str(), pivot.c_str()) =3D=3D -1) throw SysError("pivoting failed build tree"); if (rename((pivot + "/top").c_str(), top.c_str()) =3D=3D -1) throw SysError("renaming failed build tree"); if (getuid() !=3D 0) /* Running unprivileged but with CAP_CHOWN. */ chown(top.c_str(), uid, gid); rmdir(pivot.c_str()); } =2D-8<---------------cut here---------------end--------------->8--- >> I still think it would be a good idea to call unshare to create an extra >> user and mount namespace just before executing the builder in the >> unprivileged case, just to be sure that the mount-locking behavior is >> triggered in a way that is documented. > > The problem with =E2=80=9Cmount locking=E2=80=9D (and =E2=80=9Cpeer group= =E2=80=9D and in fact most > =E2=80=9Cconcepts=E2=80=9D mentioned in mount(2)) is that it=E2=80=99s no= t clearly defined. > Here I=E2=80=99m relying on unit tests to ensure that the various bits can > indeed not be remounted read-write, for instance. (=E2=80=9Cmake check= =E2=80=9D tests > the same setup as unprivileged daemon, which is an advantage over the > current situation where the separate-build-user setup is not covered by > the test suite.) Both of those concepts are described in mount_namespaces(7). While my reading of that leaves me with several questions, the section "restrictions on mount namespaces" does have this: [5] The mount(2) flags MS_RDONLY, MS_NOSUID, MS_NOEXEC, and the "ati= me" flags (MS_NOATIME, MS_NODIRATIME, MS_RELATIME) settings bec= ome locked when propagated from a more privileged to a less privile= ged mount namespace, and may not be changed in the less privile= ged mount namespace. This point is illustrated in the following example where, in a m= ore privileged mount namespace, we create a bind mount that is mar= ked as read-only. For security reasons, it should not be possible = to make the mount writable in a less privileged mount namespace, = and indeed the kernel prevents this: $ sudo mkdir /mnt/dir $ sudo mount --bind -o ro /some/path /mnt/dir $ sudo unshare --user --map-root-user --mount \ mount -o remount,rw /mnt/dir mount: /mnt/dir: permission denied. which seems to indicate that it is sufficient for preventing modification of mount flags that the caller be in a less privileged mount namespace than the one the mount was inherited from. "Less privileged" is defined as: [1] Each mount namespace has an owner user namespace. As explai= ned above, when a new mount namespace is created, its mount list= is initialized as a copy of the mount list of another mount namespa= ce. If the new namespace and the namespace from which the mount l= ist was copied are owned by different user namespaces, then the = new mount namespace is considered less privileged. So putting the builder in a fresh mount namespace owned by a fresh user namespace should suffice to achieve this. It's worth noting that EPERM is returned by mount both for attempts to modify locked mount points and for just generally not having the required capability, so a unit test may have trouble establishing why a particular behavior is being observed. Ideally it wouldn't be possible to modify the inputs even if the builder managed to acquire the required capability in its user namespace. =2D reepca --=-=-= Content-Type: application/pgp-signature; name="signature.asc" -----BEGIN PGP SIGNATURE----- iQFLBAEBCAA1FiEEdNapMPRLm4SepVYGwWaqSV9/GJwFAmexUAQXHHJlZXBjYUBy dXNzZWxzdGVpbi54eXoACgkQwWaqSV9/GJxqywf+O7JKSO8MJLvUU9VnXB+4ectV Cew3MzUpCTI5hXGzZ+F0kL3APataYHG72g1Vmgtf1Q2tJVqG9NKFrMzKTI4qKXv9 +Vg/2/UOiDr3X1ACA7zMgz/hKZ6ZVwk13JE0S8JaBjiJKvYc+4FKKDd9G0ERdq6Y RGxs2DsCDaHLefWEuzNASboh+AnOTqVI35HhwWDYibfXNmqMLT5TKCuph5jThPrO Jdl8vzlaf9kbe3qI38/RWwkH3fF8N0pjNSAEcATB1YIFZJuTiyG2o/rInj5RgEce t3PwYfuZ9JtRzU3JWYcaF+8mbiBHft4qsyTwzWxna4YZRgO1GxZSakwH+JGsAg== =fmOO -----END PGP SIGNATURE----- --=-=-=--
guix-patches@HIDDEN
:bug#75810
; Package guix-patches
.
Full text available.Received: (at 75810) by debbugs.gnu.org; 15 Feb 2025 21:34:14 +0000 From debbugs-submit-bounces <at> debbugs.gnu.org Sat Feb 15 16:34:14 2025 Received: from localhost ([127.0.0.1]:58301 helo=debbugs.gnu.org) by debbugs.gnu.org with esmtp (Exim 4.84_2) (envelope-from <debbugs-submit-bounces <at> debbugs.gnu.org>) id 1tjPnh-0003dF-SI for submit <at> debbugs.gnu.org; Sat, 15 Feb 2025 16:34:14 -0500 Received: from eggs.gnu.org ([2001:470:142:3::10]:50402) by debbugs.gnu.org with esmtps (TLS1.2:ECDHE_RSA_AES_256_GCM_SHA384:256) (Exim 4.84_2) (envelope-from <ludo@HIDDEN>) id 1tjPne-0003ct-Ma for 75810 <at> debbugs.gnu.org; Sat, 15 Feb 2025 16:34:11 -0500 Received: from fencepost.gnu.org ([2001:470:142:3::e]) by eggs.gnu.org with esmtps (TLS1.2:ECDHE_RSA_AES_256_GCM_SHA384:256) (Exim 4.90_1) (envelope-from <ludo@HIDDEN>) id 1tjPnY-0007R2-Hg; Sat, 15 Feb 2025 16:34:04 -0500 DKIM-Signature: v=1; a=rsa-sha256; q=dns/txt; c=relaxed/relaxed; d=gnu.org; s=fencepost-gnu-org; h=MIME-Version:Date:References:In-Reply-To:Subject:To: From; bh=bNnGR25Xb5WX8L+ytojYUaEv1R4QABOUAfBAC/8RKBU=; b=ecDPyOijyGr9pmxv3cS3 4RmgoXPY/9QyPewSCD88NCx3U/Q4kqY/1mPGXaMabCS3KCcS2HXzh9vkBJxPu9qcxkHaXlhVYsiEK 91z1MWIqpXuTJDZ26HkZMtweH4oIJIR0wdBFnzGuWoVufjAXbWpWLb6H4pOlgX08nN+oXM8K9mq7p QIaeGBNa8oI3l9X9+B8sDxD1Usceyr80gyebuDmjOpn7cMrR0uZlpRN2Y2vUSZ9J8SdIDxYqFS/wq OqkrrApr1C4igU0JXFlKvN1/6HXWsvEUbNe4/zerrzUqoXhV2FhfyzyCpcbZ96txl3S0wPoBPmM+y UWYlG9eVgqgrsg==; From: =?utf-8?Q?Ludovic_Court=C3=A8s?= <ludo@HIDDEN> To: Reepca Russelstein <reepca@HIDDEN> Subject: Re: [bug#75810] [PATCH 0/6] Rootless guix-daemon In-Reply-To: <87jz9sc72o.fsf@HIDDEN> (Reepca Russelstein's message of "Fri, 14 Feb 2025 19:47:27 -0600") References: <cover.1737738362.git.ludo@HIDDEN> <87r04qe7dj.fsf@HIDDEN> <87bjvshrk0.fsf@HIDDEN> <875xluehn7.fsf@HIDDEN> <877c5u2ct5.fsf@HIDDEN> <87jz9sc72o.fsf@HIDDEN> Date: Sat, 15 Feb 2025 22:33:58 +0100 Message-ID: <87o6z2vqnt.fsf@HIDDEN> User-Agent: Gnus/5.13 (Gnus v5.13) MIME-Version: 1.0 Content-Type: text/plain; charset=utf-8 Content-Transfer-Encoding: quoted-printable X-Spam-Score: -0.3 (/) X-Debbugs-Envelope-To: 75810 Cc: 75810 <at> debbugs.gnu.org X-BeenThere: debbugs-submit <at> debbugs.gnu.org X-Mailman-Version: 2.1.18 Precedence: list List-Id: <debbugs-submit.debbugs.gnu.org> List-Unsubscribe: <https://debbugs.gnu.org/cgi-bin/mailman/options/debbugs-submit>, <mailto:debbugs-submit-request <at> debbugs.gnu.org?subject=unsubscribe> List-Archive: <https://debbugs.gnu.org/cgi-bin/mailman/private/debbugs-submit/> List-Post: <mailto:debbugs-submit <at> debbugs.gnu.org> List-Help: <mailto:debbugs-submit-request <at> debbugs.gnu.org?subject=help> List-Subscribe: <https://debbugs.gnu.org/cgi-bin/mailman/listinfo/debbugs-submit>, <mailto:debbugs-submit-request <at> debbugs.gnu.org?subject=subscribe> Errors-To: debbugs-submit-bounces <at> debbugs.gnu.org Sender: "Debbugs-submit" <debbugs-submit-bounces <at> debbugs.gnu.org> X-Spam-Score: -1.3 (-) Hi, (Just a quick reply; there=E2=80=99s a lot in here. :-)) Reepca Russelstein <reepca@HIDDEN> skribis: > I expect that it should work to: > 1. go through the entire normal chroot setup > 2. bind-mount /gnu/store and /tmp to themselves within the chroot using > MS_REC so that they are treated as distinct filesystems but also > still have their existing bind-mounts underneath them > 3. bind-mount / to itself using MS_REC > 4. remount / read-only using MS_RDONLY | MS_REMOUNT | MS_BIND Yes. I pushed what I have now at <https://codeberg.org/civodul/guix/src/branch/wip-rootless-daemon>. It does work as expected: / is read-only, /tmp and /gnu/store are read-write, individual inputs in /gnu/store are read-only. > Also, _chown does the actual chown on descent, not on return, so it > first chowns a directory and then goes through its contents. This means > that, again, if there weren't the top directory there to block access, > it would be possible to access a setuid program before it was chown'ed. Right. > We seem to be relying entirely on the Linux behavior of chown to reset > setuid / setgid bits. Yes, and I think chown(2) is quite clear: When the owner or group of an executable file is changed by an unprivileged user, the S_ISUID and S_ISGID mode bits are cleared. [=E2=80=A6] since Linux 2.2.13, root is treated like other users. > Now, for the non-pedantic, significant issue that I came across while > writing all that: previously, it was not possible for the > tmpDir-exposing code to be reached without doing the _chown that also > reset setuid and setgid bits. But with this patch, in the non-root, > non-CAP_CHOWN case (which is what is currently proposed for Guix > System), it can be reached through the catch clause. In that case it > will expose tmpDir without changing any permission bits of files beneath > it, allowing anybody who can access a setuid program in tmpDir (which, > due to that 0755 chmod, is "everybody") to take control of the build > user (which in this case would be guix-daemon). I=E2=80=99m not sure I understand what you mean by =E2=80=9Cthe tmpDir-expo= sing code=E2=80=9D; are you talking about =E2=80=98DerivationGoal::deleteTmpDir=E2=80=99? > Going by the "Running unprivileged but with CAP_CHOWN" comment, it would > seem that code is meant to only be reached by reaching the end of the > "try" block, not by reaching the end of the "catch" block. I think it > would be a good idea to call secureFilePerms(tmpDir) before any attempt > at chown'ing. Yeah, we can do that to be on the safe side. > I still think it would be a good idea to call unshare to create an extra > user and mount namespace just before executing the builder in the > unprivileged case, just to be sure that the mount-locking behavior is > triggered in a way that is documented. The problem with =E2=80=9Cmount locking=E2=80=9D (and =E2=80=9Cpeer group= =E2=80=9D and in fact most =E2=80=9Cconcepts=E2=80=9D mentioned in mount(2)) is that it=E2=80=99s not = clearly defined. Here I=E2=80=99m relying on unit tests to ensure that the various bits can indeed not be remounted read-write, for instance. (=E2=80=9Cmake check=E2= =80=9D tests the same setup as unprivileged daemon, which is an advantage over the current situation where the separate-build-user setup is not covered by the test suite.) Ludo=E2=80=99.
guix-patches@HIDDEN
:bug#75810
; Package guix-patches
.
Full text available.Received: (at 75810) by debbugs.gnu.org; 15 Feb 2025 01:49:14 +0000 From debbugs-submit-bounces <at> debbugs.gnu.org Fri Feb 14 20:49:14 2025 Received: from localhost ([127.0.0.1]:52532 helo=debbugs.gnu.org) by debbugs.gnu.org with esmtp (Exim 4.84_2) (envelope-from <debbugs-submit-bounces <at> debbugs.gnu.org>) id 1tj7Iv-0002ho-Bd for submit <at> debbugs.gnu.org; Fri, 14 Feb 2025 20:49:14 -0500 Received: from mailout.russelstein.xyz ([2605:6400:20:11e::1]:50614) by debbugs.gnu.org with esmtps (TLS1.2:ECDHE_RSA_AES_256_GCM_SHA384:256) (Exim 4.84_2) (envelope-from <reepca@HIDDEN>) id 1tj7Iq-0002hZ-Ot for 75810 <at> debbugs.gnu.org; Fri, 14 Feb 2025 20:49:11 -0500 DKIM-Signature: v=1; a=ed25519-sha256; q=dns/txt; c=relaxed/relaxed; d=russelstein.xyz; s=ed25519; h=Content-Type:MIME-Version:Message-ID:Date: References:In-Reply-To:Subject:Cc:To:From:Sender:Reply-To: Content-Transfer-Encoding:Content-ID:Content-Description:Resent-Date: Resent-From:Resent-Sender:Resent-To:Resent-Cc:Resent-Message-ID:List-Id: List-Help:List-Unsubscribe:List-Subscribe:List-Post:List-Owner:List-Archive; bh=GyBiT4h3ndchOhbyPIBvBeUZxZg58Y8avyhi4+S/SHE=; b=IbmB2piICQMuTEl+uwIg2WfOvK oIvUnHAvpqm+YTbOryzxEEBN5g+NUCyir/UTDn1Sw6iIebfTtCIKHB4O2wAA==; DKIM-Signature: v=1; a=rsa-sha256; q=dns/txt; c=relaxed/relaxed; d=russelstein.xyz; s=rsa; h=Content-Type:MIME-Version:Message-ID:Date: References:In-Reply-To:Subject:Cc:To:From:Sender:Reply-To: Content-Transfer-Encoding:Content-ID:Content-Description:Resent-Date: Resent-From:Resent-Sender:Resent-To:Resent-Cc:Resent-Message-ID:List-Id: List-Help:List-Unsubscribe:List-Subscribe:List-Post:List-Owner:List-Archive; bh=GyBiT4h3ndchOhbyPIBvBeUZxZg58Y8avyhi4+S/SHE=; b=j0OIjfcLnu7VW306I6YwKa2QWU J6+6rjZ9ISjwCUGNYxlbYqnyCYpbXikt6UeM12LH3Cp8/OPlX/sZU7ZwTwwaYQdzO3JPUe0YeCen2 mFE8UgCyX0uyCzBKCJnHi07lqsJrr41dmYTnsu7qiXKecIG67HaDDVs3KuAPEElKMknx31zeeEqck 3gv4X/Y2qGtiOv8cygGeA92i6LrS6CgjKjGEraGIw4oclG34cwKNQzfLN64YHjwH0ruJ+4n1vaudh Q10j11vxaN/Hyfb4IMOYyAwYTNEsCS31q0w+TePklfdpc5eOOsywRb4jSjOpBdAHXBQpxZOcgk7gm 0DUbmBpcqxTx8dUw0p6IdZmHQkLxHARVdJQ9qo2Xtq4mp+YyCJfNOLsEGKKOar6l78SAT6EEsLlLm MHa3tFWjLjpyDaLNZt48cwzLFptHuY8XI0DMordymVH6mRHgY8acyF+De355hVJ0vm0E7RaPRVz8r 5pI6PjwBHDRzZlacsXmrvkR1zikeb7mTYu4S5aRXXs8PvXg2FYZ6QVJh2b+WCfkazI0+ry5HR/qxf 0K0ghgMayeIxd9CsqC2YJEv5zNAPHBkEBZbecAwprpGBtOu58xasoDVaml+0bbi8LpOwrLwZgjTFU MGcg2a2eST1wqwDjwbJARx9csdfzLLegmS3/PTdV8=; Received: by russelstein.xyz with esmtpsa (TLS1.3:ECDHE_SECP256R1__RSA_PSS_RSAE_SHA256__AES_256_GCM:256) (Exim 4.98) (envelope-from <reepca@HIDDEN>) id 1tj7Il-000000003B2-3mGi; Fri, 14 Feb 2025 19:49:05 -0600 From: Reepca Russelstein <reepca@HIDDEN> To: Ludovic =?utf-8?Q?Court=C3=A8s?= <ludo@HIDDEN> Subject: Re: [bug#75810] [PATCH 0/6] Rootless guix-daemon In-Reply-To: <877c5u2ct5.fsf@HIDDEN> ("Ludovic =?utf-8?Q?Court=C3=A8s=22'?= =?utf-8?Q?s?= message of "Thu, 13 Feb 2025 14:29:10 +0100") References: <cover.1737738362.git.ludo@HIDDEN> <87r04qe7dj.fsf@HIDDEN> <87bjvshrk0.fsf@HIDDEN> <875xluehn7.fsf@HIDDEN> <877c5u2ct5.fsf@HIDDEN> Date: Fri, 14 Feb 2025 19:47:27 -0600 Message-ID: <87jz9sc72o.fsf@HIDDEN> User-Agent: Gnus/5.13 (Gnus v5.13) MIME-Version: 1.0 Content-Type: multipart/signed; boundary="=-=-="; micalg=pgp-sha256; protocol="application/pgp-signature" X-Spam-Score: 0.5 X-Spam-Bar: / X-Spam-Score-Int: 5 X-Spam-Report: Spam detection software, running on the system "Sanctum", has NOT identified this incoming email as spam. The original message has been attached to this so you can view it or label similar future email. If you have any questions, see the administrator of that system for details. Content preview: Ludovic Courtès <ludo@HIDDEN> writes: > I’ve sent a v2 addressing some of the issues you mentioned before. > > Crucially, this one remains: > >> #~(let ((guile (string-append (assoc-ref %guile-build-info >> 'bindir) >> "/guile"))) >> (c [...] Content analysis details: (0.5 points, 5.0 required) pts rule name description ---- ---------------------- -------------------------------------------------- -0.0 NO_RELAYS Informational: message was not relayed via SMTP 0.5 FROM_SUSPICIOUS_NTLD From abused NTLD X-Spam-Score: 2.5 (++) X-Spam-Report: Spam detection software, running on the system "debbugs.gnu.org", has NOT identified this incoming email as spam. The original message has been attached to this so you can view it or label similar future email. If you have any questions, see the administrator of that system for details. Content preview: Ludovic Courtès <ludo@HIDDEN> writes: > I’ve sent a v2 addressing some of the issues you mentioned before. > > Crucially, this one remains: > >> #~(let ((guile (string-append (assoc-ref %guile-build-info >> 'bindir) >> "/guile"))) >> (c [...] Content analysis details: (2.5 points, 10.0 required) pts rule name description ---- ---------------------- -------------------------------------------------- -0.0 SPF_PASS SPF: sender matches SPF record 2.0 PDS_OTHER_BAD_TLD Untrustworthy TLDs [URI: russelstein.xyz (xyz)] 0.0 SPF_HELO_NONE SPF: HELO does not publish an SPF Record 0.5 FROM_SUSPICIOUS_NTLD From abused NTLD X-Debbugs-Envelope-To: 75810 Cc: 75810 <at> debbugs.gnu.org X-BeenThere: debbugs-submit <at> debbugs.gnu.org X-Mailman-Version: 2.1.18 Precedence: list List-Id: <debbugs-submit.debbugs.gnu.org> List-Unsubscribe: <https://debbugs.gnu.org/cgi-bin/mailman/options/debbugs-submit>, <mailto:debbugs-submit-request <at> debbugs.gnu.org?subject=unsubscribe> List-Archive: <https://debbugs.gnu.org/cgi-bin/mailman/private/debbugs-submit/> List-Post: <mailto:debbugs-submit <at> debbugs.gnu.org> List-Help: <mailto:debbugs-submit-request <at> debbugs.gnu.org?subject=help> List-Subscribe: <https://debbugs.gnu.org/cgi-bin/mailman/listinfo/debbugs-submit>, <mailto:debbugs-submit-request <at> debbugs.gnu.org?subject=subscribe> Errors-To: debbugs-submit-bounces <at> debbugs.gnu.org Sender: "Debbugs-submit" <debbugs-submit-bounces <at> debbugs.gnu.org> X-Spam-Score: 2.5 (++) X-Spam-Report: Spam detection software, running on the system "debbugs.gnu.org", has NOT identified this incoming email as spam. The original message has been attached to this so you can view it or label similar future email. If you have any questions, see the administrator of that system for details. Content preview: Ludovic Courtès <ludo@HIDDEN> writes: > I’ve sent a v2 addressing some of the issues you mentioned before. > > Crucially, this one remains: > >> #~(let ((guile (string-append (assoc-ref %guile-build-info >> 'bindir) >> "/guile"))) >> (c [...] Content analysis details: (2.5 points, 10.0 required) pts rule name description ---- ---------------------- -------------------------------------------------- -0.0 SPF_PASS SPF: sender matches SPF record 2.0 PDS_OTHER_BAD_TLD Untrustworthy TLDs [URI: russelstein.xyz (xyz)] 0.0 SPF_HELO_NONE SPF: HELO does not publish an SPF Record 0.5 FROM_SUSPICIOUS_NTLD From abused NTLD 1.0 BULK_RE_SUSP_NTLD Precedence bulk and RE: from a suspicious TLD -1.0 MAILING_LIST_MULTI Multiple indicators imply a widely-seen list manager --=-=-= Content-Type: text/plain; charset=utf-8 Content-Transfer-Encoding: quoted-printable Ludovic Court=C3=A8s <ludo@HIDDEN> writes: > I=E2=80=99ve sent a v2 addressing some of the issues you mentioned before. > > Crucially, this one remains: > >> #~(let ((guile (string-append (assoc-ref %guile-build-info >> 'bindir) >> "/guile"))) >> (chmod "/" #o777) >> (copy-file guile "/guile") >> (chmod "/guile" #o6755) >> (sleep 1000) > > That is, / is currently writable inside the build environment, and > that=E2=80=99s: > > 1. a security issue, but it could be addressed with a /top > sub-directory as you wrote; > > 2. a reproducibility issue because a build process now be able to > create/modify files anywhere. > > I looked for solutions to this and couldn=E2=80=99t find anything so far. > > In particular, re-mounting / read-only makes everything beneath it > read-only, including mount points that were initially read-write. It > might be that the wealth of MS_ options could be used to address that, > but honestly, it=E2=80=99s a mess and a maze (=E2=80=9Cshared subtrees=E2= =80=9D?). (Note: I've since seen your followup email on this, but I think there's still some interesting ideas in what I wrote before then) Unless there is special behavior for /, I don't see this (every mount point beneath it becoming read-only) happening. When a bind-mount is created, it inherits its options from the filesystem that the source is on ("The bind mount has the same mount options as the underlying mount" in mount(2)). This does not prevent MS_REMOUNT from being used with the MS_RDONLY bit zeroed to subsequently make the newly-created mount point writable, nor, to my knowledge, does it modify the flags of any existing mount points underneath the bind-mount when MS_REC is used with MS_BIND. I expect that it should work to: 1. go through the entire normal chroot setup 2. bind-mount /gnu/store and /tmp to themselves within the chroot using MS_REC so that they are treated as distinct filesystems but also still have their existing bind-mounts underneath them 3. bind-mount / to itself using MS_REC 4. remount / read-only using MS_RDONLY | MS_REMOUNT | MS_BIND This should ensure that the only writable files in the chroot are those either in /tmp, /gnu/store, or in another filesystem inside the chroot (e.g. /dev, /proc, any of the bind mounts in /gnu/store if we were to forget to remount them MS_RDONLY, etc). But note that this will cause open(2) and chmod(2) for filenames in the same filesystem as / to return EROFS instead of EACCES, and it will still be visible to builders that it's owned by the build user. For that matter the same difference will be observable for bind-mounted store items, but this should matter less because we are already in the practice of registered store items being in a store mounted read-only in practical usage. We could try setting the user-writable permission bit to 0 for /, so that it will give EACCES, which might avoid some of the worst of the unreproducibility. Another option would be to use a root-owned "template" root directory that just contains the (empty) subdirectories gnu, gnu/store, tmp, proc, and dev. This template directory would become the root directory used by pivot_root, with individual filesystems and bind mounts created on top of its subdirectories inside the container's mount namespace. This requires no special permissions, the template directory just has to exist and be publicly-visible. It does occur to me now, though, that we wouldn't be able to actually map any other uids within the container to anything without CAP_SETUID, so / would end up appearing as being owned by the overflow uid. Aside from the actual number, though, it should behave like it's owned by root, EACCES and all. I suppose the same behavior would also be observed if the template were owned by any user other than the build user, not just root. > Alternatively, I wondered if we could make / owned by the overflow user, > but that=E2=80=99s probably not possible. > > Perhaps yet another option would be to use subordinate IDs to map two > different users in the container, but that sounds more involved and I=E2= =80=99m > not sure how to get that done. My still-young understanding of subordinate IDs is that they're not really a kernel thing, but rather are honored by two setuid programs from the shadow package, newuidmap and newgidmap, so that would be a bit like using a configured sudo, albeit probably easier to integrate with the daemon since they basically just replace the initializeUserNamespace procedure with running a command. We would basically just pick a uid and gid for a guixbuild user (there's no reason not to use the regular user-and-group-adding processes for this), then add entries in /etc/subuid and /etc/subgid indicating that guix-daemon is allowed to map exactly that user and exactly that group, as well as its own user and group. We would then add a case in initializeUserNamespace that would fork+exec+wait calls to newuidmap and newgidmap that map two uids and gids: uid and gid 0 map to the guix-daemon user and group, and guestUID and guestGID are mapped to the guixbuild user and group. In the child, we initially have CAP_SETUID within the user namespace, and can therefore set our user and group ids to the newly-mapped guixbuild user / group. The directories created during the container setup will all appear to be owned by uid and gid 0. Note that when creating the chroot store we'll need to make sure that its group is guixbuild so that the builder can write to it, and I'm not sure how to handle chown'ing of build directories in this case (is it even possible for two cooperating unprivileged users to transfer ownership of an inode?). The earliest reference I can find to new*map in the shadow changelog is from 2013, so it's at least that old. We should probably keep the map-single-id case around in initializeUserNamespace as a fallback for the fully-unprivileged use case, e.g. test-env. While this adds an external dependency on a setuid program, it is at least a setuid program that should be fairly common and have a lot of security-minded attention on it, and be less complex than something like sudo. In exchange, we would get the cleanest rootless-with-an-asterisk daemon configuration I can think of, with no known reproducibility issues, little modification to the daemon required, and the extra safety net of a dedicated build user. It sounds like a pretty decent route to take for the privileged-but-rootless case. > @@ -2707,8 +2769,25 @@ void DerivationGoal::deleteTmpDir(bool force) > // Change the ownership if clientUid is set. Never change the > // ownership or the group to "root" for security reasons. > if (settings.clientUid !=3D (uid_t) -1 && settings.clientUid= !=3D 0) { > - _chown(tmpDir, settings.clientUid, > - settings.clientGid !=3D 0 ? settings.clientGid : = -1); > + uid_t uid =3D settings.clientUid; > + gid_t gid =3D settings.clientGid !=3D 0 ? settings.clientGid : -1; > + try { > + _chown(tmpDir, uid, gid); > + > + if (getuid() !=3D 0) { > + /* If, without being root, the '_chown' call above > + succeeded, then it means we have CAP_CHOWN. Retake > + ownership of tmpDir itself so it can be renamed > + below. */ > + chown(tmpDir.c_str(), getuid(), getgid()); > + } > + } catch (SysError & e) { > + /* When running as an unprivileged user and without > + CAP_CHOWN, we cannot chown the build tree. Print a > + message and keep going. */ > + printMsg(lvlInfo, format("cannot change ownership of build directo= ry '%1%': %2%") > + % tmpDir % strerror(e.errNo)); > + } >=20=20 > if (top !=3D tmpDir) { > // Rename tmpDir to its parent, with an intermediate step. (Note: pedantic aside here, there aren't currently issues with what is written immediately below as long as the top directory is used to shield the tmpDir - the top directory is doing a LOT of heavy lifting) It shouldn't be a problem in practice due to top only being owner-accessible, but I feel like I should still note that the second chown here would be of a file that was previously owned by the client user, and as such could, in the most general case, have been replaced with anything, such as a setuid program or symlink. While chown(2) resets setuid and setgid bits for unprivileged users, it's unspecified by posix whether this occurs for privileged users. Linux currently does this permission resetting for privileged users, but it wouldn't surprise me if there's still ways to screw things up by chown'ing a symlink. Also, _chown does the actual chown on descent, not on return, so it first chowns a directory and then goes through its contents. This means that, again, if there weren't the top directory there to block access, it would be possible to access a setuid program before it was chown'ed. We seem to be relying entirely on the Linux behavior of chown to reset setuid / setgid bits. And the man page isn't even entirely clear on this: it says those bits are cleared for "an unprivileged user", that a "privileged" user here means one with CAP_CHOWN, and that in Linux since 2.2.13 "root" is treated like other users. This doesn't answer the question of what happens for privileged non-root users. It's also not clear what happens when a user chown's a file with a uid and gid that aren't -1, but are the same as the current owner and group of the file (experimentally, it still resets the setid bits). It would probably be a good idea to explicitly reset these bits in _chown, and perhaps modify _chown to operate bottom-up instead of top-down. Alternatively, we could use secureFilePerms before calling _chown. Also, not shown here, but there's a chmod(tmpDir.c_str(), 0755) shortly before all of this, which means there's a window before _chown could be called in which a setuid program could be exposed, if not for the top directory shielding tmpDir. And if settings.clientUid is -1 or 0, then that window has no end. Just something to keep in mind. (End pedantic aside) Now, for the non-pedantic, significant issue that I came across while writing all that: previously, it was not possible for the tmpDir-exposing code to be reached without doing the _chown that also reset setuid and setgid bits. But with this patch, in the non-root, non-CAP_CHOWN case (which is what is currently proposed for Guix System), it can be reached through the catch clause. In that case it will expose tmpDir without changing any permission bits of files beneath it, allowing anybody who can access a setuid program in tmpDir (which, due to that 0755 chmod, is "everybody") to take control of the build user (which in this case would be guix-daemon). Going by the "Running unprivileged but with CAP_CHOWN" comment, it would seem that code is meant to only be reached by reaching the end of the "try" block, not by reaching the end of the "catch" block. I think it would be a good idea to call secureFilePerms(tmpDir) before any attempt at chown'ing. I still think it would be a good idea to call unshare to create an extra user and mount namespace just before executing the builder in the unprivileged case, just to be sure that the mount-locking behavior is triggered in a way that is documented. =2D reepca --=-=-= Content-Type: application/pgp-signature; name="signature.asc" -----BEGIN PGP SIGNATURE----- iQFLBAEBCAA1FiEEdNapMPRLm4SepVYGwWaqSV9/GJwFAmev8jAXHHJlZXBjYUBy dXNzZWxzdGVpbi54eXoACgkQwWaqSV9/GJxhVQgAiklMsjAnY7wew/w14L0WhFXC +esDHM9NfYrtJtozzjTuliqmRahG6G+y05Fi6PGRd7swJ6G2AjgpkM8MRVAt9wwC 2xigqEVy9y/kwGavnOjH2Dmapbek2nBXwjW1fAUgTZHEpFBiEOFHRRL34dEXJsJc CA++5/rZxhA5BnBhgh+pxAshKgq/cfljq5kulelV6rHZlfOHKk8SpVQcXEf6tvue jItLW8g9OirAjPPbI5hzE8Qy+fCw9GbAOE2zj34zqFVWkHTQmUkrpu5OOOR7rhUv LDwM5Tw9jx0pBMmoxq5rfuD6CVdNLUj/H14zTJoaXfw3fGwrTo1GQGiOo8b3ew== =AduA -----END PGP SIGNATURE----- --=-=-=--
guix-patches@HIDDEN
:bug#75810
; Package guix-patches
.
Full text available.Received: (at 75810) by debbugs.gnu.org; 14 Feb 2025 15:23:39 +0000 From debbugs-submit-bounces <at> debbugs.gnu.org Fri Feb 14 10:23:39 2025 Received: from localhost ([127.0.0.1]:51200 helo=debbugs.gnu.org) by debbugs.gnu.org with esmtp (Exim 4.84_2) (envelope-from <debbugs-submit-bounces <at> debbugs.gnu.org>) id 1tixXW-0005g2-QZ for submit <at> debbugs.gnu.org; Fri, 14 Feb 2025 10:23:39 -0500 Received: from eggs.gnu.org ([2001:470:142:3::10]:44404) by debbugs.gnu.org with esmtps (TLS1.2:ECDHE_RSA_AES_256_GCM_SHA384:256) (Exim 4.84_2) (envelope-from <ludo@HIDDEN>) id 1tixXV-0005fm-5z for 75810 <at> debbugs.gnu.org; Fri, 14 Feb 2025 10:23:37 -0500 Received: from fencepost.gnu.org ([2001:470:142:3::e]) by eggs.gnu.org with esmtps (TLS1.2:ECDHE_RSA_AES_256_GCM_SHA384:256) (Exim 4.90_1) (envelope-from <ludo@HIDDEN>) id 1tixXP-0008TT-4b; Fri, 14 Feb 2025 10:23:31 -0500 DKIM-Signature: v=1; a=rsa-sha256; q=dns/txt; c=relaxed/relaxed; d=gnu.org; s=fencepost-gnu-org; h=MIME-Version:Date:References:In-Reply-To:Subject:To: From; bh=e6PUNMTXIvuZUwE6yr8lLYrCSAO/UuoYOKh2/mF7new=; b=F0+9MZatRCOQAcxuQl23 9nZyY2sWGT6VCjqcClbFYTV1lki0lJ6nsgAXVU4CMUFZgkMAXLNquE0WvbRm7cSLQMqf+iUanH0mO ynM0r23F4nGsoW8jasQ+Ll2oEaSRDRmsRnNxcZ+jImuf41q2YQEjZf6lY4xt+AkRwRGtpztWBhZmG 8WCgiThChCRL3iWTfl86+TnP3b30aQw1FBUU3t+q0r5/sbYdZYY/Kj9OMBbBzuj8bNZk/75clqBSp xqquS4hBunOaxBGTz2kcfLiekldR+b8zhkXi1KxfJqaSrz64x0zTeDYIPq3xETIjYz9KMGr6M6VQY MPOqKhXilpvUpg==; From: =?utf-8?Q?Ludovic_Court=C3=A8s?= <ludo@HIDDEN> To: Reepca Russelstein <reepca@HIDDEN> Subject: Re: [bug#75810] [PATCH 0/6] Rootless guix-daemon In-Reply-To: <877c5u2ct5.fsf@HIDDEN> ("Ludovic =?utf-8?Q?Court=C3=A8s=22'?= =?utf-8?Q?s?= message of "Thu, 13 Feb 2025 14:29:10 +0100") References: <cover.1737738362.git.ludo@HIDDEN> <87r04qe7dj.fsf@HIDDEN> <87bjvshrk0.fsf@HIDDEN> <875xluehn7.fsf@HIDDEN> <877c5u2ct5.fsf@HIDDEN> Date: Fri, 14 Feb 2025 16:23:28 +0100 Message-ID: <87v7tcy2hb.fsf@HIDDEN> User-Agent: Gnus/5.13 (Gnus v5.13) MIME-Version: 1.0 Content-Type: text/plain; charset=utf-8 Content-Transfer-Encoding: quoted-printable X-Spam-Score: -2.3 (--) X-Debbugs-Envelope-To: 75810 Cc: 75810 <at> debbugs.gnu.org X-BeenThere: debbugs-submit <at> debbugs.gnu.org X-Mailman-Version: 2.1.18 Precedence: list List-Id: <debbugs-submit.debbugs.gnu.org> List-Unsubscribe: <https://debbugs.gnu.org/cgi-bin/mailman/options/debbugs-submit>, <mailto:debbugs-submit-request <at> debbugs.gnu.org?subject=unsubscribe> List-Archive: <https://debbugs.gnu.org/cgi-bin/mailman/private/debbugs-submit/> List-Post: <mailto:debbugs-submit <at> debbugs.gnu.org> List-Help: <mailto:debbugs-submit-request <at> debbugs.gnu.org?subject=help> List-Subscribe: <https://debbugs.gnu.org/cgi-bin/mailman/listinfo/debbugs-submit>, <mailto:debbugs-submit-request <at> debbugs.gnu.org?subject=subscribe> Errors-To: debbugs-submit-bounces <at> debbugs.gnu.org Sender: "Debbugs-submit" <debbugs-submit-bounces <at> debbugs.gnu.org> X-Spam-Score: -3.3 (---) Ludovic Court=C3=A8s <ludo@HIDDEN> skribis: > In particular, re-mounting / read-only makes everything beneath it > read-only, including mount points that were initially read-write. OK, I think I was sleepy or something yesterday: it=E2=80=99s enough to cre= ate separate mount points for /tmp and for the store in the mount namespaces, and these will remain writable after / has been remounted read-only. Working on it! Ludo=E2=80=99.
guix-patches@HIDDEN
:bug#75810
; Package guix-patches
.
Full text available.Received: (at 75810) by debbugs.gnu.org; 13 Feb 2025 13:29:23 +0000 From debbugs-submit-bounces <at> debbugs.gnu.org Thu Feb 13 08:29:23 2025 Received: from localhost ([127.0.0.1]:41379 helo=debbugs.gnu.org) by debbugs.gnu.org with esmtp (Exim 4.84_2) (envelope-from <debbugs-submit-bounces <at> debbugs.gnu.org>) id 1tiZHO-0004mw-U8 for submit <at> debbugs.gnu.org; Thu, 13 Feb 2025 08:29:23 -0500 Received: from eggs.gnu.org ([2001:470:142:3::10]:38006) by debbugs.gnu.org with esmtps (TLS1.2:ECDHE_RSA_AES_256_GCM_SHA384:256) (Exim 4.84_2) (envelope-from <ludo@HIDDEN>) id 1tiZHN-0004mf-3G for 75810 <at> debbugs.gnu.org; Thu, 13 Feb 2025 08:29:21 -0500 Received: from fencepost.gnu.org ([2001:470:142:3::e]) by eggs.gnu.org with esmtps (TLS1.2:ECDHE_RSA_AES_256_GCM_SHA384:256) (Exim 4.90_1) (envelope-from <ludo@HIDDEN>) id 1tiZHF-0005ZU-Ay; Thu, 13 Feb 2025 08:29:13 -0500 DKIM-Signature: v=1; a=rsa-sha256; q=dns/txt; c=relaxed/relaxed; d=gnu.org; s=fencepost-gnu-org; h=MIME-Version:Date:References:In-Reply-To:Subject:To: From; bh=l/esS911RSdwAeAkcZ+SdNMpJFVwnU9hjVw/Fq6zTes=; b=MyCTQ0mKX9OSWlgfSKR9 mBc3IN+gz/rabYfreyLNie+m3D31Q30wiMlM52JMhjuRck6CZCTAsd+bkyypuc4HrV8Yx4lbx6LxF TTkjnyChIrxfjTZZ+5HSeENKDHPWW4KO70bj9mKVQc+vEuE1q4MKkhGTNDwRvZOUQCqZoy+qTqkX+ fOanrkH/77HQso3gA89pRDKbmQJBoQo447Wfe26PK6JI68E3LPoiQ3ciCi9WGvGHgv0Ds/tWq6A9G XZ9VDwmlOquAJP2nfjAzL+HhrELKpRpeTDsNyPQveVBCQFktpHcrYjiW5yAiMfLZFVYz2BI6cHS/2 KROoIBlQP3Tv8w==; From: =?utf-8?Q?Ludovic_Court=C3=A8s?= <ludo@HIDDEN> To: Reepca Russelstein <reepca@HIDDEN> Subject: Re: [bug#75810] [PATCH 0/6] Rootless guix-daemon In-Reply-To: <875xluehn7.fsf@HIDDEN> (Reepca Russelstein's message of "Fri, 31 Jan 2025 16:35:24 -0600") References: <cover.1737738362.git.ludo@HIDDEN> <87r04qe7dj.fsf@HIDDEN> <87bjvshrk0.fsf@HIDDEN> <875xluehn7.fsf@HIDDEN> Date: Thu, 13 Feb 2025 14:29:10 +0100 Message-ID: <877c5u2ct5.fsf@HIDDEN> User-Agent: Gnus/5.13 (Gnus v5.13) MIME-Version: 1.0 Content-Type: text/plain; charset=utf-8 Content-Transfer-Encoding: quoted-printable X-Spam-Score: -2.3 (--) X-Debbugs-Envelope-To: 75810 Cc: 75810 <at> debbugs.gnu.org X-BeenThere: debbugs-submit <at> debbugs.gnu.org X-Mailman-Version: 2.1.18 Precedence: list List-Id: <debbugs-submit.debbugs.gnu.org> List-Unsubscribe: <https://debbugs.gnu.org/cgi-bin/mailman/options/debbugs-submit>, <mailto:debbugs-submit-request <at> debbugs.gnu.org?subject=unsubscribe> List-Archive: <https://debbugs.gnu.org/cgi-bin/mailman/private/debbugs-submit/> List-Post: <mailto:debbugs-submit <at> debbugs.gnu.org> List-Help: <mailto:debbugs-submit-request <at> debbugs.gnu.org?subject=help> List-Subscribe: <https://debbugs.gnu.org/cgi-bin/mailman/listinfo/debbugs-submit>, <mailto:debbugs-submit-request <at> debbugs.gnu.org?subject=subscribe> Errors-To: debbugs-submit-bounces <at> debbugs.gnu.org Sender: "Debbugs-submit" <debbugs-submit-bounces <at> debbugs.gnu.org> X-Spam-Score: -3.3 (---) Hello Reepca, Thanks a lot for your feedback, very useful as always. I=E2=80=99ve sent a v2 addressing some of the issues you mentioned before. Crucially, this one remains: > #~(let ((guile (string-append (assoc-ref %guile-build-info > 'bindir) > "/guile"))) > (chmod "/" #o777) > (copy-file guile "/guile") > (chmod "/guile" #o6755) > (sleep 1000) That is, / is currently writable inside the build environment, and that=E2=80=99s: 1. a security issue, but it could be addressed with a /top sub-directory as you wrote; 2. a reproducibility issue because a build process now be able to create/modify files anywhere. I looked for solutions to this and couldn=E2=80=99t find anything so far. In particular, re-mounting / read-only makes everything beneath it read-only, including mount points that were initially read-write. It might be that the wealth of MS_ options could be used to address that, but honestly, it=E2=80=99s a mess and a maze (=E2=80=9Cshared subtrees=E2= =80=9D?). Alternatively, I wondered if we could make / owned by the overflow user, but that=E2=80=99s probably not possible. Perhaps yet another option would be to use subordinate IDs to map two different users in the container, but that sounds more involved and I=E2=80= =99m not sure how to get that done. Thoughts? Ludo=E2=80=99.
guix-patches@HIDDEN
:bug#75810
; Package guix-patches
.
Full text available.Received: (at 75810) by debbugs.gnu.org; 13 Feb 2025 12:14:00 +0000 From debbugs-submit-bounces <at> debbugs.gnu.org Thu Feb 13 07:14:00 2025 Received: from localhost ([127.0.0.1]:41142 helo=debbugs.gnu.org) by debbugs.gnu.org with esmtp (Exim 4.84_2) (envelope-from <debbugs-submit-bounces <at> debbugs.gnu.org>) id 1tiY6R-0003f0-HF for submit <at> debbugs.gnu.org; Thu, 13 Feb 2025 07:13:59 -0500 Received: from eggs.gnu.org ([2001:470:142:3::10]:41578) by debbugs.gnu.org with esmtps (TLS1.2:ECDHE_RSA_AES_256_GCM_SHA384:256) (Exim 4.84_2) (envelope-from <ludo@HIDDEN>) id 1tiY64-0003ci-Ma for 75810 <at> debbugs.gnu.org; Thu, 13 Feb 2025 07:13:38 -0500 Received: from fencepost.gnu.org ([2001:470:142:3::e]) by eggs.gnu.org with esmtps (TLS1.2:ECDHE_RSA_AES_256_GCM_SHA384:256) (Exim 4.90_1) (envelope-from <ludo@HIDDEN>) id 1tiY5z-0001DJ-Bn; Thu, 13 Feb 2025 07:13:31 -0500 DKIM-Signature: v=1; a=rsa-sha256; q=dns/txt; c=relaxed/relaxed; d=gnu.org; s=fencepost-gnu-org; h=MIME-Version:References:In-Reply-To:Date:Subject:To: From; bh=SAvT4z24GIwTeHQpKPl/539zwByt/TDk4vE7n2M+zME=; b=h67w/jtcHIqsVB0qmmG/ J1P84SrKP159YVZ48w2RdQ5zmVLh4hcTg/pqsYAMb/KWtPHDEJN6r1BQ+W2gQOceyNh6eqgStuXBd NKm/slJV7BfdYqkU2rhGBHEn11h3EHcc+qpHBNv1x79WuIg7dGTwYaKpOxRoIOT/tBrm+PzYQc5EM P1yklga+NAWB+R9T4ExkvKtUqRGB6SfyBgi+NlxEKRb+7Cx1PfAiWWTLZOQ96SPG8t75onsSQQO6r nhx1ePt1ZPQw0syI192uNy8QoukIWfnJ18A/Duco0u6Ug16KF2ghrH27CrdAqwgMJE/G5WJKno0se f1rv3opQEQiLiA==; From: =?UTF-8?q?Ludovic=20Court=C3=A8s?= <ludo@HIDDEN> To: 75810 <at> debbugs.gnu.org Subject: [PATCH v2 8/9] =?UTF-8?q?etc:=20systemd=20services:=20Run=20?= =?UTF-8?q?=E2=80=98guix-daemon=E2=80=99=20as=20an=20unprivileged=20user.?= Date: Thu, 13 Feb 2025 13:13:11 +0100 Message-ID: <a706daddbcc0193cda052bd3e0c76c6cf355a9bf.1739448513.git.ludo@HIDDEN> X-Mailer: git-send-email 2.48.1 In-Reply-To: <cover.1739448513.git.ludo@HIDDEN> References: <cover.1739448513.git.ludo@HIDDEN> MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit X-Spam-Score: -2.3 (--) X-Debbugs-Envelope-To: 75810 Cc: =?UTF-8?q?Ludovic=20Court=C3=A8s?= <ludo@HIDDEN> X-BeenThere: debbugs-submit <at> debbugs.gnu.org X-Mailman-Version: 2.1.18 Precedence: list List-Id: <debbugs-submit.debbugs.gnu.org> List-Unsubscribe: <https://debbugs.gnu.org/cgi-bin/mailman/options/debbugs-submit>, <mailto:debbugs-submit-request <at> debbugs.gnu.org?subject=unsubscribe> List-Archive: <https://debbugs.gnu.org/cgi-bin/mailman/private/debbugs-submit/> List-Post: <mailto:debbugs-submit <at> debbugs.gnu.org> List-Help: <mailto:debbugs-submit-request <at> debbugs.gnu.org?subject=help> List-Subscribe: <https://debbugs.gnu.org/cgi-bin/mailman/listinfo/debbugs-submit>, <mailto:debbugs-submit-request <at> debbugs.gnu.org?subject=subscribe> Errors-To: debbugs-submit-bounces <at> debbugs.gnu.org Sender: "Debbugs-submit" <debbugs-submit-bounces <at> debbugs.gnu.org> X-Spam-Score: -3.3 (---) * etc/guix-daemon.service.in (ExecStart): Remove ‘--build-users-group’. (User, AmbientCapabilities): New fields. Change-Id: Id826b8ab535844b6024d777f6bd15fd49db6d65e --- etc/guix-daemon.service.in | 12 +++++++++++- 1 file changed, 11 insertions(+), 1 deletion(-) diff --git a/etc/guix-daemon.service.in b/etc/guix-daemon.service.in index 5c43d9b7f1b..f9f0b28b356 100644 --- a/etc/guix-daemon.service.in +++ b/etc/guix-daemon.service.in @@ -7,9 +7,19 @@ Description=Build daemon for GNU Guix [Service] ExecStart=@localstatedir@/guix/profiles/per-user/root/current-guix/bin/guix-daemon \ - --build-users-group=guixbuild --discover=no \ + --discover=no \ --substitute-urls='@GUIX_SUBSTITUTE_URLS@' Environment='GUIX_LOCPATH=@localstatedir@/guix/profiles/per-user/root/guix-profile/lib/locale' LC_ALL=en_US.utf8 + +# Run under a dedicated unprivileged user account. +User=guix-daemon + +# Provide the CAP_CHOWN capability so that guix-daemon cran create and chown +# /var/guix/profiles/per-user/$USER and also chown failed build directories +# when using '--keep-failed'. Note that guix-daemon explicitly drops ambient +# capabilities before executing build processes so they don't inherit them. +AmbientCapabilities=CAP_CHOWN + StandardOutput=journal StandardError=journal -- 2.48.1
guix-patches@HIDDEN
:bug#75810
; Package guix-patches
.
Full text available.Received: (at 75810) by debbugs.gnu.org; 13 Feb 2025 12:13:59 +0000 From debbugs-submit-bounces <at> debbugs.gnu.org Thu Feb 13 07:13:58 2025 Received: from localhost ([127.0.0.1]:41140 helo=debbugs.gnu.org) by debbugs.gnu.org with esmtp (Exim 4.84_2) (envelope-from <debbugs-submit-bounces <at> debbugs.gnu.org>) id 1tiY6N-0003ej-5f for submit <at> debbugs.gnu.org; Thu, 13 Feb 2025 07:13:58 -0500 Received: from eggs.gnu.org ([2001:470:142:3::10]:51210) by debbugs.gnu.org with esmtps (TLS1.2:ECDHE_RSA_AES_256_GCM_SHA384:256) (Exim 4.84_2) (envelope-from <ludo@HIDDEN>) id 1tiY5z-0003cJ-V8 for 75810 <at> debbugs.gnu.org; Thu, 13 Feb 2025 07:13:39 -0500 Received: from fencepost.gnu.org ([2001:470:142:3::e]) by eggs.gnu.org with esmtps (TLS1.2:ECDHE_RSA_AES_256_GCM_SHA384:256) (Exim 4.90_1) (envelope-from <ludo@HIDDEN>) id 1tiY5u-0001Br-9A; Thu, 13 Feb 2025 07:13:26 -0500 DKIM-Signature: v=1; a=rsa-sha256; q=dns/txt; c=relaxed/relaxed; d=gnu.org; s=fencepost-gnu-org; h=MIME-Version:References:In-Reply-To:Date:Subject:To: From; bh=BOeQoIgQrfkZtIX93BwNljFCfZnlkIb/zLXPFnLkIxI=; b=gxlH90pnYCnG/xTuctH8 fAOISy6CqyIuwMEDz/hN9atylBjrKRFr6TWC939E/4JY9k66j4/WySxWaSBaZhnRHBl8dmz/ZXNKf 8Bn5gsTwkeA4cNudbPPwMc+w3crleX4kuqAGwqXEa06ji7xizESnOYV+1A4SG2Q1EfBXLxRxGVq0B +W7K1GWe6h5txqcmQQ8jwVUJ53IsGp2zwGTIqtLgsDaJTo5UmovlIiZfWncSuoUUGQpCnf+w5J4nX gIUPTTP9g8GXu1rGwefBw5Np70c6pc+r4CrZoAsq0lar3seaazbiCLQGrpqZ3ArqA3TZodkYwYnyp bdPDjK3eoAum8g==; From: =?UTF-8?q?Ludovic=20Court=C3=A8s?= <ludo@HIDDEN> To: 75810 <at> debbugs.gnu.org Subject: [PATCH v2 3/9] daemon: Remount inputs as read-only. Date: Thu, 13 Feb 2025 13:13:06 +0100 Message-ID: <15b9f858aa6c636cd02801c35bbcc467a184d1b0.1739448513.git.ludo@HIDDEN> X-Mailer: git-send-email 2.48.1 In-Reply-To: <cover.1739448513.git.ludo@HIDDEN> References: <cover.1739448513.git.ludo@HIDDEN> MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit X-Spam-Score: -0.3 (/) X-Debbugs-Envelope-To: 75810 Cc: =?UTF-8?q?Ludovic=20Court=C3=A8s?= <ludo@HIDDEN>, Reepca Russelstein <reepca@HIDDEN> X-BeenThere: debbugs-submit <at> debbugs.gnu.org X-Mailman-Version: 2.1.18 Precedence: list List-Id: <debbugs-submit.debbugs.gnu.org> List-Unsubscribe: <https://debbugs.gnu.org/cgi-bin/mailman/options/debbugs-submit>, <mailto:debbugs-submit-request <at> debbugs.gnu.org?subject=unsubscribe> List-Archive: <https://debbugs.gnu.org/cgi-bin/mailman/private/debbugs-submit/> List-Post: <mailto:debbugs-submit <at> debbugs.gnu.org> List-Help: <mailto:debbugs-submit-request <at> debbugs.gnu.org?subject=help> List-Subscribe: <https://debbugs.gnu.org/cgi-bin/mailman/listinfo/debbugs-submit>, <mailto:debbugs-submit-request <at> debbugs.gnu.org?subject=subscribe> Errors-To: debbugs-submit-bounces <at> debbugs.gnu.org Sender: "Debbugs-submit" <debbugs-submit-bounces <at> debbugs.gnu.org> X-Spam-Score: -1.3 (-) * nix/libstore/build.cc (DerivationGoal::runChild): Remount ‘target’ as read-only. Reported-by: Reepca Russelstein <reepca@HIDDEN> Change-Id: Ib7201bcf4363be566f205d23d17fe2f55d3ad666 --- nix/libstore/build.cc | 7 +++++++ 1 file changed, 7 insertions(+) diff --git a/nix/libstore/build.cc b/nix/libstore/build.cc index f4cd2131c84..7151bb6c6f1 100644 --- a/nix/libstore/build.cc +++ b/nix/libstore/build.cc @@ -2094,8 +2094,15 @@ void DerivationGoal::runChild() createDirs(dirOf(target)); writeFile(target, ""); } + + /* Extra flags passed with MS_BIND are ignored, hence the + extra MS_REMOUNT. */ if (mount(source.c_str(), target.c_str(), "", MS_BIND, 0) == -1) throw SysError(format("bind mount from `%1%' to `%2%' failed") % source % target); + if (source != tmpDir) { + if (mount(source.c_str(), target.c_str(), "", MS_BIND | MS_REMOUNT | MS_RDONLY, 0) == -1) + throw SysError(format("read-only remount of `%1%' failed") % target); + } } /* Bind a new instance of procfs on /proc to reflect our -- 2.48.1
guix-patches@HIDDEN
:bug#75810
; Package guix-patches
.
Full text available.Received: (at 75810) by debbugs.gnu.org; 13 Feb 2025 12:13:55 +0000 From debbugs-submit-bounces <at> debbugs.gnu.org Thu Feb 13 07:13:55 2025 Received: from localhost ([127.0.0.1]:41138 helo=debbugs.gnu.org) by debbugs.gnu.org with esmtp (Exim 4.84_2) (envelope-from <debbugs-submit-bounces <at> debbugs.gnu.org>) id 1tiY6M-0003ec-I4 for submit <at> debbugs.gnu.org; Thu, 13 Feb 2025 07:13:55 -0500 Received: from eggs.gnu.org ([2001:470:142:3::10]:41590) by debbugs.gnu.org with esmtps (TLS1.2:ECDHE_RSA_AES_256_GCM_SHA384:256) (Exim 4.84_2) (envelope-from <ludo@HIDDEN>) id 1tiY65-0003cl-Tb for 75810 <at> debbugs.gnu.org; Thu, 13 Feb 2025 07:13:39 -0500 Received: from fencepost.gnu.org ([2001:470:142:3::e]) by eggs.gnu.org with esmtps (TLS1.2:ECDHE_RSA_AES_256_GCM_SHA384:256) (Exim 4.90_1) (envelope-from <ludo@HIDDEN>) id 1tiY60-0001Dd-Ik; Thu, 13 Feb 2025 07:13:32 -0500 DKIM-Signature: v=1; a=rsa-sha256; q=dns/txt; c=relaxed/relaxed; d=gnu.org; s=fencepost-gnu-org; h=MIME-Version:References:In-Reply-To:Date:Subject:To: From; bh=1rCJ8nHLWbW07YSX+p8fFleVwPMsQATsuCgNH7lgBhY=; b=sZdI5b+j4u5+MGlvoq0F KF73lz5gFGF634y+I710soMF4QEEIcwEcfqVZLA03sjMQ39UNO5U7i5E56iBGQAEd2D366bZDtJsf bBYxl6/+DlpDtTMPGvRE+nhfkEdZk/m65/UvVVBWPRwpVydYYzWWB6kUAxl+gAyyqens1LRuvKDUH F5i+xIhne/Sma7IG4zc37gxPmqm8f9IqIXO2LJox2nDgj4NZ6KUJ55gD7uphcmfUqUrkuF3x1QM0L o4DEHMSovpAmxnLd0jrUFyLtACzMF94Lw5a6MhGCVNeKL4fYJ1kGFGwzv33M6+i1ZaRhdRYqxQDkJ Lo0J1T3ew3Rz3A==; From: =?UTF-8?q?Ludovic=20Court=C3=A8s?= <ludo@HIDDEN> To: 75810 <at> debbugs.gnu.org Subject: [PATCH v2 9/9] guix-install.sh: Support the unprivileged daemon where possible. Date: Thu, 13 Feb 2025 13:13:12 +0100 Message-ID: <107f6e7972e083aa645e8a1bc121750c4d94fc1f.1739448513.git.ludo@HIDDEN> X-Mailer: git-send-email 2.48.1 In-Reply-To: <cover.1739448513.git.ludo@HIDDEN> References: <cover.1739448513.git.ludo@HIDDEN> MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit X-Spam-Score: -2.3 (--) X-Debbugs-Envelope-To: 75810 Cc: =?UTF-8?q?Ludovic=20Court=C3=A8s?= <ludo@HIDDEN> X-BeenThere: debbugs-submit <at> debbugs.gnu.org X-Mailman-Version: 2.1.18 Precedence: list List-Id: <debbugs-submit.debbugs.gnu.org> List-Unsubscribe: <https://debbugs.gnu.org/cgi-bin/mailman/options/debbugs-submit>, <mailto:debbugs-submit-request <at> debbugs.gnu.org?subject=unsubscribe> List-Archive: <https://debbugs.gnu.org/cgi-bin/mailman/private/debbugs-submit/> List-Post: <mailto:debbugs-submit <at> debbugs.gnu.org> List-Help: <mailto:debbugs-submit-request <at> debbugs.gnu.org?subject=help> List-Subscribe: <https://debbugs.gnu.org/cgi-bin/mailman/listinfo/debbugs-submit>, <mailto:debbugs-submit-request <at> debbugs.gnu.org?subject=subscribe> Errors-To: debbugs-submit-bounces <at> debbugs.gnu.org Sender: "Debbugs-submit" <debbugs-submit-bounces <at> debbugs.gnu.org> X-Spam-Score: -3.3 (---) * etc/guix-install.sh (create_account): New function. (sys_create_build_user): Use it. When ‘guix-daemon.service’ contains “User=guix-daemon” only create the ‘guix-daemon’ user and group. (sys_delete_build_user): Delete the ‘guix-daemon’ user and group. (can_install_unprivileged_daemon): New function. (sys_create_store): When installing the unprivileged daemon, change ownership of /gnu and /var/guix, and create /var/log/guix. (sys_authorize_build_farms): When the ‘guix-daemon’ account exists, change ownership of /etc/guix. (sys_enable_guix_daemon): Do not install ‘gnu-store.mount’ when running an unprivileged daemon. Change-Id: I73e573f1cc5c0cb3794aaaa6b576616b66e0c5e9 --- etc/guix-install.sh | 114 +++++++++++++++++++++++++++++++++++--------- 1 file changed, 91 insertions(+), 23 deletions(-) diff --git a/etc/guix-install.sh b/etc/guix-install.sh index f07b2741bb9..4f08eff8476 100755 --- a/etc/guix-install.sh +++ b/etc/guix-install.sh @@ -389,6 +389,11 @@ sys_create_store() cd "$tmp_path" _msg "${INF}Installing /var/guix and /gnu..." # Strip (skip) the leading ‘.’ component, which fails on read-only ‘/’. + # + # TODO: Eventually extract with ‘--owner=guix-daemon’ when installing + # and unprivileged guix-daemon service; for now, this script may install + # from both an old release that does not support unprivileged guix-daemon + # and a new release that does, so ‘chown -R’ later if needed. tar --extract --strip-components=1 --file "$pkg" -C / _msg "${INF}Linking the root user's profile" @@ -414,38 +419,82 @@ sys_delete_store() rm -rf ~root/.config/guix } +create_account() +{ + local user="$1" + local group="$2" + local supplementary_groups="$3" + local comment="$4" + + if id "$user" &>/dev/null; then + _msg "${INF}user '$user' is already in the system, reset" + usermod -g "$group" -G "$supplementary_groups" \ + -d /var/empty -s "$(which nologin)" \ + -c "$comment" "$user" + else + useradd -g "$group" -G "$supplementary_groups" \ + -d /var/empty -s "$(which nologin)" \ + -c "$comment" --system "$user" + _msg "${PAS}user added <$user>" + fi +} + +can_install_unprivileged_daemon() +{ # Return true if we can install guix-daemon running without privileges. + [ "$INIT_SYS" = systemd ] && \ + grep -q "User=guix-daemon" \ + ~root/.config/guix/current/lib/systemd/system/guix-daemon.service \ + && ([ ! -f /proc/sys/kernel/unprivileged_userns_clone ] \ + || [ "$(cat /proc/sys/kernel/unprivileged_userns_clone)" -eq 1 ]) +} + sys_create_build_user() { # Create the group and user accounts for build users. _debug "--- [ ${FUNCNAME[0]} ] ---" - if getent group guixbuild > /dev/null; then - _msg "${INF}group guixbuild exists" - else - groupadd --system guixbuild - _msg "${PAS}group <guixbuild> created" - fi - if getent group kvm > /dev/null; then _msg "${INF}group kvm exists and build users will be added to it" local KVMGROUP=,kvm fi - for i in $(seq -w 1 10); do - if id "guixbuilder${i}" &>/dev/null; then - _msg "${INF}user is already in the system, reset" - usermod -g guixbuild -G guixbuild${KVMGROUP} \ - -d /var/empty -s "$(which nologin)" \ - -c "Guix build user $i" \ - "guixbuilder${i}"; - else - useradd -g guixbuild -G guixbuild${KVMGROUP} \ - -d /var/empty -s "$(which nologin)" \ - -c "Guix build user $i" --system \ - "guixbuilder${i}"; - _msg "${PAS}user added <guixbuilder${i}>" - fi - done + if [ "$INIT_SYS" = systemd ] && \ + grep -q "User=guix-daemon" \ + ~root/.config/guix/current/lib/systemd/system/guix-daemon.service + then + if getent group guix-daemon > /dev/null; then + _msg "${INF}group guix-daemon exists" + else + groupadd --system guix-daemon + _msg "${PAS}group guix-daemon created" + fi + + create_account guix-daemon guix-daemon \ + guix-daemon$KVMGROUP \ + "Unprivileged Guix Daemon User" + + # ‘tar xf’ creates root:root files. Change that. + chown -R guix-daemon:guix-daemon \ + /gnu /var/guix + + # The unprivileged cannot create the log directory by itself. + mkdir /var/log/guix + chown guix-daemon:guix-daemon /var/log/guix + chmod 755 /var/log/guix + else + if getent group guixbuild > /dev/null; then + _msg "${INF}group guixbuild exists" + else + groupadd --system guixbuild + _msg "${PAS}group <guixbuild> created" + fi + + for i in $(seq -w 1 10); do + create_account "guixbuilder${i}" "guixbuild" \ + "guixbuild${KVMGROUP}" \ + "Guix build user $i" + done + fi } sys_delete_build_user() @@ -460,6 +509,14 @@ sys_delete_build_user() if getent group guixbuild &>/dev/null; then groupdel -f guixbuild fi + + _msg "${INF}remove guix-daemon user" + if id guix-daemon &>/dev/null; then + userdel -f guix-daemon + fi + if getent group guix-daemon &>/dev/null; then + groupdel -f guix-daemon + fi } sys_enable_guix_daemon() @@ -503,7 +560,14 @@ sys_enable_guix_daemon() # Install after guix-daemon.service to avoid a harmless warning. # systemd .mount units must be named after the target directory. # Here we assume a hard-coded name of /gnu/store. - install_unit gnu-store.mount + # + # FIXME: This feature is unavailable when running an + # unprivileged daemon. + if ! grep -q "User=guix-daemon" \ + /etc/systemd/system/guix-daemon.service + then + install_unit gnu-store.mount + fi systemctl daemon-reload && systemctl start guix-daemon; } && @@ -627,6 +691,10 @@ project's build farms?"; then && guix archive --authorize < "$key" \ && _msg "${PAS}Authorized public key for $host" done + if id guix-daemon &>/dev/null; then + # /etc/guix/acl must be readable by the unprivileged guix-daemon. + chown -R guix-daemon:guix-daemon /etc/guix + fi else _msg "${INF}Skipped authorizing build farm public keys" fi -- 2.48.1
guix-patches@HIDDEN
:bug#75810
; Package guix-patches
.
Full text available.Received: (at 75810) by debbugs.gnu.org; 13 Feb 2025 12:13:54 +0000 From debbugs-submit-bounces <at> debbugs.gnu.org Thu Feb 13 07:13:54 2025 Received: from localhost ([127.0.0.1]:41136 helo=debbugs.gnu.org) by debbugs.gnu.org with esmtp (Exim 4.84_2) (envelope-from <debbugs-submit-bounces <at> debbugs.gnu.org>) id 1tiY6L-0003eY-Fb for submit <at> debbugs.gnu.org; Thu, 13 Feb 2025 07:13:54 -0500 Received: from eggs.gnu.org ([2001:470:142:3::10]:51236) by debbugs.gnu.org with esmtps (TLS1.2:ECDHE_RSA_AES_256_GCM_SHA384:256) (Exim 4.84_2) (envelope-from <ludo@HIDDEN>) id 1tiY61-0003cN-Kt for 75810 <at> debbugs.gnu.org; Thu, 13 Feb 2025 07:13:38 -0500 Received: from fencepost.gnu.org ([2001:470:142:3::e]) by eggs.gnu.org with esmtps (TLS1.2:ECDHE_RSA_AES_256_GCM_SHA384:256) (Exim 4.90_1) (envelope-from <ludo@HIDDEN>) id 1tiY5v-0001C4-8t; Thu, 13 Feb 2025 07:13:27 -0500 DKIM-Signature: v=1; a=rsa-sha256; q=dns/txt; c=relaxed/relaxed; d=gnu.org; s=fencepost-gnu-org; h=MIME-Version:References:In-Reply-To:Date:Subject:To: From; bh=X9e3xrOrc9fu+8aX5VR4ar43pNbWOZRcdzd3TBJnZvU=; b=YmqmF8Ywz7zJ2XFU5LDe xMPvsgIq7+pQlxqfZ+QdNCbsilpruzH09/+/BlXMKtsc8Iqig2Qi34NE+3Ck7/T7OtAHEcDCMLM4Z 6f1EA3jb7u+9APSQqvOE0tq/dhkx4o8bN8NVaGMnxQKucvO100kaeemId8nEjQPHP8JmgwmuuNbf/ TiLyRkaV6NysNr3Hfivdt7xv4rg7YP3mV8iD3pd4f93sicvJk/2bi3iffUqC0hUDXPbJs2oD9Y1YL 1EYng8QyiP5IYJFxMzNGeBsLuqXfKZAbGWN6I3ET9+X5PbiqJhRNNV95IC59jGT1bp0xdcT69yesJ fN+Dzt8t9jfNBA==; From: =?UTF-8?q?Ludovic=20Court=C3=A8s?= <ludo@HIDDEN> To: 75810 <at> debbugs.gnu.org Subject: [PATCH v2 4/9] daemon: Allow running as non-root with unprivileged user namespaces. Date: Thu, 13 Feb 2025 13:13:07 +0100 Message-ID: <eb3f91a7e866f9a1565afd094a158269f548b89e.1739448513.git.ludo@HIDDEN> X-Mailer: git-send-email 2.48.1 In-Reply-To: <cover.1739448513.git.ludo@HIDDEN> References: <cover.1739448513.git.ludo@HIDDEN> MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 X-Debbugs-Cc: Christopher Baines <guix@HIDDEN>, Josselin Poiret <dev@HIDDEN>, Ludovic Courtès <ludo@HIDDEN>, Mathieu Othacehe <othacehe@HIDDEN>, Simon Tournier <zimon.toutoune@HIDDEN>, Tobias Geerinckx-Rice <me@HIDDEN> Content-Transfer-Encoding: 8bit X-Spam-Score: -2.3 (--) X-Debbugs-Envelope-To: 75810 Cc: =?UTF-8?q?Ludovic=20Court=C3=A8s?= <ludovic.courtes@HIDDEN> X-BeenThere: debbugs-submit <at> debbugs.gnu.org X-Mailman-Version: 2.1.18 Precedence: list List-Id: <debbugs-submit.debbugs.gnu.org> List-Unsubscribe: <https://debbugs.gnu.org/cgi-bin/mailman/options/debbugs-submit>, <mailto:debbugs-submit-request <at> debbugs.gnu.org?subject=unsubscribe> List-Archive: <https://debbugs.gnu.org/cgi-bin/mailman/private/debbugs-submit/> List-Post: <mailto:debbugs-submit <at> debbugs.gnu.org> List-Help: <mailto:debbugs-submit-request <at> debbugs.gnu.org?subject=help> List-Subscribe: <https://debbugs.gnu.org/cgi-bin/mailman/listinfo/debbugs-submit>, <mailto:debbugs-submit-request <at> debbugs.gnu.org?subject=subscribe> Errors-To: debbugs-submit-bounces <at> debbugs.gnu.org Sender: "Debbugs-submit" <debbugs-submit-bounces <at> debbugs.gnu.org> X-Spam-Score: -3.3 (---) From: Ludovic Courtès <ludovic.courtes@HIDDEN> * nix/libstore/build.cc (guestUID, guestGID): New variables. (DerivationGoal)[readiness]: New field. (initializeUserNamespace): New function. (DerivationGoal::runChild): When ‘readiness.readSide’ is positive, read from it. (DerivationGoal::startBuilder): Call ‘chown’ only when ‘buildUser.enabled()’ is true. Pass CLONE_NEWUSER to ‘clone’ when ‘buildUser.enabled()’ is false or not running as root. Retry ‘clone’ without CLONE_NEWUSER upon EPERM. (DerivationGoal::registerOutputs): Make ‘actualPath’ writable before ‘rename’. (DerivationGoal::deleteTmpDir): Catch ‘SysError’ around ‘_chown’ call. * nix/libstore/local-store.cc (LocalStore::createUser): Do nothing if ‘dirs’ already exists. Warn instead of failing when failing to chown ‘dir’. * guix/substitutes.scm (%narinfo-cache-directory): Check for ‘_NIX_OPTIONS’ rather than getuid() == 0 to determine the cache location. Change-Id: I38fbe01f80fb45a99cd8a391e55a39a54d64fcb7 --- guix/substitutes.scm | 4 +- nix/libstore/build.cc | 128 +++++++++++++++++++++++++++++------- nix/libstore/local-store.cc | 22 +++++-- 3 files changed, 123 insertions(+), 31 deletions(-) diff --git a/guix/substitutes.scm b/guix/substitutes.scm index e31b3940203..2761a3dafb4 100644 --- a/guix/substitutes.scm +++ b/guix/substitutes.scm @@ -1,5 +1,5 @@ ;;; GNU Guix --- Functional package management for GNU -;;; Copyright © 2013-2021, 2023-2024 Ludovic Courtès <ludo@HIDDEN> +;;; Copyright © 2013-2021, 2023-2025 Ludovic Courtès <ludo@HIDDEN> ;;; Copyright © 2014 Nikita Karetnikov <nikita@HIDDEN> ;;; Copyright © 2018 Kyle Meyer <kyle@HIDDEN> ;;; Copyright © 2020 Christopher Baines <mail@HIDDEN> @@ -76,7 +76,7 @@ (define %narinfo-cache-directory ;; time, 'guix substitute' is called by guix-daemon as root and stores its ;; cached data in /var/guix/…. However, when invoked from 'guix challenge' ;; as a user, it stores its cache in ~/.cache. - (if (zero? (getuid)) + (if (getenv "_NIX_OPTIONS") ;invoked by guix-daemon (or (and=> (getenv "XDG_CACHE_HOME") (cut string-append <> "/guix/substitute")) (string-append %state-directory "/substitute/cache")) diff --git a/nix/libstore/build.cc b/nix/libstore/build.cc index 7151bb6c6f1..18dd27460b7 100644 --- a/nix/libstore/build.cc +++ b/nix/libstore/build.cc @@ -747,6 +747,10 @@ private: friend int childEntry(void *); + /* Pipe to notify readiness to the child process when using unprivileged + user namespaces. */ + Pipe readiness; + /* Check that the derivation outputs all exist and register them as valid. */ void registerOutputs(); @@ -1622,6 +1626,25 @@ int childEntry(void * arg) } +/* UID and GID of the build user inside its own user namespace. */ +static const uid_t guestUID = 30001; +static const gid_t guestGID = 30000; + +/* Initialize the user namespace of CHILD. */ +static void initializeUserNamespace(pid_t child) +{ + auto hostUID = getuid(); + auto hostGID = getgid(); + + writeFile("/proc/" + std::to_string(child) + "/uid_map", + (format("%d %d 1") % guestUID % hostUID).str()); + + writeFile("/proc/" + std::to_string(child) + "/setgroups", "deny"); + + writeFile("/proc/" + std::to_string(child) + "/gid_map", + (format("%d %d 1") % guestGID % hostGID).str()); +} + void DerivationGoal::startBuilder() { auto f = format( @@ -1685,7 +1708,7 @@ void DerivationGoal::startBuilder() then an attacker could create in it a hardlink to a root-owned file such as /etc/shadow. If 'keepFailed' is true, the daemon would then chown that hardlink to the user, giving them write access to - that file. */ + that file. See CVE-2021-27851. */ tmpDir += "/top"; if (mkdir(tmpDir.c_str(), 0700) == 1) throw SysError("creating top-level build directory"); @@ -1802,7 +1825,7 @@ void DerivationGoal::startBuilder() if (mkdir(chrootRootDir.c_str(), 0750) == -1) throw SysError(format("cannot create ‘%1%’") % chrootRootDir); - if (chown(chrootRootDir.c_str(), 0, buildUser.getGID()) == -1) + if (buildUser.enabled() && chown(chrootRootDir.c_str(), 0, buildUser.getGID()) == -1) throw SysError(format("cannot change ownership of ‘%1%’") % chrootRootDir); /* Create a writable /tmp in the chroot. Many builders need @@ -1821,8 +1844,8 @@ void DerivationGoal::startBuilder() (format( "nixbld:x:%1%:%2%:Nix build user:/:/noshell\n" "nobody:x:65534:65534:Nobody:/:/noshell\n") - % (buildUser.enabled() ? buildUser.getUID() : getuid()) - % (buildUser.enabled() ? buildUser.getGID() : getgid())).str()); + % (buildUser.enabled() ? buildUser.getUID() : guestUID) + % (buildUser.enabled() ? buildUser.getGID() : guestGID)).str()); /* Declare the build user's group so that programs get a consistent view of the system (e.g., "id -gn"). */ @@ -1857,7 +1880,7 @@ void DerivationGoal::startBuilder() createDirs(chrootStoreDir); chmod_(chrootStoreDir, 01775); - if (chown(chrootStoreDir.c_str(), 0, buildUser.getGID()) == -1) + if (buildUser.enabled() && chown(chrootStoreDir.c_str(), 0, buildUser.getGID()) == -1) throw SysError(format("cannot change ownership of ‘%1%’") % chrootStoreDir); foreach (PathSet::iterator, i, inputPaths) { @@ -1948,14 +1971,34 @@ void DerivationGoal::startBuilder() if (useChroot) { char stack[32 * 1024]; int flags = CLONE_NEWPID | CLONE_NEWNS | CLONE_NEWIPC | CLONE_NEWUTS | SIGCHLD; - if (!fixedOutput) flags |= CLONE_NEWNET; + if (!fixedOutput) { + flags |= CLONE_NEWNET; + } + if (!buildUser.enabled() || getuid() != 0) { + flags |= CLONE_NEWUSER; + readiness.create(); + } + /* Ensure proper alignment on the stack. On aarch64, it has to be 16 bytes. */ - pid = clone(childEntry, + pid = clone(childEntry, (char *)(((uintptr_t)stack + sizeof(stack) - 8) & ~(uintptr_t)0xf), flags, this); - if (pid == -1) - throw SysError("cloning builder process"); + if (pid == -1) { + if ((flags & CLONE_NEWUSER) != 0 && getuid() != 0) + /* 'clone' fails with EPERM on distros where unprivileged user + namespaces are disabled. Error out instead of giving up on + isolation. */ + throw SysError("cannot create process in unprivileged user namespace"); + else + throw SysError("cloning builder process"); + } + + if ((flags & CLONE_NEWUSER) != 0) { + /* Initialize the UID/GID mapping of the child process. */ + initializeUserNamespace(pid); + writeFull(readiness.writeSide, (unsigned char*)"go\n", 3); + } } else #endif { @@ -2001,23 +2044,34 @@ void DerivationGoal::runChild() _writeToStderr = 0; + if (readiness.readSide > 0) { + /* Wait for the parent process to initialize the UID/GID mapping + of our user namespace. */ + char str[20] = { '\0' }; + readFull(readiness.readSide, (unsigned char*)str, 3); + if (strcmp(str, "go\n") != 0) + throw Error("failed to initialize process in unprivileged user namespace"); + } + restoreAffinity(); commonChildInit(builderOut); #if CHROOT_ENABLED if (useChroot) { - /* Initialise the loopback interface. */ - AutoCloseFD fd(socket(PF_INET, SOCK_DGRAM, IPPROTO_IP)); - if (fd == -1) throw SysError("cannot open IP socket"); + if (!fixedOutput) { + /* Initialise the loopback interface. */ + AutoCloseFD fd(socket(PF_INET, SOCK_DGRAM, IPPROTO_IP)); + if (fd == -1) throw SysError("cannot open IP socket"); - struct ifreq ifr; - strcpy(ifr.ifr_name, "lo"); - ifr.ifr_flags = IFF_UP | IFF_LOOPBACK | IFF_RUNNING; - if (ioctl(fd, SIOCSIFFLAGS, &ifr) == -1) - throw SysError("cannot set loopback interface flags"); + struct ifreq ifr; + strcpy(ifr.ifr_name, "lo"); + ifr.ifr_flags = IFF_UP | IFF_LOOPBACK | IFF_RUNNING; + if (ioctl(fd, SIOCSIFFLAGS, &ifr) == -1) + throw SysError("cannot set loopback interface flags"); - fd.close(); + fd.close(); + } /* Set the hostname etc. to fixed values. */ char hostname[] = "localhost"; @@ -2447,8 +2501,16 @@ void DerivationGoal::registerOutputs() 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) { + if (S_ISDIR(st.st_mode)) + /* Change mode on the directory to allow for + rename(2). */ + chmod(actualPath.c_str(), st.st_mode | 0700); + if (rename(actualPath.c_str(), path.c_str()) == -1) + throw SysError(format("moving build output `%1%' from the chroot to the store") % path); + if (S_ISDIR(st.st_mode) && chmod(path.c_str(), st.st_mode) == -1) + throw SysError(format("restoring permissions on directory `%1%'") % actualPath); + } } if (buildMode != bmCheck) actualPath = path; } @@ -2707,8 +2769,25 @@ void DerivationGoal::deleteTmpDir(bool force) // Change the ownership if clientUid is set. Never change the // ownership or the group to "root" for security reasons. if (settings.clientUid != (uid_t) -1 && settings.clientUid != 0) { - _chown(tmpDir, settings.clientUid, - settings.clientGid != 0 ? settings.clientGid : -1); + uid_t uid = settings.clientUid; + gid_t gid = settings.clientGid != 0 ? settings.clientGid : -1; + try { + _chown(tmpDir, uid, gid); + + if (getuid() != 0) { + /* If, without being root, the '_chown' call above + succeeded, then it means we have CAP_CHOWN. Retake + ownership of tmpDir itself so it can be renamed + below. */ + chown(tmpDir.c_str(), getuid(), getgid()); + } + } catch (SysError & e) { + /* When running as an unprivileged user and without + CAP_CHOWN, we cannot chown the build tree. Print a + message and keep going. */ + printMsg(lvlInfo, format("cannot change ownership of build directory '%1%': %2%") + % tmpDir % strerror(e.errNo)); + } if (top != tmpDir) { // Rename tmpDir to its parent, with an intermediate step. @@ -2717,6 +2796,11 @@ void DerivationGoal::deleteTmpDir(bool force) throw SysError("pivoting failed build tree"); if (rename((pivot + "/top").c_str(), top.c_str()) == -1) throw SysError("renaming failed build tree"); + + if (getuid() != 0) + /* Running unprivileged but with CAP_CHOWN. */ + chown(top.c_str(), uid, gid); + rmdir(pivot.c_str()); } } diff --git a/nix/libstore/local-store.cc b/nix/libstore/local-store.cc index 0883a4bbcee..4308264a4f3 100644 --- a/nix/libstore/local-store.cc +++ b/nix/libstore/local-store.cc @@ -306,14 +306,14 @@ void LocalStore::openDB(bool create) void LocalStore::makeStoreWritable() { #if HAVE_UNSHARE && HAVE_STATVFS && HAVE_SYS_MOUNT_H && defined(MS_BIND) && defined(MS_REMOUNT) - if (getuid() != 0) return; /* Check if /nix/store is on a read-only mount. */ struct statvfs stat; if (statvfs(settings.nixStore.c_str(), &stat) != 0) throw SysError("getting info about the store mount point"); if (stat.f_flag & ST_RDONLY) { - if (unshare(CLONE_NEWNS) == -1) + int flags = CLONE_NEWNS | (getpid() == 0 ? 0 : CLONE_NEWUSER); + if (unshare(flags) == -1) throw SysError("setting up a private mount namespace"); if (mount(0, settings.nixStore.c_str(), "none", MS_REMOUNT | MS_BIND, 0) == -1) @@ -1614,11 +1614,19 @@ void LocalStore::createUser(const std::string & userName, uid_t userId) { auto dir = settings.nixStateDir + "/profiles/per-user/" + userName; - createDirs(dir); - if (chmod(dir.c_str(), 0755) == -1) - throw SysError(format("changing permissions of directory '%s'") % dir); - if (chown(dir.c_str(), userId, -1) == -1) - throw SysError(format("changing owner of directory '%s'") % dir); + auto created = createDirs(dir); + if (!created.empty()) { + if (chmod(dir.c_str(), 0755) == -1) + throw SysError(format("changing permissions of directory '%s'") % dir); + + /* The following operation requires CAP_CHOWN or can be handled + manually by a user with CAP_CHOWN. */ + if (chown(dir.c_str(), userId, -1) == -1) { + rmdir(dir.c_str()); + string message = strerror(errno); + printMsg(lvlInfo, format("failed to change owner of directory '%1%' to %2%: %3%") % dir % userId % message); + } + } } -- 2.48.1
guix@HIDDEN, dev@HIDDEN, ludo@HIDDEN, othacehe@HIDDEN, zimon.toutoune@HIDDEN, me@HIDDEN, guix-patches@HIDDEN
:bug#75810
; Package guix-patches
.
Full text available.Received: (at 75810) by debbugs.gnu.org; 13 Feb 2025 12:13:47 +0000 From debbugs-submit-bounces <at> debbugs.gnu.org Thu Feb 13 07:13:47 2025 Received: from localhost ([127.0.0.1]:41134 helo=debbugs.gnu.org) by debbugs.gnu.org with esmtp (Exim 4.84_2) (envelope-from <debbugs-submit-bounces <at> debbugs.gnu.org>) id 1tiY6E-0003eE-PO for submit <at> debbugs.gnu.org; Thu, 13 Feb 2025 07:13:47 -0500 Received: from eggs.gnu.org ([2001:470:142:3::10]:51220) by debbugs.gnu.org with esmtps (TLS1.2:ECDHE_RSA_AES_256_GCM_SHA384:256) (Exim 4.84_2) (envelope-from <ludo@HIDDEN>) id 1tiY61-0003cM-Jl for 75810 <at> debbugs.gnu.org; Thu, 13 Feb 2025 07:13:37 -0500 Received: from fencepost.gnu.org ([2001:470:142:3::e]) by eggs.gnu.org with esmtps (TLS1.2:ECDHE_RSA_AES_256_GCM_SHA384:256) (Exim 4.90_1) (envelope-from <ludo@HIDDEN>) id 1tiY5w-0001Cb-9l; Thu, 13 Feb 2025 07:13:28 -0500 DKIM-Signature: v=1; a=rsa-sha256; q=dns/txt; c=relaxed/relaxed; d=gnu.org; s=fencepost-gnu-org; h=MIME-Version:References:In-Reply-To:Date:Subject:To: From; bh=a5JtM26SxyhofCBFMp0yoAhLEcbZEpHKDsd7swN2muU=; b=OSxRTznh/gM3SjY+6BWG yP2Ib2pQ2zagVzkvjFk+LHc/J+azdFmsxcSHvnGgzSQOkGEiEUSIglGCkBO8AhGr4GkyVYW7XmC0v pdMzjoOZUPiZBUbvkIXP1V6Ztl7Q4XbKKLgVrH7hmUdigvuWNRE7tDc8p6TKRfS5MbSThYiljAkI5 qPW7eu/lQrJdp0zcEOvC9nCQCvTam2nn8AffU1/MSr7j1D7LqhHbi+vSjb/Qy2J/iV4+B/RFxq/Dl UE7T9q6AVnkPOkNjdpLpxiUmfCiaVbsClSQsemFjrWD4G+QPwCT5xA2hzZIftrjYwXnCCOwXCtI62 2qG1hlVR07WoTA==; From: =?UTF-8?q?Ludovic=20Court=C3=A8s?= <ludo@HIDDEN> To: 75810 <at> debbugs.gnu.org Subject: [PATCH v2 5/9] DRAFT tests: Run in a chroot and unprivileged user namespaces. Date: Thu, 13 Feb 2025 13:13:08 +0100 Message-ID: <913c41825df54b9c7d1fbad1fb1e7e9f48bd0d13.1739448513.git.ludo@HIDDEN> X-Mailer: git-send-email 2.48.1 In-Reply-To: <cover.1739448513.git.ludo@HIDDEN> References: <cover.1739448513.git.ludo@HIDDEN> MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit X-Spam-Score: -2.3 (--) X-Debbugs-Envelope-To: 75810 Cc: =?UTF-8?q?Ludovic=20Court=C3=A8s?= <ludo@HIDDEN> X-BeenThere: debbugs-submit <at> debbugs.gnu.org X-Mailman-Version: 2.1.18 Precedence: list List-Id: <debbugs-submit.debbugs.gnu.org> List-Unsubscribe: <https://debbugs.gnu.org/cgi-bin/mailman/options/debbugs-submit>, <mailto:debbugs-submit-request <at> debbugs.gnu.org?subject=unsubscribe> List-Archive: <https://debbugs.gnu.org/cgi-bin/mailman/private/debbugs-submit/> List-Post: <mailto:debbugs-submit <at> debbugs.gnu.org> List-Help: <mailto:debbugs-submit-request <at> debbugs.gnu.org?subject=help> List-Subscribe: <https://debbugs.gnu.org/cgi-bin/mailman/listinfo/debbugs-submit>, <mailto:debbugs-submit-request <at> debbugs.gnu.org?subject=subscribe> Errors-To: debbugs-submit-bounces <at> debbugs.gnu.org Sender: "Debbugs-submit" <debbugs-submit-bounces <at> debbugs.gnu.org> X-Spam-Score: -3.3 (---) DRAFT: - Double-check the test suite. * build-aux/test-env.in: Pass ‘--disable-chroot’ only when unprivileged user namespace support is lacking. * tests/store.scm ("build-things, check mode"): Use ‘gettimeofday’ rather than a shared file as a source of entropy. ("isolated environment", "inputs are read-only") ("inputs cannot be remounted read-write"): New tests. Change-Id: Iedb816ef548c77799e5b2f9b6a3b7510ad19ec2a --- build-aux/test-env.in | 14 +++- tests/store.scm | 144 ++++++++++++++++++++++++++++++++---------- 2 files changed, 121 insertions(+), 37 deletions(-) diff --git a/build-aux/test-env.in b/build-aux/test-env.in index 9caa29da581..5626152b346 100644 --- a/build-aux/test-env.in +++ b/build-aux/test-env.in @@ -1,7 +1,7 @@ #!/bin/sh # GNU Guix --- Functional package management for GNU -# Copyright © 2012, 2013, 2014, 2015, 2016, 2017, 2018, 2019, 2021 Ludovic Courtès <ludo@HIDDEN> +# Copyright © 2012-2019, 2021, 2025 Ludovic Courtès <ludo@HIDDEN> # # This file is part of GNU Guix. # @@ -102,10 +102,20 @@ then rm -rf "$GUIX_STATE_DIRECTORY/daemon-socket" mkdir -m 0700 "$GUIX_STATE_DIRECTORY/daemon-socket" + # If unprivileged user namespaces are not supported, pass + # '--disable-chroot'. + if [ ! -f /proc/sys/kernel/unprivileged_userns_clone ] \ + || [ "$(cat /proc/sys/kernel/unprivileged_userns_clone)" -eq 1 ]; then + extra_options="" + else + extra_options="--disable-chroot" + fi + # Launch the daemon without chroot support because is may be # unavailable, for instance if we're not running as root. "@abs_top_builddir@/pre-inst-env" \ - "@abs_top_builddir@/guix-daemon" --disable-chroot \ + "@abs_top_builddir@/guix-daemon" \ + $extra_options \ --substitute-urls="$GUIX_BINARY_SUBSTITUTE_URL" & daemon_pid=$! diff --git a/tests/store.scm b/tests/store.scm index 45948f4f433..cf19cf91211 100644 --- a/tests/store.scm +++ b/tests/store.scm @@ -1,5 +1,5 @@ ;;; GNU Guix --- Functional package management for GNU -;;; Copyright © 2012-2021, 2023 Ludovic Courtès <ludo@HIDDEN> +;;; Copyright © 2012-2021, 2023, 2025 Ludovic Courtès <ludo@HIDDEN> ;;; ;;; This file is part of GNU Guix. ;;; @@ -28,8 +28,12 @@ (define-module (test-store) #:use-module (guix base32) #:use-module (guix packages) #:use-module (guix derivations) + #:use-module ((guix modules) + #:select (source-module-closure)) #:use-module (guix serialization) #:use-module (guix build utils) + #:use-module ((gnu build linux-container) + #:select (unprivileged-user-namespace-supported?)) #:use-module (guix gexp) #:use-module (gnu packages) #:use-module (gnu packages bootstrap) @@ -391,6 +395,85 @@ (define %shell (equal? (valid-derivers %store o) (list (derivation-file-name d)))))) +(unless (unprivileged-user-namespace-supported?) + (test-skip 1)) +(test-equal "isolated environment" + (string-join (append + '("PID: 1" "UID: 30001") + (delete-duplicates + (sort (list "/dev" "/tmp" "/proc" "/etc" + (match (string-tokenize (%store-prefix) + (char-set-complement + (char-set #\/))) + ((top _ ...) (string-append "/" top)))) + string<?)) + '("/etc/group" "/etc/hosts" "/etc/passwd"))) + (let* ((b (add-text-to-store %store "build.sh" + "echo -n PID: $$ UID: $UID /* /etc/* > $out")) + (s (add-to-store %store "bash" #t "sha256" + (search-bootstrap-binary "bash" + (%current-system)))) + (d (derivation %store "the-thing" + s `("-e" ,b) + #:env-vars `(("foo" . ,(random-text))) + #:sources (list b s))) + (o (derivation->output-path d))) + (and (build-derivations %store (list d)) + (call-with-input-file o get-string-all)))) + +(unless (unprivileged-user-namespace-supported?) + (test-skip 1)) +(test-equal "inputs are read-only" + "All good!" + (let* ((input (plain-file (string-append "might-be-tampered-with-" + (number->string + (car (gettimeofday)) + 16)) + "All good!")) + (drv + (run-with-store %store + (gexp->derivation + "attempt-to-remount-input-read-write" + (with-imported-modules (source-module-closure + '((guix build syscalls))) + #~(begin + (use-modules (guix build syscalls)) + + (let ((input #$input)) + (chmod input #o666) + (call-with-output-file input + (lambda (port) + (display "BAD!" port))) + (mkdir #$output)))))))) + (and (guard (c ((store-protocol-error? c) #t)) + (build-derivations %store (list drv))) + (call-with-input-file (run-with-store %store + (lower-object input)) + get-string-all)))) + +(unless (unprivileged-user-namespace-supported?) + (test-skip 1)) +(test-assert "inputs cannot be remounted read-write" + (let ((drv + (run-with-store %store + (gexp->derivation + "attempt-to-remount-input-read-write" + (with-imported-modules (source-module-closure + '((guix build syscalls))) + #~(begin + (use-modules (guix build syscalls)) + + (let ((input #$(plain-file "input-that-might-be-tampered-with" + "All good!"))) + (mount "none" input "none" (logior MS_BIND MS_REMOUNT)) + (call-with-output-file input + (lambda (port) + (display "BAD!" port))) + (mkdir #$output)))))))) + (guard (c ((store-protocol-error? c) #t)) + (build-derivations %store (list drv)) + #f))) + (test-equal "with-build-handler" 'success (let* ((b (add-text-to-store %store "build" "echo $foo > $out" '())) @@ -1333,40 +1416,31 @@ (define %shell (test-assert "build-things, check mode" (with-store store - (call-with-temporary-output-file - (lambda (entropy entropy-port) - (write (random-text) entropy-port) - (force-output entropy-port) - (let* ((drv (build-expression->derivation - store "non-deterministic" - `(begin - (use-modules (rnrs io ports)) - (let ((out (assoc-ref %outputs "out"))) - (call-with-output-file out - (lambda (port) - ;; Rely on the fact that tests do not use the - ;; chroot, and thus ENTROPY is readable. - (display (call-with-input-file ,entropy - get-string-all) - port))) - #t)) - #:guile-for-build - (package-derivation store %bootstrap-guile (%current-system)))) - (file (derivation->output-path drv))) - (and (build-things store (list (derivation-file-name drv))) - (begin - (write (random-text) entropy-port) - (force-output entropy-port) - (guard (c ((store-protocol-error? c) - (pk 'determinism-exception c) - (and (not (zero? (store-protocol-error-status c))) - (string-contains (store-protocol-error-message c) - "deterministic")))) - ;; This one will produce a different result. Since we're in - ;; 'check' mode, this must fail. - (build-things store (list (derivation-file-name drv)) - (build-mode check)) - #f)))))))) + (let* ((drv (build-expression->derivation + store "non-deterministic" + `(begin + (use-modules (rnrs io ports)) + (let ((out (assoc-ref %outputs "out"))) + (call-with-output-file out + (lambda (port) + (let ((now (gettimeofday))) + (display (+ (car now) (cdr now)) port)))) + #t)) + #:guile-for-build + (package-derivation store %bootstrap-guile (%current-system)))) + (file (derivation->output-path drv))) + (and (build-things store (list (derivation-file-name drv))) + (begin + (guard (c ((store-protocol-error? c) + (pk 'determinism-exception c) + (and (not (zero? (store-protocol-error-status c))) + (string-contains (store-protocol-error-message c) + "deterministic")))) + ;; This one will produce a different result. Since we're in + ;; 'check' mode, this must fail. + (build-things store (list (derivation-file-name drv)) + (build-mode check)) + #f)))))) (test-assert "build-succeeded trace in check mode" (string-contains -- 2.48.1
guix-patches@HIDDEN
:bug#75810
; Package guix-patches
.
Full text available.Received: (at 75810) by debbugs.gnu.org; 13 Feb 2025 12:13:46 +0000 From debbugs-submit-bounces <at> debbugs.gnu.org Thu Feb 13 07:13:46 2025 Received: from localhost ([127.0.0.1]:41132 helo=debbugs.gnu.org) by debbugs.gnu.org with esmtp (Exim 4.84_2) (envelope-from <debbugs-submit-bounces <at> debbugs.gnu.org>) id 1tiY6E-0003e4-Ai for submit <at> debbugs.gnu.org; Thu, 13 Feb 2025 07:13:46 -0500 Received: from eggs.gnu.org ([2001:470:142:3::10]:41562) by debbugs.gnu.org with esmtps (TLS1.2:ECDHE_RSA_AES_256_GCM_SHA384:256) (Exim 4.84_2) (envelope-from <ludo@HIDDEN>) id 1tiY63-0003cc-L3 for 75810 <at> debbugs.gnu.org; Thu, 13 Feb 2025 07:13:37 -0500 Received: from fencepost.gnu.org ([2001:470:142:3::e]) by eggs.gnu.org with esmtps (TLS1.2:ECDHE_RSA_AES_256_GCM_SHA384:256) (Exim 4.90_1) (envelope-from <ludo@HIDDEN>) id 1tiY5y-0001D3-Aa; Thu, 13 Feb 2025 07:13:30 -0500 DKIM-Signature: v=1; a=rsa-sha256; q=dns/txt; c=relaxed/relaxed; d=gnu.org; s=fencepost-gnu-org; h=MIME-Version:References:In-Reply-To:Date:Subject:To: From; bh=pd3jEQEVWdyi/LNttJNlAO+MmH58xfjNxu8WkPG+5kM=; b=lyniOA6dfNo4JP+NNQ8e N9QkR5DkhTP20jWd1mhD1JcTaERQEu9V1xqPg5paD7vHFQotpXHjPQbrZpi5UYOJsGAgt3G8bESCa rxBSfgB8AkEbyOtx7agNw3z1c2Jln3ZxtZfrQc+mHniMzNKnzAnsjFJMjyzCH1m838tTdXVJsHJFj ojilptPNCvglWaNR/NALcnlsI9lwfmCDKM5BDvWUnJb0JWLq5ZR54hy7Gco5FU+Q98ggEerQ86kVT azIDvv0drEWHIG+dAo74b007uTZz//iRv42as6bUIFj2T6K6WnSweP0pznTpoUdJ4UTlzwG4zXH1P VCVkLbQccmcA6A==; From: =?UTF-8?q?Ludovic=20Court=C3=A8s?= <ludo@HIDDEN> To: 75810 <at> debbugs.gnu.org Subject: [PATCH v2 7/9] daemon: Drop Linux ambient capabilities before executing builder. Date: Thu, 13 Feb 2025 13:13:10 +0100 Message-ID: <06b47bf0dcee78ac73405afe118f7ed7f0a374fa.1739448513.git.ludo@HIDDEN> X-Mailer: git-send-email 2.48.1 In-Reply-To: <cover.1739448513.git.ludo@HIDDEN> References: <cover.1739448513.git.ludo@HIDDEN> MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit X-Spam-Score: -2.3 (--) X-Debbugs-Envelope-To: 75810 Cc: =?UTF-8?q?Ludovic=20Court=C3=A8s?= <ludo@HIDDEN> X-BeenThere: debbugs-submit <at> debbugs.gnu.org X-Mailman-Version: 2.1.18 Precedence: list List-Id: <debbugs-submit.debbugs.gnu.org> List-Unsubscribe: <https://debbugs.gnu.org/cgi-bin/mailman/options/debbugs-submit>, <mailto:debbugs-submit-request <at> debbugs.gnu.org?subject=unsubscribe> List-Archive: <https://debbugs.gnu.org/cgi-bin/mailman/private/debbugs-submit/> List-Post: <mailto:debbugs-submit <at> debbugs.gnu.org> List-Help: <mailto:debbugs-submit-request <at> debbugs.gnu.org?subject=help> List-Subscribe: <https://debbugs.gnu.org/cgi-bin/mailman/listinfo/debbugs-submit>, <mailto:debbugs-submit-request <at> debbugs.gnu.org?subject=subscribe> Errors-To: debbugs-submit-bounces <at> debbugs.gnu.org Sender: "Debbugs-submit" <debbugs-submit-bounces <at> debbugs.gnu.org> X-Spam-Score: -3.3 (---) * config-daemon.ac: Check for <sys/prctl.h>. * nix/libstore/build.cc (DerivationGoal::runChild): When ‘useChroot’ is true, call ‘prctl’ to drop all ambient capabilities. Change-Id: If34637fc508e5fb6d278167f5df7802fc595284f --- config-daemon.ac | 2 +- nix/libstore/build.cc | 9 +++++++++ 2 files changed, 10 insertions(+), 1 deletion(-) diff --git a/config-daemon.ac b/config-daemon.ac index 4e949bc88a3..35d9c8cd56b 100644 --- a/config-daemon.ac +++ b/config-daemon.ac @@ -79,7 +79,7 @@ if test "x$guix_build_daemon" = "xyes"; then dnl Chroot support. AC_CHECK_FUNCS([chroot unshare]) AC_CHECK_HEADERS([sched.h sys/param.h sys/mount.h sys/syscall.h \ - linux/close_range.h]) + linux/close_range.h sys/prctl.h]) if test "x$ac_cv_func_chroot" != "xyes"; then AC_MSG_ERROR(['chroot' function missing, bailing out]) diff --git a/nix/libstore/build.cc b/nix/libstore/build.cc index 18dd27460b7..4280b8abff8 100644 --- a/nix/libstore/build.cc +++ b/nix/libstore/build.cc @@ -50,6 +50,9 @@ #if HAVE_SCHED_H #include <sched.h> #endif +#if HAVE_SYS_PRCTL_H +#include <sys/prctl.h> +#endif #define CHROOT_ENABLED HAVE_CHROOT && HAVE_SYS_MOUNT_H && defined(MS_BIND) && defined(MS_PRIVATE) @@ -2059,6 +2062,12 @@ void DerivationGoal::runChild() #if CHROOT_ENABLED if (useChroot) { +# if HAVE_SYS_PRCTL_H + /* Drop ambient capabilities such as CAP_CHOWN that might have + been granted when starting guix-daemon. */ + prctl(PR_CAP_AMBIENT, PR_CAP_AMBIENT_CLEAR_ALL, 0, 0, 0); +# endif + if (!fixedOutput) { /* Initialise the loopback interface. */ AutoCloseFD fd(socket(PF_INET, SOCK_DGRAM, IPPROTO_IP)); -- 2.48.1
guix-patches@HIDDEN
:bug#75810
; Package guix-patches
.
Full text available.Received: (at 75810) by debbugs.gnu.org; 13 Feb 2025 12:13:46 +0000 From debbugs-submit-bounces <at> debbugs.gnu.org Thu Feb 13 07:13:46 2025 Received: from localhost ([127.0.0.1]:41130 helo=debbugs.gnu.org) by debbugs.gnu.org with esmtp (Exim 4.84_2) (envelope-from <debbugs-submit-bounces <at> debbugs.gnu.org>) id 1tiY6D-0003dx-Va for submit <at> debbugs.gnu.org; Thu, 13 Feb 2025 07:13:46 -0500 Received: from eggs.gnu.org ([2001:470:142:3::10]:51242) by debbugs.gnu.org with esmtps (TLS1.2:ECDHE_RSA_AES_256_GCM_SHA384:256) (Exim 4.84_2) (envelope-from <ludo@HIDDEN>) id 1tiY62-0003cU-Ky for 75810 <at> debbugs.gnu.org; Thu, 13 Feb 2025 07:13:36 -0500 Received: from fencepost.gnu.org ([2001:470:142:3::e]) by eggs.gnu.org with esmtps (TLS1.2:ECDHE_RSA_AES_256_GCM_SHA384:256) (Exim 4.90_1) (envelope-from <ludo@HIDDEN>) id 1tiY5x-0001Cm-B1; Thu, 13 Feb 2025 07:13:29 -0500 DKIM-Signature: v=1; a=rsa-sha256; q=dns/txt; c=relaxed/relaxed; d=gnu.org; s=fencepost-gnu-org; h=MIME-Version:References:In-Reply-To:Date:Subject:To: From; bh=Zsh2zvgPChPdygWDGttbjWAWpTHmsPY3r3V/6RFHAxg=; b=fMn3QqCxdzRdQFsZTqUX zd/SpdmJNbIFmnsu7WATyaUFOTRr2YFsXgytj6rUDsZTcLaWt8EOr8B5LTrhkXl/HQAnN4Eu7KH99 hUkCOL9/zrRv6ciGJL5iXofAZT2bnllch/SmbsCalac1IDt2JQVnvN9SQsKh+8YqIOhret4B4wSyT yPhON0UyrR7yWH0sxESN9Hxl5LQTPkgFNy6d6eJrThe1VdH/eAc7cuPfgT4G6nQVrN6WgAuPTl/+D Bdi6+fSeI/dC6qvrRHY+ynSj/UkGnqj3g/ERVrj/SqDNnBXqGyTaR16hN57HXX3Nz0ZfI0Y0P0tM5 YQqXv7no1lB5pA==; From: =?UTF-8?q?Ludovic=20Court=C3=A8s?= <ludo@HIDDEN> To: 75810 <at> debbugs.gnu.org Subject: [PATCH v2 6/9] daemon: Create /var/guix/profiles/per-user unconditionally. Date: Thu, 13 Feb 2025 13:13:09 +0100 Message-ID: <d6e5382ab3c33c467cb753969ca574561e90d8de.1739448513.git.ludo@HIDDEN> X-Mailer: git-send-email 2.48.1 In-Reply-To: <cover.1739448513.git.ludo@HIDDEN> References: <cover.1739448513.git.ludo@HIDDEN> MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit X-Spam-Score: -2.3 (--) X-Debbugs-Envelope-To: 75810 Cc: =?UTF-8?q?Ludovic=20Court=C3=A8s?= <ludo@HIDDEN> X-BeenThere: debbugs-submit <at> debbugs.gnu.org X-Mailman-Version: 2.1.18 Precedence: list List-Id: <debbugs-submit.debbugs.gnu.org> List-Unsubscribe: <https://debbugs.gnu.org/cgi-bin/mailman/options/debbugs-submit>, <mailto:debbugs-submit-request <at> debbugs.gnu.org?subject=unsubscribe> List-Archive: <https://debbugs.gnu.org/cgi-bin/mailman/private/debbugs-submit/> List-Post: <mailto:debbugs-submit <at> debbugs.gnu.org> List-Help: <mailto:debbugs-submit-request <at> debbugs.gnu.org?subject=help> List-Subscribe: <https://debbugs.gnu.org/cgi-bin/mailman/listinfo/debbugs-submit>, <mailto:debbugs-submit-request <at> debbugs.gnu.org?subject=subscribe> Errors-To: debbugs-submit-bounces <at> debbugs.gnu.org Sender: "Debbugs-submit" <debbugs-submit-bounces <at> debbugs.gnu.org> X-Spam-Score: -3.3 (---) * nix/libstore/local-store.cc (LocalStore::LocalStore): Create ‘perUserDir’ unconditionally. Change-Id: I5188320f9630a81d16f79212d0fffabd55d94abe --- nix/libstore/local-store.cc | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/nix/libstore/local-store.cc b/nix/libstore/local-store.cc index 4308264a4f3..63846695194 100644 --- a/nix/libstore/local-store.cc +++ b/nix/libstore/local-store.cc @@ -79,12 +79,12 @@ LocalStore::LocalStore(bool reserveSpace) createSymlink(profilesDir, gcRootsDir + "/profiles"); } - /* Optionally, create directories and set permissions for a - multi-user install. */ + Path perUserDir = profilesDir + "/per-user"; + createDirs(perUserDir); + + /* Optionally, set permissions for a multi-user install. */ if (getuid() == 0 && settings.buildUsersGroup != "") { - Path perUserDir = profilesDir + "/per-user"; - createDirs(perUserDir); if (chmod(perUserDir.c_str(), 0755) == -1) throw SysError(format("could not set permissions on '%1%' to 755") % perUserDir); -- 2.48.1
guix-patches@HIDDEN
:bug#75810
; Package guix-patches
.
Full text available.Received: (at 75810) by debbugs.gnu.org; 13 Feb 2025 12:13:46 +0000 From debbugs-submit-bounces <at> debbugs.gnu.org Thu Feb 13 07:13:46 2025 Received: from localhost ([127.0.0.1]:41128 helo=debbugs.gnu.org) by debbugs.gnu.org with esmtp (Exim 4.84_2) (envelope-from <debbugs-submit-bounces <at> debbugs.gnu.org>) id 1tiY6A-0003dr-2R for submit <at> debbugs.gnu.org; Thu, 13 Feb 2025 07:13:45 -0500 Received: from eggs.gnu.org ([2001:470:142:3::10]:51204) by debbugs.gnu.org with esmtps (TLS1.2:ECDHE_RSA_AES_256_GCM_SHA384:256) (Exim 4.84_2) (envelope-from <ludo@HIDDEN>) id 1tiY5z-0003cI-TK for 75810 <at> debbugs.gnu.org; Thu, 13 Feb 2025 07:13:35 -0500 Received: from fencepost.gnu.org ([2001:470:142:3::e]) by eggs.gnu.org with esmtps (TLS1.2:ECDHE_RSA_AES_256_GCM_SHA384:256) (Exim 4.90_1) (envelope-from <ludo@HIDDEN>) id 1tiY5t-0001Be-0u; Thu, 13 Feb 2025 07:13:25 -0500 DKIM-Signature: v=1; a=rsa-sha256; q=dns/txt; c=relaxed/relaxed; d=gnu.org; s=fencepost-gnu-org; h=MIME-Version:References:In-Reply-To:Date:Subject:To: From; bh=G7Jx1/74uyahpmNN6NOOyHz1Zj53iERfANavhA6dHdE=; b=k6urEGcSlNkV/klITo0O 5R6XmUCLsMQMEnezImNYpeuRtW7qhd/d2+gozWagQFj5nubRHZRZ6nYvcWw622KQIetyN/zbvhGCw 0UEOo75yzg40xfZqAfgV9iekpmESAZkG6ElAkVy6IqQvYcXaB8k0WPMbflY79vLTyLyUvUaJhJznp TwAfUpHI4/9VX4itswxYIS1pNwOP4G5vBb1k81YxYDg8UnkGpdjHsAfEPfUM5eTTl/LF78zOx2KsJ wH5GcdOoEFjfNf4D4zu4HrM0XjdRI07CuN9Hn+Z5NtDOIxHslEyC52jjtq6XitIEDxaOSXeTXNfGc H7naFnX0R+LWJA==; From: =?UTF-8?q?Ludovic=20Court=C3=A8s?= <ludo@HIDDEN> To: 75810 <at> debbugs.gnu.org Subject: [PATCH v2 2/9] daemon: Bind-mount all the inputs, not just directories. Date: Thu, 13 Feb 2025 13:13:05 +0100 Message-ID: <1a481f7f9df95b1c76e69c5e923fa30098e33cbe.1739448513.git.ludo@HIDDEN> X-Mailer: git-send-email 2.48.1 In-Reply-To: <cover.1739448513.git.ludo@HIDDEN> References: <cover.1739448513.git.ludo@HIDDEN> MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit X-Spam-Score: -0.3 (/) X-Debbugs-Envelope-To: 75810 Cc: =?UTF-8?q?Ludovic=20Court=C3=A8s?= <ludo@HIDDEN>, Reepca Russelstein <reepca@HIDDEN> X-BeenThere: debbugs-submit <at> debbugs.gnu.org X-Mailman-Version: 2.1.18 Precedence: list List-Id: <debbugs-submit.debbugs.gnu.org> List-Unsubscribe: <https://debbugs.gnu.org/cgi-bin/mailman/options/debbugs-submit>, <mailto:debbugs-submit-request <at> debbugs.gnu.org?subject=unsubscribe> List-Archive: <https://debbugs.gnu.org/cgi-bin/mailman/private/debbugs-submit/> List-Post: <mailto:debbugs-submit <at> debbugs.gnu.org> List-Help: <mailto:debbugs-submit-request <at> debbugs.gnu.org?subject=help> List-Subscribe: <https://debbugs.gnu.org/cgi-bin/mailman/listinfo/debbugs-submit>, <mailto:debbugs-submit-request <at> debbugs.gnu.org?subject=subscribe> Errors-To: debbugs-submit-bounces <at> debbugs.gnu.org Sender: "Debbugs-submit" <debbugs-submit-bounces <at> debbugs.gnu.org> X-Spam-Score: -1.3 (-) * nix/libstore/build.cc (DerivationGoal::startBuilder): Add all of ‘inputPaths’ to ‘dirsInChroot’ instead of hard-linking regular files. Reported-by: Reepca Russelstein <reepca@HIDDEN> Change-Id: I070987f92d73f187f7826a975bee9ee309d67f56 --- nix/libstore/build.cc | 27 ++------------------------- 1 file changed, 2 insertions(+), 25 deletions(-) diff --git a/nix/libstore/build.cc b/nix/libstore/build.cc index edd01bab34d..f4cd2131c84 100644 --- a/nix/libstore/build.cc +++ b/nix/libstore/build.cc @@ -1850,9 +1850,7 @@ void DerivationGoal::startBuilder() /* Make the closure of the inputs available in the chroot, rather than the whole store. This prevents any access - to undeclared dependencies. Directories are bind-mounted, - while other inputs are hard-linked (since only directories - can be bind-mounted). !!! As an extra security + to undeclared dependencies. !!! As an extra security precaution, make the fake store only writable by the build user. */ Path chrootStoreDir = chrootRootDir + settings.nixStore; @@ -1863,28 +1861,7 @@ void DerivationGoal::startBuilder() throw SysError(format("cannot change ownership of ‘%1%’") % chrootStoreDir); foreach (PathSet::iterator, i, inputPaths) { - struct stat st; - if (lstat(i->c_str(), &st)) - throw SysError(format("getting attributes of path `%1%'") % *i); - if (S_ISDIR(st.st_mode)) - dirsInChroot[*i] = *i; - else { - Path p = chrootRootDir + *i; - if (link(i->c_str(), p.c_str()) == -1) { - /* Hard-linking fails if we exceed the maximum - link count on a file (e.g. 32000 of ext3), - which is quite possible after a `nix-store - --optimise'. */ - if (errno != EMLINK) - throw SysError(format("linking `%1%' to `%2%'") % p % *i); - StringSink sink; - dumpPath(*i, sink); - StringSource source(sink.s); - restorePath(p, source); - } - - regularInputPaths.insert(*i); - } + dirsInChroot[*i] = *i; } /* If we're repairing, checking or rebuilding part of a -- 2.48.1
guix-patches@HIDDEN
:bug#75810
; Package guix-patches
.
Full text available.Received: (at 75810) by debbugs.gnu.org; 13 Feb 2025 12:13:39 +0000 From debbugs-submit-bounces <at> debbugs.gnu.org Thu Feb 13 07:13:39 2025 Received: from localhost ([127.0.0.1]:41124 helo=debbugs.gnu.org) by debbugs.gnu.org with esmtp (Exim 4.84_2) (envelope-from <debbugs-submit-bounces <at> debbugs.gnu.org>) id 1tiY65-0003dI-RU for submit <at> debbugs.gnu.org; Thu, 13 Feb 2025 07:13:38 -0500 Received: from eggs.gnu.org ([2001:470:142:3::10]:51198) by debbugs.gnu.org with esmtps (TLS1.2:ECDHE_RSA_AES_256_GCM_SHA384:256) (Exim 4.84_2) (envelope-from <ludo@HIDDEN>) id 1tiY5x-0003cE-6y for 75810 <at> debbugs.gnu.org; Thu, 13 Feb 2025 07:13:29 -0500 Received: from fencepost.gnu.org ([2001:470:142:3::e]) by eggs.gnu.org with esmtps (TLS1.2:ECDHE_RSA_AES_256_GCM_SHA384:256) (Exim 4.90_1) (envelope-from <ludo@HIDDEN>) id 1tiY5r-0001BO-Ru; Thu, 13 Feb 2025 07:13:23 -0500 DKIM-Signature: v=1; a=rsa-sha256; q=dns/txt; c=relaxed/relaxed; d=gnu.org; s=fencepost-gnu-org; h=MIME-Version:References:In-Reply-To:Date:Subject:To: From; bh=0izMrOHlIq4NgLJJUeAlULEe8K+llpxfq6yctCHxero=; b=c2yrriY4hF1VWc6VKtTm 7bAd/X3xGfk3UO0lpYY1RU/3DX8TIJNRnM0geIxhrYduszsxV9NDo4dU+nV0P9ExYih8SdkMXTK2h Uq5QGXuLqzsnhG4ZS5Rr4NXosrnyYalrvbOJw6JbtYgc2puBcVwb9oEIpzk5lklUOUJ83yLSW7rvK dFgJshRBp/NHFuOBg009dgfEXFf1r75X7M0V1mro9qyn+IbZlh6t2Kum8ib/NqwrXdUmPY7b827Z9 qCG0ddm0FfrHoA+JB+ra2Vdx7YCuHRXxCSNeRZ1KiTFWwzMSxREUYHUBtENOd73XUvMX98mj6jWZM g5y+rDUoTPvmTA==; From: =?UTF-8?q?Ludovic=20Court=C3=A8s?= <ludo@HIDDEN> To: 75810 <at> debbugs.gnu.org Subject: [PATCH v2 1/9] =?UTF-8?q?daemon:=20Use=20=E2=80=98close=5Frange?= =?UTF-8?q?=E2=80=99=20where=20available.?= Date: Thu, 13 Feb 2025 13:13:04 +0100 Message-ID: <bd91ab23e03ab06c821e9e41b69c0f87c7945a85.1739448513.git.ludo@HIDDEN> X-Mailer: git-send-email 2.48.1 In-Reply-To: <cover.1739448513.git.ludo@HIDDEN> References: <cover.1739448513.git.ludo@HIDDEN> MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit X-Spam-Score: -2.3 (--) X-Debbugs-Envelope-To: 75810 Cc: =?UTF-8?q?Ludovic=20Court=C3=A8s?= <ludo@HIDDEN> X-BeenThere: debbugs-submit <at> debbugs.gnu.org X-Mailman-Version: 2.1.18 Precedence: list List-Id: <debbugs-submit.debbugs.gnu.org> List-Unsubscribe: <https://debbugs.gnu.org/cgi-bin/mailman/options/debbugs-submit>, <mailto:debbugs-submit-request <at> debbugs.gnu.org?subject=unsubscribe> List-Archive: <https://debbugs.gnu.org/cgi-bin/mailman/private/debbugs-submit/> List-Post: <mailto:debbugs-submit <at> debbugs.gnu.org> List-Help: <mailto:debbugs-submit-request <at> debbugs.gnu.org?subject=help> List-Subscribe: <https://debbugs.gnu.org/cgi-bin/mailman/listinfo/debbugs-submit>, <mailto:debbugs-submit-request <at> debbugs.gnu.org?subject=subscribe> Errors-To: debbugs-submit-bounces <at> debbugs.gnu.org Sender: "Debbugs-submit" <debbugs-submit-bounces <at> debbugs.gnu.org> X-Spam-Score: -3.3 (---) * nix/libutil/util.cc (closeMostFDs) [HAVE_CLOSE_RANGE]: Use ‘close_range’ when ‘exceptions’ is empty. * config-daemon.ac: Check for <linux/close_range.h> and the ‘close_range’ symbol. Change-Id: I12fa3bde58b003fcce5ea5a1fee1dcf9a92c0359 --- config-daemon.ac | 5 +++-- nix/libutil/util.cc | 23 +++++++++++++++++------ 2 files changed, 20 insertions(+), 8 deletions(-) diff --git a/config-daemon.ac b/config-daemon.ac index 6731c68bc39..4e949bc88a3 100644 --- a/config-daemon.ac +++ b/config-daemon.ac @@ -78,7 +78,8 @@ if test "x$guix_build_daemon" = "xyes"; then dnl Chroot support. AC_CHECK_FUNCS([chroot unshare]) - AC_CHECK_HEADERS([sched.h sys/param.h sys/mount.h sys/syscall.h]) + AC_CHECK_HEADERS([sched.h sys/param.h sys/mount.h sys/syscall.h \ + linux/close_range.h]) if test "x$ac_cv_func_chroot" != "xyes"; then AC_MSG_ERROR(['chroot' function missing, bailing out]) @@ -95,7 +96,7 @@ if test "x$guix_build_daemon" = "xyes"; then dnl strsignal: for error reporting. dnl statx: fine-grain 'stat' call, new in glibc 2.28. AC_CHECK_FUNCS([lutimes lchown posix_fallocate sched_setaffinity \ - statvfs nanosleep strsignal statx]) + statvfs nanosleep strsignal statx close_range]) dnl Check for <locale>. AC_LANG_PUSH(C++) diff --git a/nix/libutil/util.cc b/nix/libutil/util.cc index 3206dea11b1..eb2d16e1cc3 100644 --- a/nix/libutil/util.cc +++ b/nix/libutil/util.cc @@ -23,6 +23,10 @@ #include <sys/prctl.h> #endif +#ifdef HAVE_LINUX_CLOSE_RANGE_H +# include <linux/close_range.h> +#endif + extern char * * environ; @@ -1087,12 +1091,19 @@ string runProgram(Path program, bool searchPath, const Strings & args) void closeMostFDs(const set<int> & exceptions) { - int maxFD = 0; - maxFD = sysconf(_SC_OPEN_MAX); - for (int fd = 0; fd < maxFD; ++fd) - if (fd != STDIN_FILENO && fd != STDOUT_FILENO && fd != STDERR_FILENO - && exceptions.find(fd) == exceptions.end()) - close(fd); /* ignore result */ +#ifdef HAVE_CLOSE_RANGE + if (exceptions.empty()) + close_range(3, ~0U, 0); + else +#endif + { + int maxFD = 0; + maxFD = sysconf(_SC_OPEN_MAX); + for (int fd = 0; fd < maxFD; ++fd) + if (fd != STDIN_FILENO && fd != STDOUT_FILENO && fd != STDERR_FILENO + && exceptions.find(fd) == exceptions.end()) + close(fd); /* ignore result */ + } } -- 2.48.1
guix-patches@HIDDEN
:bug#75810
; Package guix-patches
.
Full text available.Received: (at 75810) by debbugs.gnu.org; 13 Feb 2025 12:13:38 +0000 From debbugs-submit-bounces <at> debbugs.gnu.org Thu Feb 13 07:13:37 2025 Received: from localhost ([127.0.0.1]:41108 helo=debbugs.gnu.org) by debbugs.gnu.org with esmtp (Exim 4.84_2) (envelope-from <debbugs-submit-bounces <at> debbugs.gnu.org>) id 1tiY5z-0003cg-C7 for submit <at> debbugs.gnu.org; Thu, 13 Feb 2025 07:13:37 -0500 Received: from eggs.gnu.org ([2001:470:142:3::10]:51184) by debbugs.gnu.org with esmtps (TLS1.2:ECDHE_RSA_AES_256_GCM_SHA384:256) (Exim 4.84_2) (envelope-from <ludo@HIDDEN>) id 1tiY5v-0003cC-Tp for 75810 <at> debbugs.gnu.org; Thu, 13 Feb 2025 07:13:29 -0500 Received: from fencepost.gnu.org ([2001:470:142:3::e]) by eggs.gnu.org with esmtps (TLS1.2:ECDHE_RSA_AES_256_GCM_SHA384:256) (Exim 4.90_1) (envelope-from <ludo@HIDDEN>) id 1tiY5q-0001B9-EI; Thu, 13 Feb 2025 07:13:22 -0500 DKIM-Signature: v=1; a=rsa-sha256; q=dns/txt; c=relaxed/relaxed; d=gnu.org; s=fencepost-gnu-org; h=MIME-Version:Date:Subject:To:From:in-reply-to: references; bh=iQGBJmWfz5H9oeW6AXc3OxWRIYKjYzuahq1EFH4TLac=; b=RT04WP6+2sT+IJ bcUxVAQ8NcH9t9/C8tl3d4ZZeFv+I4vU+A8Hf30YR/+pheuYZbReiWaXzIi9SK8z0XuKvazPjJ6jl E5oJSnPgWKOwBlLI419fbM04yaqJX5aF9YqdB8H0klpQC93f5sHsCd+3A1f9MQRNdANgSfZQpGINO rMiRbyrjakzL+Z2Mwc+eNdNRhWzhpEpTrouMeX/NGa7jSN/S6dTqbVjJgir8K24bXfh5iX5QL9zfv sFMLC0w5JmEa3DIbZhNvQ5616zvqsSUTMLHaMIa6NSvQ4dMWzsexPC7czx8PAER+ZzPVZ7ikn+mbt Bj4B8bcXg9vrrhJDGDQQ==; From: =?UTF-8?q?Ludovic=20Court=C3=A8s?= <ludo@HIDDEN> To: 75810 <at> debbugs.gnu.org Subject: [PATCH v2 0/9] Rootless daemon Date: Thu, 13 Feb 2025 13:13:03 +0100 Message-ID: <cover.1739448513.git.ludo@HIDDEN> X-Mailer: git-send-email 2.48.1 MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit X-Spam-Score: -2.3 (--) X-Debbugs-Envelope-To: 75810 Cc: =?UTF-8?q?Ludovic=20Court=C3=A8s?= <ludo@HIDDEN> X-BeenThere: debbugs-submit <at> debbugs.gnu.org X-Mailman-Version: 2.1.18 Precedence: list List-Id: <debbugs-submit.debbugs.gnu.org> List-Unsubscribe: <https://debbugs.gnu.org/cgi-bin/mailman/options/debbugs-submit>, <mailto:debbugs-submit-request <at> debbugs.gnu.org?subject=unsubscribe> List-Archive: <https://debbugs.gnu.org/cgi-bin/mailman/private/debbugs-submit/> List-Post: <mailto:debbugs-submit <at> debbugs.gnu.org> List-Help: <mailto:debbugs-submit-request <at> debbugs.gnu.org?subject=help> List-Subscribe: <https://debbugs.gnu.org/cgi-bin/mailman/listinfo/debbugs-submit>, <mailto:debbugs-submit-request <at> debbugs.gnu.org?subject=subscribe> Errors-To: debbugs-submit-bounces <at> debbugs.gnu.org Sender: "Debbugs-submit" <debbugs-submit-bounces <at> debbugs.gnu.org> X-Spam-Score: -1.0 (-) Hello, Here’s an update with some of the fixes suggested by Reepca: • Remounting inputs as read-only since MS_BIND | MS_RDONLY doesn’t do what one might think; • Bind-mounting everything and not just directories; • Adding tests to ensure that inputs cannot be remounted as read-write, overwritten, etc.; • Fix bogus synchronization for uid_map/gid_map creation; • Use ‘clone_range’ (unrelated to the rest of this series but nice). One of the critical open issues that remain is the fact that the root file system in the build environment is writable, and thus a build process can (chmod "/" #o777) and expose setuid binaries etc. The other one is lack of support for read-only store remount (‘--backing-store’ option has yet to be added). Ludo’. Ludovic Courtès (9): daemon: Use ‘close_range’ where available. daemon: Bind-mount all the inputs, not just directories. daemon: Remount inputs as read-only. daemon: Allow running as non-root with unprivileged user namespaces. DRAFT tests: Run in a chroot and unprivileged user namespaces. daemon: Create /var/guix/profiles/per-user unconditionally. daemon: Drop Linux ambient capabilities before executing builder. etc: systemd services: Run ‘guix-daemon’ as an unprivileged user. guix-install.sh: Support the unprivileged daemon where possible. build-aux/test-env.in | 14 ++- config-daemon.ac | 5 +- etc/guix-daemon.service.in | 12 ++- etc/guix-install.sh | 114 +++++++++++++++++++----- guix/substitutes.scm | 4 +- nix/libstore/build.cc | 171 ++++++++++++++++++++++++++---------- nix/libstore/local-store.cc | 30 ++++--- nix/libutil/util.cc | 23 +++-- tests/store.scm | 144 ++++++++++++++++++++++-------- 9 files changed, 388 insertions(+), 129 deletions(-) base-commit: bc6769f1211104dbc9341c064275cd930f5dfa3a -- 2.48.1
guix-patches@HIDDEN
:bug#75810
; Package guix-patches
.
Full text available.Received: (at 75810) by debbugs.gnu.org; 31 Jan 2025 22:36:21 +0000 From debbugs-submit-bounces <at> debbugs.gnu.org Fri Jan 31 17:36:21 2025 Received: from localhost ([127.0.0.1]:55304 helo=debbugs.gnu.org) by debbugs.gnu.org with esmtp (Exim 4.84_2) (envelope-from <debbugs-submit-bounces <at> debbugs.gnu.org>) id 1tdzca-00010m-Om for submit <at> debbugs.gnu.org; Fri, 31 Jan 2025 17:36:21 -0500 Received: from mailout.russelstein.xyz ([2605:6400:20:11e::1]:35892) by debbugs.gnu.org with esmtps (TLS1.2:ECDHE_RSA_AES_256_GCM_SHA384:256) (Exim 4.84_2) (envelope-from <reepca@HIDDEN>) id 1tdzcV-00010X-LD for 75810 <at> debbugs.gnu.org; Fri, 31 Jan 2025 17:36:18 -0500 DKIM-Signature: v=1; a=ed25519-sha256; q=dns/txt; c=relaxed/relaxed; d=russelstein.xyz; s=ed25519; h=Content-Type:MIME-Version:Message-ID:Date: References:In-Reply-To:Subject:Cc:To:From:Sender:Reply-To: Content-Transfer-Encoding:Content-ID:Content-Description:Resent-Date: Resent-From:Resent-Sender:Resent-To:Resent-Cc:Resent-Message-ID:List-Id: List-Help:List-Unsubscribe:List-Subscribe:List-Post:List-Owner:List-Archive; bh=WttHpXVgzn/HB06VS3KcNGePd+sdhHakYWPshDyVBZg=; b=zJ4gZ064TrvnicplXbZSduiIYB 9VDfK8YMgMgC1/b7tBTvDkamCpwZyqfZYsTZDaJ/xgfXv9UqQ3kV1GMtEDAw==; DKIM-Signature: v=1; a=rsa-sha256; q=dns/txt; c=relaxed/relaxed; d=russelstein.xyz; s=rsa; h=Content-Type:MIME-Version:Message-ID:Date: References:In-Reply-To:Subject:Cc:To:From:Sender:Reply-To: Content-Transfer-Encoding:Content-ID:Content-Description:Resent-Date: Resent-From:Resent-Sender:Resent-To:Resent-Cc:Resent-Message-ID:List-Id: List-Help:List-Unsubscribe:List-Subscribe:List-Post:List-Owner:List-Archive; bh=WttHpXVgzn/HB06VS3KcNGePd+sdhHakYWPshDyVBZg=; b=iMHYBfl3aJtWCcKFbkysJnFRzA 27Qh1UzIB6SwSO/02C2WmXUXH8afwz+v01GfJXSTfB9ggj9WFFjw8XW9g+ytnaooqkyqlcCZfK0DA hDtHelO+Xa0nG/3Qhz97CxUdUPi0CXCcOjJ0s7yHAtsj01eRVEIVUbxjkqr3GQihyXbAIF1g9aaFu qpdeLYfE7UEmfPYvnHHROXEIy7RwAj7hrXcPdsHlabgZ2bPJtsZ9XqADWJICi2YmXdhK1IrFPnMwu qpLp8PUMIdJ7YSJugN66UMvGxSTAfvRVXaeL/rPD5FVhkRPDTX+xjJglMdJJx5dzolK+SLGPK+5Rg v1hs18QvSLKPw7BmU2lZSn85Q/U/HcvXxxXiIox1052t51MlVPdeFZ8JC5sNl6YgfuvWrcyQhRPBl 8XAxek455UNcd6gpR+yizrFT0P4NvQXzjoaTrPnj7oEmpdbUKCNDFEq8uBk5HqmbmtYvsvbzdhzyo i6+fz7oyBsoDnDlhOspuQDr7K4ZSKZKjTWZN2nSKlbE00Un6OfXQXIF1gr7s5V9jgfh5bwUo+SvB8 rzz7ohd+cJpV6QHDdKCkF5SQlAlSsgP8eQI/mpjcfCkE4ud2QlFBfLtrFP8cjyvhBiy/+jERcl50s z7YGHrlOr9d4BILNe2FWEDPQouG4VXjvDc0Robi4c=; Received: by russelstein.xyz with esmtpsa (TLS1.3:ECDHE_SECP256R1__RSA_PSS_RSAE_SHA256__AES_256_GCM:256) (Exim 4.98) (envelope-from <reepca@HIDDEN>) id 1tdzcR-000000006kN-2U8z; Fri, 31 Jan 2025 16:36:12 -0600 From: Reepca Russelstein <reepca@HIDDEN> To: Ludovic =?utf-8?Q?Court=C3=A8s?= <ludo@HIDDEN> Subject: Re: [bug#75810] [PATCH 0/6] Rootless guix-daemon In-Reply-To: <87bjvshrk0.fsf@HIDDEN> ("Ludovic =?utf-8?Q?Court=C3=A8s=22'?= =?utf-8?Q?s?= message of "Mon, 27 Jan 2025 22:31:43 +0100") References: <cover.1737738362.git.ludo@HIDDEN> <87r04qe7dj.fsf@HIDDEN> <87bjvshrk0.fsf@HIDDEN> Date: Fri, 31 Jan 2025 16:35:24 -0600 Message-ID: <875xluehn7.fsf@HIDDEN> User-Agent: Gnus/5.13 (Gnus v5.13) MIME-Version: 1.0 Content-Type: multipart/signed; boundary="=-=-="; micalg=pgp-sha256; protocol="application/pgp-signature" X-Spam-Score: 0.5 X-Spam-Bar: / X-Spam-Score-Int: 5 X-Spam-Report: Spam detection software, running on the system "Sanctum", has NOT identified this incoming email as spam. The original message has been attached to this so you can view it or label similar future email. If you have any questions, see the administrator of that system for details. Content preview: I've found another vulnerability in using guix-daemon as the build user: the chroot root directory is owned by the build user. By itself this would normally only cause some reproducibility issues, but [...] Content analysis details: (0.5 points, 5.0 required) pts rule name description ---- ---------------------- -------------------------------------------------- -0.0 NO_RELAYS Informational: message was not relayed via SMTP 0.5 FROM_SUSPICIOUS_NTLD From abused NTLD X-Spam-Score: 1.1 (+) X-Spam-Report: Spam detection software, running on the system "debbugs.gnu.org", has NOT identified this incoming email as spam. The original message has been attached to this so you can view it or label similar future email. If you have any questions, see the administrator of that system for details. Content preview: I've found another vulnerability in using guix-daemon as the build user: the chroot root directory is owned by the build user. By itself this would normally only cause some reproducibility issues, but [...] Content analysis details: (1.1 points, 10.0 required) pts rule name description ---- ---------------------- -------------------------------------------------- 0.6 PDS_OTHER_BAD_TLD Untrustworthy TLDs [URI: russelstein.xyz (xyz)] 0.0 SPF_HELO_NONE SPF: HELO does not publish an SPF Record -0.0 SPF_PASS SPF: sender matches SPF record 0.5 FROM_SUSPICIOUS_NTLD From abused NTLD X-Debbugs-Envelope-To: 75810 Cc: 75810 <at> debbugs.gnu.org X-BeenThere: debbugs-submit <at> debbugs.gnu.org X-Mailman-Version: 2.1.18 Precedence: list List-Id: <debbugs-submit.debbugs.gnu.org> List-Unsubscribe: <https://debbugs.gnu.org/cgi-bin/mailman/options/debbugs-submit>, <mailto:debbugs-submit-request <at> debbugs.gnu.org?subject=unsubscribe> List-Archive: <https://debbugs.gnu.org/cgi-bin/mailman/private/debbugs-submit/> List-Post: <mailto:debbugs-submit <at> debbugs.gnu.org> List-Help: <mailto:debbugs-submit-request <at> debbugs.gnu.org?subject=help> List-Subscribe: <https://debbugs.gnu.org/cgi-bin/mailman/listinfo/debbugs-submit>, <mailto:debbugs-submit-request <at> debbugs.gnu.org?subject=subscribe> Errors-To: debbugs-submit-bounces <at> debbugs.gnu.org Sender: "Debbugs-submit" <debbugs-submit-bounces <at> debbugs.gnu.org> X-Spam-Score: 1.1 (+) X-Spam-Report: Spam detection software, running on the system "debbugs.gnu.org", has NOT identified this incoming email as spam. The original message has been attached to this so you can view it or label similar future email. If you have any questions, see the administrator of that system for details. Content preview: I've found another vulnerability in using guix-daemon as the build user: the chroot root directory is owned by the build user. By itself this would normally only cause some reproducibility issues, but [...] Content analysis details: (1.1 points, 10.0 required) pts rule name description ---- ---------------------- -------------------------------------------------- 0.6 PDS_OTHER_BAD_TLD Untrustworthy TLDs [URI: russelstein.xyz (xyz)] 0.0 SPF_HELO_NONE SPF: HELO does not publish an SPF Record -0.0 SPF_PASS SPF: sender matches SPF record 0.5 FROM_SUSPICIOUS_NTLD From abused NTLD 1.0 BULK_RE_SUSP_NTLD Precedence bulk and RE: from a suspicious TLD -1.0 MAILING_LIST_MULTI Multiple indicators imply a widely-seen list manager --=-=-= Content-Type: text/plain Content-Transfer-Encoding: quoted-printable I've found another vulnerability in using guix-daemon as the build user: the chroot root directory is owned by the build user. By itself this would normally only cause some reproducibility issues, but that directory is also visible from the outside world as /gnu/store/...-packagename.drv.chroot. Consequently, a simple chmod from the builder can expose the contents of the chroot, including any setuid programs. Demonstration: =2D-8<---------------cut here---------------start------------->8--- (use-modules (guix) (gnu) (guix build-system trivial)) (define-public sneakysneaky (package (name "sneakysneaky") (version "0") (source #f) (build-system trivial-build-system) (arguments (list #:builder #~(let ((guile (string-append (assoc-ref %guile-build-info 'bindir) "/guile"))) (chmod "/" #o777) (copy-file guile "/guile") (chmod "/guile" #o6755) (sleep 1000) (mkdir #$output)))) (home-page "") (synopsis "") (description "") (license #f))) sneakysneaky =2D-8<---------------cut here---------------end--------------->8--- If I save this as /tmp/mal-test3.scm, I can observe the following: =2D-8<---------------cut here---------------start------------->8--- user@debian:~$ guix build --derivations --no-grafts -f /tmp/mal-test3.scm /gnu/store/qx5m1iq72628qy90wpwczypzfc28ss57-sneakysneaky-0.drv user@debian:~$ guix build /gnu/store/qx5m1iq72628qy90wpwczypzfc28ss57-sneak= ysneaky-0.drv substitute: looking for substitutes on 'https://bordeaux.guix.gnu.org'... 1= 00.0% substitute: looking for substitutes on 'https://ci.guix.gnu.org'... 100.0% The following derivation will be built: /gnu/store/qx5m1iq72628qy90wpwczypzfc28ss57-sneakysneaky-0.drv building /gnu/store/qx5m1iq72628qy90wpwczypzfc28ss57-sneakysneaky-0.drv... C-c C-z [1]+ Stopped guix build /gnu/store/qx5m1iq72628qy90wpwczyp= zfc28ss57-sneakysneaky-0.drv user@debian:~$=20 user@debian:~$ ls /gnu/store/qx5m1iq72628qy90wpwczypzfc28ss57-sneakysneaky-= 0.drv.chroot dev etc gnu guile proc tmp user@debian:~$ /gnu/store/qx5m1iq72628qy90wpwczypzfc28ss57-sneakysneaky-0.d= rv.chroot/guile guile: warning: failed to install locale warning: failed to install locale: Invalid argument GNU Guile 3.0.9 Copyright (C) 1995-2023 Free Software Foundation, Inc. Guile comes with ABSOLUTELY NO WARRANTY; for details type `,show w'. This program is free software, and you are welcome to redistribute it under certain conditions; type `,show c' for details. Enter `,help' for help. scheme@(guile-user)> (geteuid) $1 =3D 999 scheme@(guile-user)> (getegid) $2 =3D 996 scheme@(guile-user)>=20 user@debian:~$ id uid=3D1000(user) gid=3D1000(user) groups=3D1000(user),24(cdrom),25(floppy),= 27(sudo),29(audio),30(dip),44(video),46(plugdev),100(users),106(netdev),113= (bluetooth),117(scanner) user@debian:~$=20 =2D-8<---------------cut here---------------end--------------->8--- The security impact of this could be resolved by doing the same thing we do with build directories - have the actual mounted-into-the-chroot directory be the "/top" subdirectory of the externally-visible chroot directory. In the example above, that would be /gnu/store/qx5m1iq72628qy90wpwczypzfc28ss57-sneakysneaky-0.drv.chroot/top. Due to the use of pivot_root, the upper .chroot directory would become completely inaccessible to the builder, ensuring that it remains inaccessible for unprivileged users. I'm less sure about how to resolve the impact to reproducibility. We could try mounting the root directory specifically as read-only, perhaps, though my understanding is that this may cause open, chmod, etc to return EROFS instead of EACCES or EPERM. =2D reepca --=-=-= Content-Type: application/pgp-signature; name="signature.asc" -----BEGIN PGP SIGNATURE----- iQFLBAEBCAA1FiEEdNapMPRLm4SepVYGwWaqSV9/GJwFAmedUCwXHHJlZXBjYUBy dXNzZWxzdGVpbi54eXoACgkQwWaqSV9/GJyBtQgAmXPI8k1Os1tVCb6Py8Rn++1Q tPR0TL9wItX0hN+RQTHNpIsPE6hbgc2FgKQ3zbIUk2D4VGn8YA1qh9nFt/UJMuoK QGHbE+6ctuADAbU4KubRR5N/NxyP+IupG7zttEtiO6rOGfSeoVaugdsjoLE5ZUx1 MX9qr5asjfx8SO8oEkafM7bQpDDNJrTSj8OWrQ5KhJclIwMdaXVFGScJUU4igvZX LfL4Bo8tnK2V6urP87xEDindHRBUsFLvI//TTUuZzl1qyYmB6+AFtRTfpr/zIQH5 m2gOdoXi3mbdOnNwD7q+BCfC7Nh+a/1mmfJrP/mRHfosYen4Jl8wnjWkFgucNQ== =jv04 -----END PGP SIGNATURE----- --=-=-=--
guix-patches@HIDDEN
:bug#75810
; Package guix-patches
.
Full text available.Received: (at 75810) by debbugs.gnu.org; 29 Jan 2025 07:52:34 +0000 From debbugs-submit-bounces <at> debbugs.gnu.org Wed Jan 29 02:52:34 2025 Received: from localhost ([127.0.0.1]:39782 helo=debbugs.gnu.org) by debbugs.gnu.org with esmtp (Exim 4.84_2) (envelope-from <debbugs-submit-bounces <at> debbugs.gnu.org>) id 1td2sD-0005tW-EQ for submit <at> debbugs.gnu.org; Wed, 29 Jan 2025 02:52:34 -0500 Received: from mailout.russelstein.xyz ([2605:6400:20:11e::1]:57690) by debbugs.gnu.org with esmtps (TLS1.2:ECDHE_RSA_AES_256_GCM_SHA384:256) (Exim 4.84_2) (envelope-from <reepca@HIDDEN>) id 1td2s9-0005tL-Nl for 75810 <at> debbugs.gnu.org; Wed, 29 Jan 2025 02:52:31 -0500 DKIM-Signature: v=1; a=ed25519-sha256; q=dns/txt; c=relaxed/relaxed; d=russelstein.xyz; s=ed25519; h=Content-Type:MIME-Version:Message-ID:Date: References:In-Reply-To:Subject:Cc:To:From:Sender:Reply-To: Content-Transfer-Encoding:Content-ID:Content-Description:Resent-Date: Resent-From:Resent-Sender:Resent-To:Resent-Cc:Resent-Message-ID:List-Id: List-Help:List-Unsubscribe:List-Subscribe:List-Post:List-Owner:List-Archive; bh=gl+n7dEdqtg50yw59FPf0Baaad1/mvyEDFo+FqvjDr4=; b=5RPIHZEQvol8/XaJLDG1ZezzSz CQuOzmdZnJj5hKDmZ/QSYajJm8MkCDnC1UvYgk9oZ54zrBoXXaJm3eyuSdDg==; DKIM-Signature: v=1; a=rsa-sha256; q=dns/txt; c=relaxed/relaxed; d=russelstein.xyz; s=rsa; h=Content-Type:MIME-Version:Message-ID:Date: References:In-Reply-To:Subject:Cc:To:From:Sender:Reply-To: Content-Transfer-Encoding:Content-ID:Content-Description:Resent-Date: Resent-From:Resent-Sender:Resent-To:Resent-Cc:Resent-Message-ID:List-Id: List-Help:List-Unsubscribe:List-Subscribe:List-Post:List-Owner:List-Archive; bh=gl+n7dEdqtg50yw59FPf0Baaad1/mvyEDFo+FqvjDr4=; b=iFnP6sZhXNQBc82w2OHN+KmdZu xCpW8GRjL6uO8AAVhO1ENsBynewtzQGWumFKxLS70hi2PkqG/h1nyw/sPF/LG7MOZhRSuenMyQaKV Pk87OARprML/g46GVLvQEhUS6OYtMijZ7b18TGgwW53+Rwk39b3c9Soi5X5482Hm2jJWV18I8GD7F 09pL6PbNZmdgMH+Ta3Hq/nppISp6VyNRftCyV8mJaJpc+LFCCAkCw99POxXE7UURFhY1xg2XzWg3r pfcfzZjSev/B8O13+e8pAUAY03kth0dPDTpmnGV8wwWFUz7Oo8IR5oVtsO26TTqucMq7yvJZ5yX5t JsnPUA8mv8aLzi/pEyHMKUsyQzqw9vIa9OWGh2mRtoOWv5MovVfVN1q6Yv+Kb3MpjWvqHzHHVPfXV wO0k7THzmk4M65D7xKhxsM/vLnpc+G4xBQ/YNIWFDeANAMVOnP75WV5OYfQE79GV65V3MQy7Lr358 y11lsRG7df8dYedyzk3Oem1+TnSUOCMu4huV9jWp8aAElAmGpq0DBOAKIPteUE6YMnNT2Szri1UC4 V/h8h/15ks4PXc1x1YNbDnh6JlpO8CaGWbdt7IebO9or2CLc9cCL71lD2r/ghUwu7tu6yDp3IZ1Yz F5wOW976RDSKcxO4HkXylhKbvkoHF58598Do1fRPo=; Received: by russelstein.xyz with esmtpsa (TLS1.3:ECDHE_SECP256R1__RSA_PSS_RSAE_SHA256__AES_256_GCM:256) (Exim 4.98) (envelope-from <reepca@HIDDEN>) id 1td2s4-000000006WI-3kM4; Wed, 29 Jan 2025 01:52:26 -0600 From: Reepca Russelstein <reepca@HIDDEN> To: Ludovic =?utf-8?Q?Court=C3=A8s?= <ludo@HIDDEN> Subject: Re: [bug#75810] [PATCH 0/6] Rootless guix-daemon In-Reply-To: <87bjvshrk0.fsf@HIDDEN> ("Ludovic =?utf-8?Q?Court=C3=A8s=22'?= =?utf-8?Q?s?= message of "Mon, 27 Jan 2025 22:31:43 +0100") References: <cover.1737738362.git.ludo@HIDDEN> <87r04qe7dj.fsf@HIDDEN> <87bjvshrk0.fsf@HIDDEN> Date: Wed, 29 Jan 2025 01:51:33 -0600 Message-ID: <87msfadpmi.fsf@HIDDEN> User-Agent: Gnus/5.13 (Gnus v5.13) MIME-Version: 1.0 Content-Type: multipart/signed; boundary="=-=-="; micalg=pgp-sha256; protocol="application/pgp-signature" X-Spam-Score: 0.5 X-Spam-Bar: / X-Spam-Score-Int: 5 X-Spam-Report: Spam detection software, running on the system "Sanctum", has NOT identified this incoming email as spam. The original message has been attached to this so you can view it or label similar future email. If you have any questions, see the administrator of that system for details. Content preview: Ludovic Courtès <ludo@HIDDEN> writes: > Hello Reepca, > > Reepca Russelstein <reepca@HIDDEN> skribis: > >> user@debian:~$ /gnu/store/8bjy9g0cssjrw9ljz2r8ww1sma95isfj-hello-2.12.1/bin/hello >> GOOOOOD BYYEEEEEE > > This particular [...] Content analysis details: (0.5 points, 5.0 required) pts rule name description ---- ---------------------- -------------------------------------------------- -0.0 NO_RELAYS Informational: message was not relayed via SMTP 0.5 FROM_SUSPICIOUS_NTLD From abused NTLD X-Spam-Score: 1.0 (+) X-Debbugs-Envelope-To: 75810 Cc: 75810 <at> debbugs.gnu.org X-BeenThere: debbugs-submit <at> debbugs.gnu.org X-Mailman-Version: 2.1.18 Precedence: list List-Id: <debbugs-submit.debbugs.gnu.org> List-Unsubscribe: <https://debbugs.gnu.org/cgi-bin/mailman/options/debbugs-submit>, <mailto:debbugs-submit-request <at> debbugs.gnu.org?subject=unsubscribe> List-Archive: <https://debbugs.gnu.org/cgi-bin/mailman/private/debbugs-submit/> List-Post: <mailto:debbugs-submit <at> debbugs.gnu.org> List-Help: <mailto:debbugs-submit-request <at> debbugs.gnu.org?subject=help> List-Subscribe: <https://debbugs.gnu.org/cgi-bin/mailman/listinfo/debbugs-submit>, <mailto:debbugs-submit-request <at> debbugs.gnu.org?subject=subscribe> Errors-To: debbugs-submit-bounces <at> debbugs.gnu.org Sender: "Debbugs-submit" <debbugs-submit-bounces <at> debbugs.gnu.org> X-Spam-Score: 1.0 (+) --=-=-= Content-Type: text/plain; charset=utf-8 Content-Transfer-Encoding: quoted-printable Ludovic Court=C3=A8s <ludo@HIDDEN> writes: > Hello Reepca, > > Reepca Russelstein <reepca@HIDDEN> skribis: > >> user@debian:~$ /gnu/store/8bjy9g0cssjrw9ljz2r8ww1sma95isfj-hello-2.12.1/= bin/hello >> GOOOOOD BYYEEEEEE > > This particular issue is fixed with read-only mounts: > > diff --git a/nix/libstore/build.cc b/nix/libstore/build.cc > index c95bd2821f..e8e4a56e2d 100644 > --- a/nix/libstore/build.cc > +++ b/nix/libstore/build.cc > @@ -2175,7 +2175,7 @@ void DerivationGoal::runChild() > createDirs(dirOf(target)); > writeFile(target, ""); > } > - if (mount(source.c_str(), target.c_str(), "", MS_BIND, 0= ) =3D=3D -1) > + if (mount(source.c_str(), target.c_str(), "", MS_BIND | = MS_RDONLY, 0) =3D=3D -1) > throw SysError(format("bind mount from `%1%' to `%2%= ' failed") % source % target); > } >=20=20 > > > (I checked that it does the right thing.) > > The fix is trivial, but I=E2=80=99m glad you found the bug in the first p= lace; > it does stress that we have to be careful here. Not quite trivial, consider this section from mount(2): Creating a bind mount If mountflags includes MS_BIND (available since Linux 2.4), then p= er=E2=80=90 form a bind mount. A bind mount makes a file or a directory subt= ree visible at another point within the single directory hierarchy. B= ind mounts may cross filesystem boundaries and span chroot(2) jails. The filesystemtype and data arguments are ignored. The remaining bits (other than MS_REC, described below) in the mou= nt=E2=80=90 flags argument are also ignored. (The bind mount has the same mo= unt options as the underlying mount.) However, see the discussion of = re=E2=80=90 mounting above, for a method of making an existing bind mount re= ad- only. If you run my sneakysneaky example from before, you'll find that it still succeeds at replacing the "hello" binary because of this, even with your MS_RDONLY patch. This can be resolved by instead using MS_RDONLY with a followup mount call using MS_REMOUNT. Note also that store items that are files instead of directories (e.g. sour= ce tarballs) are hardlinked if possible. This seems to stem from an old misconception that only directories can be bind-mounted. The hardlinks, of course, do not have any write-protection on them aside from their permission bits. This can be resolved by always bind-mounting them instead. Despite the name, there is actually already support for bind-mounting non-directory files that are listed in dirsInChroot. >> I suppose we could try to perform these bind-mounts with the MS_RDONLY >> flag, but we would need some way to ensure that the builder can't just >> remount them read-write > > The example below tests that; =E2=80=98mount=E2=80=99 fails with EPERM wh= en using the > unprivileged daemon (=E2=80=98./test-env guix build -f =E2=80=A6=E2=80=99= ): > > (use-modules (guix) > (guix modules) > (gnu packages bootstrap)) > > (computed-file "try-to-remount-input-read-write" > (with-imported-modules (source-module-closure > '((guix build syscalls))) > #~(begin > (use-modules (guix build syscalls)) > > (let ((input #$(plain-file "input-that-might-be-tamp= ered-with" > "All good!"))) > (mount "none" input "none" (logior MS_BIND MS_REMO= UNT)) > (call-with-output-file input > (lambda (port) > (display "BAD!" port))) > (mkdir #$output)))) > #:guile %bootstrap-guile) > > > This is similar to: > > guix shell -C guile guix -- \ > guile -c '(use-modules (guix build syscalls)) (mount "none" (getenv "= GUIX_ENVIRONMENT") "none" (logior MS_BIND MS_REMOUNT))' > > mount(2) has this: > > EPERM An attempt was made to modify (MS_REMOUNT) the MS_RDONLY, MS_NO= =E2=80=90 > SUID, or MS_NOEXEC flag, or one of the "atime" flags (MS_NOAT= =E2=80=90 > IME, MS_NODIRATIME, MS_RELATIME) of an existing mount, but the > mount is locked; see mount_namespaces(7). > > I couldn=E2=80=99t find the definite answer in mount_namespaces(7) as to = whether > this applies in this case (same namespace but after chroot); I can only > tell empirically that it does apply. I don't think that's why we're getting EPERM. I think we're running into this, from user_namespaces(7): Note that a call to execve(2) will cause a process's capabilities to be recalculated in the usual way (see capabilities(7)). Consequently, unless the process has a user ID of 0 within the namespace, or the executable file has a nonempty inheritable capabilities mask, the process will lose all capabilities. See the discussion of user and group ID mappings, below. As the builder is in the store, it can't have any associated capability masks, and your added call to prctl to drop ambient capabilities, together with the fact that the mapped UID inside the container is nonzero, should make it so that it therefore wouldn't be able to inherit any. On a tangentially-related note, the ambient capability set didn't come into being until Linux 4.3 (around 2016), which is a fair bit newer than unprivileged user namespaces. Take that for what you will. Now, according to capabilities(7): Per-user-namespace "set-user-ID-root" programs A set-user-ID program whose UID matches the UID that created a u= ser namespace will confer capabilities in the process's permitted and = ef=E2=80=90 fective sets when executed by any process inside that namespace or = any descendant user namespace. The rules about the transformation of the process's capabilities dur= ing the execve(2) are exactly as described in Transformation of capabi= li=E2=80=90 ties during execve() and Capabilities and execution of programs by r= oot above, with the difference that, in the latter subsection, "root"= is the UID of the creator of the user namespace. This would seem to suggest that the capabilities within the user namespace could be regained by creating a setuid binary and executing it, but experimentally this doesn't happen, and I am unsure whether this is a bug in the documentation, kernel, or my reading comprehension. At any rate, I am less than confident in relying on this behavior. I think it would be a good idea to, in the no-build-user case, add an extra call to unshare right at the point where the user and group would be changed in the build-user case. This extra call would create a fresh user and mount namespace, ensuring that the mount-locking behavior you referenced applies. My understanding is that the setuid behavior documented above only grants capabilities, it doesn't change the user namespace that the process is in, so it should be impossible for the builder to gain capabilities inside the user namespace owning the bind-mounted store items, even if it somehow gained full capabilities within this fresh user namespace. > - pid =3D clone(childEntry, > + pid =3D clone(childEntry, > (char *)(((uintptr_t)stack + sizeof(stack) - 8) & ~(uintptr_t)0xf), > flags, this); > - if (pid =3D=3D -1) > - throw SysError("cloning builder process"); > + if (pid =3D=3D -1) { > + if ((flags & CLONE_NEWUSER) !=3D 0 && getuid() !=3D 0) > + /* 'clone' fails with EPERM on distros where unprivileged user > + namespaces are disabled. Error out instead of giving up on > + isolation. */ > + throw SysError("cannot create process in unprivileged user namespace"); > + else > + throw SysError("cloning builder process"); > + } > + > + if ((flags & CLONE_NEWUSER) !=3D 0) { > + /* Initialize the UID/GID mapping of the guest. */ > + if (pid =3D=3D 0) { > + char str[20] =3D { '\0' }; > + readFull(readiness.readSide, (unsigned char*)str, 3); > + if (strcmp(str, "go\n") !=3D 0) > + throw Error("failed to initialize process in unprivileged user nam= espace"); > + } else { > + initializeUserNamespace(pid); > + writeFull(readiness.writeSide, (unsigned char*)"go\n", 3); > + } This doesn't actually do any synchronizing with the child process, because clone never returns 0. It's not like fork where it returns twice with a different return value each time, control in the new thread instead goes straight to childEntry. The parent doesn't get stuck and hang when writing because PIPE_BUF > 3. >> This does raise the question, though, of how these failed build >> directories would get deleted, aside from rebooting the system. > > Note that in the early days (and in current Nix actually), build trees > were not chowned. That=E2=80=99s OK: they=E2=80=99re deleted upon reboot= or by the > system administrator. > > Current Nix has this: > > void DerivationGoal::deleteTmpDir(bool force) > { > if (tmpDir !=3D "") { > /* Don't keep temporary directories for builtins because they > might have privileged stuff (like a copy of netrc). */ > if (settings.keepFailed && !force && !drv->isBuiltin()) { > printError("note: keeping build directory '%s'", tmpDir); > chmod(tmpDir.c_str(), 0755); > } > else > deletePath(tmpDir); > tmpDir =3D ""; > } > } > > We could go back to this. It=E2=80=99s less convenient, but okay. > > In this patch series, it attempts to chown the tree; if it fails to do > so (because it lacks CAP_CHOWN), it prints a warning and keeps going. My concern comes from knowing that I've at times gone through 100 sequential failed builds while trying to package something tricky, and I tend to keep my disk on the low end of free space to minimize how often I need to rebuild stuff. That and the one time I tried tinkering with ungoogled-chromium. I know I'd probably cause a lot of trouble if I tried doing that stuff on a shared system I didn't have administrative access to. A best-effort chown attempt should do fine for now, though. >> We currently remount /gnu/store read-write at LocalStore-creation-time, >> which happens in the newly-forked guix-daemon process at the start of a >> connection. I don't think there's any particularly elevated risk from >> instead doing that before the per-connection process is forked. There >> are a number of ways we could do this: we could make it the >> responsibility of the init system to create the mount namespace and do >> the remounting, or we could have guix-daemon do it immediately on >> startup and subsequently switch its uid and gid to >> guix-daemon:guix-daemon. These lack the slick appeal of "see, you never >> have to give it root, and you can prove it just by looking at the >> service file", but realistically should be just as secure. It may be >> useful to provide a small wrapper around guix-daemon that does the >> remount and privilege-dropping, to more succinctly express this to >> anybody wishing to see for themselves. > > I think I=E2=80=99d prefer to have a systemd (or other) service make a > read-write bind-mount at /gnu/store/.rw-store, and then we=E2=80=99d run > =E2=80=98guix-daemon --backing-store=3D/gnu/store/.rw-store=E2=80=99. > > WDYT? So if I understand correctly, we would have /gnu/store hold all of its usual contents in the usual manner, and a service would bind-mount /gnu/store to /gnu/store/.rw-store without MS_RDONLY, and then it (or another service that depends on it) would bind-mount /gnu/store to itself with MS_RDONLY, and then guix-daemon would, in its own mount namespace, bind-mount /gnu/store/.rw-store to /gnu/store, again without MS_RDONLY. I assume that making /gnu/store read-only wouldn't make the already-bind-mounted /gnu/store/.rw-store read-only too? If it does, it's not going to work, and if it doesn't, it's going to remain writable for footgun appreciators. But I suppose it's at least a little more out-of-the-way. I think it might be simpler to integrate the change if we instead made it /gnu/.rw-store or something like that, since that way we don't have to worry about updating the garbage collector and such to treat it specially. Actually, now that I think about it, another possibility would be having a service that the read-only store-mount service depends on that first creates a persistent user+mount namespace combo which saves a view of the writable store (I don't recall exactly how creating the persistent namespace works, but I know the 'ip netns ...' commands can do something similar to create named network namespaces). The process that creates this namespace would run as the guix-daemon user, and therefore when guix-daemon starts it would have full capabilities within that user namespace, and could setns straight into it. This would leave no writable store in the root mount namespace. >> Personally, I think that if a guix-daemon can use privilege separation >> users, it would probably be a good idea to. We're certainly going to >> need to support them on non-linux systems either way. Could it be >> possible to have guix-install.sh modify /etc/sudoers on systems that use >> it to allow the guix-daemon user to run processes under guix builder >> users? I am currently less worried about arbitrary code execution >> vulnerabilities being found in the daemon than about the possibility of >> malicious builders (but it is possible I am underexposed to the ways >> those can happen in C++). > > What would you put in /etc/sudoers? I=E2=80=99m not sure what you had in > mind. I'm not sure what I had in mind either, I've only seen some opine that it's usually better to configure sudo than to write your own setuid programs, which was the first thing that came to mind for how to use dedicated build users without needing the entire daemon running as root. I recall reading somewhere that it could be configured to allow certain users to run certain commands as certain other users? So maybe it could be configured to allow the guix-daemon user to run any command as any of the guixbuilder users. Although granted, the way that container setup is currently done wouldn't work very well with that, since by the time we're ready to execute the builder we're already fully in the container, where setuid-root binaries should probably not be. I know that "how to use dedicated build users without root" probably isn't what you were asking for feedback on, but it did show up in my thoughts quite a bit. =2D reepca --=-=-= Content-Type: application/pgp-signature; name="signature.asc" -----BEGIN PGP SIGNATURE----- iQFLBAEBCAA1FiEEdNapMPRLm4SepVYGwWaqSV9/GJwFAmeZ3gYXHHJlZXBjYUBy dXNzZWxzdGVpbi54eXoACgkQwWaqSV9/GJzAkQf/VZjUTwuxVy5Aid8p4p+ovhT0 0tkp7zheyG8TojG/YSgBhjF4YXfA5vAymdMjCMFCmt6J3gIlOgGjgbDyVylvzFxG KnE5nYXnujP2XKJ61pbWKVrAP2Lqdz7gGq+EKu9dCsHBDkPQkWo0idoSW6oIdXSF EISvUGtZ5wrzm6uAl5D0YINqw/aAEbharanfZYin2eRIy7hH5k598Wca7hgBC9e0 fDy+dBn7vME3bUzitXHpvdZVsgHOSDpKogacsIJRbsAqEVPYXNU/tN5xTjomb5dM ycF4epwPKqDcy+/rWX3N3vP266E5vxUL3SvQ0ujYlafrC+OiEICySu4BLTPoSA== =6lw/ -----END PGP SIGNATURE----- --=-=-=--
guix-patches@HIDDEN
:bug#75810
; Package guix-patches
.
Full text available.Received: (at 75810) by debbugs.gnu.org; 27 Jan 2025 22:06:28 +0000 From debbugs-submit-bounces <at> debbugs.gnu.org Mon Jan 27 17:06:28 2025 Received: from localhost ([127.0.0.1]:34734 helo=debbugs.gnu.org) by debbugs.gnu.org with esmtp (Exim 4.84_2) (envelope-from <debbugs-submit-bounces <at> debbugs.gnu.org>) id 1tcXFU-0005tH-7X for submit <at> debbugs.gnu.org; Mon, 27 Jan 2025 17:06:28 -0500 Received: from eggs.gnu.org ([2001:470:142:3::10]:49858) by debbugs.gnu.org with esmtps (TLS1.2:ECDHE_RSA_AES_256_GCM_SHA384:256) (Exim 4.84_2) (envelope-from <ludo@HIDDEN>) id 1tcXFO-0005sv-T5 for 75810 <at> debbugs.gnu.org; Mon, 27 Jan 2025 17:06:26 -0500 Received: from fencepost.gnu.org ([2001:470:142:3::e]) by eggs.gnu.org with esmtps (TLS1.2:ECDHE_RSA_AES_256_GCM_SHA384:256) (Exim 4.90_1) (envelope-from <ludo@HIDDEN>) id 1tcXFG-0000y9-G2; Mon, 27 Jan 2025 17:06:15 -0500 DKIM-Signature: v=1; a=rsa-sha256; q=dns/txt; c=relaxed/relaxed; d=gnu.org; s=fencepost-gnu-org; h=MIME-Version:Date:References:In-Reply-To:Subject:To: From; bh=FZsZtn8hQb4MqBPsBayyvYeriMYuiItagcbZynF5vWE=; b=eL85oeL6tksyFAc/pETY ijrRKvEQ1HikFxb6M+UVdJAl+rbw6C77c6WGBFrgZ4RTd1nB7EE9cSmV4frYYVRYquvx8E0hbUtmg R1Zowr0k+AnlzSoUwYQNYOPkNljpv8FIqd1f8vYreROOpxUA/3BFv5c6wBedrQKN2DZb3wHau/Ut7 XInkboSJIk4DLL86ziS2emVZQD3CAJjLBdZgwooDQuVmqYqxWgcLWROkr/9c4LXAlkcMwjtTzjgR3 rKNysWRhEQ62Cjy3Hg4R9TdguIH3NgQlz85y67YwY2vat+/6Otw8cyWbsHlrUZeeQ9AQGiYzOjJHE ERfse9CkCPcX6A==; From: =?utf-8?Q?Ludovic_Court=C3=A8s?= <ludo@HIDDEN> To: =?utf-8?Q?No=C3=A9?= Lopez <noe@HIDDEN> Subject: Re: [PATCH 0/6] Rootless guix-daemon In-Reply-To: <87ed0ox6wj.fsf@HIDDEN> (=?utf-8?Q?=22No=C3=A9?= Lopez"'s message of "Mon, 27 Jan 2025 22:51:08 +0100") References: <87ed0ox6wj.fsf@HIDDEN> X-URL: http://www.fdn.fr/~lcourtes/ X-Revolutionary-Date: Octidi 8 =?utf-8?Q?Pluvi=C3=B4se?= an 233 de la =?utf-8?Q?R=C3=A9volution=2C?= jour du =?utf-8?B?TcOpesOpcsOpb24=?= X-PGP-Key-ID: 0x090B11993D9AEBB5 X-PGP-Key: http://www.fdn.fr/~lcourtes/ludovic.asc X-PGP-Fingerprint: 3CE4 6455 8A84 FDC6 9DB4 0CFB 090B 1199 3D9A EBB5 X-OS: x86_64-pc-linux-gnu Date: Mon, 27 Jan 2025 23:05:21 +0100 Message-ID: <87r04nhpzy.fsf@HIDDEN> User-Agent: Gnus/5.13 (Gnus v5.13) MIME-Version: 1.0 Content-Type: text/plain; charset=utf-8 Content-Transfer-Encoding: quoted-printable X-Spam-Score: -2.3 (--) X-Debbugs-Envelope-To: 75810 Cc: Reepca Russelstein <reepca@HIDDEN>, 75810 <at> debbugs.gnu.org, Janneke Nieuwenhuizen <janneke@HIDDEN> X-BeenThere: debbugs-submit <at> debbugs.gnu.org X-Mailman-Version: 2.1.18 Precedence: list List-Id: <debbugs-submit.debbugs.gnu.org> List-Unsubscribe: <https://debbugs.gnu.org/cgi-bin/mailman/options/debbugs-submit>, <mailto:debbugs-submit-request <at> debbugs.gnu.org?subject=unsubscribe> List-Archive: <https://debbugs.gnu.org/cgi-bin/mailman/private/debbugs-submit/> List-Post: <mailto:debbugs-submit <at> debbugs.gnu.org> List-Help: <mailto:debbugs-submit-request <at> debbugs.gnu.org?subject=help> List-Subscribe: <https://debbugs.gnu.org/cgi-bin/mailman/listinfo/debbugs-submit>, <mailto:debbugs-submit-request <at> debbugs.gnu.org?subject=subscribe> Errors-To: debbugs-submit-bounces <at> debbugs.gnu.org Sender: "Debbugs-submit" <debbugs-submit-bounces <at> debbugs.gnu.org> X-Spam-Score: -3.3 (---) Hi, No=C3=A9 Lopez <noe@no=C3=A9.eu> skribis: > If the store is not read-only, is there not a risk of applications > running as root modifying their own files in the store? Yes, there=E2=80=99s a risk. > As a possible solution, maybe it is possible to have a modifiable store > directory for the daemon and a read-only bind mount as /gnu/store. If > it does not have performance implications, applications would be started > from /gnu/store as usual and the builder can still use the other > directory. I agree, that=E2=80=99s what I alluded to with having /gnu/.rw-store as the backing store used by guix-daemon, while /gnu/store would be read-only. Thanks, Ludo=E2=80=99.
guix-patches@HIDDEN
:bug#75810
; Package guix-patches
.
Full text available.Received: (at 75810) by debbugs.gnu.org; 27 Jan 2025 21:51:30 +0000 From debbugs-submit-bounces <at> debbugs.gnu.org Mon Jan 27 16:51:30 2025 Received: from localhost ([127.0.0.1]:34677 helo=debbugs.gnu.org) by debbugs.gnu.org with esmtp (Exim 4.84_2) (envelope-from <debbugs-submit-bounces <at> debbugs.gnu.org>) id 1tcX10-00059v-Fv for submit <at> debbugs.gnu.org; Mon, 27 Jan 2025 16:51:30 -0500 Received: from smtp.domeneshop.no ([2a01:5b40:0:3006::1]:48092) by debbugs.gnu.org with esmtps (TLS1.2:ECDHE_RSA_AES_256_GCM_SHA384:256) (Exim 4.84_2) (envelope-from <noe@HIDDEN>) id 1tcX0x-00059h-TM for 75810 <at> debbugs.gnu.org; Mon, 27 Jan 2025 16:51:28 -0500 DKIM-Signature: v=1; a=rsa-sha256; q=dns/txt; c=relaxed/relaxed; d=xn--no-cja.eu; s=ds202402; h=Content-Transfer-Encoding:Content-Type: MIME-Version:Message-ID:Date:In-Reply-To:Subject:Cc:To:From:From:Sender: Reply-To:Subject:Date:Message-ID:To:Cc:MIME-Version:Content-Type: Content-Transfer-Encoding:Content-ID:Content-Description:Resent-Date: Resent-From:Resent-Sender:Resent-To:Resent-Cc:Resent-Message-ID:In-Reply-To: References:List-Id:List-Help:List-Unsubscribe:List-Subscribe:List-Post: List-Owner:List-Archive; bh=GgPEyd3fk1s6cfcwQ3m466y4tXWO39lJaumX+dc0l6A=; b=e BbTqvC8t+hNcMIibYGo3qvDzVtYWItsEafHZu1q8nT5iZ4BQG4YI8W3zzY+gjkI5QiUKCTkuLEKl6 bVjPp2eWdlfzRNFkwKfiuZZWbaoZG5L3VHX69vtm9Vtwlebs9OcMtenXGfC6IB67GGPzglFF3gYrw mbdJjH2fdTeJAip6XbRXvgg0CZr0XYZdUpDE4MRDsJOFOZdFBWr6zT7rIqtz2dIhXOdoNdOaoxQQT PFkYQSZFeX2F6Nme/E19PcR9RDQXR+MjgKXg9GwZKMrnj2CIEEkUzM299vJCf5b3dLKEAm8iESFAI YfvrPixHRE+uo7YtJQeWY/oXQmKFJEGvQ==; Received: from smtp by smtp.domeneshop.no with esmtpsa (TLS1.3) tls TLS_ECDHE_RSA_WITH_AES_256_GCM_SHA384 (Exim 4.95) id 1tcX0q-003nln-U6; Mon, 27 Jan 2025 22:51:21 +0100 From: =?utf-8?Q?No=C3=A9_Lopez?= <noe@HIDDEN> To: 75810 <at> debbugs.gnu.org Subject: Re: [PATCH 0/6] Rootless guix-daemon In-Reply-To: <87bjvshrk0.fsf@HIDDEN> Date: Mon, 27 Jan 2025 22:51:08 +0100 Message-ID: <87ed0ox6wj.fsf@HIDDEN> MIME-Version: 1.0 Content-Type: text/plain; charset=utf-8 Content-Transfer-Encoding: quoted-printable X-Spam-Score: -0.0 (/) X-Debbugs-Envelope-To: 75810 Cc: Ludovic =?utf-8?Q?Court=C3=A8s?= <ludo@HIDDEN>, Reepca Russelstein <reepca@HIDDEN>, Janneke Nieuwenhuizen <janneke@HIDDEN> X-BeenThere: debbugs-submit <at> debbugs.gnu.org X-Mailman-Version: 2.1.18 Precedence: list List-Id: <debbugs-submit.debbugs.gnu.org> List-Unsubscribe: <https://debbugs.gnu.org/cgi-bin/mailman/options/debbugs-submit>, <mailto:debbugs-submit-request <at> debbugs.gnu.org?subject=unsubscribe> List-Archive: <https://debbugs.gnu.org/cgi-bin/mailman/private/debbugs-submit/> List-Post: <mailto:debbugs-submit <at> debbugs.gnu.org> List-Help: <mailto:debbugs-submit-request <at> debbugs.gnu.org?subject=help> List-Subscribe: <https://debbugs.gnu.org/cgi-bin/mailman/listinfo/debbugs-submit>, <mailto:debbugs-submit-request <at> debbugs.gnu.org?subject=subscribe> Errors-To: debbugs-submit-bounces <at> debbugs.gnu.org Sender: "Debbugs-submit" <debbugs-submit-bounces <at> debbugs.gnu.org> X-Spam-Score: -1.0 (-) Hi Ludovic, If the store is not read-only, is there not a risk of applications running as root modifying their own files in the store? As a possible solution, maybe it is possible to have a modifiable store directory for the daemon and a read-only bind mount as /gnu/store. If it does not have performance implications, applications would be started from /gnu/store as usual and the builder can still use the other directory. What do you think? No=C3=A9
guix-patches@HIDDEN
:bug#75810
; Package guix-patches
.
Full text available.Received: (at 75810) by debbugs.gnu.org; 27 Jan 2025 21:32:04 +0000 From debbugs-submit-bounces <at> debbugs.gnu.org Mon Jan 27 16:32:04 2025 Received: from localhost ([127.0.0.1]:34655 helo=debbugs.gnu.org) by debbugs.gnu.org with esmtp (Exim 4.84_2) (envelope-from <debbugs-submit-bounces <at> debbugs.gnu.org>) id 1tcWiB-0004Ie-Lk for submit <at> debbugs.gnu.org; Mon, 27 Jan 2025 16:32:04 -0500 Received: from eggs.gnu.org ([2001:470:142:3::10]:40310) by debbugs.gnu.org with esmtps (TLS1.2:ECDHE_RSA_AES_256_GCM_SHA384:256) (Exim 4.84_2) (envelope-from <ludo@HIDDEN>) id 1tcWi7-0004I4-BZ for 75810 <at> debbugs.gnu.org; Mon, 27 Jan 2025 16:32:02 -0500 Received: from fencepost.gnu.org ([2001:470:142:3::e]) by eggs.gnu.org with esmtps (TLS1.2:ECDHE_RSA_AES_256_GCM_SHA384:256) (Exim 4.90_1) (envelope-from <ludo@HIDDEN>) id 1tcWi0-0003ut-Nv; Mon, 27 Jan 2025 16:31:52 -0500 DKIM-Signature: v=1; a=rsa-sha256; q=dns/txt; c=relaxed/relaxed; d=gnu.org; s=fencepost-gnu-org; h=MIME-Version:Date:References:In-Reply-To:Subject:To: From; bh=YDM+EJL5NRiIdzlKPrzEycEEJGbMu9+2u59HSqzLKLs=; b=EJ/eIRR6f+aXGcbQUCDO d6BOIyX+v9RlccedEoZGj2GsYTLLxi9w4MjJ+YgPxDzQ4ETvQicWWcZMIKAdkGVTr3JASJyGJ24pV VnUP2+AZ5mWSHB8yQnMe0KY4VAvaMtsmN+GOKb7Pms3dgZlf7K5Zk6UANPrisX1pFKTiKH0DIbJK8 SGMlqn1HB0eBBrVpI2fDPRE5BzkI7P4OpoC8+6lPWdcHyeZLcO4Rr1ZqyStOKkjb6meBEm1rRjXye /g+V++5dXIdymTm9HE8Ab8DNVHvMluvEyOLrbJ3l3CtdFTNwYcM0nV6o5tbfVK8mSbry5SyLGkHyZ 8JN8uLXVJBB+Yw==; From: =?utf-8?Q?Ludovic_Court=C3=A8s?= <ludo@HIDDEN> To: Reepca Russelstein <reepca@HIDDEN> Subject: Re: [bug#75810] [PATCH 0/6] Rootless guix-daemon In-Reply-To: <87r04qe7dj.fsf@HIDDEN> (Reepca Russelstein's message of "Sat, 25 Jan 2025 18:39:04 -0600") References: <cover.1737738362.git.ludo@HIDDEN> <87r04qe7dj.fsf@HIDDEN> Date: Mon, 27 Jan 2025 22:31:43 +0100 Message-ID: <87bjvshrk0.fsf@HIDDEN> User-Agent: Gnus/5.13 (Gnus v5.13) MIME-Version: 1.0 Content-Type: multipart/mixed; boundary="=-=-=" X-Spam-Score: -1.8 (-) X-Debbugs-Envelope-To: 75810 Cc: 75810 <at> debbugs.gnu.org X-BeenThere: debbugs-submit <at> debbugs.gnu.org X-Mailman-Version: 2.1.18 Precedence: list List-Id: <debbugs-submit.debbugs.gnu.org> List-Unsubscribe: <https://debbugs.gnu.org/cgi-bin/mailman/options/debbugs-submit>, <mailto:debbugs-submit-request <at> debbugs.gnu.org?subject=unsubscribe> List-Archive: <https://debbugs.gnu.org/cgi-bin/mailman/private/debbugs-submit/> List-Post: <mailto:debbugs-submit <at> debbugs.gnu.org> List-Help: <mailto:debbugs-submit-request <at> debbugs.gnu.org?subject=help> List-Subscribe: <https://debbugs.gnu.org/cgi-bin/mailman/listinfo/debbugs-submit>, <mailto:debbugs-submit-request <at> debbugs.gnu.org?subject=subscribe> Errors-To: debbugs-submit-bounces <at> debbugs.gnu.org Sender: "Debbugs-submit" <debbugs-submit-bounces <at> debbugs.gnu.org> X-Spam-Score: -2.8 (--) --=-=-= Content-Type: text/plain Hello Reepca, Reepca Russelstein <reepca@HIDDEN> skribis: > user@debian:~$ /gnu/store/8bjy9g0cssjrw9ljz2r8ww1sma95isfj-hello-2.12.1/bin/hello > GOOOOOD BYYEEEEEE This particular issue is fixed with read-only mounts: --=-=-= Content-Type: text/x-patch Content-Disposition: inline diff --git a/nix/libstore/build.cc b/nix/libstore/build.cc index c95bd2821f..e8e4a56e2d 100644 --- a/nix/libstore/build.cc +++ b/nix/libstore/build.cc @@ -2175,7 +2175,7 @@ void DerivationGoal::runChild() createDirs(dirOf(target)); writeFile(target, ""); } - if (mount(source.c_str(), target.c_str(), "", MS_BIND, 0) == -1) + if (mount(source.c_str(), target.c_str(), "", MS_BIND | MS_RDONLY, 0) == -1) throw SysError(format("bind mount from `%1%' to `%2%' failed") % source % target); } --=-=-= Content-Type: text/plain; charset=utf-8 Content-Transfer-Encoding: quoted-printable (I checked that it does the right thing.) The fix is trivial, but I=E2=80=99m glad you found the bug in the first pla= ce; it does stress that we have to be careful here. > I suppose we could try to perform these bind-mounts with the MS_RDONLY > flag, but we would need some way to ensure that the builder can't just > remount them read-write The example below tests that; =E2=80=98mount=E2=80=99 fails with EPERM when= using the unprivileged daemon (=E2=80=98./test-env guix build -f =E2=80=A6=E2=80=99): --8<---------------cut here---------------start------------->8--- (use-modules (guix) (guix modules) (gnu packages bootstrap)) (computed-file "try-to-remount-input-read-write" (with-imported-modules (source-module-closure '((guix build syscalls))) #~(begin (use-modules (guix build syscalls)) (let ((input #$(plain-file "input-that-might-be-tamper= ed-with" "All good!"))) (mount "none" input "none" (logior MS_BIND MS_REMOUN= T)) (call-with-output-file input (lambda (port) (display "BAD!" port))) (mkdir #$output)))) #:guile %bootstrap-guile) --8<---------------cut here---------------end--------------->8--- This is similar to: guix shell -C guile guix -- \ guile -c '(use-modules (guix build syscalls)) (mount "none" (getenv "GU= IX_ENVIRONMENT") "none" (logior MS_BIND MS_REMOUNT))' mount(2) has this: EPERM An attempt was made to modify (MS_REMOUNT) the MS_RDONLY, MS_NO= =E2=80=90 SUID, or MS_NOEXEC flag, or one of the "atime" flags (MS_NOAT= =E2=80=90 IME, MS_NODIRATIME, MS_RELATIME) of an existing mount, but the mount is locked; see mount_namespaces(7). I couldn=E2=80=99t find the definite answer in mount_namespaces(7) as to wh= ether this applies in this case (same namespace but after chroot); I can only tell empirically that it does apply. >> This patch changes guix-daemon so it can run as an unprivileged >> user, using unprivileged user namespaces to still support isolated >> builds. There=E2=80=99s a couple of cases where root is/was still neces= sary: >>=20 >> 1. To create /var/guix/profiles/per-user/$USER and chown it >> as $USER (see CVE-2019-18192). >>=20 >> 2. To chown /tmp/guix-build-* when using =E2=80=98--keep-failed=E2=80= =99. >>=20 >> Both can be addressed by giving CAP_CHOWN to guix-daemon, and this is >> what this patch series does on distros using systemd. (For some >> reason CAP_CHOWN had to be added to the set of =E2=80=9Cambient capabili= ties=E2=80=9D, >> which are inherited by child processes; this is why there=E2=80=99s a pa= tch >> to drop ambient capabilities in build processes.) >>=20 >> On Guix System (not implemented here), we could address (1) by >> creating /var/guix/profiles/per-user/$USER upfront for all the >> user accounts. We could leave (2) unaddressed (so failed build >> directories would be owned by guix-daemon:guix-daemon) or we=E2=80=99d >> have to pass CAP_CHOWN as well. [...] > This does raise the question, though, of how these failed build > directories would get deleted, aside from rebooting the system. Note that in the early days (and in current Nix actually), build trees were not chowned. That=E2=80=99s OK: they=E2=80=99re deleted upon reboot o= r by the system administrator. Current Nix has this: --8<---------------cut here---------------start------------->8--- void DerivationGoal::deleteTmpDir(bool force) { if (tmpDir !=3D "") { /* Don't keep temporary directories for builtins because they might have privileged stuff (like a copy of netrc). */ if (settings.keepFailed && !force && !drv->isBuiltin()) { printError("note: keeping build directory '%s'", tmpDir); chmod(tmpDir.c_str(), 0755); } else deletePath(tmpDir); tmpDir =3D ""; } } --8<---------------cut here---------------end--------------->8--- We could go back to this. It=E2=80=99s less convenient, but okay. In this patch series, it attempts to chown the tree; if it fails to do so (because it lacks CAP_CHOWN), it prints a warning and keeps going. > Perhaps the garbage collector could be modified to get rid of them? > In which case it may be best to make it so that the failed build > directories are automatically added to the temp roots for a client, > and the client takes care to copy the failed build directory to a > fresh path owned by the current user? Or we could make it so that the > failed build directory gets sent over the wire in nar form to the > client. Not sure what the best approach there is. Dunno. Sending it as nar may be too heavyweight and quite a bit of work. I=E2=80=99d say it goes beyond the scope of this patch series, though. > We currently remount /gnu/store read-write at LocalStore-creation-time, > which happens in the newly-forked guix-daemon process at the start of a > connection. I don't think there's any particularly elevated risk from > instead doing that before the per-connection process is forked. There > are a number of ways we could do this: we could make it the > responsibility of the init system to create the mount namespace and do > the remounting, or we could have guix-daemon do it immediately on > startup and subsequently switch its uid and gid to > guix-daemon:guix-daemon. These lack the slick appeal of "see, you never > have to give it root, and you can prove it just by looking at the > service file", but realistically should be just as secure. It may be > useful to provide a small wrapper around guix-daemon that does the > remount and privilege-dropping, to more succinctly express this to > anybody wishing to see for themselves. I think I=E2=80=99d prefer to have a systemd (or other) service make a read-write bind-mount at /gnu/store/.rw-store, and then we=E2=80=99d run =E2=80=98guix-daemon --backing-store=3D/gnu/store/.rw-store=E2=80=99. WDYT? > There are, effectively, 3 platforms that guix currently supports: posix, > linux, and hurd. Rather two: Linux and Hurd. But note: we don=E2=80=99t use any Hurd-specif= ic features yet, and in practice all the energy and focus is on Linux (on the Hurd we run =E2=80=98guix-daemon --disable-chroot=E2=80=99 anyway). Adding the privileged/unprivileged setting, we=E2=80=99d have two configura= tions really, again setting aside the Hurd. The way I see it, if everything goes well, we=E2=80=99d default to unprivil= eged guix-daemon on Guix System as well and eventually (longer term) drop the privileged daemon. > Personally, I think that if a guix-daemon can use privilege separation > users, it would probably be a good idea to. We're certainly going to > need to support them on non-linux systems either way. Could it be > possible to have guix-install.sh modify /etc/sudoers on systems that use > it to allow the guix-daemon user to run processes under guix builder > users? I am currently less worried about arbitrary code execution > vulnerabilities being found in the daemon than about the possibility of > malicious builders (but it is possible I am underexposed to the ways > those can happen in C++). What would you put in /etc/sudoers? I=E2=80=99m not sure what you had in m= ind. Aside, I=E2=80=99d rather avoid relying on external tools like =E2=80=98sud= o=E2=80=99. > Additionally, CAP_CHOWN, while not having a direct path to privilege > escalation due to setuid and setgid bits being reset when chown is > called, can nevertheless be easily leveraged into privilege escalation > in most real-world situations where arbitrary code execution is > possible, so switching to using just that capability would realistically > only add defense in less-than-arbitrary-code-execution scenarios. I agree about CAP_CHOWN, which is why I proposed scenarios without it. Thanks a lot for your feedback! I=E2=80=99ll send a second version addressing the immediate issue you found and, if everything goes well, an attempt at restoring the /gnu/store read-only bind-mount. Ludo=E2=80=99. --=-=-=--
guix-patches@HIDDEN
:bug#75810
; Package guix-patches
.
Full text available.Received: (at 75810) by debbugs.gnu.org; 26 Jan 2025 00:39:59 +0000 From debbugs-submit-bounces <at> debbugs.gnu.org Sat Jan 25 19:39:59 2025 Received: from localhost ([127.0.0.1]:53216 helo=debbugs.gnu.org) by debbugs.gnu.org with esmtp (Exim 4.84_2) (envelope-from <debbugs-submit-bounces <at> debbugs.gnu.org>) id 1tbqgw-0000n8-G9 for submit <at> debbugs.gnu.org; Sat, 25 Jan 2025 19:39:59 -0500 Received: from mailout.russelstein.xyz ([2605:6400:20:11e::1]:39146) by debbugs.gnu.org with esmtps (TLS1.2:ECDHE_RSA_AES_256_GCM_SHA384:256) (Exim 4.84_2) (envelope-from <reepca@HIDDEN>) id 1tbqgs-0000mn-Ey for 75810 <at> debbugs.gnu.org; Sat, 25 Jan 2025 19:39:56 -0500 DKIM-Signature: v=1; a=ed25519-sha256; q=dns/txt; c=relaxed/relaxed; d=russelstein.xyz; s=ed25519; h=Content-Type:MIME-Version:Message-ID:Date: Subject:Cc:To:From:Sender:Reply-To:Content-Transfer-Encoding:Content-ID: Content-Description:Resent-Date:Resent-From:Resent-Sender:Resent-To:Resent-Cc :Resent-Message-ID:In-Reply-To:References:List-Id:List-Help:List-Unsubscribe: List-Subscribe:List-Post:List-Owner:List-Archive; bh=wQyG0DCngy20L29OZSejT2Qh3hLwn3VWOUvdKlWjcVg=; b=/6zn4adiQKpucNvSmUJg+pEHzg M26VPPAHEVejXfDUlyv1qNLE8HWVUdbqPOJXiKujCdorRGN66Rm1bXjtXdDA==; DKIM-Signature: v=1; a=rsa-sha256; q=dns/txt; c=relaxed/relaxed; d=russelstein.xyz; s=rsa; h=Content-Type:MIME-Version:Message-ID:Date:Subject :Cc:To:From:Sender:Reply-To:Content-Transfer-Encoding:Content-ID: Content-Description:Resent-Date:Resent-From:Resent-Sender:Resent-To:Resent-Cc :Resent-Message-ID:In-Reply-To:References:List-Id:List-Help:List-Unsubscribe: List-Subscribe:List-Post:List-Owner:List-Archive; bh=wQyG0DCngy20L29OZSejT2Qh3hLwn3VWOUvdKlWjcVg=; b=OMo1scxXbK08D7aDTzNoFjnoMM UTftPxQ1L+EKF0Jn1kF2oJTuNehbBygqlAVMHFd4B9lheCPSWhIvkKakwNhXgcCNA4p7iBDV1yLG2 WAUADo41MxADlPVH1KGwmVrYHoWoRa6Mo/jzV4ah147nGO/6Y3g9cvUpI76DOPCutuVpLb+3xrAVk R5XeygdadPnehzqfnsqs7xPU0XEXlMF/a+UB5mE3rm0L4P/m1i49vfgFoB5/yhbovOObYrmgW9vfx 1ui1eXO10ndX6BhAc9VV2sjVHJwkMqOrQhJiXvVAdFYZy5LvJz5Sm+hI9UPIlepqkU4JEnCzSKGQ1 Aecb5CsXlmDlISMufMAaqqCJJmeMbrnDbFqpywgwbOTKAA3ZD3gBQ6sB1ldOxDEJe8sl0uE3sPesB 2WfDuvbck7OfQRceGFeJ5q13eVl0rtIL32xsN1eNiZYDgkLj1PHTN3rsPpfe3N3IiDdGjAF10cs7I Mphb0ydeZRvETGOxqgEr3uY/ruzO0tyWeN4fdhtirdjNHj2PTjncKa13oZJ1w4Dwzh+fBWUAJ/RhG ISOS1BndKRNSSDYJni6q5n7ObZ0S3rLo13Ig75M8S4x0QfNNgwFF0P0h4zbivsVypUk2CRIQf2ceH kMte+W3slXU7XPf+V680ZSrmy0dZ0VUWoahtC5FmU=; Received: by russelstein.xyz with esmtpsa (TLS1.3:ECDHE_SECP256R1__RSA_PSS_RSAE_SHA256__AES_256_GCM:256) (Exim 4.98) (envelope-from <reepca@HIDDEN>) id 1tbqgl-000000004KD-2tF4; Sat, 25 Jan 2025 18:39:49 -0600 From: Reepca Russelstein <reepca@HIDDEN> To: 75810 <at> debbugs.gnu.org Subject: Re: [bug#75810] [PATCH 0/6] Rootless guix-daemon Date: Sat, 25 Jan 2025 18:39:04 -0600 Message-ID: <87r04qe7dj.fsf@HIDDEN> User-Agent: Gnus/5.13 (Gnus v5.13) MIME-Version: 1.0 Content-Type: multipart/signed; boundary="=-=-="; micalg=pgp-sha256; protocol="application/pgp-signature" X-Spam-Score: 0.9 X-Spam-Bar: / X-Spam-Score-Int: 9 X-Spam-Report: Spam detection software, running on the system "Sanctum", has NOT identified this incoming email as spam. The original message has been attached to this so you can view it or label similar future email. If you have any questions, see the administrator of that system for details. Content preview: > Hello Guix! > > That guix-daemon runs as root is not confidence-inspiring for many. > Initially, the main reason for running it as root was, in the absence > of user namespaces, the fact that builde [...] Content analysis details: (0.9 points, 5.0 required) pts rule name description ---- ---------------------- -------------------------------------------------- -0.0 NO_RELAYS Informational: message was not relayed via SMTP 0.4 FROM_SUSPICIOUS_NTLD_FP From abused NTLD 0.5 FROM_SUSPICIOUS_NTLD From abused NTLD 0.0 FAKE_REPLY_C No description available. X-Spam-Score: 3.0 (+++) X-Spam-Report: Spam detection software, running on the system "debbugs.gnu.org", has NOT identified this incoming email as spam. The original message has been attached to this so you can view it or label similar future email. If you have any questions, see the administrator of that system for details. Content preview: > Hello Guix! > > That guix-daemon runs as root is not confidence-inspiring for many. > Initially, the main reason for running it as root was, in the absence > of user namespaces, the fact that builde [...] Content analysis details: (3.0 points, 10.0 required) pts rule name description ---- ---------------------- -------------------------------------------------- -0.0 SPF_PASS SPF: sender matches SPF record 0.0 SPF_HELO_NONE SPF: HELO does not publish an SPF Record 0.7 PDS_OTHER_BAD_TLD Untrustworthy TLDs [URI: russelstein.xyz (xyz)] 0.5 FROM_SUSPICIOUS_NTLD From abused NTLD -0.0 T_SCC_BODY_TEXT_LINE No description available. 1.7 FROM_SUSPICIOUS_NTLD_FP From abused NTLD 0.0 FAKE_REPLY_C No description available. X-Debbugs-Envelope-To: 75810 Cc: ludo@HIDDEN X-BeenThere: debbugs-submit <at> debbugs.gnu.org X-Mailman-Version: 2.1.18 Precedence: list List-Id: <debbugs-submit.debbugs.gnu.org> List-Unsubscribe: <https://debbugs.gnu.org/cgi-bin/mailman/options/debbugs-submit>, <mailto:debbugs-submit-request <at> debbugs.gnu.org?subject=unsubscribe> List-Archive: <https://debbugs.gnu.org/cgi-bin/mailman/private/debbugs-submit/> List-Post: <mailto:debbugs-submit <at> debbugs.gnu.org> List-Help: <mailto:debbugs-submit-request <at> debbugs.gnu.org?subject=help> List-Subscribe: <https://debbugs.gnu.org/cgi-bin/mailman/listinfo/debbugs-submit>, <mailto:debbugs-submit-request <at> debbugs.gnu.org?subject=subscribe> Errors-To: debbugs-submit-bounces <at> debbugs.gnu.org Sender: "Debbugs-submit" <debbugs-submit-bounces <at> debbugs.gnu.org> X-Spam-Score: 1.2 (+) X-Spam-Report: Spam detection software, running on the system "debbugs.gnu.org", has NOT identified this incoming email as spam. The original message has been attached to this so you can view it or label similar future email. If you have any questions, see the administrator of that system for details. Content preview: > Hello Guix! > > That guix-daemon runs as root is not confidence-inspiring for many. > Initially, the main reason for running it as root was, in the absence > of user namespaces, the fact that builde [...] Content analysis details: (1.2 points, 10.0 required) pts rule name description ---- ---------------------- -------------------------------------------------- -0.0 SPF_PASS SPF: sender matches SPF record 0.0 SPF_HELO_NONE SPF: HELO does not publish an SPF Record 0.7 PDS_OTHER_BAD_TLD Untrustworthy TLDs [URI: russelstein.xyz (xyz)] 0.5 FROM_SUSPICIOUS_NTLD From abused NTLD -0.0 T_SCC_BODY_TEXT_LINE No description available. 1.0 BULK_RE_SUSP_NTLD Precedence bulk and RE: from a suspicious TLD 0.0 FAKE_REPLY_C No description available. -1.0 MAILING_LIST_MULTI Multiple indicators imply a widely-seen list manager --=-=-= Content-Type: text/plain; charset=utf-8 Content-Transfer-Encoding: quoted-printable > Hello Guix! >=20 > That guix-daemon runs as root is not confidence-inspiring for many. > Initially, the main reason for running it as root was, in the absence > of user namespaces, the fact that builders would be started under one > of the build user accounts, which only root can do. Now that > unprivileged user namespaces are almost ubiquitous (even on HPC > clusters), this is no longer a good reason. Without the build users, we're relying entirely on kernel-specific sandboxing mechanisms to protect the system from rogue builders. It's probably (?) not impossible to make it work, but, as with every time security mechanisms are changed, it does require some very careful thought. For example, consider the following: =2D-8<---------------cut here---------------start------------->8--- (use-modules (guix) (gnu) (guix build-system trivial)) (define-public sneakysneaky (package (name "sneakysneaky") (version "0") (source #f) (build-system trivial-build-system) (arguments (list #:builder #~(let ((hello (string-append #$(this-package-input "hello") "/bin/hello"))) (chmod (dirname hello) #o775) (chmod hello #o775) (delete-file hello) (call-with-output-file hello (lambda (port) (chmod port #o775) (display "#!/bin/sh echo \"GOOOOOD BYYEEEEEE\"" port))) (mkdir #$output)))) (inputs (list (@ (gnu packages base) hello))) (home-page "") (synopsis "") (description "") (license #f))) sneakysneaky =2D-8<---------------cut here---------------end--------------->8--- If we save this as /tmp/mal-test.scm on a debian VM with these patches applied, we can see the following: =2D-8<---------------cut here---------------start------------->8--- user@debian:~$ guix build --no-grafts hello /gnu/store/8bjy9g0cssjrw9ljz2r8ww1sma95isfj-hello-2.12.1 user@debian:~$ /gnu/store/8bjy9g0cssjrw9ljz2r8ww1sma95isfj-hello-2.12.1/bin= /hello Hello, world! user@debian:~$ guix build --no-grafts -f /tmp/mal-test.scm substitute: looking for substitutes on 'https://bordeaux.guix.gnu.org'... 1= 00.0% substitute: looking for substitutes on 'https://ci.guix.gnu.org'... 100.0% The following derivation will be built: /gnu/store/p15g92hfs7254pqfa3kss63dprw2clis-sneakysneaky-0.drv building /gnu/store/p15g92hfs7254pqfa3kss63dprw2clis-sneakysneaky-0.drv... successfully built /gnu/store/p15g92hfs7254pqfa3kss63dprw2clis-sneakysneaky= -0.drv /gnu/store/y1jzqg30cgkydl8kymjsh99zqgzh1yj1-sneakysneaky-0 user@debian:~$ /gnu/store/8bjy9g0cssjrw9ljz2r8ww1sma95isfj-hello-2.12.1/bin= /hello GOOOOOD BYYEEEEEE user@debian:~$=20 =2D-8<---------------cut here---------------end--------------->8--- This happens because the daemon bind-mounts store items into the container, so it's the same underlying inode both inside and out of the container. The build runs as the same user as the store owner, so there's nothing stopping it from freely modifying its input store items and any of their transitive references. I suppose we could try to perform these bind-mounts with the MS_RDONLY flag, but we would need some way to ensure that the builder can't just remount them read-write (I haven't yet looked into how to do this). The nuclear option, of course, would be to simply do a full copy of the store items in question instead of a bind-mount. > This patch changes guix-daemon so it can run as an unprivileged > user, using unprivileged user namespaces to still support isolated > builds. There=E2=80=99s a couple of cases where root is/was still necess= ary: >=20 > 1. To create /var/guix/profiles/per-user/$USER and chown it > as $USER (see CVE-2019-18192). >=20 > 2. To chown /tmp/guix-build-* when using =E2=80=98--keep-failed=E2=80= =99. >=20 > Both can be addressed by giving CAP_CHOWN to guix-daemon, and this is > what this patch series does on distros using systemd. (For some > reason CAP_CHOWN had to be added to the set of =E2=80=9Cambient capabilit= ies=E2=80=9D, > which are inherited by child processes; this is why there=E2=80=99s a pat= ch > to drop ambient capabilities in build processes.) >=20 > On Guix System (not implemented here), we could address (1) by > creating /var/guix/profiles/per-user/$USER upfront for all the > user accounts. We could leave (2) unaddressed (so failed build > directories would be owned by guix-daemon:guix-daemon) or we=E2=80=99d > have to pass CAP_CHOWN as well. The automatic chown of /tmp/guix-build-* has always been a litte strange considering that multiple users could attempt the same doomed-to-failure derivation build at the same time, and it comes down to a race to see who gets the build (and therefore the build directory). This does raise the question, though, of how these failed build directories would get deleted, aside from rebooting the system. Perhaps the garbage collector could be modified to get rid of them? In which case it may be best to make it so that the failed build directories are automatically added to the temp roots for a client, and the client takes care to copy the failed build directory to a fresh path owned by the current user? Or we could make it so that the failed build directory gets sent over the wire in nar form to the client. Not sure what the best approach there is. > There=E2=80=99s another issue: /gnu/store can no longer be remounted > read-only (like we do on Guix System and on systemd with > =E2=80=98gnu-store.mount=E2=80=99) because then unprivileged guix-daemon = would > be unable to remount it read-write (or at least I couldn=E2=80=99t find > a way to do that). Thus =E2=80=98guix-install.sh=E2=80=99 no longer inst= alls > =E2=80=98gnu-store.mount=E2=80=99 in that case. It=E2=80=99s a bit sad t= o lose that > so if anyone can think of a way to achieve it, that=E2=80=99d be great. We currently remount /gnu/store read-write at LocalStore-creation-time, which happens in the newly-forked guix-daemon process at the start of a connection. I don't think there's any particularly elevated risk from instead doing that before the per-connection process is forked. There are a number of ways we could do this: we could make it the responsibility of the init system to create the mount namespace and do the remounting, or we could have guix-daemon do it immediately on startup and subsequently switch its uid and gid to guix-daemon:guix-daemon. These lack the slick appeal of "see, you never have to give it root, and you can prove it just by looking at the service file", but realistically should be just as secure. It may be useful to provide a small wrapper around guix-daemon that does the remount and privilege-dropping, to more succinctly express this to anybody wishing to see for themselves. > The next step (in another patch series) would be Guix System support > with automatic transition (essentially =E2=80=9Cchown -R > guix-daemon:guix-daemon /gnu/store=E2=80=9D). >=20 > Thoughts? There are, effectively, 3 platforms that guix currently supports: posix, linux, and hurd. Posix doesn't get much attention since we don't chase Mac like nix does, but there do exist configurations where we use neither linux-specific nor hurd-specific functionality. Additionally, a given guix-daemon may be either privileged or unprivileged. Thus, we end up with a total of 6 configurations. Except there is now also the question of whether less-than-fully-trusted users are allowed access to the guix-daemon's socket. Now we're in theory at 12 configurations. Which of these configurations to use is, in some circumstances, going to come down to judgement calls. For example, one user may not care at all about the risk of malicious builders (e.g. "the admins on this shared system all use the debian tools anyway"), but be quite concerned about the possibility of a root-granting exploit being found in guix-daemon. Another (like myself and other Guix System users) may consider a risk to the store to be the same as a risk to the entire system itself. In theory splitting between "privileged-with-root" and "privileged-with-capabilities" will only increase the number of configurations further. Personally, I think that if a guix-daemon can use privilege separation users, it would probably be a good idea to. We're certainly going to need to support them on non-linux systems either way. Could it be possible to have guix-install.sh modify /etc/sudoers on systems that use it to allow the guix-daemon user to run processes under guix builder users? I am currently less worried about arbitrary code execution vulnerabilities being found in the daemon than about the possibility of malicious builders (but it is possible I am underexposed to the ways those can happen in C++). Additionally, CAP_CHOWN, while not having a direct path to privilege escalation due to setuid and setgid bits being reset when chown is called, can nevertheless be easily leveraged into privilege escalation in most real-world situations where arbitrary code execution is possible, so switching to using just that capability would realistically only add defense in less-than-arbitrary-code-execution scenarios. Using unprivileged user namespaces would, however, be an excellent addition for unprivileged daemons, like the one started by test-env, or one started by an unprivileged user on a system without a whole-system guix installation. Hope that helps. =2D reepca --=-=-= Content-Type: application/pgp-signature; name="signature.asc" -----BEGIN PGP SIGNATURE----- iQFLBAEBCAA1FiEEdNapMPRLm4SepVYGwWaqSV9/GJwFAmeVhCkXHHJlZXBjYUBy dXNzZWxzdGVpbi54eXoACgkQwWaqSV9/GJynXgf+JjAkPl4ovl0cvNj774zFtcoa iXEzBEt9UX6Yu48Ja6f5OhqyuNd7ZxkZMCSz2ZrnOEABBk+hzTsRvg1VX1RFBqxo jOyXWtPZYtSzFQdPL/CM5GD4oO8gW0QNf1/dn5cJDR1c4To6MSAt4v6CxLBspUZw 2DHKhGJwrKtFLWIR/6iFmmMzmn19npgFRjcL55Sb8qs691jvV1LmHJ4wN2E6p8M+ BtbWWulOGKClud2frYdI9zJp51iKIAm0V7xX6dnKhyz55OimlEv2vUHqktBOGehU ymEqXwTf8ickK3XDPoYlRjcmv6BzuuQ4AR4I7ud8aHPF9rYSodXV64jNmnJ16w== =3cRE -----END PGP SIGNATURE----- --=-=-=--
guix-patches@HIDDEN
:bug#75810
; Package guix-patches
.
Full text available.Received: (at 75810) by debbugs.gnu.org; 24 Jan 2025 22:18:31 +0000 From debbugs-submit-bounces <at> debbugs.gnu.org Fri Jan 24 17:18:31 2025 Received: from localhost ([127.0.0.1]:47341 helo=debbugs.gnu.org) by debbugs.gnu.org with esmtp (Exim 4.84_2) (envelope-from <debbugs-submit-bounces <at> debbugs.gnu.org>) id 1tbS0U-0006mQ-Vu for submit <at> debbugs.gnu.org; Fri, 24 Jan 2025 17:18:31 -0500 Received: from eggs.gnu.org ([2001:470:142:3::10]:54166) by debbugs.gnu.org with esmtps (TLS1.2:ECDHE_RSA_AES_256_GCM_SHA384:256) (Exim 4.84_2) (envelope-from <ludo@HIDDEN>) id 1tbS0S-0006m7-9o for 75810 <at> debbugs.gnu.org; Fri, 24 Jan 2025 17:18:28 -0500 Received: from fencepost.gnu.org ([2001:470:142:3::e]) by eggs.gnu.org with esmtps (TLS1.2:ECDHE_RSA_AES_256_GCM_SHA384:256) (Exim 4.90_1) (envelope-from <ludo@HIDDEN>) id 1tbS0L-0002mr-VI; Fri, 24 Jan 2025 17:18:22 -0500 DKIM-Signature: v=1; a=rsa-sha256; q=dns/txt; c=relaxed/relaxed; d=gnu.org; s=fencepost-gnu-org; h=MIME-Version:Date:References:In-Reply-To:Subject:To: From; bh=mA5ShXo6qYQGH/TtdGwNkoLoxQrZVdArwGgcsnqoirM=; b=aVBOmG7sDco3knuAJPhB W7US1MQ9pfko2Ne2Lf4TozJRfLkVa2jGiWkwP7l710pc431vq0UgBCFDCoUbyjqBsZ+dSt2v2kXof 2TMYphoAgF3WX9SQ63RWgoF+Tr5xEGNi3YI4k1MxlScAHWq+r7mpGyyj68wYXF4Ke/EA6yGwGbo1H QXdvHtaHtF322Z8Fss3Jv5Ll7+o+42JXYnvlJCr/nd6itFIdDCk8aXgmMlmDfawolnnMcXXc8Ho2j b2UmIyGcGwQFIZs6WVWV270HrXepUjSehumELb235AVhj3oPjQlYgWnezdZ7UzhzVCwxapv05uMVG zv5Hf8ubCiF9ow==; From: =?utf-8?Q?Ludovic_Court=C3=A8s?= <ludo@HIDDEN> To: Janneke Nieuwenhuizen <janneke@HIDDEN> Subject: Re: [bug#75810] [PATCH 0/6] Rootless guix-daemon In-Reply-To: <87ikq49fxx.fsf@HIDDEN> (Janneke Nieuwenhuizen's message of "Fri, 24 Jan 2025 20:20:42 +0100") References: <cover.1737738362.git.ludo@HIDDEN> <87ikq49fxx.fsf@HIDDEN> Date: Fri, 24 Jan 2025 23:18:16 +0100 Message-ID: <87y0yzdffb.fsf@HIDDEN> User-Agent: Gnus/5.13 (Gnus v5.13) MIME-Version: 1.0 Content-Type: text/plain; charset=utf-8 Content-Transfer-Encoding: quoted-printable X-Spam-Score: -2.3 (--) X-Debbugs-Envelope-To: 75810 Cc: 75810 <at> debbugs.gnu.org X-BeenThere: debbugs-submit <at> debbugs.gnu.org X-Mailman-Version: 2.1.18 Precedence: list List-Id: <debbugs-submit.debbugs.gnu.org> List-Unsubscribe: <https://debbugs.gnu.org/cgi-bin/mailman/options/debbugs-submit>, <mailto:debbugs-submit-request <at> debbugs.gnu.org?subject=unsubscribe> List-Archive: <https://debbugs.gnu.org/cgi-bin/mailman/private/debbugs-submit/> List-Post: <mailto:debbugs-submit <at> debbugs.gnu.org> List-Help: <mailto:debbugs-submit-request <at> debbugs.gnu.org?subject=help> List-Subscribe: <https://debbugs.gnu.org/cgi-bin/mailman/listinfo/debbugs-submit>, <mailto:debbugs-submit-request <at> debbugs.gnu.org?subject=subscribe> Errors-To: debbugs-submit-bounces <at> debbugs.gnu.org Sender: "Debbugs-submit" <debbugs-submit-bounces <at> debbugs.gnu.org> X-Spam-Score: -3.3 (---) Hello, Janneke Nieuwenhuizen <janneke@HIDDEN> skribis: >> There=E2=80=99s another issue: /gnu/store can no longer be remounted >> read-only (like we do on Guix System and on systemd with >> =E2=80=98gnu-store.mount=E2=80=99) because then unprivileged guix-daemon= would >> be unable to remount it read-write (or at least I couldn=E2=80=99t find >> a way to do that). Thus =E2=80=98guix-install.sh=E2=80=99 no longer ins= talls >> =E2=80=98gnu-store.mount=E2=80=99 in that case. It=E2=80=99s a bit sad = to lose that >> so if anyone can think of a way to achieve it, that=E2=80=99d be great. > > Hmm. So this is is about using guix as a package manager on foreign > systems, for now? Yes, but the goal is to eventually make it available (as an option) on Guix System. > Will there be an option for users to choose between a non-root > guix-daemon or a read-only store? I would prefer not having to choose between the two, but as I wrote, I don=E2=80=99t know how to make it work. Currently =E2=80=98makeStoreWritable=E2=80=99 does this: if (stat.f_flag & ST_RDONLY) { if (unshare(CLONE_NEWNS) =3D=3D -1) throw SysError("setting up a private mount namespace"); if (mount(0, settings.nixStore.c_str(), "none", MS_REMOUNT | MS_BIN= D, 0) =3D=3D -1) throw SysError(format("remounting %1% writable") % settings.nix= Store); } But the remount trick only works if you=E2=80=99re actually root. As non-root, what can guix-daemon do? It could (bind-)mount the underlying file system, but how to do that? (Thinking out loud.) Perhaps =E2=80=98gnu-store.mount=E2=80=99 could stash the read-write varian= t aside, say in /gnu/.rw-store, and guix-daemon would bind-mount that to /gnu/store? > I'm kind of afraid that having a writable /gnu/store, even if it's just > on foreign distributions, is going to cause a whole lot of problems/bug > reports with people changing files in the store. When I came to guix I > ran it on Debian for a couple of months and I certainly changed files in > the store, even with the read-only mount hurdle, to "get stuff to > build". Only later to realise that by doing so I was making things much > more difficult for myself. Yeah, agreed. Thanks for your feedback! Ludo=E2=80=99.
guix-patches@HIDDEN
:bug#75810
; Package guix-patches
.
Full text available.Received: (at 75810) by debbugs.gnu.org; 24 Jan 2025 19:21:15 +0000 From debbugs-submit-bounces <at> debbugs.gnu.org Fri Jan 24 14:21:15 2025 Received: from localhost ([127.0.0.1]:47089 helo=debbugs.gnu.org) by debbugs.gnu.org with esmtp (Exim 4.84_2) (envelope-from <debbugs-submit-bounces <at> debbugs.gnu.org>) id 1tbPEx-0003hd-3t for submit <at> debbugs.gnu.org; Fri, 24 Jan 2025 14:21:15 -0500 Received: from eggs.gnu.org ([2001:470:142:3::10]:34204) by debbugs.gnu.org with esmtps (TLS1.2:ECDHE_RSA_AES_256_GCM_SHA384:256) (Exim 4.84_2) (envelope-from <janneke@HIDDEN>) id 1tbPEr-0003hJ-Aq for 75810 <at> debbugs.gnu.org; Fri, 24 Jan 2025 14:21:10 -0500 Received: from fencepost.gnu.org ([2001:470:142:3::e]) by eggs.gnu.org with esmtps (TLS1.2:ECDHE_RSA_AES_256_GCM_SHA384:256) (Exim 4.90_1) (envelope-from <janneke@HIDDEN>) id 1tbPEV-0000RN-Fp; Fri, 24 Jan 2025 14:20:47 -0500 DKIM-Signature: v=1; a=rsa-sha256; q=dns/txt; c=relaxed/relaxed; d=gnu.org; s=fencepost-gnu-org; h=MIME-Version:Date:References:In-Reply-To:Subject:To: From; bh=Apq6hxtpX8+MuuC+sRbkcgdil4CvMM9W0jHH/AtkjVI=; b=OcwjYbqwT+bz/26U9cwu UI7r+kGp2wQ/1imOPVVkE/FdHYJLMepWjrDmrQvbeqd2/LTWxz/zk5VBaE/P4a2Z7DkLmQnQOBDWa +9cIaYCvSQNfHi0a8T9kd8/4hPK37InHzcKpruXW0PRr+b/w/KiExQTo9qYDULyj/3UeaXnlNdhs9 TKCJLLrQ8Qloj39ge2uhcUusigrkfk+6IjSu8thP/PKQvGidigxoihrjZv7YfCKDMyHcNE7YNxHpN +bA+SZH9u2Q9odsMFOad+dwnSZWtMK8Qkwf/xtM2cBusrPUgWyDB6j9XZUKOtjTqpC1i+cOU05TJX jfrsevEVPBuDIw==; From: Janneke Nieuwenhuizen <janneke@HIDDEN> To: Ludovic =?utf-8?Q?Court=C3=A8s?= <ludo@HIDDEN> Subject: Re: [bug#75810] [PATCH 0/6] Rootless guix-daemon In-Reply-To: <cover.1737738362.git.ludo@HIDDEN> ("Ludovic =?utf-8?Q?Court?= =?utf-8?Q?=C3=A8s=22's?= message of "Fri, 24 Jan 2025 18:23:08 +0100") Organization: AvatarAcademy.nl References: <cover.1737738362.git.ludo@HIDDEN> X-Url: http://AvatarAcademy.nl Date: Fri, 24 Jan 2025 20:20:42 +0100 Message-ID: <87ikq49fxx.fsf@HIDDEN> User-Agent: Gnus/5.13 (Gnus v5.13) MIME-Version: 1.0 Content-Type: text/plain; charset=utf-8 Content-Transfer-Encoding: quoted-printable X-Spam-Score: -2.3 (--) X-Debbugs-Envelope-To: 75810 Cc: 75810 <at> debbugs.gnu.org X-BeenThere: debbugs-submit <at> debbugs.gnu.org X-Mailman-Version: 2.1.18 Precedence: list List-Id: <debbugs-submit.debbugs.gnu.org> List-Unsubscribe: <https://debbugs.gnu.org/cgi-bin/mailman/options/debbugs-submit>, <mailto:debbugs-submit-request <at> debbugs.gnu.org?subject=unsubscribe> List-Archive: <https://debbugs.gnu.org/cgi-bin/mailman/private/debbugs-submit/> List-Post: <mailto:debbugs-submit <at> debbugs.gnu.org> List-Help: <mailto:debbugs-submit-request <at> debbugs.gnu.org?subject=help> List-Subscribe: <https://debbugs.gnu.org/cgi-bin/mailman/listinfo/debbugs-submit>, <mailto:debbugs-submit-request <at> debbugs.gnu.org?subject=subscribe> Errors-To: debbugs-submit-bounces <at> debbugs.gnu.org Sender: "Debbugs-submit" <debbugs-submit-bounces <at> debbugs.gnu.org> X-Spam-Score: -3.3 (---) Ludovic Court=C3=A8s writes: Hello! > That guix-daemon runs as root is not confidence-inspiring for many. Certainly, in fact, this and the many build users was [sadly?] the reason I didn't look further into Nix around 2010 or so... [..] > This patch changes guix-daemon so it can run as an unprivileged > user, using unprivileged user namespaces to still support isolated > builds. Yay, awesome! > There=E2=80=99s a couple of cases where root is/was still necessary: [..] > There=E2=80=99s another issue: /gnu/store can no longer be remounted > read-only (like we do on Guix System and on systemd with > =E2=80=98gnu-store.mount=E2=80=99) because then unprivileged guix-daemon = would > be unable to remount it read-write (or at least I couldn=E2=80=99t find > a way to do that). Thus =E2=80=98guix-install.sh=E2=80=99 no longer inst= alls > =E2=80=98gnu-store.mount=E2=80=99 in that case. It=E2=80=99s a bit sad t= o lose that > so if anyone can think of a way to achieve it, that=E2=80=99d be great. Hmm. So this is is about using guix as a package manager on foreign systems, for now? Will there be an option for users to choose between a non-root guix-daemon or a read-only store? I'm kind of afraid that having a writable /gnu/store, even if it's just on foreign distributions, is going to cause a whole lot of problems/bug reports with people changing files in the store. When I came to guix I ran it on Debian for a couple of months and I certainly changed files in the store, even with the read-only mount hurdle, to "get stuff to build". Only later to realise that by doing so I was making things much more difficult for myself. Hopefully I'm either misunderstanding this patch set, or else too pessimistict, and maybe other people aren't as stupid as I was when I first came to Guix? Greetings, Janneke --=20 Janneke Nieuwenhuizen <janneke@HIDDEN> | GNU LilyPond https://LilyPond.org Freelance IT https://www.JoyOfSource.com | Avatar=C2=AE https://AvatarAcade= my.com
guix-patches@HIDDEN
:bug#75810
; Package guix-patches
.
Full text available.Received: (at 75810) by debbugs.gnu.org; 24 Jan 2025 17:25:26 +0000 From debbugs-submit-bounces <at> debbugs.gnu.org Fri Jan 24 12:25:26 2025 Received: from localhost ([127.0.0.1]:46906 helo=debbugs.gnu.org) by debbugs.gnu.org with esmtp (Exim 4.84_2) (envelope-from <debbugs-submit-bounces <at> debbugs.gnu.org>) id 1tbNQs-0003UD-52 for submit <at> debbugs.gnu.org; Fri, 24 Jan 2025 12:25:26 -0500 Received: from eggs.gnu.org ([2001:470:142:3::10]:39782) by debbugs.gnu.org with esmtps (TLS1.2:ECDHE_RSA_AES_256_GCM_SHA384:256) (Exim 4.84_2) (envelope-from <ludo@HIDDEN>) id 1tbNQm-0003Qt-U1 for 75810 <at> debbugs.gnu.org; Fri, 24 Jan 2025 12:25:21 -0500 Received: from fencepost.gnu.org ([2001:470:142:3::e]) by eggs.gnu.org with esmtps (TLS1.2:ECDHE_RSA_AES_256_GCM_SHA384:256) (Exim 4.90_1) (envelope-from <ludo@HIDDEN>) id 1tbNQh-00083r-LL; Fri, 24 Jan 2025 12:25:15 -0500 DKIM-Signature: v=1; a=rsa-sha256; q=dns/txt; c=relaxed/relaxed; d=gnu.org; s=fencepost-gnu-org; h=MIME-Version:References:In-Reply-To:Date:Subject:To: From; bh=CyAW63unydjdK3bGh0fu/fzPuWtUxy3K5XUchGmxeSg=; b=KT72z/lctyH4OjwoNNdE o5/75ESzb5N8Y0bW9U+789AIm3B/KcEQtRgp4avGhwqOkstsB2pjEFbmNFEYZtLlcb3KV6UOWZ+0H iDqAmTZEPj2zYqrUHhGmYd5L3uQCe8CtBVD0js0xl+3dNuiluNcmXe6UVGCSDag9sIHGEbZsXZWSe EPm9dlasF+3h8xAf23rAmlQiFqyFVG//XTcRPEL2WzeJy8rxapf/9V8/iYVsZ3a9TJEmE5dHEtFkk Ty19FaunyVISMYeWGOBJZ6pDfom1DX5WOVIIyB/klw30bxZSliHi6+wBmPF8+TyH3kIhwO1abLXG1 a8MOeentOPwwmg==; From: =?UTF-8?q?Ludovic=20Court=C3=A8s?= <ludo@HIDDEN> To: 75810 <at> debbugs.gnu.org Subject: [PATCH 6/6] guix-install.sh: Support the unprivileged daemon where possible. Date: Fri, 24 Jan 2025 18:24:56 +0100 Message-ID: <2c04ad0cb868e4f41047f971c05915c5419729bd.1737738362.git.ludo@HIDDEN> X-Mailer: git-send-email 2.47.1 In-Reply-To: <cover.1737738362.git.ludo@HIDDEN> References: <cover.1737738362.git.ludo@HIDDEN> MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit X-Spam-Score: -2.3 (--) X-Debbugs-Envelope-To: 75810 Cc: =?UTF-8?q?Ludovic=20Court=C3=A8s?= <ludo@HIDDEN> X-BeenThere: debbugs-submit <at> debbugs.gnu.org X-Mailman-Version: 2.1.18 Precedence: list List-Id: <debbugs-submit.debbugs.gnu.org> List-Unsubscribe: <https://debbugs.gnu.org/cgi-bin/mailman/options/debbugs-submit>, <mailto:debbugs-submit-request <at> debbugs.gnu.org?subject=unsubscribe> List-Archive: <https://debbugs.gnu.org/cgi-bin/mailman/private/debbugs-submit/> List-Post: <mailto:debbugs-submit <at> debbugs.gnu.org> List-Help: <mailto:debbugs-submit-request <at> debbugs.gnu.org?subject=help> List-Subscribe: <https://debbugs.gnu.org/cgi-bin/mailman/listinfo/debbugs-submit>, <mailto:debbugs-submit-request <at> debbugs.gnu.org?subject=subscribe> Errors-To: debbugs-submit-bounces <at> debbugs.gnu.org Sender: "Debbugs-submit" <debbugs-submit-bounces <at> debbugs.gnu.org> X-Spam-Score: -3.3 (---) * etc/guix-install.sh (create_account): New function. (sys_create_build_user): Use it. When ‘guix-daemon.service’ contains “User=guix-daemon” only create the ‘guix-daemon’ user and group. (sys_delete_build_user): Delete the ‘guix-daemon’ user and group. (can_install_unprivileged_daemon): New function. (sys_create_store): When installing the unprivileged daemon, change ownership of /gnu and /var/guix, and create /var/log/guix. (sys_authorize_build_farms): When the ‘guix-daemon’ account exists, change ownership of /etc/guix. (sys_enable_guix_daemon): Do not install ‘gnu-store.mount’ when running an unprivileged daemon. Change-Id: I73e573f1cc5c0cb3794aaaa6b576616b66e0c5e9 --- etc/guix-install.sh | 114 +++++++++++++++++++++++++++++++++++--------- 1 file changed, 91 insertions(+), 23 deletions(-) diff --git a/etc/guix-install.sh b/etc/guix-install.sh index f07b2741bb..4f08eff847 100755 --- a/etc/guix-install.sh +++ b/etc/guix-install.sh @@ -389,6 +389,11 @@ sys_create_store() cd "$tmp_path" _msg "${INF}Installing /var/guix and /gnu..." # Strip (skip) the leading ‘.’ component, which fails on read-only ‘/’. + # + # TODO: Eventually extract with ‘--owner=guix-daemon’ when installing + # and unprivileged guix-daemon service; for now, this script may install + # from both an old release that does not support unprivileged guix-daemon + # and a new release that does, so ‘chown -R’ later if needed. tar --extract --strip-components=1 --file "$pkg" -C / _msg "${INF}Linking the root user's profile" @@ -414,38 +419,82 @@ sys_delete_store() rm -rf ~root/.config/guix } +create_account() +{ + local user="$1" + local group="$2" + local supplementary_groups="$3" + local comment="$4" + + if id "$user" &>/dev/null; then + _msg "${INF}user '$user' is already in the system, reset" + usermod -g "$group" -G "$supplementary_groups" \ + -d /var/empty -s "$(which nologin)" \ + -c "$comment" "$user" + else + useradd -g "$group" -G "$supplementary_groups" \ + -d /var/empty -s "$(which nologin)" \ + -c "$comment" --system "$user" + _msg "${PAS}user added <$user>" + fi +} + +can_install_unprivileged_daemon() +{ # Return true if we can install guix-daemon running without privileges. + [ "$INIT_SYS" = systemd ] && \ + grep -q "User=guix-daemon" \ + ~root/.config/guix/current/lib/systemd/system/guix-daemon.service \ + && ([ ! -f /proc/sys/kernel/unprivileged_userns_clone ] \ + || [ "$(cat /proc/sys/kernel/unprivileged_userns_clone)" -eq 1 ]) +} + sys_create_build_user() { # Create the group and user accounts for build users. _debug "--- [ ${FUNCNAME[0]} ] ---" - if getent group guixbuild > /dev/null; then - _msg "${INF}group guixbuild exists" - else - groupadd --system guixbuild - _msg "${PAS}group <guixbuild> created" - fi - if getent group kvm > /dev/null; then _msg "${INF}group kvm exists and build users will be added to it" local KVMGROUP=,kvm fi - for i in $(seq -w 1 10); do - if id "guixbuilder${i}" &>/dev/null; then - _msg "${INF}user is already in the system, reset" - usermod -g guixbuild -G guixbuild${KVMGROUP} \ - -d /var/empty -s "$(which nologin)" \ - -c "Guix build user $i" \ - "guixbuilder${i}"; - else - useradd -g guixbuild -G guixbuild${KVMGROUP} \ - -d /var/empty -s "$(which nologin)" \ - -c "Guix build user $i" --system \ - "guixbuilder${i}"; - _msg "${PAS}user added <guixbuilder${i}>" - fi - done + if [ "$INIT_SYS" = systemd ] && \ + grep -q "User=guix-daemon" \ + ~root/.config/guix/current/lib/systemd/system/guix-daemon.service + then + if getent group guix-daemon > /dev/null; then + _msg "${INF}group guix-daemon exists" + else + groupadd --system guix-daemon + _msg "${PAS}group guix-daemon created" + fi + + create_account guix-daemon guix-daemon \ + guix-daemon$KVMGROUP \ + "Unprivileged Guix Daemon User" + + # ‘tar xf’ creates root:root files. Change that. + chown -R guix-daemon:guix-daemon \ + /gnu /var/guix + + # The unprivileged cannot create the log directory by itself. + mkdir /var/log/guix + chown guix-daemon:guix-daemon /var/log/guix + chmod 755 /var/log/guix + else + if getent group guixbuild > /dev/null; then + _msg "${INF}group guixbuild exists" + else + groupadd --system guixbuild + _msg "${PAS}group <guixbuild> created" + fi + + for i in $(seq -w 1 10); do + create_account "guixbuilder${i}" "guixbuild" \ + "guixbuild${KVMGROUP}" \ + "Guix build user $i" + done + fi } sys_delete_build_user() @@ -460,6 +509,14 @@ sys_delete_build_user() if getent group guixbuild &>/dev/null; then groupdel -f guixbuild fi + + _msg "${INF}remove guix-daemon user" + if id guix-daemon &>/dev/null; then + userdel -f guix-daemon + fi + if getent group guix-daemon &>/dev/null; then + groupdel -f guix-daemon + fi } sys_enable_guix_daemon() @@ -503,7 +560,14 @@ sys_enable_guix_daemon() # Install after guix-daemon.service to avoid a harmless warning. # systemd .mount units must be named after the target directory. # Here we assume a hard-coded name of /gnu/store. - install_unit gnu-store.mount + # + # FIXME: This feature is unavailable when running an + # unprivileged daemon. + if ! grep -q "User=guix-daemon" \ + /etc/systemd/system/guix-daemon.service + then + install_unit gnu-store.mount + fi systemctl daemon-reload && systemctl start guix-daemon; } && @@ -627,6 +691,10 @@ project's build farms?"; then && guix archive --authorize < "$key" \ && _msg "${PAS}Authorized public key for $host" done + if id guix-daemon &>/dev/null; then + # /etc/guix/acl must be readable by the unprivileged guix-daemon. + chown -R guix-daemon:guix-daemon /etc/guix + fi else _msg "${INF}Skipped authorizing build farm public keys" fi -- 2.47.1
guix-patches@HIDDEN
:bug#75810
; Package guix-patches
.
Full text available.Received: (at 75810) by debbugs.gnu.org; 24 Jan 2025 17:25:26 +0000 From debbugs-submit-bounces <at> debbugs.gnu.org Fri Jan 24 12:25:26 2025 Received: from localhost ([127.0.0.1]:46904 helo=debbugs.gnu.org) by debbugs.gnu.org with esmtp (Exim 4.84_2) (envelope-from <debbugs-submit-bounces <at> debbugs.gnu.org>) id 1tbNQr-0003U6-N7 for submit <at> debbugs.gnu.org; Fri, 24 Jan 2025 12:25:26 -0500 Received: from eggs.gnu.org ([2001:470:142:3::10]:39776) by debbugs.gnu.org with esmtps (TLS1.2:ECDHE_RSA_AES_256_GCM_SHA384:256) (Exim 4.84_2) (envelope-from <ludo@HIDDEN>) id 1tbNQm-0003Pe-0g for 75810 <at> debbugs.gnu.org; Fri, 24 Jan 2025 12:25:20 -0500 Received: from fencepost.gnu.org ([2001:470:142:3::e]) by eggs.gnu.org with esmtps (TLS1.2:ECDHE_RSA_AES_256_GCM_SHA384:256) (Exim 4.90_1) (envelope-from <ludo@HIDDEN>) id 1tbNQg-00083e-Lr; Fri, 24 Jan 2025 12:25:14 -0500 DKIM-Signature: v=1; a=rsa-sha256; q=dns/txt; c=relaxed/relaxed; d=gnu.org; s=fencepost-gnu-org; h=MIME-Version:References:In-Reply-To:Date:Subject:To: From; bh=fSDfv9Lxo7q8Hsp8XW9PKQoYdqQwT7VmmKky0xhAbcI=; b=W6eLg23Pxz1Cteorp7el 9OMHLil4xhz9F2DC3McI82HhKJIjEMuj7TuZIq9QiVKr0JSxYTwlTDyviiE+fbf2puVxawKUvFJKB WQzzYNPm/82UHzOV/6x97Uy+K87Gcadis+eiJjbUI8QtLfW7m5FLBRT+hcaavBH+x3+AEFHNABr0J cSYxEbX80yG/ThhrJQo+gXCLKrllHtNof/wZYBAXfMkOK6gpB9R/xcGogDITvk0MsWSfnER/50Gbf K8S6jqEatajb4sMX2J2C2ZKXwHQ/e0kzkHxUFqQnnKq/61lX2uTh2BXsWyTpUtEnAdZpKUf4Z0xpf IkcW8dccFhci4w==; From: =?UTF-8?q?Ludovic=20Court=C3=A8s?= <ludo@HIDDEN> To: 75810 <at> debbugs.gnu.org Subject: [PATCH 5/6] =?UTF-8?q?etc:=20systemd=20services:=20Run=20?= =?UTF-8?q?=E2=80=98guix-daemon=E2=80=99=20as=20an=20unprivileged=20user.?= Date: Fri, 24 Jan 2025 18:24:55 +0100 Message-ID: <713be4d9b744226c4922f3eec66adfb3547c95bc.1737738362.git.ludo@HIDDEN> X-Mailer: git-send-email 2.47.1 In-Reply-To: <cover.1737738362.git.ludo@HIDDEN> References: <cover.1737738362.git.ludo@HIDDEN> MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit X-Spam-Score: -2.3 (--) X-Debbugs-Envelope-To: 75810 Cc: =?UTF-8?q?Ludovic=20Court=C3=A8s?= <ludo@HIDDEN> X-BeenThere: debbugs-submit <at> debbugs.gnu.org X-Mailman-Version: 2.1.18 Precedence: list List-Id: <debbugs-submit.debbugs.gnu.org> List-Unsubscribe: <https://debbugs.gnu.org/cgi-bin/mailman/options/debbugs-submit>, <mailto:debbugs-submit-request <at> debbugs.gnu.org?subject=unsubscribe> List-Archive: <https://debbugs.gnu.org/cgi-bin/mailman/private/debbugs-submit/> List-Post: <mailto:debbugs-submit <at> debbugs.gnu.org> List-Help: <mailto:debbugs-submit-request <at> debbugs.gnu.org?subject=help> List-Subscribe: <https://debbugs.gnu.org/cgi-bin/mailman/listinfo/debbugs-submit>, <mailto:debbugs-submit-request <at> debbugs.gnu.org?subject=subscribe> Errors-To: debbugs-submit-bounces <at> debbugs.gnu.org Sender: "Debbugs-submit" <debbugs-submit-bounces <at> debbugs.gnu.org> X-Spam-Score: -3.3 (---) * etc/guix-daemon.service.in (ExecStart): Remove ‘--build-users-group’. (User, AmbientCapabilities): New fields. Change-Id: Id826b8ab535844b6024d777f6bd15fd49db6d65e --- etc/guix-daemon.service.in | 12 +++++++++++- 1 file changed, 11 insertions(+), 1 deletion(-) diff --git a/etc/guix-daemon.service.in b/etc/guix-daemon.service.in index 5c43d9b7f1..f9f0b28b35 100644 --- a/etc/guix-daemon.service.in +++ b/etc/guix-daemon.service.in @@ -7,9 +7,19 @@ Description=Build daemon for GNU Guix [Service] ExecStart=@localstatedir@/guix/profiles/per-user/root/current-guix/bin/guix-daemon \ - --build-users-group=guixbuild --discover=no \ + --discover=no \ --substitute-urls='@GUIX_SUBSTITUTE_URLS@' Environment='GUIX_LOCPATH=@localstatedir@/guix/profiles/per-user/root/guix-profile/lib/locale' LC_ALL=en_US.utf8 + +# Run under a dedicated unprivileged user account. +User=guix-daemon + +# Provide the CAP_CHOWN capability so that guix-daemon cran create and chown +# /var/guix/profiles/per-user/$USER and also chown failed build directories +# when using '--keep-failed'. Note that guix-daemon explicitly drops ambient +# capabilities before executing build processes so they don't inherit them. +AmbientCapabilities=CAP_CHOWN + StandardOutput=journal StandardError=journal -- 2.47.1
guix-patches@HIDDEN
:bug#75810
; Package guix-patches
.
Full text available.Received: (at 75810) by debbugs.gnu.org; 24 Jan 2025 17:25:25 +0000 From debbugs-submit-bounces <at> debbugs.gnu.org Fri Jan 24 12:25:25 2025 Received: from localhost ([127.0.0.1]:46902 helo=debbugs.gnu.org) by debbugs.gnu.org with esmtp (Exim 4.84_2) (envelope-from <debbugs-submit-bounces <at> debbugs.gnu.org>) id 1tbNQr-0003Ty-8R for submit <at> debbugs.gnu.org; Fri, 24 Jan 2025 12:25:25 -0500 Received: from eggs.gnu.org ([2001:470:142:3::10]:39768) by debbugs.gnu.org with esmtps (TLS1.2:ECDHE_RSA_AES_256_GCM_SHA384:256) (Exim 4.84_2) (envelope-from <ludo@HIDDEN>) id 1tbNQk-0003Oo-Ky for 75810 <at> debbugs.gnu.org; Fri, 24 Jan 2025 12:25:19 -0500 Received: from fencepost.gnu.org ([2001:470:142:3::e]) by eggs.gnu.org with esmtps (TLS1.2:ECDHE_RSA_AES_256_GCM_SHA384:256) (Exim 4.90_1) (envelope-from <ludo@HIDDEN>) id 1tbNQf-00083D-9K; Fri, 24 Jan 2025 12:25:13 -0500 DKIM-Signature: v=1; a=rsa-sha256; q=dns/txt; c=relaxed/relaxed; d=gnu.org; s=fencepost-gnu-org; h=MIME-Version:References:In-Reply-To:Date:Subject:To: From; bh=EJBKOU++7w/goxoEBuHLi3cBsE8e18X1/aR/9Jrf8LE=; b=fB+G4mN2dIcVTtbIfWdw MgcupQqBw2810LhWVSmlEWRVsjDJKjpS8Vtm/MZcnSIsV0naVdz+oEePbqjPrqKWhHrygl0HBP0E8 WRH5WFPvzxEzoXoq/eXYxloUG31MGrzu1nVjbnhRalfOhIyqwhqYuD+yGfd2QQqNQOEhaF7Hn6Mz8 TveWbZ4iO2wnzMxmO67lJZShHgwTQVY5sgSof18plO49997H+u+c3E0bMX21RNZuao1TSQ2KeXqnU 7xeQbH1hpueJKB/xYjcXskeNcywddrfXJrpymARsRQdSlKjsE663erac8q8lnr0Wju1icfctI8scT XnLfPgve3bG0yQ==; From: =?UTF-8?q?Ludovic=20Court=C3=A8s?= <ludo@HIDDEN> To: 75810 <at> debbugs.gnu.org Subject: [PATCH 4/6] daemon: Drop Linux ambient capabilities before executing builder. Date: Fri, 24 Jan 2025 18:24:54 +0100 Message-ID: <d0fe57ac1b0f14d2fcfb01b9c9de80905cee73e1.1737738362.git.ludo@HIDDEN> X-Mailer: git-send-email 2.47.1 In-Reply-To: <cover.1737738362.git.ludo@HIDDEN> References: <cover.1737738362.git.ludo@HIDDEN> MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit X-Spam-Score: -2.3 (--) X-Debbugs-Envelope-To: 75810 Cc: =?UTF-8?q?Ludovic=20Court=C3=A8s?= <ludo@HIDDEN> X-BeenThere: debbugs-submit <at> debbugs.gnu.org X-Mailman-Version: 2.1.18 Precedence: list List-Id: <debbugs-submit.debbugs.gnu.org> List-Unsubscribe: <https://debbugs.gnu.org/cgi-bin/mailman/options/debbugs-submit>, <mailto:debbugs-submit-request <at> debbugs.gnu.org?subject=unsubscribe> List-Archive: <https://debbugs.gnu.org/cgi-bin/mailman/private/debbugs-submit/> List-Post: <mailto:debbugs-submit <at> debbugs.gnu.org> List-Help: <mailto:debbugs-submit-request <at> debbugs.gnu.org?subject=help> List-Subscribe: <https://debbugs.gnu.org/cgi-bin/mailman/listinfo/debbugs-submit>, <mailto:debbugs-submit-request <at> debbugs.gnu.org?subject=subscribe> Errors-To: debbugs-submit-bounces <at> debbugs.gnu.org Sender: "Debbugs-submit" <debbugs-submit-bounces <at> debbugs.gnu.org> X-Spam-Score: -3.3 (---) * config-daemon.ac: Check for <sys/prctl.h>. * nix/libstore/build.cc (DerivationGoal::runChild): When ‘useChroot’ is true, call ‘prctl’ to drop all ambient capabilities. Change-Id: If34637fc508e5fb6d278167f5df7802fc595284f --- config-daemon.ac | 2 +- nix/libstore/build.cc | 9 +++++++++ 2 files changed, 10 insertions(+), 1 deletion(-) diff --git a/config-daemon.ac b/config-daemon.ac index 6731c68bc3..aeec5f3239 100644 --- a/config-daemon.ac +++ b/config-daemon.ac @@ -78,7 +78,7 @@ if test "x$guix_build_daemon" = "xyes"; then dnl Chroot support. AC_CHECK_FUNCS([chroot unshare]) - AC_CHECK_HEADERS([sched.h sys/param.h sys/mount.h sys/syscall.h]) + AC_CHECK_HEADERS([sched.h sys/param.h sys/mount.h sys/syscall.h sys/prctl.h]) if test "x$ac_cv_func_chroot" != "xyes"; then AC_MSG_ERROR(['chroot' function missing, bailing out]) diff --git a/nix/libstore/build.cc b/nix/libstore/build.cc index 727472c77f..c95bd2821f 100644 --- a/nix/libstore/build.cc +++ b/nix/libstore/build.cc @@ -50,6 +50,9 @@ #if HAVE_SCHED_H #include <sched.h> #endif +#if HAVE_SYS_PRCTL_H +#include <sys/prctl.h> +#endif #define CHROOT_ENABLED HAVE_CHROOT && HAVE_SYS_MOUNT_H && defined(MS_BIND) && defined(MS_PRIVATE) @@ -2077,6 +2080,12 @@ void DerivationGoal::runChild() #if CHROOT_ENABLED if (useChroot) { +# if HAVE_SYS_PRCTL_H + /* Drop ambient capabilities such as CAP_CHOWN that might have + been granted when starting guix-daemon. */ + prctl(PR_CAP_AMBIENT, PR_CAP_AMBIENT_CLEAR_ALL, 0, 0, 0); +# endif + if (!fixedOutput) { /* Initialise the loopback interface. */ AutoCloseFD fd(socket(PF_INET, SOCK_DGRAM, IPPROTO_IP)); -- 2.47.1
guix-patches@HIDDEN
:bug#75810
; Package guix-patches
.
Full text available.Received: (at 75810) by debbugs.gnu.org; 24 Jan 2025 17:25:25 +0000 From debbugs-submit-bounces <at> debbugs.gnu.org Fri Jan 24 12:25:25 2025 Received: from localhost ([127.0.0.1]:46900 helo=debbugs.gnu.org) by debbugs.gnu.org with esmtp (Exim 4.84_2) (envelope-from <debbugs-submit-bounces <at> debbugs.gnu.org>) id 1tbNQq-0003Tt-T4 for submit <at> debbugs.gnu.org; Fri, 24 Jan 2025 12:25:25 -0500 Received: from eggs.gnu.org ([2001:470:142:3::10]:39752) by debbugs.gnu.org with esmtps (TLS1.2:ECDHE_RSA_AES_256_GCM_SHA384:256) (Exim 4.84_2) (envelope-from <ludo@HIDDEN>) id 1tbNQj-0003Nd-Jy for 75810 <at> debbugs.gnu.org; Fri, 24 Jan 2025 12:25:17 -0500 Received: from fencepost.gnu.org ([2001:470:142:3::e]) by eggs.gnu.org with esmtps (TLS1.2:ECDHE_RSA_AES_256_GCM_SHA384:256) (Exim 4.90_1) (envelope-from <ludo@HIDDEN>) id 1tbNQe-000830-9V; Fri, 24 Jan 2025 12:25:12 -0500 DKIM-Signature: v=1; a=rsa-sha256; q=dns/txt; c=relaxed/relaxed; d=gnu.org; s=fencepost-gnu-org; h=MIME-Version:References:In-Reply-To:Date:Subject:To: From; bh=+scMzR3E2mTiYzHwZP6c6yC+K2EC253ixfUcI5GQnC0=; b=lHG2Nur75MT5dtAMk4hL 02G6w8l7tkVittNIFRzYryUXLQIdCZEKJKuqwkj+emUQPr9xB/1M5ZEqf5znvBFmiqYf03GgHVw7a jBGez9Ic4jlpwoOt6sVrvdOWv57oSQ7Sv3XkBb6pYqNL5z3O7efKYU6zFDIRUUP90g+t4bnwhEe2v TJCi1r3jDrbVbC/54JyrauF2BYj8bvQU0DPnHybBUyUfKbfQOj09Ne7NquZRfLRQ4rRxsST7bpi06 P7Pi2WDlp6RNQUZ77+zYFllKCLfMBDLZOcZr2rTJ9LxhifcSVJJ7NSVKvOOeCINLUn7ykwUl3ReXp XT83szKuVx62eA==; From: =?UTF-8?q?Ludovic=20Court=C3=A8s?= <ludo@HIDDEN> To: 75810 <at> debbugs.gnu.org Subject: [PATCH 3/6] daemon: Create /var/guix/profiles/per-user unconditionally. Date: Fri, 24 Jan 2025 18:24:53 +0100 Message-ID: <d68dadd3e97944bc3339402d3be9fe8899b8c1dc.1737738362.git.ludo@HIDDEN> X-Mailer: git-send-email 2.47.1 In-Reply-To: <cover.1737738362.git.ludo@HIDDEN> References: <cover.1737738362.git.ludo@HIDDEN> MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit X-Spam-Score: -2.3 (--) X-Debbugs-Envelope-To: 75810 Cc: =?UTF-8?q?Ludovic=20Court=C3=A8s?= <ludo@HIDDEN> X-BeenThere: debbugs-submit <at> debbugs.gnu.org X-Mailman-Version: 2.1.18 Precedence: list List-Id: <debbugs-submit.debbugs.gnu.org> List-Unsubscribe: <https://debbugs.gnu.org/cgi-bin/mailman/options/debbugs-submit>, <mailto:debbugs-submit-request <at> debbugs.gnu.org?subject=unsubscribe> List-Archive: <https://debbugs.gnu.org/cgi-bin/mailman/private/debbugs-submit/> List-Post: <mailto:debbugs-submit <at> debbugs.gnu.org> List-Help: <mailto:debbugs-submit-request <at> debbugs.gnu.org?subject=help> List-Subscribe: <https://debbugs.gnu.org/cgi-bin/mailman/listinfo/debbugs-submit>, <mailto:debbugs-submit-request <at> debbugs.gnu.org?subject=subscribe> Errors-To: debbugs-submit-bounces <at> debbugs.gnu.org Sender: "Debbugs-submit" <debbugs-submit-bounces <at> debbugs.gnu.org> X-Spam-Score: -3.3 (---) * nix/libstore/local-store.cc (LocalStore::LocalStore): Create ‘perUserDir’ unconditionally. Change-Id: I5188320f9630a81d16f79212d0fffabd55d94abe --- nix/libstore/local-store.cc | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/nix/libstore/local-store.cc b/nix/libstore/local-store.cc index 4308264a4f..6384669519 100644 --- a/nix/libstore/local-store.cc +++ b/nix/libstore/local-store.cc @@ -79,12 +79,12 @@ LocalStore::LocalStore(bool reserveSpace) createSymlink(profilesDir, gcRootsDir + "/profiles"); } - /* Optionally, create directories and set permissions for a - multi-user install. */ + Path perUserDir = profilesDir + "/per-user"; + createDirs(perUserDir); + + /* Optionally, set permissions for a multi-user install. */ if (getuid() == 0 && settings.buildUsersGroup != "") { - Path perUserDir = profilesDir + "/per-user"; - createDirs(perUserDir); if (chmod(perUserDir.c_str(), 0755) == -1) throw SysError(format("could not set permissions on '%1%' to 755") % perUserDir); -- 2.47.1
guix-patches@HIDDEN
:bug#75810
; Package guix-patches
.
Full text available.Received: (at 75810) by debbugs.gnu.org; 24 Jan 2025 17:25:24 +0000 From debbugs-submit-bounces <at> debbugs.gnu.org Fri Jan 24 12:25:24 2025 Received: from localhost ([127.0.0.1]:46898 helo=debbugs.gnu.org) by debbugs.gnu.org with esmtp (Exim 4.84_2) (envelope-from <debbugs-submit-bounces <at> debbugs.gnu.org>) id 1tbNQq-0003To-5Q for submit <at> debbugs.gnu.org; Fri, 24 Jan 2025 12:25:24 -0500 Received: from eggs.gnu.org ([2001:470:142:3::10]:39746) by debbugs.gnu.org with esmtps (TLS1.2:ECDHE_RSA_AES_256_GCM_SHA384:256) (Exim 4.84_2) (envelope-from <ludo@HIDDEN>) id 1tbNQi-0003NN-Tg for 75810 <at> debbugs.gnu.org; Fri, 24 Jan 2025 12:25:17 -0500 Received: from fencepost.gnu.org ([2001:470:142:3::e]) by eggs.gnu.org with esmtps (TLS1.2:ECDHE_RSA_AES_256_GCM_SHA384:256) (Exim 4.90_1) (envelope-from <ludo@HIDDEN>) id 1tbNQd-00082m-D2; Fri, 24 Jan 2025 12:25:11 -0500 DKIM-Signature: v=1; a=rsa-sha256; q=dns/txt; c=relaxed/relaxed; d=gnu.org; s=fencepost-gnu-org; h=MIME-Version:References:In-Reply-To:Date:Subject:To: From; bh=bRN6Nu59+C3SYAE0PEM9bbTrcQYq/PayE8qd5RFzwjI=; b=M9DURPznSXpt/+0Faw8C EdqRR1TvbFB7f6yj81bRRhFhl1Vc1JeO65oV8gml+XdJTxFRZ5ijqmD853y1AoMF0nbhaeLxgdq4f q7hmO+LYKdWkIvi4uEzUVVCHdHl0CNtMVbIt4YWgZ1b6bAedkxM8DtSVBeI/dDCMoJ6XplYoNIvXB WKD3IamMG5IxYZlDg7gBjEoEK45fms4irhWHmes9jcc++Riww16spzf0+6NLr4ZJG0M2ElvMexhAv F5ngTtp3LOzbY5eid1vrzM9akT4G6GAGL1oNUaJDm8r9ntfwuM4r4FzjoR/p1YOrKA2FJgu7l1bJP vBZ7RxfdQgwm4w==; From: =?UTF-8?q?Ludovic=20Court=C3=A8s?= <ludo@HIDDEN> To: 75810 <at> debbugs.gnu.org Subject: [PATCH 2/6] DRAFT tests: Run in a chroot and unprivileged user namespaces. Date: Fri, 24 Jan 2025 18:24:52 +0100 Message-ID: <6fb69ee481d628317ed09c6e762f38489bab0ea7.1737738362.git.ludo@HIDDEN> X-Mailer: git-send-email 2.47.1 In-Reply-To: <cover.1737738362.git.ludo@HIDDEN> References: <cover.1737738362.git.ludo@HIDDEN> MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit X-Spam-Score: -2.3 (--) X-Debbugs-Envelope-To: 75810 Cc: =?UTF-8?q?Ludovic=20Court=C3=A8s?= <ludo@HIDDEN> X-BeenThere: debbugs-submit <at> debbugs.gnu.org X-Mailman-Version: 2.1.18 Precedence: list List-Id: <debbugs-submit.debbugs.gnu.org> List-Unsubscribe: <https://debbugs.gnu.org/cgi-bin/mailman/options/debbugs-submit>, <mailto:debbugs-submit-request <at> debbugs.gnu.org?subject=unsubscribe> List-Archive: <https://debbugs.gnu.org/cgi-bin/mailman/private/debbugs-submit/> List-Post: <mailto:debbugs-submit <at> debbugs.gnu.org> List-Help: <mailto:debbugs-submit-request <at> debbugs.gnu.org?subject=help> List-Subscribe: <https://debbugs.gnu.org/cgi-bin/mailman/listinfo/debbugs-submit>, <mailto:debbugs-submit-request <at> debbugs.gnu.org?subject=subscribe> Errors-To: debbugs-submit-bounces <at> debbugs.gnu.org Sender: "Debbugs-submit" <debbugs-submit-bounces <at> debbugs.gnu.org> X-Spam-Score: -3.3 (---) DRAFT: - Double-check the test suite. * build-aux/test-env.in: Pass ‘--disable-chroot’ only when unprivileged user namespace support is lacking. * tests/store.scm ("build-things, check mode"): Use ‘gettimeofday’ rather than a shared file as a source of entropy. ("isolated environment"): New test. Change-Id: Iedb816ef548c77799e5b2f9b6a3b7510ad19ec2a --- build-aux/test-env.in | 14 ++++++- tests/store.scm | 89 ++++++++++++++++++++++++++----------------- 2 files changed, 66 insertions(+), 37 deletions(-) diff --git a/build-aux/test-env.in b/build-aux/test-env.in index 9caa29da58..5626152b34 100644 --- a/build-aux/test-env.in +++ b/build-aux/test-env.in @@ -1,7 +1,7 @@ #!/bin/sh # GNU Guix --- Functional package management for GNU -# Copyright © 2012, 2013, 2014, 2015, 2016, 2017, 2018, 2019, 2021 Ludovic Courtès <ludo@HIDDEN> +# Copyright © 2012-2019, 2021, 2025 Ludovic Courtès <ludo@HIDDEN> # # This file is part of GNU Guix. # @@ -102,10 +102,20 @@ then rm -rf "$GUIX_STATE_DIRECTORY/daemon-socket" mkdir -m 0700 "$GUIX_STATE_DIRECTORY/daemon-socket" + # If unprivileged user namespaces are not supported, pass + # '--disable-chroot'. + if [ ! -f /proc/sys/kernel/unprivileged_userns_clone ] \ + || [ "$(cat /proc/sys/kernel/unprivileged_userns_clone)" -eq 1 ]; then + extra_options="" + else + extra_options="--disable-chroot" + fi + # Launch the daemon without chroot support because is may be # unavailable, for instance if we're not running as root. "@abs_top_builddir@/pre-inst-env" \ - "@abs_top_builddir@/guix-daemon" --disable-chroot \ + "@abs_top_builddir@/guix-daemon" \ + $extra_options \ --substitute-urls="$GUIX_BINARY_SUBSTITUTE_URL" & daemon_pid=$! diff --git a/tests/store.scm b/tests/store.scm index 45948f4f43..bdbb026dd9 100644 --- a/tests/store.scm +++ b/tests/store.scm @@ -1,5 +1,5 @@ ;;; GNU Guix --- Functional package management for GNU -;;; Copyright © 2012-2021, 2023 Ludovic Courtès <ludo@HIDDEN> +;;; Copyright © 2012-2021, 2023, 2025 Ludovic Courtès <ludo@HIDDEN> ;;; ;;; This file is part of GNU Guix. ;;; @@ -30,6 +30,8 @@ (define-module (test-store) #:use-module (guix derivations) #:use-module (guix serialization) #:use-module (guix build utils) + #:use-module ((gnu build linux-container) + #:select (unprivileged-user-namespace-supported?)) #:use-module (guix gexp) #:use-module (gnu packages) #:use-module (gnu packages bootstrap) @@ -391,6 +393,32 @@ (define %shell (equal? (valid-derivers %store o) (list (derivation-file-name d)))))) +(unless (unprivileged-user-namespace-supported?) + (test-skip 1)) +(test-equal "isolated environment" + (string-join (append + '("PID: 1" "UID: 30001") + (delete-duplicates + (sort (list "/dev" "/tmp" "/proc" "/etc" + (match (string-tokenize (%store-prefix) + (char-set-complement + (char-set #\/))) + ((top _ ...) (string-append "/" top)))) + string<?)) + '("/etc/group" "/etc/hosts" "/etc/passwd"))) + (let* ((b (add-text-to-store %store "build.sh" + "echo -n PID: $$ UID: $UID /* /etc/* > $out")) + (s (add-to-store %store "bash" #t "sha256" + (search-bootstrap-binary "bash" + (%current-system)))) + (d (derivation %store "the-thing" + s `("-e" ,b) + #:env-vars `(("foo" . ,(random-text))) + #:inputs `((,b) (,s)))) + (o (derivation->output-path d))) + (and (build-derivations %store (list d)) + (call-with-input-file o get-string-all)))) + (test-equal "with-build-handler" 'success (let* ((b (add-text-to-store %store "build" "echo $foo > $out" '())) @@ -1333,40 +1361,31 @@ (define %shell (test-assert "build-things, check mode" (with-store store - (call-with-temporary-output-file - (lambda (entropy entropy-port) - (write (random-text) entropy-port) - (force-output entropy-port) - (let* ((drv (build-expression->derivation - store "non-deterministic" - `(begin - (use-modules (rnrs io ports)) - (let ((out (assoc-ref %outputs "out"))) - (call-with-output-file out - (lambda (port) - ;; Rely on the fact that tests do not use the - ;; chroot, and thus ENTROPY is readable. - (display (call-with-input-file ,entropy - get-string-all) - port))) - #t)) - #:guile-for-build - (package-derivation store %bootstrap-guile (%current-system)))) - (file (derivation->output-path drv))) - (and (build-things store (list (derivation-file-name drv))) - (begin - (write (random-text) entropy-port) - (force-output entropy-port) - (guard (c ((store-protocol-error? c) - (pk 'determinism-exception c) - (and (not (zero? (store-protocol-error-status c))) - (string-contains (store-protocol-error-message c) - "deterministic")))) - ;; This one will produce a different result. Since we're in - ;; 'check' mode, this must fail. - (build-things store (list (derivation-file-name drv)) - (build-mode check)) - #f)))))))) + (let* ((drv (build-expression->derivation + store "non-deterministic" + `(begin + (use-modules (rnrs io ports)) + (let ((out (assoc-ref %outputs "out"))) + (call-with-output-file out + (lambda (port) + (let ((now (gettimeofday))) + (display (+ (car now) (cdr now)) port)))) + #t)) + #:guile-for-build + (package-derivation store %bootstrap-guile (%current-system)))) + (file (derivation->output-path drv))) + (and (build-things store (list (derivation-file-name drv))) + (begin + (guard (c ((store-protocol-error? c) + (pk 'determinism-exception c) + (and (not (zero? (store-protocol-error-status c))) + (string-contains (store-protocol-error-message c) + "deterministic")))) + ;; This one will produce a different result. Since we're in + ;; 'check' mode, this must fail. + (build-things store (list (derivation-file-name drv)) + (build-mode check)) + #f)))))) (test-assert "build-succeeded trace in check mode" (string-contains -- 2.47.1
guix-patches@HIDDEN
:bug#75810
; Package guix-patches
.
Full text available.Received: (at 75810) by debbugs.gnu.org; 24 Jan 2025 17:25:20 +0000 From debbugs-submit-bounces <at> debbugs.gnu.org Fri Jan 24 12:25:20 2025 Received: from localhost ([127.0.0.1]:46890 helo=debbugs.gnu.org) by debbugs.gnu.org with esmtp (Exim 4.84_2) (envelope-from <debbugs-submit-bounces <at> debbugs.gnu.org>) id 1tbNQk-0003Sl-7c for submit <at> debbugs.gnu.org; Fri, 24 Jan 2025 12:25:20 -0500 Received: from eggs.gnu.org ([2001:470:142:3::10]:39734) by debbugs.gnu.org with esmtps (TLS1.2:ECDHE_RSA_AES_256_GCM_SHA384:256) (Exim 4.84_2) (envelope-from <ludo@HIDDEN>) id 1tbNQh-0003N4-Ab for 75810 <at> debbugs.gnu.org; Fri, 24 Jan 2025 12:25:16 -0500 Received: from fencepost.gnu.org ([2001:470:142:3::e]) by eggs.gnu.org with esmtps (TLS1.2:ECDHE_RSA_AES_256_GCM_SHA384:256) (Exim 4.90_1) (envelope-from <ludo@HIDDEN>) id 1tbNQc-00082X-0O; Fri, 24 Jan 2025 12:25:10 -0500 DKIM-Signature: v=1; a=rsa-sha256; q=dns/txt; c=relaxed/relaxed; d=gnu.org; s=fencepost-gnu-org; h=MIME-Version:References:In-Reply-To:Date:Subject:To: From; bh=xpCSNZlKD/xC2GsfHtr1wqnKQLVLgRRMGCIqgMVlQ94=; b=QBQPaD4IAa/nSt+g28pj jh5L6YWqgV/CvdgjR+5jgXgV4uZTPZX0U2j7ZtZ5TREl0bwCo+g1xRkGJXb9lSR9o+cKFeFifmWRz 9J/ZZZ58Yd4Y35oVCyuyzSrlvYe4QqIEsf8aB5Rk/3RiOx6aIHd98Aw0FN4GzVz64Z8+HI0adWkeD mGIO7H4a9M095pamkOHgr6LhaAbMZJ6EiS+b+fuELhroa+QAeoozF0KcdwBNfZYztFWKYe42epvQ+ +tn8TFNzuCbPEZ5p7UsD0GMoEZ2UWYq1iZ0Dn9z45sR++NKd+0it6MljZ4KZ0Qzre2xvx5hPyMzWY t5y7kS7+4HDZag==; From: =?UTF-8?q?Ludovic=20Court=C3=A8s?= <ludo@HIDDEN> To: 75810 <at> debbugs.gnu.org Subject: [PATCH 1/6] daemon: Allow running as non-root with unprivileged user namespaces. Date: Fri, 24 Jan 2025 18:24:51 +0100 Message-ID: <41862c6aa51aa70c69a348635eb03a5ca8069695.1737738362.git.ludo@HIDDEN> X-Mailer: git-send-email 2.47.1 In-Reply-To: <cover.1737738362.git.ludo@HIDDEN> References: <cover.1737738362.git.ludo@HIDDEN> MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 X-Debbugs-Cc: Christopher Baines <guix@HIDDEN>, Josselin Poiret <dev@HIDDEN>, Ludovic Courtès <ludo@HIDDEN>, Mathieu Othacehe <othacehe@HIDDEN>, Simon Tournier <zimon.toutoune@HIDDEN>, Tobias Geerinckx-Rice <me@HIDDEN> Content-Transfer-Encoding: 8bit X-Spam-Score: -2.3 (--) X-Debbugs-Envelope-To: 75810 Cc: =?UTF-8?q?Ludovic=20Court=C3=A8s?= <ludovic.courtes@HIDDEN> X-BeenThere: debbugs-submit <at> debbugs.gnu.org X-Mailman-Version: 2.1.18 Precedence: list List-Id: <debbugs-submit.debbugs.gnu.org> List-Unsubscribe: <https://debbugs.gnu.org/cgi-bin/mailman/options/debbugs-submit>, <mailto:debbugs-submit-request <at> debbugs.gnu.org?subject=unsubscribe> List-Archive: <https://debbugs.gnu.org/cgi-bin/mailman/private/debbugs-submit/> List-Post: <mailto:debbugs-submit <at> debbugs.gnu.org> List-Help: <mailto:debbugs-submit-request <at> debbugs.gnu.org?subject=help> List-Subscribe: <https://debbugs.gnu.org/cgi-bin/mailman/listinfo/debbugs-submit>, <mailto:debbugs-submit-request <at> debbugs.gnu.org?subject=subscribe> Errors-To: debbugs-submit-bounces <at> debbugs.gnu.org Sender: "Debbugs-submit" <debbugs-submit-bounces <at> debbugs.gnu.org> X-Spam-Score: -3.3 (---) From: Ludovic Courtès <ludovic.courtes@HIDDEN> * nix/libstore/build.cc (guestUID, guestGID): New variables. (initializeUserNamespace): New function. (DerivationGoal::startBuilder): Call ‘chown’ only when ‘buildUser.enabled()’ is true. Pass CLONE_NEWUSER to ‘clone’ when ‘buildUser.enabled()’ is false or not running as root. Retry ‘clone’ without CLONE_NEWUSER upon EPERM. (DerivationGoal::registerOutputs): Make ‘actualPath’ writable before ‘rename’. (DerivationGoal::deleteTmpDir): Catch ‘SysError’ around ‘_chown’ call. * nix/libstore/local-store.cc (LocalStore::createUser): Do nothing if ‘dirs’ already exists. Warn instead of failing when failing to chown ‘dir’. * guix/substitutes.scm (%narinfo-cache-directory): Check for ‘_NIX_OPTIONS’ rather than getuid() == 0 to determine the cache location. Change-Id: I38fbe01f80fb45a99cd8a391e55a39a54d64fcb7 --- guix/substitutes.scm | 4 +- nix/libstore/build.cc | 123 +++++++++++++++++++++++++++++------- nix/libstore/local-store.cc | 22 +++++-- 3 files changed, 118 insertions(+), 31 deletions(-) diff --git a/guix/substitutes.scm b/guix/substitutes.scm index e31b394020..2761a3dafb 100644 --- a/guix/substitutes.scm +++ b/guix/substitutes.scm @@ -1,5 +1,5 @@ ;;; GNU Guix --- Functional package management for GNU -;;; Copyright © 2013-2021, 2023-2024 Ludovic Courtès <ludo@HIDDEN> +;;; Copyright © 2013-2021, 2023-2025 Ludovic Courtès <ludo@HIDDEN> ;;; Copyright © 2014 Nikita Karetnikov <nikita@HIDDEN> ;;; Copyright © 2018 Kyle Meyer <kyle@HIDDEN> ;;; Copyright © 2020 Christopher Baines <mail@HIDDEN> @@ -76,7 +76,7 @@ (define %narinfo-cache-directory ;; time, 'guix substitute' is called by guix-daemon as root and stores its ;; cached data in /var/guix/…. However, when invoked from 'guix challenge' ;; as a user, it stores its cache in ~/.cache. - (if (zero? (getuid)) + (if (getenv "_NIX_OPTIONS") ;invoked by guix-daemon (or (and=> (getenv "XDG_CACHE_HOME") (cut string-append <> "/guix/substitute")) (string-append %state-directory "/substitute/cache")) diff --git a/nix/libstore/build.cc b/nix/libstore/build.cc index edd01bab34..727472c77f 100644 --- a/nix/libstore/build.cc +++ b/nix/libstore/build.cc @@ -1622,6 +1622,25 @@ int childEntry(void * arg) } +/* UID and GID of the build user inside its own user namespace. */ +static const uid_t guestUID = 30001; +static const gid_t guestGID = 30000; + +/* Initialize the user namespace of CHILD. */ +static void initializeUserNamespace(pid_t child) +{ + auto hostUID = getuid(); + auto hostGID = getgid(); + + writeFile("/proc/" + std::to_string(child) + "/uid_map", + (format("%d %d 1") % guestUID % hostUID).str()); + + writeFile("/proc/" + std::to_string(child) + "/setgroups", "deny"); + + writeFile("/proc/" + std::to_string(child) + "/gid_map", + (format("%d %d 1") % guestGID % hostGID).str()); +} + void DerivationGoal::startBuilder() { auto f = format( @@ -1685,7 +1704,7 @@ void DerivationGoal::startBuilder() then an attacker could create in it a hardlink to a root-owned file such as /etc/shadow. If 'keepFailed' is true, the daemon would then chown that hardlink to the user, giving them write access to - that file. */ + that file. See CVE-2021-27851. */ tmpDir += "/top"; if (mkdir(tmpDir.c_str(), 0700) == 1) throw SysError("creating top-level build directory"); @@ -1802,7 +1821,7 @@ void DerivationGoal::startBuilder() if (mkdir(chrootRootDir.c_str(), 0750) == -1) throw SysError(format("cannot create ‘%1%’") % chrootRootDir); - if (chown(chrootRootDir.c_str(), 0, buildUser.getGID()) == -1) + if (buildUser.enabled() && chown(chrootRootDir.c_str(), 0, buildUser.getGID()) == -1) throw SysError(format("cannot change ownership of ‘%1%’") % chrootRootDir); /* Create a writable /tmp in the chroot. Many builders need @@ -1821,8 +1840,8 @@ void DerivationGoal::startBuilder() (format( "nixbld:x:%1%:%2%:Nix build user:/:/noshell\n" "nobody:x:65534:65534:Nobody:/:/noshell\n") - % (buildUser.enabled() ? buildUser.getUID() : getuid()) - % (buildUser.enabled() ? buildUser.getGID() : getgid())).str()); + % (buildUser.enabled() ? buildUser.getUID() : guestUID) + % (buildUser.enabled() ? buildUser.getGID() : guestGID)).str()); /* Declare the build user's group so that programs get a consistent view of the system (e.g., "id -gn"). */ @@ -1859,7 +1878,7 @@ void DerivationGoal::startBuilder() createDirs(chrootStoreDir); chmod_(chrootStoreDir, 01775); - if (chown(chrootStoreDir.c_str(), 0, buildUser.getGID()) == -1) + if (buildUser.enabled() && chown(chrootStoreDir.c_str(), 0, buildUser.getGID()) == -1) throw SysError(format("cannot change ownership of ‘%1%’") % chrootStoreDir); foreach (PathSet::iterator, i, inputPaths) { @@ -1971,14 +1990,42 @@ void DerivationGoal::startBuilder() if (useChroot) { char stack[32 * 1024]; int flags = CLONE_NEWPID | CLONE_NEWNS | CLONE_NEWIPC | CLONE_NEWUTS | SIGCHLD; - if (!fixedOutput) flags |= CLONE_NEWNET; + Pipe readiness; + if (!fixedOutput) { + flags |= CLONE_NEWNET; + } + if (!buildUser.enabled() || getuid() != 0) { + flags |= CLONE_NEWUSER; + readiness.create(); + } + /* Ensure proper alignment on the stack. On aarch64, it has to be 16 bytes. */ - pid = clone(childEntry, + pid = clone(childEntry, (char *)(((uintptr_t)stack + sizeof(stack) - 8) & ~(uintptr_t)0xf), flags, this); - if (pid == -1) - throw SysError("cloning builder process"); + if (pid == -1) { + if ((flags & CLONE_NEWUSER) != 0 && getuid() != 0) + /* 'clone' fails with EPERM on distros where unprivileged user + namespaces are disabled. Error out instead of giving up on + isolation. */ + throw SysError("cannot create process in unprivileged user namespace"); + else + throw SysError("cloning builder process"); + } + + if ((flags & CLONE_NEWUSER) != 0) { + /* Initialize the UID/GID mapping of the guest. */ + if (pid == 0) { + char str[20] = { '\0' }; + readFull(readiness.readSide, (unsigned char*)str, 3); + if (strcmp(str, "go\n") != 0) + throw Error("failed to initialize process in unprivileged user namespace"); + } else { + initializeUserNamespace(pid); + writeFull(readiness.writeSide, (unsigned char*)"go\n", 3); + } + } } else #endif { @@ -2030,17 +2077,19 @@ void DerivationGoal::runChild() #if CHROOT_ENABLED if (useChroot) { - /* Initialise the loopback interface. */ - AutoCloseFD fd(socket(PF_INET, SOCK_DGRAM, IPPROTO_IP)); - if (fd == -1) throw SysError("cannot open IP socket"); + if (!fixedOutput) { + /* Initialise the loopback interface. */ + AutoCloseFD fd(socket(PF_INET, SOCK_DGRAM, IPPROTO_IP)); + if (fd == -1) throw SysError("cannot open IP socket"); - struct ifreq ifr; - strcpy(ifr.ifr_name, "lo"); - ifr.ifr_flags = IFF_UP | IFF_LOOPBACK | IFF_RUNNING; - if (ioctl(fd, SIOCSIFFLAGS, &ifr) == -1) - throw SysError("cannot set loopback interface flags"); + struct ifreq ifr; + strcpy(ifr.ifr_name, "lo"); + ifr.ifr_flags = IFF_UP | IFF_LOOPBACK | IFF_RUNNING; + if (ioctl(fd, SIOCSIFFLAGS, &ifr) == -1) + throw SysError("cannot set loopback interface flags"); - fd.close(); + fd.close(); + } /* Set the hostname etc. to fixed values. */ char hostname[] = "localhost"; @@ -2463,8 +2512,16 @@ void DerivationGoal::registerOutputs() 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) { + if (S_ISDIR(st.st_mode)) + /* Change mode on the directory to allow for + rename(2). */ + chmod(actualPath.c_str(), st.st_mode | 0700); + if (rename(actualPath.c_str(), path.c_str()) == -1) + throw SysError(format("moving build output `%1%' from the chroot to the store") % path); + if (S_ISDIR(st.st_mode) && chmod(path.c_str(), st.st_mode) == -1) + throw SysError(format("restoring permissions on directory `%1%'") % actualPath); + } } if (buildMode != bmCheck) actualPath = path; } @@ -2723,8 +2780,25 @@ void DerivationGoal::deleteTmpDir(bool force) // Change the ownership if clientUid is set. Never change the // ownership or the group to "root" for security reasons. if (settings.clientUid != (uid_t) -1 && settings.clientUid != 0) { - _chown(tmpDir, settings.clientUid, - settings.clientGid != 0 ? settings.clientGid : -1); + uid_t uid = settings.clientUid; + gid_t gid = settings.clientGid != 0 ? settings.clientGid : -1; + try { + _chown(tmpDir, uid, gid); + + if (getuid() != 0) { + /* If, without being root, the '_chown' call above + succeeded, then it means we have CAP_CHOWN. Retake + ownership of tmpDir itself so it can be renamed + below. */ + chown(tmpDir.c_str(), getuid(), getgid()); + } + } catch (SysError & e) { + /* When running as an unprivileged user and without + CAP_CHOWN, we cannot chown the build tree. Print a + message and keep going. */ + printMsg(lvlInfo, format("cannot change ownership of build directory '%1%': %2%") + % tmpDir % strerror(e.errNo)); + } if (top != tmpDir) { // Rename tmpDir to its parent, with an intermediate step. @@ -2733,6 +2807,11 @@ void DerivationGoal::deleteTmpDir(bool force) throw SysError("pivoting failed build tree"); if (rename((pivot + "/top").c_str(), top.c_str()) == -1) throw SysError("renaming failed build tree"); + + if (getuid() != 0) + /* Running unprivileged but with CAP_CHOWN. */ + chown(top.c_str(), uid, gid); + rmdir(pivot.c_str()); } } diff --git a/nix/libstore/local-store.cc b/nix/libstore/local-store.cc index 0883a4bbce..4308264a4f 100644 --- a/nix/libstore/local-store.cc +++ b/nix/libstore/local-store.cc @@ -306,14 +306,14 @@ void LocalStore::openDB(bool create) void LocalStore::makeStoreWritable() { #if HAVE_UNSHARE && HAVE_STATVFS && HAVE_SYS_MOUNT_H && defined(MS_BIND) && defined(MS_REMOUNT) - if (getuid() != 0) return; /* Check if /nix/store is on a read-only mount. */ struct statvfs stat; if (statvfs(settings.nixStore.c_str(), &stat) != 0) throw SysError("getting info about the store mount point"); if (stat.f_flag & ST_RDONLY) { - if (unshare(CLONE_NEWNS) == -1) + int flags = CLONE_NEWNS | (getpid() == 0 ? 0 : CLONE_NEWUSER); + if (unshare(flags) == -1) throw SysError("setting up a private mount namespace"); if (mount(0, settings.nixStore.c_str(), "none", MS_REMOUNT | MS_BIND, 0) == -1) @@ -1614,11 +1614,19 @@ void LocalStore::createUser(const std::string & userName, uid_t userId) { auto dir = settings.nixStateDir + "/profiles/per-user/" + userName; - createDirs(dir); - if (chmod(dir.c_str(), 0755) == -1) - throw SysError(format("changing permissions of directory '%s'") % dir); - if (chown(dir.c_str(), userId, -1) == -1) - throw SysError(format("changing owner of directory '%s'") % dir); + auto created = createDirs(dir); + if (!created.empty()) { + if (chmod(dir.c_str(), 0755) == -1) + throw SysError(format("changing permissions of directory '%s'") % dir); + + /* The following operation requires CAP_CHOWN or can be handled + manually by a user with CAP_CHOWN. */ + if (chown(dir.c_str(), userId, -1) == -1) { + rmdir(dir.c_str()); + string message = strerror(errno); + printMsg(lvlInfo, format("failed to change owner of directory '%1%' to %2%: %3%") % dir % userId % message); + } + } } -- 2.47.1
guix@HIDDEN, dev@HIDDEN, ludo@HIDDEN, othacehe@HIDDEN, zimon.toutoune@HIDDEN, me@HIDDEN, guix-patches@HIDDEN
:bug#75810
; Package guix-patches
.
Full text available.Received: (at submit) by debbugs.gnu.org; 24 Jan 2025 17:23:39 +0000 From debbugs-submit-bounces <at> debbugs.gnu.org Fri Jan 24 12:23:39 2025 Received: from localhost ([127.0.0.1]:46876 helo=debbugs.gnu.org) by debbugs.gnu.org with esmtp (Exim 4.84_2) (envelope-from <debbugs-submit-bounces <at> debbugs.gnu.org>) id 1tbNP4-0003JI-FG for submit <at> debbugs.gnu.org; Fri, 24 Jan 2025 12:23:38 -0500 Received: from lists.gnu.org ([2001:470:142::17]:42976) by debbugs.gnu.org with esmtps (TLS1.2:ECDHE_RSA_AES_256_GCM_SHA384:256) (Exim 4.84_2) (envelope-from <ludo@HIDDEN>) id 1tbNP1-0003Iq-4f for submit <at> debbugs.gnu.org; Fri, 24 Jan 2025 12:23:32 -0500 Received: from eggs.gnu.org ([2001:470:142:3::10]) by lists.gnu.org with esmtps (TLS1.2:ECDHE_RSA_AES_256_GCM_SHA384:256) (Exim 4.90_1) (envelope-from <ludo@HIDDEN>) id 1tbNOv-0002jg-NH for guix-patches@HIDDEN; Fri, 24 Jan 2025 12:23:25 -0500 Received: from fencepost.gnu.org ([2001:470:142:3::e]) by eggs.gnu.org with esmtps (TLS1.2:ECDHE_RSA_AES_256_GCM_SHA384:256) (Exim 4.90_1) (envelope-from <ludo@HIDDEN>) id 1tbNOu-0007lR-MV; Fri, 24 Jan 2025 12:23:24 -0500 DKIM-Signature: v=1; a=rsa-sha256; q=dns/txt; c=relaxed/relaxed; d=gnu.org; s=fencepost-gnu-org; h=MIME-Version:Date:Subject:To:From:in-reply-to: references; bh=PD6esGgynPOINnX7oSt5mYPBliDR3e5pryXB3tW8/8Y=; b=o5s3EXNxJjPzrE QAPCs6SEqUTl9K8Ax/LFlk2P11elT2FIKR+lUR3P1O0PZXD2EK8/2ko/zGqP/I06vUW6fCzWfztCC JMufeWCYISqjvsRBj1a2rxWkdhh9fBCDANPrb8b0uMNptCuVvL2g3AoTBGWlzQdMbQfXdHmSkCdMy q6lhuJ5FY7omSLwY/RiFK4Taq4sEh0kisiNawfpj/gwQsPUUaL01CUOiBhs3JT+xvkFrZDj7sieZ4 EBK8WRIYlzu2X7zBKezFo50L/cC49p4OKy5GiuKz7gQdF1GfnCyA/VGWwVMJN68doY2D004fQKtgR logQONcnHtvbM+5exx7Q==; From: =?UTF-8?q?Ludovic=20Court=C3=A8s?= <ludo@HIDDEN> To: guix-patches@HIDDEN Subject: [PATCH 0/6] Rootless guix-daemon Date: Fri, 24 Jan 2025 18:23:08 +0100 Message-ID: <cover.1737738362.git.ludo@HIDDEN> X-Mailer: git-send-email 2.47.1 MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit X-Spam-Score: -0.0 (/) X-Debbugs-Envelope-To: submit Cc: =?UTF-8?q?Ludovic=20Court=C3=A8s?= <ludovic.courtes@HIDDEN> X-BeenThere: debbugs-submit <at> debbugs.gnu.org X-Mailman-Version: 2.1.18 Precedence: list List-Id: <debbugs-submit.debbugs.gnu.org> List-Unsubscribe: <https://debbugs.gnu.org/cgi-bin/mailman/options/debbugs-submit>, <mailto:debbugs-submit-request <at> debbugs.gnu.org?subject=unsubscribe> List-Archive: <https://debbugs.gnu.org/cgi-bin/mailman/private/debbugs-submit/> List-Post: <mailto:debbugs-submit <at> debbugs.gnu.org> List-Help: <mailto:debbugs-submit-request <at> debbugs.gnu.org?subject=help> List-Subscribe: <https://debbugs.gnu.org/cgi-bin/mailman/listinfo/debbugs-submit>, <mailto:debbugs-submit-request <at> debbugs.gnu.org?subject=subscribe> Errors-To: debbugs-submit-bounces <at> debbugs.gnu.org Sender: "Debbugs-submit" <debbugs-submit-bounces <at> debbugs.gnu.org> X-Spam-Score: -1.0 (-) From: Ludovic Courtès <ludovic.courtes@HIDDEN> Hello Guix! That guix-daemon runs as root is not confidence-inspiring for many. Initially, the main reason for running it as root was, in the absence of user namespaces, the fact that builders would be started under one of the build user accounts, which only root can do. Now that unprivileged user namespaces are almost ubiquitous (even on HPC clusters), this is no longer a good reason. This patch changes guix-daemon so it can run as an unprivileged user, using unprivileged user namespaces to still support isolated builds. There’s a couple of cases where root is/was still necessary: 1. To create /var/guix/profiles/per-user/$USER and chown it as $USER (see CVE-2019-18192). 2. To chown /tmp/guix-build-* when using ‘--keep-failed’. Both can be addressed by giving CAP_CHOWN to guix-daemon, and this is what this patch series does on distros using systemd. (For some reason CAP_CHOWN had to be added to the set of “ambient capabilities”, which are inherited by child processes; this is why there’s a patch to drop ambient capabilities in build processes.) On Guix System (not implemented here), we could address (1) by creating /var/guix/profiles/per-user/$USER upfront for all the user accounts. We could leave (2) unaddressed (so failed build directories would be owned by guix-daemon:guix-daemon) or we’d have to pass CAP_CHOWN as well. There’s another issue: /gnu/store can no longer be remounted read-only (like we do on Guix System and on systemd with ‘gnu-store.mount’) because then unprivileged guix-daemon would be unable to remount it read-write (or at least I couldn’t find a way to do that). Thus ‘guix-install.sh’ no longer installs ‘gnu-store.mount’ in that case. It’s a bit sad to lose that so if anyone can think of a way to achieve it, that’d be great. I tested all this in a Debian VM¹, along these lines: 1. GUIX_ALLOW_ME_TO_USE_PRIVATE_COMMIT=yes make update-guix-package 2. ./pre-inst-env guix pack -C zstd guix --without-tests=guix \ --localstatedir --profile-name=current-guix 3. Copy ‘guix-install.sh’ and the tarball to the VM over SSH. 4. In the VM: GUIX_BINARY_FILE_NAME=pack.tar.zst ./guix-install.sh The next step (in another patch series) would be Guix System support with automatic transition (essentially “chown -R guix-daemon:guix-daemon /gnu/store”). Thoughts? Ludo’. ¹ https://cdimage.debian.org/debian-cd/current-live/amd64/iso-hybrid/debian-live-12.9.0-amd64-standard.iso Ludovic Courtès (6): daemon: Allow running as non-root with unprivileged user namespaces. DRAFT tests: Run in a chroot and unprivileged user namespaces. daemon: Create /var/guix/profiles/per-user unconditionally. daemon: Drop Linux ambient capabilities before executing builder. etc: systemd services: Run ‘guix-daemon’ as an unprivileged user. guix-install.sh: Support the unprivileged daemon where possible. build-aux/test-env.in | 14 +++- config-daemon.ac | 2 +- etc/guix-daemon.service.in | 12 +++- etc/guix-install.sh | 114 ++++++++++++++++++++++++------- guix/substitutes.scm | 4 +- nix/libstore/build.cc | 132 ++++++++++++++++++++++++++++++------ nix/libstore/local-store.cc | 30 +++++--- tests/store.scm | 89 ++++++++++++++---------- 8 files changed, 300 insertions(+), 97 deletions(-) base-commit: bc6769f1211104dbc9341c064275cd930f5dfa3a -- 2.47.1
Ludovic Courtès <ludo@HIDDEN>
:guix-patches@HIDDEN
.
Full text available.guix-patches@HIDDEN
:bug#75810
; Package guix-patches
.
Full text available.
GNU bug tracking system
Copyright (C) 1999 Darren O. Benham,
1997 nCipher Corporation Ltd,
1994-97 Ian Jackson.