diff options
author | Ludovic Courtès <ludo@gnu.org> | 2020-10-31 23:02:33 +0100 |
---|---|---|
committer | Ludovic Courtès <ludo@gnu.org> | 2020-10-31 23:16:43 +0100 |
commit | bfe82fe2f6e9f34c0774fe2114cdc7e937ba8bd2 (patch) | |
tree | 5140552cb16dc6a5eb611054a2b44023e259fdf6 /tests | |
parent | 95460da83b6ffd2bf3b96b3ab7cd302ab76be38a (diff) | |
download | guix-bfe82fe2f6e9f34c0774fe2114cdc7e937ba8bd2.tar.gz |
pack: Relocatable wrapper leaves root available to child processes.
Fixes <https://bugs.gnu.org/44261>. Reported by Jan Nieuwenhuizen <janneke@gnu.org>. * gnu/packages/aux-files/run-in-namespace.c (exec_in_user_namespace): Add call to 'prctl'. Call 'mount' for NEW_ROOT and define 'is_tmpfs'. When IS_TMPFS is true, call 'umount' and 'rmdir' after 'waitpid'; otherwise, call 'rm_rf' only when 'waitpid' returns -1 the second time. (exec_with_loader): Call 'prctl'. Remove NEW_ROOT only when 'waitpid' returns -1 the second time, otherwise leave it behind. * tests/guix-pack-relocatable.sh (wait_for_file): New function. Add test.
Diffstat (limited to 'tests')
-rw-r--r-- | tests/guix-pack-relocatable.sh | 73 |
1 files changed, 73 insertions, 0 deletions
diff --git a/tests/guix-pack-relocatable.sh b/tests/guix-pack-relocatable.sh index eb04231d16..2beb1b1eb6 100644 --- a/tests/guix-pack-relocatable.sh +++ b/tests/guix-pack-relocatable.sh @@ -59,6 +59,19 @@ run_without_store () fi } +# Wait for the given file to show up. Error out if it doesn't show up in a +# timely fashion. +wait_for_file () +{ + i=0 + while ! test -f "$1" && test $i -lt 20 + do + sleep 0.3 + i=`expr $i + 1` + done + test -f "$1" +} + test_directory="`mktemp -d`" export test_directory trap 'chmod -Rf +w "$test_directory"; rm -rf "$test_directory"' EXIT @@ -131,6 +144,66 @@ case "`uname -m`" in ;; esac +if unshare -r true +then + # Check what happens if the wrapped binary forks and leaves child + # processes behind, like a daemon. The root file system should remain + # available to those child processes. See <https://bugs.gnu.org/44261>. + cat > "$test_directory/manifest.scm" <<EOF +(use-modules (guix)) + +(define daemon + (program-file "daemon" + #~(begin + (use-modules (ice-9 match) + (ice-9 ftw)) + + (call-with-output-file "parent-store" + (lambda (port) + (write (scandir (ungexp (%store-prefix))) + port))) + + (match (primitive-fork) + (0 (sigaction SIGHUP (const #t)) + (call-with-output-file "pid" + (lambda (port) + (display (getpid) port))) + (pause) + (call-with-output-file "child-store" + (lambda (port) + (write (scandir (ungexp (%store-prefix))) + port)))) + (_ #t))))) + +(define package + (computed-file "package" + #~(let ((out (ungexp output))) + (mkdir out) + (mkdir (string-append out "/bin")) + (symlink (ungexp daemon) + (string-append out "/bin/daemon"))))) + +(manifest (list (manifest-entry + (name "daemon") + (version "0") + (item package)))) +EOF + + tarball="$(guix pack -S /bin=bin -R -m "$test_directory/manifest.scm")" + (cd "$test_directory"; tar xf "$tarball") + + # Run '/bin/daemon', which forks, then wait for the child, send it SIGHUP + # so that it dumps its view of the store, and make sure the child and + # parent both see the same store contents. + (cd "$test_directory"; run_without_store ./bin/daemon) + wait_for_file "$test_directory/pid" + kill -HUP $(cat "$test_directory/pid") + wait_for_file "$test_directory/child-store" + diff -u "$test_directory/parent-store" "$test_directory/child-store" + + chmod -Rf +w "$test_directory"; rm -rf "$test_directory"/* +fi + # Ensure '-R' works with outputs other than "out". tarball="`guix pack -R -S /share=share groff:doc`" (cd "$test_directory"; tar xf "$tarball") |