From: Luca Boccassi Date: Tue, 3 Jan 2023 17:11:04 +0000 (+0100) Subject: creds: import 'vmm.notify_socket' and use it to set X-Git-Tag: v253-rc1~168^2~1 X-Git-Url: http://git.ipfire.org/gitweb.cgi?a=commitdiff_plain;h=4a91ace5bc737d552fa20444d99d1100d9c1f9f7;p=thirdparty%2Fsystemd.git creds: import 'vmm.notify_socket' and use it to set This is intended to be used with VSOCK, to notify the hypervisor/VMM, eg on the host: qemu <...> -smbios type=11,value=io.systemd.credential:vmm.notify_socket=vsock:2:1234 -device vhost-vsock-pci,id=vhost-vsock-pci0,guest-cid=42 (vsock:2:1234 -> send to host on vsock port 1234, default is to send to 0 which is the hypervisor itself) Also on the host: $ socat - VSOCK-LISTEN:1234,socktype=5 READY=1 STATUS=Ready. --- diff --git a/docs/CREDENTIALS.md b/docs/CREDENTIALS.md index 9e16dd3ba4f..debe0a714f4 100644 --- a/docs/CREDENTIALS.md +++ b/docs/CREDENTIALS.md @@ -330,6 +330,18 @@ systemd-run -p LoadCredential=mycred -P --wait systemd-creds cat mycred Various services shipped with `systemd` consume credentials for tweaking behaviour: +* [`systemd(1)`](https://www.freedesktop.org/software/systemd/man/systemd.html) + (I.E.: PID1, the system manager) will look for the credential `vmm.notify_socket` + and will use it to send a `READY=1` datagram when the system has finished + booting. This is useful for hypervisors/VMMs or other processes on the host + to receive a notification via VSOCK when a virtual machine has finished booting. + Note that in case the hypervisor does not support `SOCK_DGRAM` over `AF_VSOCK`, + `SOCK_SEQPACKET` will be tried instead. The credential payload should be in the + form: `vsock::`, where `` is optional and if omitted will + default to talking to the hypervisor (`0`). Also note that this requires + support for VHOST to be built-in both the guest and the host kernels, and the + kernel modules to be loaded. + * [`systemd-sysusers(8)`](https://www.freedesktop.org/software/systemd/man/systemd-sysusers.html) will look for the credentials `passwd.hashed-password.`, `passwd.plaintext-password.` and `passwd.shell.` to @@ -382,7 +394,8 @@ qemu-system-x86_64 \ ``` This boots the specified disk image via qemu, provisioning public key SSH access -for the root user from the caller's key: +for the root user from the caller's key, and sends a notification when booting +has finished to a process on the host: ``` qemu-system-x86_64 \ @@ -396,8 +409,18 @@ qemu-system-x86_64 \ -drive if=none,id=hd,file=test.raw,format=raw \ -device virtio-scsi-pci,id=scsi \ -device scsi-hd,drive=hd,bootindex=1 \ + -device vhost-vsock-pci,id=vhost-vsock-pci0,guest-cid=42 \ + -smbios type=11,value=io.systemd.credential:vmm.notify_socket=vsock:2:1234 \ -smbios type=11,value=io.systemd.credential.binary:tmpfiles.extra=$(echo "f~ /root/.ssh/authorized_keys 700 root root - $(ssh-add -L | base64 -w 0)" | base64 -w 0) ``` + +A process on the host can listen for the notification, for example: + +``` +$ socat - VSOCK-LISTEN:1234,socktype=5 +READY=1 +``` + ## Relevant Paths From *service* perspective the runtime path to find loaded credentials in is diff --git a/man/systemd.system-credentials.xml b/man/systemd.system-credentials.xml index 3eadf9b9852..2a87139a116 100644 --- a/man/systemd.system-credentials.xml +++ b/man/systemd.system-credentials.xml @@ -190,6 +190,24 @@ + + vmm.notify_socket + + This credential is parsed looking for an AF_VSOCK or + AF_UNIX address where to send a READY=1 + notification datagram when the system has finished booting. See: + sd_notify3 + This is useful for hypervisors/VMMs or other processes on the host + to receive a notification via VSOCK when a virtual machine has finished booting. + Note that in case the hypervisor does not support SOCK_DGRAM + over AF_VSOCK, SOCK_SEQPACKET will be + tried instead. The credential payload for AF_VSOCK should be + in the form: vsock:CID:PORT, where CID is + optional and if omitted will default to talking to the hypervisor + (0). + + + diff --git a/src/core/import-creds.c b/src/core/import-creds.c index 1f5a15f73b4..ade509be348 100644 --- a/src/core/import-creds.c +++ b/src/core/import-creds.c @@ -713,5 +713,18 @@ int import_credentials(void) { r = q; } + if (r >= 0) { + _cleanup_free_ char *address = NULL; + + r = read_credential("vmm.notify_socket", (void **)&address, /* ret_size= */ NULL); + if (r < 0 && !IN_SET(r, -ENOENT, -ENXIO)) + log_warning_errno(r, "Failed to read 'vmm.notify_socket' credential, ignoring: %m"); + else if (r >= 0 && !isempty(address)) { + r = setenv("NOTIFY_SOCKET", address, /* replace= */ 1); + if (r < 0) + log_warning_errno(errno, "Failed to set $NOTIFY_SOCKET environment variable, ignoring: %m"); + } + } + return r; }