summary refs log tree commit diff
diff options
context:
space:
mode:
authorArthur Gautier <baloo@superbaloo.net>2023-08-01 07:05:58 +0000
committerRaito Bezarius <masterancpp@gmail.com>2023-10-23 01:02:24 +0200
commit08f4fe20874ea19c55849138fb3af734cb72a5a1 (patch)
tree9a907d164cda443b1ff24eb7c935f2fdc4ed0474
parent83b131bb55bde0511a17d3beb52145d778dd4105 (diff)
downloadnixpkgs-08f4fe20874ea19c55849138fb3af734cb72a5a1.tar
nixpkgs-08f4fe20874ea19c55849138fb3af734cb72a5a1.tar.gz
nixpkgs-08f4fe20874ea19c55849138fb3af734cb72a5a1.tar.bz2
nixpkgs-08f4fe20874ea19c55849138fb3af734cb72a5a1.tar.lz
nixpkgs-08f4fe20874ea19c55849138fb3af734cb72a5a1.tar.xz
nixpkgs-08f4fe20874ea19c55849138fb3af734cb72a5a1.tar.zst
nixpkgs-08f4fe20874ea19c55849138fb3af734cb72a5a1.zip
qemu-vm: stop the swtpm once qemu stops
The idea is to run an async process waiting for swtpm
and we have to ensure that `FD_CLOEXEC` is cleared on this process'
stdin file descriptor, we use `fdflags` for this, a loadable builtin in
Bash ≥ 5.

The async process when exited will terminate `swtpm`, we bind the
termination of the async process to the termination of QEMU by virtue of
having `qemu` exec in that Bash script.

Signed-off-by: Arthur Gautier <baloo@superbaloo.net>
Co-authored-by: Raito Bezarius <masterancpp@gmail.com>
-rw-r--r--nixos/modules/virtualisation/qemu-vm.nix27
1 files changed, 25 insertions, 2 deletions
diff --git a/nixos/modules/virtualisation/qemu-vm.nix b/nixos/modules/virtualisation/qemu-vm.nix
index a1606839b6c..3bf8bbd9dab 100644
--- a/nixos/modules/virtualisation/qemu-vm.nix
+++ b/nixos/modules/virtualisation/qemu-vm.nix
@@ -204,8 +204,31 @@ let
         ${lib.getExe cfg.tpm.package} \
           socket \
           --tpmstate dir="$NIX_SWTPM_DIR" \
-          --ctrl type=unixio,path="$NIX_SWTPM_DIR"/socket \
-          "--tpm2" 1>"$NIX_SWTPM_DIR"/stdout 2>"$NIX_SWTPM_DIR"/stderr &
+          --ctrl type=unixio,path="$NIX_SWTPM_DIR"/socket,terminate \
+          --pid file="$NIX_SWTPM_DIR"/pid --daemon \
+          --tpm2 \
+          --log file="$NIX_SWTPM_DIR"/stdout,level=6
+
+        # Enable `fdflags` builtin in Bash
+        # We will need it to perform surgical modification of the file descriptor
+        # passed in the coprocess to remove `FD_CLOEXEC`, i.e. close the file descriptor
+        # on exec.
+        # If let alone, it will trigger the coprocess to read EOF when QEMU is `exec`
+        # at the end of this script. To work around that, we will just clear
+        # the `FD_CLOEXEC` bits as a first step.
+        enable -f ${hostPkgs.bash}/lib/bash/fdflags fdflags
+        # leave a dangling subprocess because the swtpm ctrl socket has
+        # "terminate" when the last connection disconnects, it stops swtpm.
+        # When qemu stops, or if the main shell process ends, the coproc will
+        # get signaled by virtue of the pipe between main and coproc ending.
+        # Which in turns triggers a socat connect-disconnect to swtpm which
+        # will stop it.
+        coproc waitingswtpm {
+          read || :
+          echo "" | ${lib.getExe hostPkgs.socat} STDIO UNIX-CONNECT:"$NIX_SWTPM_DIR"/socket
+        }
+        # Clear `FD_CLOEXEC` on the coprocess' file descriptor stdin.
+        fdflags -s-cloexec ''${waitingswtpm[1]}
       ''}
 
       cd "$TMPDIR"