From mboxrd@z Thu Jan 1 00:00:00 1970 Return-Path: Received: from mp2 ([2001:41d0:2:4a6f::]) (using TLSv1.3 with cipher TLS_AES_256_GCM_SHA384 (256/256 bits)) by ms11 with LMTPS id 0EBoNl2HuV5RZwAA0tVLHw (envelope-from ) for ; Mon, 11 May 2020 17:11:57 +0000 Received: from aspmx1.migadu.com ([2001:41d0:2:4a6f::]) (using TLSv1.3 with cipher TLS_AES_256_GCM_SHA384 (256/256 bits)) by mp2 with LMTPS id rCsLN2uHuV6UNgAAB5/wlQ (envelope-from ) for ; Mon, 11 May 2020 17:12:11 +0000 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 8BFCA940DEA for ; Mon, 11 May 2020 17:12:09 +0000 (UTC) Received: from localhost ([::1]:57336 helo=lists1p.gnu.org) by lists.gnu.org with esmtp (Exim 4.90_1) (envelope-from ) id 1jYByM-0004wh-Cq for larch@yhetil.org; Mon, 11 May 2020 13:12:10 -0400 Received: from eggs.gnu.org ([2001:470:142:3::10]:60372) by lists.gnu.org with esmtps (TLS1.2:ECDHE_RSA_AES_256_GCM_SHA384:256) (Exim 4.90_1) (envelope-from ) id 1jYByE-0004v5-Ea for guix-patches@gnu.org; Mon, 11 May 2020 13:12:02 -0400 Received: from debbugs.gnu.org ([209.51.188.43]:41588) by eggs.gnu.org with esmtps (TLS1.2:ECDHE_RSA_AES_128_GCM_SHA256:128) (Exim 4.90_1) (envelope-from ) id 1jYByE-0001Ux-4S for guix-patches@gnu.org; Mon, 11 May 2020 13:12:02 -0400 Received: from Debian-debbugs by debbugs.gnu.org with local (Exim 4.84_2) (envelope-from ) id 1jYByD-0001d4-VS for guix-patches@gnu.org; Mon, 11 May 2020 13:12:01 -0400 X-Loop: help-debbugs@gnu.org Subject: [bug#41189] [PATCH 1/3] pack: Wrapper honors 'GUIX_EXECUTION_ENGINE' environment variable. References: <20200511170554.22916-1-ludo@gnu.org> In-Reply-To: <20200511170554.22916-1-ludo@gnu.org> Resent-From: Ludovic =?UTF-8?Q?Court=C3=A8s?= Original-Sender: "Debbugs-submit" Resent-CC: guix-patches@gnu.org Resent-Date: Mon, 11 May 2020 17:12:01 +0000 Resent-Message-ID: Resent-Sender: help-debbugs@gnu.org X-GNU-PR-Message: followup 41189 X-GNU-PR-Package: guix-patches X-GNU-PR-Keywords: patch To: 41189@debbugs.gnu.org Cc: Ludovic =?UTF-8?Q?Court=C3=A8s?= Received: via spool by 41189-submit@debbugs.gnu.org id=B41189.15892171126236 (code B ref 41189); Mon, 11 May 2020 17:12:01 +0000 Received: (at 41189) by debbugs.gnu.org; 11 May 2020 17:11:52 +0000 Received: from localhost ([127.0.0.1]:53129 helo=debbugs.gnu.org) by debbugs.gnu.org with esmtp (Exim 4.84_2) (envelope-from ) id 1jYBy4-0001cV-AI for submit@debbugs.gnu.org; Mon, 11 May 2020 13:11:52 -0400 Received: from eggs.gnu.org ([209.51.188.92]:57330) by debbugs.gnu.org with esmtp (Exim 4.84_2) (envelope-from ) id 1jYBy1-0001cA-TN for 41189@debbugs.gnu.org; Mon, 11 May 2020 13:11:50 -0400 Received: from fencepost.gnu.org ([2001:470:142:3::e]:41566) by eggs.gnu.org with esmtp (Exim 4.90_1) (envelope-from ) id 1jYBxw-0001TU-HO; Mon, 11 May 2020 13:11:44 -0400 Received: from [2a01:e0a:1d:7270:af76:b9b:ca24:c465] (port=38172 helo=gnu.org) by fencepost.gnu.org with esmtpsa (TLS1.2:DHE_RSA_AES_256_CBC_SHA1:256) (Exim 4.82) (envelope-from ) id 1jYBxv-0005Cj-Sf; Mon, 11 May 2020 13:11:44 -0400 From: Ludovic =?UTF-8?Q?Court=C3=A8s?= Date: Mon, 11 May 2020 19:11:33 +0200 Message-Id: <20200511171135.23157-1-ludo@gnu.org> X-Mailer: git-send-email 2.26.2 MIME-Version: 1.0 Content-Transfer-Encoding: 8bit X-Spam-Score: -2.3 (--) X-BeenThere: debbugs-submit@debbugs.gnu.org X-Mailman-Version: 2.1.18 Precedence: list X-Spam-Score: -3.3 (---) 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" X-Scanner: scn0 X-Spam-Score: 3.99 Authentication-Results: aspmx1.migadu.com; dkim=none; dmarc=none; spf=pass (aspmx1.migadu.com: domain of guix-patches-bounces@gnu.org designates 209.51.188.17 as permitted sender) smtp.mailfrom=guix-patches-bounces@gnu.org X-Scan-Result: default: False [3.99 / 13.00]; RCVD_VIA_SMTP_AUTH(0.00)[]; GENERIC_REPUTATION(0.00)[-0.54012220889554]; TO_DN_SOME(0.00)[]; R_SPF_ALLOW(-0.20)[+ip4:209.51.188.0/24:c]; R_MISSING_CHARSET(2.50)[]; DWL_DNSWL_FAIL(0.00)[209.51.188.17:server fail]; IP_REPUTATION_HAM(0.00)[asn: 22989(0.07), country: US(-0.00), ip: 209.51.188.17(-0.54)]; BROKEN_CONTENT_TYPE(1.50)[]; MX_GOOD(-0.50)[cached: eggs.gnu.org]; RCPT_COUNT_TWO(0.00)[2]; MAILLIST(-0.20)[mailman]; FORGED_RECIPIENTS_MAILLIST(0.00)[]; RCVD_TLS_LAST(0.00)[]; R_DKIM_NA(0.00)[]; ASN(0.00)[asn:22989, ipnet:209.51.188.0/24, country:US]; MIME_TRACE(0.00)[0:+]; TAGGED_FROM(0.00)[larch=yhetil.org]; ARC_NA(0.00)[]; FROM_NEQ_ENVFROM(0.00)[ludo@gnu.org,guix-patches-bounces@gnu.org]; FROM_HAS_DN(0.00)[]; URIBL_BLOCKED(0.00)[proot-me.github.io:url]; MIME_GOOD(-0.10)[text/plain]; DMARC_NA(0.00)[gnu.org]; HAS_LIST_UNSUB(-0.01)[]; DNSWL_BLOCKED(0.00)[209.51.188.17:from]; MID_CONTAINS_FROM(1.00)[]; RWL_MAILSPIKE_POSSIBLE(0.00)[209.51.188.17:from]; RCVD_COUNT_SEVEN(0.00)[9]; FORGED_SENDER_MAILLIST(0.00)[] X-TUID: PmaMuh/l9G9q * gnu/packages/aux-files/run-in-namespace.c (struct engine): New type. (exec_default): New function. (engines): New variable. (execution_engine): New function. (main): Use it instead of calling 'exec_in_user_namespace' and 'exec_with_proot' directly. * tests/guix-pack-relocatable.sh: Add test with 'GUIX_EXECUTION_ENGINE'. * doc/guix.texi (Invoking guix pack): Document 'GUIX_EXECUTION_ENGINE'. --- doc/guix.texi | 30 +++++++-- gnu/packages/aux-files/run-in-namespace.c | 78 ++++++++++++++++++++--- tests/guix-pack-relocatable.sh | 17 +++++ 3 files changed, 110 insertions(+), 15 deletions(-) diff --git a/doc/guix.texi b/doc/guix.texi index 0cba0ee1ec..958ed9ceec 100644 --- a/doc/guix.texi +++ b/doc/guix.texi @@ -5185,9 +5185,9 @@ When this option is passed once, the resulting binaries require support for @dfn{user namespaces} in the kernel Linux; when passed @emph{twice}@footnote{Here's a trick to memorize it: @code{-RR}, which adds PRoot support, can be thought of as the abbreviation of ``Really -Relocatable''. Neat, isn't it?}, relocatable binaries fall to back to PRoot -if user namespaces are unavailable, and essentially work anywhere---see below -for the implications. +Relocatable''. Neat, isn't it?}, relocatable binaries fall to back to +other techniques if user namespaces are unavailable, and essentially +work anywhere---see below for the implications. For example, if you create a pack containing Bash with: @@ -5219,14 +5219,32 @@ turn it off. To produce relocatable binaries that work even in the absence of user namespaces, pass @option{--relocatable} or @option{-R} @emph{twice}. In that -case, binaries will try user namespace support and fall back to PRoot if user -namespaces are not supported. +case, binaries will try user namespace support and fall back to another +@dfn{execution engine} if user namespaces are not supported. The +following execution engines are supported: -The @uref{https://proot-me.github.io/, PRoot} program provides the necessary +@table @code +@item default +Try user namespaces and fall back to PRoot if user namespaces are not +supported (see below). + +@item userns +Run the program through user namespaces and abort if they are not +supported. + +@item proot +Run through PRoot. The @uref{https://proot-me.github.io/, PRoot} program +provides the necessary support for file system virtualization. It achieves that by using the @code{ptrace} system call on the running program. This approach has the advantage to work without requiring special kernel support, but it incurs run-time overhead every time a system call is made. +@end table + +@vindex GUIX_EXECUTION_ENGINE +When running a wrapped program, you can explicitly request one of the +execution engines listed above by setting the +@code{GUIX_EXECUTION_ENGINE} environment variable accordingly. @end quotation @cindex entry point, for Docker images diff --git a/gnu/packages/aux-files/run-in-namespace.c b/gnu/packages/aux-files/run-in-namespace.c index 23e7875173..6beac7fd53 100644 --- a/gnu/packages/aux-files/run-in-namespace.c +++ b/gnu/packages/aux-files/run-in-namespace.c @@ -336,6 +336,71 @@ exec_with_proot (const char *store, int argc, char *argv[]) #endif + +/* Execution engines. */ + +struct engine +{ + const char *name; + void (* exec) (const char *, int, char **); +}; + +static void +buffer_stderr (void) +{ + static char stderr_buffer[4096]; + setvbuf (stderr, stderr_buffer, _IOFBF, sizeof stderr_buffer); +} + +/* The default engine. */ +static void +exec_default (const char *store, int argc, char *argv[]) +{ + /* Buffer stderr so that nothing's displayed if 'exec_in_user_namespace' + fails but 'exec_with_proot' works. */ + buffer_stderr (); + + exec_in_user_namespace (store, argc, argv); +#ifdef PROOT_PROGRAM + exec_with_proot (store, argc, argv); +#endif +} + +/* List of supported engines. */ +static const struct engine engines[] = + { + { "default", exec_default }, + { "userns", exec_in_user_namespace }, +#ifdef PROOT_PROGRAM + { "proot", exec_with_proot }, +#endif + { NULL, NULL } + }; + +/* Return the "execution engine" to use. */ +static const struct engine * +execution_engine (void) +{ + const char *str = getenv ("GUIX_EXECUTION_ENGINE"); + + if (str == NULL) + str = "default"; + + try: + for (const struct engine *engine = engines; + engine->name != NULL; + engine++) + { + if (strcmp (engine->name, str) == 0) + return engine; + } + + fprintf (stderr, "%s: unsupported Guix execution engine; ignoring\n", + str); + str = "default"; + goto try; +} + int main (int argc, char *argv[]) @@ -362,22 +427,17 @@ main (int argc, char *argv[]) if (strcmp (store, "@STORE_DIRECTORY@") != 0 && lstat ("@WRAPPED_PROGRAM@", &statbuf) != 0) { - /* Buffer stderr so that nothing's displayed if 'exec_in_user_namespace' - fails but 'exec_with_proot' works. */ - static char stderr_buffer[4096]; - setvbuf (stderr, stderr_buffer, _IOFBF, sizeof stderr_buffer); + const struct engine *engine = execution_engine (); + engine->exec (store, argc, argv); - exec_in_user_namespace (store, argc, argv); -#ifdef PROOT_PROGRAM - exec_with_proot (store, argc, argv); -#else + /* If we reach this point, that's because ENGINE failed to do the + job. */ fprintf (stderr, "\ This may be because \"user namespaces\" are not supported on this system.\n\ Consequently, we cannot run '@WRAPPED_PROGRAM@',\n\ unless you move it to the '@STORE_DIRECTORY@' directory.\n\ \n\ Please refer to the 'guix pack' documentation for more information.\n"); -#endif return EXIT_FAILURE; } diff --git a/tests/guix-pack-relocatable.sh b/tests/guix-pack-relocatable.sh index a3fd45623c..cb56815fed 100644 --- a/tests/guix-pack-relocatable.sh +++ b/tests/guix-pack-relocatable.sh @@ -84,6 +84,23 @@ fi grep 'GNU sed' "$test_directory/output" chmod -Rf +w "$test_directory"; rm -rf "$test_directory"/* +case "`uname -m`" in + x86_64|i?86) + # Try '-RR' and PRoot. + tarball="`guix pack -RR -S /Bin=bin sed`" + tar tvf "$tarball" | grep /bin/proot + (cd "$test_directory"; tar xvf "$tarball") + GUIX_EXECUTION_ENGINE="proot" + export GUIX_EXECUTION_ENGINE + "$test_directory/Bin/sed" --version > "$test_directory/output" + grep 'GNU sed' "$test_directory/output" + chmod -Rf +w "$test_directory"; rm -rf "$test_directory"/* + ;; + *) + echo "skipping PRoot test" >&2 + ;; +esac + # Ensure '-R' works with outputs other than "out". tarball="`guix pack -R -S /share=share groff:doc`" (cd "$test_directory"; tar xvf "$tarball") -- 2.26.2