Commit 08f4fe20 authored by Arthur Gautier's avatar Arthur Gautier Committed by Raito Bezarius
Browse files

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: default avatarArthur Gautier <baloo@superbaloo.net>
Co-authored-by: default avatarRaito Bezarius <masterancpp@gmail.com>
parent 83b131bb
Loading
Loading
Loading
Loading
+25 −2
Original line number Diff line number Diff line
@@ -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"