summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorLudovic Courtès <ludo@gnu.org>2020-05-11 16:32:24 +0200
committerLudovic Courtès <ludo@gnu.org>2020-05-14 17:21:27 +0200
commitfde2aec3f498d5ec6db2121d72068e2b203e86cd (patch)
treed0d3c9b723c3e694ca107cff9315075e8267ebf4
parent80963744a242257921917df5a901dc343d3a93db (diff)
pack: Wrapper honors 'GUIX_EXECUTION_ENGINE' environment variable.
* 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'.
-rw-r--r--doc/guix.texi30
-rw-r--r--gnu/packages/aux-files/run-in-namespace.c78
-rw-r--r--tests/guix-pack-relocatable.sh17
3 files changed, 110 insertions, 15 deletions
diff --git a/doc/guix.texi b/doc/guix.texi
index d6fbd85fded..906ebff555c 100644
--- a/doc/guix.texi
+++ b/doc/guix.texi
@@ -5187,9 +5187,9 @@ When this option is passed once, the resulting binaries require support for
5187@dfn{user namespaces} in the kernel Linux; when passed 5187@dfn{user namespaces} in the kernel Linux; when passed
5188@emph{twice}@footnote{Here's a trick to memorize it: @code{-RR}, which adds 5188@emph{twice}@footnote{Here's a trick to memorize it: @code{-RR}, which adds
5189PRoot support, can be thought of as the abbreviation of ``Really 5189PRoot support, can be thought of as the abbreviation of ``Really
5190Relocatable''. Neat, isn't it?}, relocatable binaries fall to back to PRoot 5190Relocatable''. Neat, isn't it?}, relocatable binaries fall to back to
5191if user namespaces are unavailable, and essentially work anywhere---see below 5191other techniques if user namespaces are unavailable, and essentially
5192for the implications. 5192work anywhere---see below for the implications.
5193 5193
5194For example, if you create a pack containing Bash with: 5194For example, if you create a pack containing Bash with:
5195 5195
@@ -5221,14 +5221,32 @@ turn it off.
5221 5221
5222To produce relocatable binaries that work even in the absence of user 5222To produce relocatable binaries that work even in the absence of user
5223namespaces, pass @option{--relocatable} or @option{-R} @emph{twice}. In that 5223namespaces, pass @option{--relocatable} or @option{-R} @emph{twice}. In that
5224case, binaries will try user namespace support and fall back to PRoot if user 5224case, binaries will try user namespace support and fall back to another
5225namespaces are not supported. 5225@dfn{execution engine} if user namespaces are not supported. The
5226following execution engines are supported:
5226 5227
5227The @uref{https://proot-me.github.io/, PRoot} program provides the necessary 5228@table @code
5229@item default
5230Try user namespaces and fall back to PRoot if user namespaces are not
5231supported (see below).
5232
5233@item userns
5234Run the program through user namespaces and abort if they are not
5235supported.
5236
5237@item proot
5238Run through PRoot. The @uref{https://proot-me.github.io/, PRoot} program
5239provides the necessary
5228support for file system virtualization. It achieves that by using the 5240support for file system virtualization. It achieves that by using the
5229@code{ptrace} system call on the running program. This approach has the 5241@code{ptrace} system call on the running program. This approach has the
5230advantage to work without requiring special kernel support, but it incurs 5242advantage to work without requiring special kernel support, but it incurs
5231run-time overhead every time a system call is made. 5243run-time overhead every time a system call is made.
5244@end table
5245
5246@vindex GUIX_EXECUTION_ENGINE
5247When running a wrapped program, you can explicitly request one of the
5248execution engines listed above by setting the
5249@code{GUIX_EXECUTION_ENGINE} environment variable accordingly.
5232@end quotation 5250@end quotation
5233 5251
5234@cindex entry point, for Docker images 5252@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 23e78751735..6beac7fd53c 100644
--- a/gnu/packages/aux-files/run-in-namespace.c
+++ b/gnu/packages/aux-files/run-in-namespace.c
@@ -337,6 +337,71 @@ exec_with_proot (const char *store, int argc, char *argv[])
337#endif 337#endif
338 338
339 339
340/* Execution engines. */
341
342struct engine
343{
344 const char *name;
345 void (* exec) (const char *, int, char **);
346};
347
348static void
349buffer_stderr (void)
350{
351 static char stderr_buffer[4096];
352 setvbuf (stderr, stderr_buffer, _IOFBF, sizeof stderr_buffer);
353}
354
355/* The default engine. */
356static void
357exec_default (const char *store, int argc, char *argv[])
358{
359 /* Buffer stderr so that nothing's displayed if 'exec_in_user_namespace'
360 fails but 'exec_with_proot' works. */
361 buffer_stderr ();
362
363 exec_in_user_namespace (store, argc, argv);
364#ifdef PROOT_PROGRAM
365 exec_with_proot (store, argc, argv);
366#endif
367}
368
369/* List of supported engines. */
370static const struct engine engines[] =
371 {
372 { "default", exec_default },
373 { "userns", exec_in_user_namespace },
374#ifdef PROOT_PROGRAM
375 { "proot", exec_with_proot },
376#endif
377 { NULL, NULL }
378 };
379
380/* Return the "execution engine" to use. */
381static const struct engine *
382execution_engine (void)
383{
384 const char *str = getenv ("GUIX_EXECUTION_ENGINE");
385
386 if (str == NULL)
387 str = "default";
388
389 try:
390 for (const struct engine *engine = engines;
391 engine->name != NULL;
392 engine++)
393 {
394 if (strcmp (engine->name, str) == 0)
395 return engine;
396 }
397
398 fprintf (stderr, "%s: unsupported Guix execution engine; ignoring\n",
399 str);
400 str = "default";
401 goto try;
402}
403
404
340int 405int
341main (int argc, char *argv[]) 406main (int argc, char *argv[])
342{ 407{
@@ -362,22 +427,17 @@ main (int argc, char *argv[])
362 if (strcmp (store, "@STORE_DIRECTORY@") != 0 427 if (strcmp (store, "@STORE_DIRECTORY@") != 0
363 && lstat ("@WRAPPED_PROGRAM@", &statbuf) != 0) 428 && lstat ("@WRAPPED_PROGRAM@", &statbuf) != 0)
364 { 429 {
365 /* Buffer stderr so that nothing's displayed if 'exec_in_user_namespace' 430 const struct engine *engine = execution_engine ();
366 fails but 'exec_with_proot' works. */ 431 engine->exec (store, argc, argv);
367 static char stderr_buffer[4096];
368 setvbuf (stderr, stderr_buffer, _IOFBF, sizeof stderr_buffer);
369 432
370 exec_in_user_namespace (store, argc, argv); 433 /* If we reach this point, that's because ENGINE failed to do the
371#ifdef PROOT_PROGRAM 434 job. */
372 exec_with_proot (store, argc, argv);
373#else
374 fprintf (stderr, "\ 435 fprintf (stderr, "\
375This may be because \"user namespaces\" are not supported on this system.\n\ 436This may be because \"user namespaces\" are not supported on this system.\n\
376Consequently, we cannot run '@WRAPPED_PROGRAM@',\n\ 437Consequently, we cannot run '@WRAPPED_PROGRAM@',\n\
377unless you move it to the '@STORE_DIRECTORY@' directory.\n\ 438unless you move it to the '@STORE_DIRECTORY@' directory.\n\
378\n\ 439\n\
379Please refer to the 'guix pack' documentation for more information.\n"); 440Please refer to the 'guix pack' documentation for more information.\n");
380#endif
381 return EXIT_FAILURE; 441 return EXIT_FAILURE;
382 } 442 }
383 443
diff --git a/tests/guix-pack-relocatable.sh b/tests/guix-pack-relocatable.sh
index a3fd45623c2..cb56815fed7 100644
--- a/tests/guix-pack-relocatable.sh
+++ b/tests/guix-pack-relocatable.sh
@@ -84,6 +84,23 @@ fi
84grep 'GNU sed' "$test_directory/output" 84grep 'GNU sed' "$test_directory/output"
85chmod -Rf +w "$test_directory"; rm -rf "$test_directory"/* 85chmod -Rf +w "$test_directory"; rm -rf "$test_directory"/*
86 86
87case "`uname -m`" in
88 x86_64|i?86)
89 # Try '-RR' and PRoot.
90 tarball="`guix pack -RR -S /Bin=bin sed`"
91 tar tvf "$tarball" | grep /bin/proot
92 (cd "$test_directory"; tar xvf "$tarball")
93 GUIX_EXECUTION_ENGINE="proot"
94 export GUIX_EXECUTION_ENGINE
95 "$test_directory/Bin/sed" --version > "$test_directory/output"
96 grep 'GNU sed' "$test_directory/output"
97 chmod -Rf +w "$test_directory"; rm -rf "$test_directory"/*
98 ;;
99 *)
100 echo "skipping PRoot test" >&2
101 ;;
102esac
103
87# Ensure '-R' works with outputs other than "out". 104# Ensure '-R' works with outputs other than "out".
88tarball="`guix pack -R -S /share=share groff:doc`" 105tarball="`guix pack -R -S /share=share groff:doc`"
89(cd "$test_directory"; tar xvf "$tarball") 106(cd "$test_directory"; tar xvf "$tarball")