Re: [systemd-devel] Issues supporting systems with and without TPM and firmware TPM (was Re: Handle device node timeout?)
On Mon, Feb 19, 2024 at 11:37 AM Mikko Rapeli wrote: > > Hi, > > On Fri, Feb 16, 2024 at 11:28:31AM +0200, Mikko Rapeli wrote: > > Hi, > > > > Following up to my previous question which worked around with > > Wants: and After: to dev-tpmrm0.device and tee-supplicant@teepriv0.service, > > which don't seem to work fully. > > > > In short, I want to support devices with and without TPM. The TPM device > > can also be a firmware fTPM device which depends on tee-supplicant in > > userspace > > for RPMB storage. > > > > If TPM device is found, systemd repart in initramfs will create an > > encrypted rootfs > > and if not a plaintext ext4 partition. > > > > Support for TPM devices is ok and drivers are built into kernel. systemd > > repart config > > for rootfs is: > > > > [Partition] > > Type=root > > Weight=100 > > Format=ext4 > > Encrypt=tpm2 > > FactoryReset=yes > > MakeDirectories=/boot /usr /home /home/root > > # copying etc from build time /usr image > > CopyFiles=/usr/etc:/etc > > > > /usr partition generated at build time is dm-verity protected and contains > > /etc which is copied over to newly created rootfs. > > > > Support for fTPM devices is problematic. First, the kernel support must be > > modules > > but loading needs to be specially handled after starting tee-supplicant. > > For normal > > boot udev handles optee detection and triggers > > tee-supplicant@teepriv0.service > > startup which unloads tpm_ftpm_tee kernel module, starts tee-supplicant and > > then > > loads the kernel module again. After this RPMB works. To do the same in > > initramfs, I added > > Wants: and After: dependencies from systemd-repart.service, > > systemd-cryptsetup@.service, > > systemd-pcrmachine.service and systemd-pcrphase-initrd.service: > > > > After=dev-tpmrm0.device tee-supplicant@teepriv0.service > > Wants=dev-tpmrm0.device tee-supplicant@teepriv0.service > > I think my problems come from: > > After=tee-supplicant@teepriv0.service > Wants=tee-supplicant@teepriv0.service > > Basically tee-supplicant should only be started if /dev/teepriv* device node > is available. Then in my case with fTPM devices, all TPM using and encrypted > rootfs creating services need to depend on the service which starts > tee-supplicant > but only if /dev/teepriv0 exists. If teepriv0 doesn't exist, then > tee-supplicant > should not be started and the dependencies to it should not exist either. > The standard way to start a unit when a device becomes available is to set SYSTEMD_WANTS udev property for this device. > How should this dependency be expressed in systemd services? > > Can tee-supplicant@.service include: > > Before=systemd-pcrphase-initrd.service systemd-pcrphase.service > systemd-pcrmachine.service > WantedBy=systemd-pcrphase-initrd.service systemd-pcrphase.service > systemd-pcrmachine.service > If those service has to be started only if tee-supplicant is also started, this is backward. tee-supplicant@ needs to pull in these services, not another way round. > In my testing this does not seem to work inside initramfs. > > If systemd-pcrphase-initrd.service systemd-pcrphase.service and > systemd-pcrmachine.service > service have After= and Wants= to tee-supplicant@teepriv0.service then things > work, > except on boards which have no optee and no /dev/teepriv0 where > tee-supplicant seems > be started and fails due to missing optee which breaks the initramfs boot. > > Cheers, > > -Mikko > > > The base tee-supplicant@.service is: > > > > [Unit] > > Description=TEE Supplicant on %i > > # Needs to be started earlier > > DefaultDependencies=no > > Conflicts=shutdown.target initrd-switch-root.target > > Before=local-fs-pre.target cryptsetup-pre.target cryptsetup.target > > shutdown.target initrd-switch-root.target systemd-sysext.service > > Before=systemd-pcrphase-initrd.service systemd-pcrphase.service > > systemd-pcrmachine.service > > > > [Service] > > User=root > > EnvironmentFile=-@sysconfdir@/default/tee-supplicant > > ExecStartPre=-@sbindir@/modprobe -r tpm_ftpm_tee > > ExecStartPre=@sbindir@/create-tee-supplicant-env > > @localstatedir@/run/tee-supplicant.env > > ExecStart=/bin/sh -c "if [ -c /dev/teepriv0 ]; then > > @sbindir@/tee-supplicant $RPMB_CID $OPTARGS; fi" > > ExecStartPost=-/bin/sh -c "while [ ! $(pgrep tee-supplicant) ]; do sleep > > 0.1; done; /sbin/modprobe tpm_ftpm_tee" > > ExecStop=-/sbin/modprobe -r tpm_ftpm_tee > > > > [Install] > > # fTPM encrypted filesystems, needs to start in initrd stage > > WantedBy=local-fs-pre.target > > > > These seem to work for devices with and without TPM, but on devices with > > missing optee > > and /dev/teepriv0 not. The missing TPM device is detected after timeout, > > which is ok, > > and the fallback to unencrypted ext4 happens since systemd-repart.service > > has: > > > > ExecStart=/bin/sh -c "/usr/bin/test -c /dev/tpmrm0 && > > /usr/bin/systemd-repart --dry-run=no > > --definitions=${nonarch_libdir}/repart.d/ || /usr/bin/systemd-repart >
Re: [systemd-devel] Issues supporting systems with and without TPM and firmware TPM (was Re: Handle device node timeout?)
On Mo, 19.02.24 10:36, Mikko Rapeli (mikko.rap...@linaro.org) wrote: > > After=dev-tpmrm0.device tee-supplicant@teepriv0.service > > Wants=dev-tpmrm0.device tee-supplicant@teepriv0.service > > I think my problems come from: > > After=tee-supplicant@teepriv0.service > Wants=tee-supplicant@teepriv0.service > > Basically tee-supplicant should only be started if /dev/teepriv* device node > is available. Then in my case with fTPM devices, all TPM using and encrypted > rootfs creating services need to depend on the service which starts > tee-supplicant > but only if /dev/teepriv0 exists. If teepriv0 doesn't exist, then > tee-supplicant > should not be started and the dependencies to it should not exist > either. Is /dev/teepriv* guaranteed to be available when userspace is invoked? or is it something that itself requires some kmod loading to show up, i.e. that "udevadm trigger" causes to load? > How should this dependency be expressed in systemd services? > > Can tee-supplicant@.service include: > > Before=systemd-pcrphase-initrd.service systemd-pcrphase.service > systemd-pcrmachine.service > WantedBy=systemd-pcrphase-initrd.service systemd-pcrphase.service > systemd-pcrmachine.service > > In my testing this does not seem to work inside initramfs. > > If systemd-pcrphase-initrd.service systemd-pcrphase.service and > systemd-pcrmachine.service > service have After= and Wants= to tee-supplicant@teepriv0.service then things > work, > except on boards which have no optee and no /dev/teepriv0 where > tee-supplicant seems > be started and fails due to missing optee which breaks the initramfs boot. For your usecase the new tpm2.target available in git main is what you really should focus on: all TPM using services should order themselves after that. All stuff needed to make a TPM device appear should be placed before that. The systemd-tpm2-generator that now exists in git main analyzes the uefi/acpi firmware situation and automatically adds a dev-tpm0.device dependency on tpm2.target if it comes to the conclusion that such a device will show up. This generator is not going to cover your specific case, but I think it would be a good blueprint for you: i.e. write a generator that checks if /dev/teepriv* exists. If not, just exit. If yes, generate the required deps to pull in tee-supplicatnt@.service, and add the dev-tpmrm0.device dep just like systemd-tpm2-generator does. Lennart -- Lennart Poettering, Berlin
Re: [systemd-devel] Issues supporting systems with and without TPM and firmware TPM (was Re: Handle device node timeout?)
On Fr, 16.02.24 11:28, Mikko Rapeli (mikko.rap...@linaro.org) wrote: > Support for fTPM devices is problematic. First, the kernel support must be > modules > but loading needs to be specially handled after starting tee-supplicant. For > normal > boot udev handles optee detection and triggers tee-supplicant@teepriv0.service > startup which unloads tpm_ftpm_tee kernel module, starts tee-supplicant and > then > loads the kernel module again. After this RPMB works. To do the same in > initramfs, I added > Wants: and After: dependencies from systemd-repart.service, > systemd-cryptsetup@.service, > systemd-pcrmachine.service and systemd-pcrphase-initrd.service: Kernel module unloading is not supposed to happen in clean codepaths. It's a debug/development feature, it's not safe to do as part of regular boot. But why do you need an unload a kernel module at all? that smells... Lennart -- Lennart Poettering, Berlin
Re: [systemd-devel] Handle device node timeout?
On Di, 16.01.24 16:06, Mikko Rapeli (mikko.rap...@linaro.org) wrote: > Hi, > > I have services which depend on a specific device node. How can I run > some recovery actions when the default 90s timeout for finding this > device is hit? > > OnFailure= doesn't work as the service is not even started. > > Specifically the case is about supporting TPM2 encrypted rootfs but falling > back to plain-text rootfs generation if there is no TPM2 device. Currently > my initramfs works with TPM2 but without it fails with: In git main there's new infra to deal with this case: https://github.com/systemd/systemd/pull/30194 That should hopefully solve this systematically and generically. Lennart -- Lennart Poettering, Berlin
Re: [systemd-devel] Issues supporting systems with and without TPM and firmware TPM (was Re: Handle device node timeout?)
Hi, On Fri, Feb 16, 2024 at 11:28:31AM +0200, Mikko Rapeli wrote: > Hi, > > Following up to my previous question which worked around with > Wants: and After: to dev-tpmrm0.device and tee-supplicant@teepriv0.service, > which don't seem to work fully. > > In short, I want to support devices with and without TPM. The TPM device > can also be a firmware fTPM device which depends on tee-supplicant in > userspace > for RPMB storage. > > If TPM device is found, systemd repart in initramfs will create an encrypted > rootfs > and if not a plaintext ext4 partition. > > Support for TPM devices is ok and drivers are built into kernel. systemd > repart config > for rootfs is: > > [Partition] > Type=root > Weight=100 > Format=ext4 > Encrypt=tpm2 > FactoryReset=yes > MakeDirectories=/boot /usr /home /home/root > # copying etc from build time /usr image > CopyFiles=/usr/etc:/etc > > /usr partition generated at build time is dm-verity protected and contains > /etc which is copied over to newly created rootfs. > > Support for fTPM devices is problematic. First, the kernel support must be > modules > but loading needs to be specially handled after starting tee-supplicant. For > normal > boot udev handles optee detection and triggers tee-supplicant@teepriv0.service > startup which unloads tpm_ftpm_tee kernel module, starts tee-supplicant and > then > loads the kernel module again. After this RPMB works. To do the same in > initramfs, I added > Wants: and After: dependencies from systemd-repart.service, > systemd-cryptsetup@.service, > systemd-pcrmachine.service and systemd-pcrphase-initrd.service: > > After=dev-tpmrm0.device tee-supplicant@teepriv0.service > Wants=dev-tpmrm0.device tee-supplicant@teepriv0.service I think my problems come from: After=tee-supplicant@teepriv0.service Wants=tee-supplicant@teepriv0.service Basically tee-supplicant should only be started if /dev/teepriv* device node is available. Then in my case with fTPM devices, all TPM using and encrypted rootfs creating services need to depend on the service which starts tee-supplicant but only if /dev/teepriv0 exists. If teepriv0 doesn't exist, then tee-supplicant should not be started and the dependencies to it should not exist either. How should this dependency be expressed in systemd services? Can tee-supplicant@.service include: Before=systemd-pcrphase-initrd.service systemd-pcrphase.service systemd-pcrmachine.service WantedBy=systemd-pcrphase-initrd.service systemd-pcrphase.service systemd-pcrmachine.service In my testing this does not seem to work inside initramfs. If systemd-pcrphase-initrd.service systemd-pcrphase.service and systemd-pcrmachine.service service have After= and Wants= to tee-supplicant@teepriv0.service then things work, except on boards which have no optee and no /dev/teepriv0 where tee-supplicant seems be started and fails due to missing optee which breaks the initramfs boot. Cheers, -Mikko > The base tee-supplicant@.service is: > > [Unit] > Description=TEE Supplicant on %i > # Needs to be started earlier > DefaultDependencies=no > Conflicts=shutdown.target initrd-switch-root.target > Before=local-fs-pre.target cryptsetup-pre.target cryptsetup.target > shutdown.target initrd-switch-root.target systemd-sysext.service > Before=systemd-pcrphase-initrd.service systemd-pcrphase.service > systemd-pcrmachine.service > > [Service] > User=root > EnvironmentFile=-@sysconfdir@/default/tee-supplicant > ExecStartPre=-@sbindir@/modprobe -r tpm_ftpm_tee > ExecStartPre=@sbindir@/create-tee-supplicant-env > @localstatedir@/run/tee-supplicant.env > ExecStart=/bin/sh -c "if [ -c /dev/teepriv0 ]; then @sbindir@/tee-supplicant > $RPMB_CID $OPTARGS; fi" > ExecStartPost=-/bin/sh -c "while [ ! $(pgrep tee-supplicant) ]; do sleep 0.1; > done; /sbin/modprobe tpm_ftpm_tee" > ExecStop=-/sbin/modprobe -r tpm_ftpm_tee > > [Install] > # fTPM encrypted filesystems, needs to start in initrd stage > WantedBy=local-fs-pre.target > > These seem to work for devices with and without TPM, but on devices with > missing optee > and /dev/teepriv0 not. The missing TPM device is detected after timeout, > which is ok, > and the fallback to unencrypted ext4 happens since systemd-repart.service has: > > ExecStart=/bin/sh -c "/usr/bin/test -c /dev/tpmrm0 && /usr/bin/systemd-repart > --dry-run=no --definitions=${nonarch_libdir}/repart.d/ || > /usr/bin/systemd-repart --dry-run=no > --definitions=${nonarch_libdir}/repart.d_notpm/" > > But the missing optee and /dev/teepriv0 causes issues where > tee-supplicant@teepriv0.service gets > started in initramfs stage but since optee is not found from firmware > tee-supplicant exits with error. > > So what could be done better or correctly? > > The problematic part is to run these tee-supplicant and tpm_ftpm_tee loading > steps > only when /dev/teepriv0 is available and early enough for TPM2 dependencies > to work > for systemd. > > Should I rather setup a dedicated service for initramfs