diff options
| author | Ludovic Courtès <ludo@gnu.org> | 2020-05-11 16:32:24 +0200 |
|---|---|---|
| committer | Ludovic Courtès <ludo@gnu.org> | 2020-05-14 17:21:27 +0200 |
| commit | fde2aec3f498d5ec6db2121d72068e2b203e86cd (patch) | |
| tree | d0d3c9b723c3e694ca107cff9315075e8267ebf4 | |
| parent | 80963744a242257921917df5a901dc343d3a93db (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.texi | 30 | ||||
| -rw-r--r-- | gnu/packages/aux-files/run-in-namespace.c | 78 | ||||
| -rw-r--r-- | tests/guix-pack-relocatable.sh | 17 |
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 |
| 5189 | PRoot support, can be thought of as the abbreviation of ``Really | 5189 | PRoot support, can be thought of as the abbreviation of ``Really |
| 5190 | Relocatable''. Neat, isn't it?}, relocatable binaries fall to back to PRoot | 5190 | Relocatable''. Neat, isn't it?}, relocatable binaries fall to back to |
| 5191 | if user namespaces are unavailable, and essentially work anywhere---see below | 5191 | other techniques if user namespaces are unavailable, and essentially |
| 5192 | for the implications. | 5192 | work anywhere---see below for the implications. |
| 5193 | 5193 | ||
| 5194 | For example, if you create a pack containing Bash with: | 5194 | For example, if you create a pack containing Bash with: |
| 5195 | 5195 | ||
| @@ -5221,14 +5221,32 @@ turn it off. | |||
| 5221 | 5221 | ||
| 5222 | To produce relocatable binaries that work even in the absence of user | 5222 | To produce relocatable binaries that work even in the absence of user |
| 5223 | namespaces, pass @option{--relocatable} or @option{-R} @emph{twice}. In that | 5223 | namespaces, pass @option{--relocatable} or @option{-R} @emph{twice}. In that |
| 5224 | case, binaries will try user namespace support and fall back to PRoot if user | 5224 | case, binaries will try user namespace support and fall back to another |
| 5225 | namespaces are not supported. | 5225 | @dfn{execution engine} if user namespaces are not supported. The |
| 5226 | following execution engines are supported: | ||
| 5226 | 5227 | ||
| 5227 | The @uref{https://proot-me.github.io/, PRoot} program provides the necessary | 5228 | @table @code |
| 5229 | @item default | ||
| 5230 | Try user namespaces and fall back to PRoot if user namespaces are not | ||
| 5231 | supported (see below). | ||
| 5232 | |||
| 5233 | @item userns | ||
| 5234 | Run the program through user namespaces and abort if they are not | ||
| 5235 | supported. | ||
| 5236 | |||
| 5237 | @item proot | ||
| 5238 | Run through PRoot. The @uref{https://proot-me.github.io/, PRoot} program | ||
| 5239 | provides the necessary | ||
| 5228 | support for file system virtualization. It achieves that by using the | 5240 | support 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 |
| 5230 | advantage to work without requiring special kernel support, but it incurs | 5242 | advantage to work without requiring special kernel support, but it incurs |
| 5231 | run-time overhead every time a system call is made. | 5243 | run-time overhead every time a system call is made. |
| 5244 | @end table | ||
| 5245 | |||
| 5246 | @vindex GUIX_EXECUTION_ENGINE | ||
| 5247 | When running a wrapped program, you can explicitly request one of the | ||
| 5248 | execution 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 | |||
| 342 | struct engine | ||
| 343 | { | ||
| 344 | const char *name; | ||
| 345 | void (* exec) (const char *, int, char **); | ||
| 346 | }; | ||
| 347 | |||
| 348 | static void | ||
| 349 | buffer_stderr (void) | ||
| 350 | { | ||
| 351 | static char stderr_buffer[4096]; | ||
| 352 | setvbuf (stderr, stderr_buffer, _IOFBF, sizeof stderr_buffer); | ||
| 353 | } | ||
| 354 | |||
| 355 | /* The default engine. */ | ||
| 356 | static void | ||
| 357 | exec_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. */ | ||
| 370 | static 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. */ | ||
| 381 | static const struct engine * | ||
| 382 | execution_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 | |||
| 340 | int | 405 | int |
| 341 | main (int argc, char *argv[]) | 406 | main (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, "\ |
| 375 | This may be because \"user namespaces\" are not supported on this system.\n\ | 436 | This may be because \"user namespaces\" are not supported on this system.\n\ |
| 376 | Consequently, we cannot run '@WRAPPED_PROGRAM@',\n\ | 437 | Consequently, we cannot run '@WRAPPED_PROGRAM@',\n\ |
| 377 | unless you move it to the '@STORE_DIRECTORY@' directory.\n\ | 438 | unless you move it to the '@STORE_DIRECTORY@' directory.\n\ |
| 378 | \n\ | 439 | \n\ |
| 379 | Please refer to the 'guix pack' documentation for more information.\n"); | 440 | Please 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 | |||
| 84 | grep 'GNU sed' "$test_directory/output" | 84 | grep 'GNU sed' "$test_directory/output" |
| 85 | chmod -Rf +w "$test_directory"; rm -rf "$test_directory"/* | 85 | chmod -Rf +w "$test_directory"; rm -rf "$test_directory"/* |
| 86 | 86 | ||
| 87 | case "`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 | ;; | ||
| 102 | esac | ||
| 103 | |||
| 87 | # Ensure '-R' works with outputs other than "out". | 104 | # Ensure '-R' works with outputs other than "out". |
| 88 | tarball="`guix pack -R -S /share=share groff:doc`" | 105 | tarball="`guix pack -R -S /share=share groff:doc`" |
| 89 | (cd "$test_directory"; tar xvf "$tarball") | 106 | (cd "$test_directory"; tar xvf "$tarball") |
