Hello Ilias, hello Christian,
with commit ec80b4735a59 ("efi_loader: Implement FileLoad2 for initramfs loading") Ilias provided the possibility to specify a device path (CONFIG_EFI_INITRD_FILESPEC) from which an initial RAM disk can be served via the EFI_FILE_LOAD2_PROTOCOL.
Ard extended the Linux EFI stub to allow loading the initial RAM disk via the EFI_FILE_LOAD2_PROTOCOL with the utmost priority.
With commit ecc7fdaa9ef1 ("bootm: Add a bootm command for type IH_OS_EFI") Cristian enabled signed FIT images that contain a device tree and a UEFI binary (enabled by CONFIG_BOOTM_EFI=y).
In the DTE calls we have discussed that it is unfortunate that we do not have a method to validate initial RAM images in the UEFI context.
To me it would look like a good path forward to combine the two ideas:
* Let the signed FIT image (of type IH_OS_EFI) contain a RAM disk * Pass location and size to the UEFI subsystem and serve them via the EFI_FILE_LOAD2_PROTOCOL.
We could also extend the bootefi command to be callable as
bootefi $kernel_addr_r $ramdisk_addr_r:$filesize $fdt_addr_r
like the booti command to serve an initial RAM disk.
What are your thoughts?
Best regards
Heinrich
Le sam. 3 oct. 2020 à 10:51, Heinrich Schuchardt xypron.glpk@gmx.de a écrit :
Hello Ilias, hello Christian,
with commit ec80b4735a59 ("efi_loader: Implement FileLoad2 for initramfs
loading") Ilias provided the possibility to specify a device path
(CONFIG_EFI_INITRD_FILESPEC) from which an initial RAM disk can be
served via the EFI_FILE_LOAD2_PROTOCOL.
Ard extended the Linux EFI stub to allow loading the initial RAM disk
via the EFI_FILE_LOAD2_PROTOCOL with the utmost priority.
With commit ecc7fdaa9ef1 ("bootm: Add a bootm command for type
IH_OS_EFI") Cristian enabled signed FIT images that contain a device
tree and a UEFI binary (enabled by CONFIG_BOOTM_EFI=y).
In the DTE calls we have discussed that it is unfortunate that we do not
have a method to validate initial RAM images in the UEFI context.
To me it would look like a good path forward to combine the two ideas:
Let the signed FIT image (of type IH_OS_EFI) contain a RAM disk
Pass location and size to the UEFI subsystem and serve them via
the EFI_FILE_LOAD2_PROTOCOL.
We could also extend the bootefi command to be callable as
bootefi $kernel_addr_r $ramdisk_addr_r:$filesize $fdt_addr_r
like the booti command to serve an initial RAM disk.
What are your thoughts?
that looks super interesting. I propose something (in the latest desk preparing oct 14th) similar except the an efi application boots the FIT. I view UEFI as booting a PE coff and pass a set of config tables. Today we have DTB, we could just add Initrd (you command line). Bootefi would be responsible to valide the containing FIT before pushing initrd (and dTB?)into the table. It would be the responsibility of the efi stub to get the initrd from the config table (GUID to be defined).
Best regards
Heinrich
--
François-Frédéric Ozog | *Director Linaro Edge & Fog Computing Group* T: +33.67221.6485 francois.ozog@linaro.org | Skype: ffozog
Le sam. 3 oct. 2020 à 13:14, François Ozog francois.ozog@linaro.org a écrit :
Le sam. 3 oct. 2020 à 10:51, Heinrich Schuchardt xypron.glpk@gmx.de a écrit :
Hello Ilias, hello Christian,
with commit ec80b4735a59 ("efi_loader: Implement FileLoad2 for initramfs
loading") Ilias provided the possibility to specify a device path
(CONFIG_EFI_INITRD_FILESPEC) from which an initial RAM disk can be
served via the EFI_FILE_LOAD2_PROTOCOL.
Ard extended the Linux EFI stub to allow loading the initial RAM disk
via the EFI_FILE_LOAD2_PROTOCOL with the utmost priority.
With commit ecc7fdaa9ef1 ("bootm: Add a bootm command for type
IH_OS_EFI") Cristian enabled signed FIT images that contain a device
tree and a UEFI binary (enabled by CONFIG_BOOTM_EFI=y).
In the DTE calls we have discussed that it is unfortunate that we do not
have a method to validate initial RAM images in the UEFI context.
To me it would look like a good path forward to combine the two ideas:
Let the signed FIT image (of type IH_OS_EFI) contain a RAM disk
Pass location and size to the UEFI subsystem and serve them via
the EFI_FILE_LOAD2_PROTOCOL.
We could also extend the bootefi command to be callable as
bootefi $kernel_addr_r $ramdisk_addr_r:$filesize $fdt_addr_r
like the booti command to serve an initial RAM disk.
What are your thoughts?
that looks super interesting. I propose something (in the latest desk preparing oct 14th) similar except the an efi application boots the FIT. I view UEFI as booting a PE coff and pass a set of config tables. Today we have DTB, we could just add Initrd (you command line). Bootefi would be responsible to valide the containing FIT before pushing initrd (and dTB?)into the table. It would be the responsibility of the efi stub to get the initrd from the config table (GUID to be defined).
the memory attributes of the initrd config table should be such that it can be recovered for normal use. That may be tricky though.
Best regards
Heinrich
--
François-Frédéric Ozog | *Director Linaro Edge & Fog Computing Group* T: +33.67221.6485 francois.ozog@linaro.org | Skype: ffozog
--
François-Frédéric Ozog | *Director Linaro Edge & Fog Computing Group* T: +33.67221.6485 francois.ozog@linaro.org | Skype: ffozog
On Sat, 3 Oct 2020 at 13:16, François Ozog francois.ozog@linaro.org wrote:
Le sam. 3 oct. 2020 à 13:14, François Ozog francois.ozog@linaro.org a écrit :
Le sam. 3 oct. 2020 à 10:51, Heinrich Schuchardt xypron.glpk@gmx.de a écrit :
Hello Ilias, hello Christian,
with commit ec80b4735a59 ("efi_loader: Implement FileLoad2 for initramfs
loading") Ilias provided the possibility to specify a device path
(CONFIG_EFI_INITRD_FILESPEC) from which an initial RAM disk can be
served via the EFI_FILE_LOAD2_PROTOCOL.
Ard extended the Linux EFI stub to allow loading the initial RAM disk
via the EFI_FILE_LOAD2_PROTOCOL with the utmost priority.
With commit ecc7fdaa9ef1 ("bootm: Add a bootm command for type
IH_OS_EFI") Cristian enabled signed FIT images that contain a device
tree and a UEFI binary (enabled by CONFIG_BOOTM_EFI=y).
In the DTE calls we have discussed that it is unfortunate that we do not
have a method to validate initial RAM images in the UEFI context.
To me it would look like a good path forward to combine the two ideas:
Let the signed FIT image (of type IH_OS_EFI) contain a RAM disk
Pass location and size to the UEFI subsystem and serve them via
the EFI_FILE_LOAD2_PROTOCOL.
We could also extend the bootefi command to be callable as
bootefi $kernel_addr_r $ramdisk_addr_r:$filesize $fdt_addr_r
like the booti command to serve an initial RAM disk.
What are your thoughts?
that looks super interesting. I propose something (in the latest desk preparing oct 14th) similar except the an efi application boots the FIT. I view UEFI as booting a PE coff and pass a set of config tables. Today we have DTB, we could just add Initrd (you command line). Bootefi would be responsible to valide the containing FIT before pushing initrd (and dTB?)into the table. It would be the responsibility of the efi stub to get the initrd from the config table (GUID to be defined).
the memory attributes of the initrd config table should be such that it can be recovered for normal use. That may be tricky though.
The purpose of the EFI_FILE_LOAD2_PROTOCOL based initrd loading mechanism is to allow the EFI stub (which is tightly coupled to the kernel arch/version/etc) to allocate the memory for the initrd, and pass it into the LoadFile2() request, using whichever policy it wants to adhere to for alignment, offset and/or vicinity of the kernel image. It also ensures that any measurement performed by the bootloader for attestation or authentication can be delayed to the point where the booting kernel assumes ownership of the initrd contents, preventing potential TOCTOU issues where intermediate boot stages are involved (shim+grub etc)
Creating an initrd config table would mean that the bootloader decides where to load the initrd in memory, and only passes the address and size. This is exactly what we wanted to avoid, because now, the bootloader has to know all these different rules that vary between kernel version, configurations and architectures.
For uboot's implementation of FIT based EFI_FILE_LOAD2_PROTOCOL, this might mean that the initrd is loaded into memory first, and copied to another location (and [re-]authenticated) when LoadFile2() is invoked. I don't think this is a problem in the general case, but we might think about ways to avoid this if this turns out to be a problem for memory constrained devices with huge initrds.
On 10/3/20 3:12 PM, Ard Biesheuvel wrote:
On Sat, 3 Oct 2020 at 13:16, François Ozog <francois.ozog@linaro.org mailto:francois.ozog@linaro.org> wrote:
Le sam. 3 oct. 2020 à 13:14, François Ozog <francois.ozog@linaro.org <mailto:francois.ozog@linaro.org>> a écrit : Le sam. 3 oct. 2020 à 10:51, Heinrich Schuchardt <xypron.glpk@gmx.de <mailto:xypron.glpk@gmx.de>> a écrit : Hello Ilias, hello Christian, with commit ec80b4735a59 ("efi_loader: Implement FileLoad2 for initramfs loading") Ilias provided the possibility to specify a device path (CONFIG_EFI_INITRD_FILESPEC) from which an initial RAM disk can be served via the EFI_FILE_LOAD2_PROTOCOL. Ard extended the Linux EFI stub to allow loading the initial RAM disk via the EFI_FILE_LOAD2_PROTOCOL with the utmost priority. With commit ecc7fdaa9ef1 ("bootm: Add a bootm command for type IH_OS_EFI") Cristian enabled signed FIT images that contain a device tree and a UEFI binary (enabled by CONFIG_BOOTM_EFI=y). In the DTE calls we have discussed that it is unfortunate that we do not have a method to validate initial RAM images in the UEFI context. To me it would look like a good path forward to combine the two ideas: * Let the signed FIT image (of type IH_OS_EFI) contain a RAM disk * Pass location and size to the UEFI subsystem and serve them via the EFI_FILE_LOAD2_PROTOCOL. We could also extend the bootefi command to be callable as bootefi $kernel_addr_r $ramdisk_addr_r:$filesize $fdt_addr_r like the booti command to serve an initial RAM disk. What are your thoughts? that looks super interesting. I propose something (in the latest desk preparing oct 14th) similar except the an efi application boots the FIT. I view UEFI as booting a PE coff and pass a set of config tables. Today we have DTB, we could just add Initrd (you command line). Bootefi would be responsible to valide the containing FIT before pushing initrd (and dTB?)into the table. It would be the responsibility of the efi stub to get the initrd from the config table (GUID to be defined). the memory attributes of the initrd config table should be such that it can be recovered for normal use. That may be tricky though.
The purpose of the EFI_FILE_LOAD2_PROTOCOL based initrd loading mechanism is to allow the EFI stub (which is tightly coupled to the kernel arch/version/etc) to allocate the memory for the initrd, and pass it into the LoadFile2() request, using whichever policy it wants to adhere to for alignment, offset and/or vicinity of the kernel image. It also ensures that any measurement performed by the bootloader for attestation or authentication can be delayed to the point where the booting kernel assumes ownership of the initrd contents, preventing potential TOCTOU issues where intermediate boot stages are involved (shim+grub etc)
Any UEFI binary that you invoke can overwrite the complete system table and replace the existing UEFI API by its own implementation which may be malicious.
So the EFI_FILE_LOAD2_PROTOCOL does not provide any safety guarantees whatsoever.
Either you have a chain of trust or not. If you have a chain of trust, it is sufficient that user input, e.g. an initrd loaded from disk is verified once.
Creating an initrd config table would mean that the bootloader decides where to load the initrd in memory, and only passesthe address and size. This is exactly what we wanted to avoid, because now, the bootloader has to know all these different rules that vary between kernel version, configurations and architectures.
For uboot's implementation of FIT based EFI_FILE_LOAD2_PROTOCOL, this might mean that the initrd is loaded into memory first, and copied to another location (and [re-]authenticated) when LoadFile2() is invoked. I don't think this is a problem in the general case, but we might think about ways to avoid this if this turns out to be a problem for memory constrained devices with huge initrds.
Securitywise this all makes no difference. See above.
Best regards
Heinrich
On Sat, 3 Oct 2020 at 18:35, Heinrich Schuchardt xypron.glpk@gmx.de wrote:
On 10/3/20 3:12 PM, Ard Biesheuvel wrote:
On Sat, 3 Oct 2020 at 13:16, François Ozog <francois.ozog@linaro.org mailto:francois.ozog@linaro.org> wrote:
Le sam. 3 oct. 2020 à 13:14, François Ozog <francois.ozog@linaro.org <mailto:francois.ozog@linaro.org>> a écrit : Le sam. 3 oct. 2020 à 10:51, Heinrich Schuchardt <xypron.glpk@gmx.de <mailto:xypron.glpk@gmx.de>> a écrit : Hello Ilias, hello Christian, with commit ec80b4735a59 ("efi_loader: Implement FileLoad2 for initramfs loading") Ilias provided the possibility to specify a device path (CONFIG_EFI_INITRD_FILESPEC) from which an initial RAM disk can be served via the EFI_FILE_LOAD2_PROTOCOL. Ard extended the Linux EFI stub to allow loading the initial RAM disk via the EFI_FILE_LOAD2_PROTOCOL with the utmost priority. With commit ecc7fdaa9ef1 ("bootm: Add a bootm command for type IH_OS_EFI") Cristian enabled signed FIT images that contain a device tree and a UEFI binary (enabled by CONFIG_BOOTM_EFI=y). In the DTE calls we have discussed that it is unfortunate that we do not have a method to validate initial RAM images in the UEFI context. To me it would look like a good path forward to combine the two ideas: * Let the signed FIT image (of type IH_OS_EFI) contain a RAM disk * Pass location and size to the UEFI subsystem and serve them via the EFI_FILE_LOAD2_PROTOCOL. We could also extend the bootefi command to be callable as bootefi $kernel_addr_r $ramdisk_addr_r:$filesize $fdt_addr_r like the booti command to serve an initial RAM disk. What are your thoughts? that looks super interesting. I propose something (in the latest desk preparing oct 14th) similar except the an efi application boots the FIT. I view UEFI as booting a PE coff and pass a set of config tables. Today we have DTB, we could just add Initrd (you command line). Bootefi would be responsible to valide the containing FIT before pushing initrd (and dTB?)into the table. It would be the responsibility of the efi stub to get the initrd from the config table (GUID to be defined). the memory attributes of the initrd config table should be such that it can be recovered for normal use. That may be tricky though.
The purpose of the EFI_FILE_LOAD2_PROTOCOL based initrd loading mechanism is to allow the EFI stub (which is tightly coupled to the kernel arch/version/etc) to allocate the memory for the initrd, and pass it into the LoadFile2() request, using whichever policy it wants to adhere to for alignment, offset and/or vicinity of the kernel image. It also ensures that any measurement performed by the bootloader for attestation or authentication can be delayed to the point where the booting kernel assumes ownership of the initrd contents, preventing potential TOCTOU issues where intermediate boot stages are involved (shim+grub etc)
Any UEFI binary that you invoke can overwrite the complete system table and replace the existing UEFI API by its own implementation which may be malicious.
I don't see how this has anything to do with what I wrote above.
So the EFI_FILE_LOAD2_PROTOCOL does not provide any safety guarantees whatsoever.
Either you have a chain of trust or not. If you have a chain of trust, it is sufficient that user input, e.g. an initrd loaded from disk is verified once.
Creating an initrd config table would mean that the bootloader decides where to load the initrd in memory, and only passesthe address and size. This is exactly what we wanted to avoid, because now, the bootloader has to know all these different rules that vary between kernel version, configurations and architectures.
For uboot's implementation of FIT based EFI_FILE_LOAD2_PROTOCOL, this might mean that the initrd is loaded into memory first, and copied to another location (and [re-]authenticated) when LoadFile2() is invoked. I don't think this is a problem in the general case, but we might think about ways to avoid this if this turns out to be a problem for memory constrained devices with huge initrds.
Securitywise this all makes no difference. See above.
Yes it does. TPM based measured boot could be used for local attestation, e.g., to seal the rootfs encryption keys against the measurements of the boot stages. This is especially useful for initrds, given that they are created on the target, and so signing them would involve a secret key on the target as well.
Whether or not measured boot is being used is a platform policy, and so it is up to the firmware to take the measurement at the right time. Having a callback from the OS when it is ready to consume the initrd is a far better moment to take this measurement than some earlier time, e.g., before interactive boot loaders like GRUB or mokmanager can be invoked.
On Sat, Oct 03, 2020 at 03:12:30PM +0200, Ard Biesheuvel wrote:
On Sat, 3 Oct 2020 at 13:16, François Ozog francois.ozog@linaro.org wrote:
that looks super interesting.
[...]
I propose something (in the latest desk preparing oct 14th) similar except the an efi application boots the FIT. I view UEFI as booting a PE coff and pass a set of config tables. Today we have DTB, we could just add Initrd (you command line). Bootefi would be responsible to valide the containing FIT before pushing initrd (and dTB?)into the table. It would be the responsibility of the efi stub to get the initrd from the config table (GUID to be defined).
the memory attributes of the initrd config table should be such that it can be recovered for normal use. That may be tricky though.
The purpose of the EFI_FILE_LOAD2_PROTOCOL based initrd loading mechanism is to allow the EFI stub (which is tightly coupled to the kernel arch/version/etc) to allocate the memory for the initrd, and pass it into the LoadFile2() request, using whichever policy it wants to adhere to for alignment, offset and/or vicinity of the kernel image. It also ensures that any measurement performed by the bootloader for attestation or authentication can be delayed to the point where the booting kernel assumes ownership of the initrd contents, preventing potential TOCTOU issues where intermediate boot stages are involved (shim+grub etc)
Creating an initrd config table would mean that the bootloader decides where to load the initrd in memory, and only passes the address and size. This is exactly what we wanted to avoid, because now, the bootloader has to know all these different rules that vary between kernel version, configurations and architectures.
For uboot's implementation of FIT based EFI_FILE_LOAD2_PROTOCOL, this might mean that the initrd is loaded into memory first, and copied to another location (and [re-]authenticated) when LoadFile2() is invoked. I don't think this is a problem in the general case, but we might think about ways to avoid this if this turns out to be a problem for memory constrained devices with huge initrds.
+1 That sounds like the easiest and sanest path at the moment. I think that standardizing a Linux construct (initramfs) authentication from a firmware doesn't make too much sense. I haven't seen FIT images in detail (so shout if I am horribly wrong), but changing lib/efi_loader/efi_load_initrd.c to authenticate the FIT image and extract the initramfs for the kernel seems possible and it's close to what we do today.
Right now u-boot is reading a .config path to determine and load the file, something like <device> <partition> <file> i.e mmc 0:1 initrd.cpio.gz. Can't we just detect it's a FIT image that contains it, authenticate and extract it before passing it on?
Cheers /Ilias
The driving idea is that there is an existing bootflow, non UEFI that allows vmlinuz, initrd and DTB to be protected in a single FIT. The trustworthiness of the solution is higher that regular distro on pure UEFI systems but does not allow initrd changes as you install stuff. We need to keep in mind the use cases: most of the cases are for production devices where updates are not "calculated" in place but rather deployed with various means.
I'd like to define two EBBR boot flows: 1) typical distro (with its weakness) 2) typical embedded (as of today, addressing security and mix/match protection)
The 1) is described in slide 4 of the deck The 2) is described in slide 5.
The UEFI interface is still OS independent but comes with an additional opportunity: the ESP File System is "merged" with contents of a FIT (kind of overlayfs). This way the content of the FIT can be checked and EFIStub with EFI-LOAD_FILE2 the initrd. The bootXXXX will still indirectly point to the FIT contained .EFI application, the firmware DTB may be overwritten by a FIT DTB.
Is this a better scenario to establish 2)?
Cheers
FF
On Sat, 3 Oct 2020 at 15:12, Ard Biesheuvel ardb@kernel.org wrote:
On Sat, 3 Oct 2020 at 13:16, François Ozog francois.ozog@linaro.org wrote:
Le sam. 3 oct. 2020 à 13:14, François Ozog francois.ozog@linaro.org a écrit :
Le sam. 3 oct. 2020 à 10:51, Heinrich Schuchardt xypron.glpk@gmx.de a écrit :
Hello Ilias, hello Christian,
with commit ec80b4735a59 ("efi_loader: Implement FileLoad2 for initramfs
loading") Ilias provided the possibility to specify a device path
(CONFIG_EFI_INITRD_FILESPEC) from which an initial RAM disk can be
served via the EFI_FILE_LOAD2_PROTOCOL.
Ard extended the Linux EFI stub to allow loading the initial RAM disk
via the EFI_FILE_LOAD2_PROTOCOL with the utmost priority.
With commit ecc7fdaa9ef1 ("bootm: Add a bootm command for type
IH_OS_EFI") Cristian enabled signed FIT images that contain a device
tree and a UEFI binary (enabled by CONFIG_BOOTM_EFI=y).
In the DTE calls we have discussed that it is unfortunate that we do not
have a method to validate initial RAM images in the UEFI context.
To me it would look like a good path forward to combine the two ideas:
Let the signed FIT image (of type IH_OS_EFI) contain a RAM disk
Pass location and size to the UEFI subsystem and serve them via
the EFI_FILE_LOAD2_PROTOCOL.
We could also extend the bootefi command to be callable as
bootefi $kernel_addr_r $ramdisk_addr_r:$filesize $fdt_addr_r
like the booti command to serve an initial RAM disk.
What are your thoughts?
that looks super interesting. I propose something (in the latest desk preparing oct 14th) similar except the an efi application boots the FIT. I view UEFI as booting a PE coff and pass a set of config tables. Today we have DTB, we could just add Initrd (you command line). Bootefi would be responsible to valide the containing FIT before pushing initrd (and dTB?)into the table. It would be the responsibility of the efi stub to get the initrd from the config table (GUID to be defined).
the memory attributes of the initrd config table should be such that it can be recovered for normal use. That may be tricky though.
The purpose of the EFI_FILE_LOAD2_PROTOCOL based initrd loading mechanism is to allow the EFI stub (which is tightly coupled to the kernel arch/version/etc) to allocate the memory for the initrd, and pass it into the LoadFile2() request, using whichever policy it wants to adhere to for alignment, offset and/or vicinity of the kernel image. It also ensures that any measurement performed by the bootloader for attestation or authentication can be delayed to the point where the booting kernel assumes ownership of the initrd contents, preventing potential TOCTOU issues where intermediate boot stages are involved (shim+grub etc)
Creating an initrd config table would mean that the bootloader decides where to load the initrd in memory, and only passes the address and size. This is exactly what we wanted to avoid, because now, the bootloader has to know all these different rules that vary between kernel version, configurations and architectures.
For uboot's implementation of FIT based EFI_FILE_LOAD2_PROTOCOL, this might mean that the initrd is loaded into memory first, and copied to another location (and [re-]authenticated) when LoadFile2() is invoked. I don't think this is a problem in the general case, but we might think about ways to avoid this if this turns out to be a problem for memory constrained devices with huge initrds.
On Mon, Oct 05, 2020 at 04:12:11PM +0200, François Ozog wrote:
The driving idea is that there is an existing bootflow, non UEFI that allows vmlinuz, initrd and DTB to be protected in a single FIT. The trustworthiness of the solution is higher that regular distro on pure UEFI systems but does not allow initrd changes as you install stuff. We need to keep in mind the use cases: most of the cases are for production devices where updates are not "calculated" in place but rather deployed with various means.
I'd like to define two EBBR boot flows:
- typical distro (with its weakness)
- typical embedded (as of today, addressing security and mix/match
protection)
The 1) is described in slide 4 of the deck The 2) is described in slide 5.
It seems these discussion keeps looping back to out-of-band resources. If we have to keep referring to out-of-band resources to follow discussion can you ensure there is a link to said out-of-band resources when citing modifications to them.
It's frustrating to have to go rummaging through my mail archives to find your doc.
Daniel.
The UEFI interface is still OS independent but comes with an additional opportunity: the ESP File System is "merged" with contents of a FIT (kind of overlayfs). This way the content of the FIT can be checked and EFIStub with EFI-LOAD_FILE2 the initrd. The bootXXXX will still indirectly point to the FIT contained .EFI application, the firmware DTB may be overwritten by a FIT DTB.
Is this a better scenario to establish 2)?
Cheers
FF
On Sat, 3 Oct 2020 at 15:12, Ard Biesheuvel ardb@kernel.org wrote:
On Sat, 3 Oct 2020 at 13:16, François Ozog francois.ozog@linaro.org wrote:
Le sam. 3 oct. 2020 à 13:14, François Ozog francois.ozog@linaro.org a écrit :
Le sam. 3 oct. 2020 à 10:51, Heinrich Schuchardt xypron.glpk@gmx.de a écrit :
Hello Ilias, hello Christian,
with commit ec80b4735a59 ("efi_loader: Implement FileLoad2 for initramfs
loading") Ilias provided the possibility to specify a device path
(CONFIG_EFI_INITRD_FILESPEC) from which an initial RAM disk can be
served via the EFI_FILE_LOAD2_PROTOCOL.
Ard extended the Linux EFI stub to allow loading the initial RAM disk
via the EFI_FILE_LOAD2_PROTOCOL with the utmost priority.
With commit ecc7fdaa9ef1 ("bootm: Add a bootm command for type
IH_OS_EFI") Cristian enabled signed FIT images that contain a device
tree and a UEFI binary (enabled by CONFIG_BOOTM_EFI=y).
In the DTE calls we have discussed that it is unfortunate that we do not
have a method to validate initial RAM images in the UEFI context.
To me it would look like a good path forward to combine the two ideas:
Let the signed FIT image (of type IH_OS_EFI) contain a RAM disk
Pass location and size to the UEFI subsystem and serve them via
the EFI_FILE_LOAD2_PROTOCOL.
We could also extend the bootefi command to be callable as
bootefi $kernel_addr_r $ramdisk_addr_r:$filesize $fdt_addr_r
like the booti command to serve an initial RAM disk.
What are your thoughts?
that looks super interesting. I propose something (in the latest desk preparing oct 14th) similar except the an efi application boots the FIT. I view UEFI as booting a PE coff and pass a set of config tables. Today we have DTB, we could just add Initrd (you command line). Bootefi would be responsible to valide the containing FIT before pushing initrd (and dTB?)into the table. It would be the responsibility of the efi stub to get the initrd from the config table (GUID to be defined).
the memory attributes of the initrd config table should be such that it can be recovered for normal use. That may be tricky though.
The purpose of the EFI_FILE_LOAD2_PROTOCOL based initrd loading mechanism is to allow the EFI stub (which is tightly coupled to the kernel arch/version/etc) to allocate the memory for the initrd, and pass it into the LoadFile2() request, using whichever policy it wants to adhere to for alignment, offset and/or vicinity of the kernel image. It also ensures that any measurement performed by the bootloader for attestation or authentication can be delayed to the point where the booting kernel assumes ownership of the initrd contents, preventing potential TOCTOU issues where intermediate boot stages are involved (shim+grub etc)
Creating an initrd config table would mean that the bootloader decides where to load the initrd in memory, and only passes the address and size. This is exactly what we wanted to avoid, because now, the bootloader has to know all these different rules that vary between kernel version, configurations and architectures.
For uboot's implementation of FIT based EFI_FILE_LOAD2_PROTOCOL, this might mean that the initrd is loaded into memory first, and copied to another location (and [re-]authenticated) when LoadFile2() is invoked. I don't think this is a problem in the general case, but we might think about ways to avoid this if this turns out to be a problem for memory constrained devices with huge initrds.
-- François-Frédéric Ozog | *Director Linaro Edge & Fog Computing Group* T: +33.67221.6485 francois.ozog@linaro.org | Skype: ffozog _______________________________________________ boot-architecture mailing list boot-architecture@lists.linaro.org https://lists.linaro.org/mailman/listinfo/boot-architecture
On Mon, 5 Oct 2020 at 17:25, Daniel Thompson daniel.thompson@linaro.org wrote:
On Mon, Oct 05, 2020 at 04:12:11PM +0200, François Ozog wrote:
The driving idea is that there is an existing bootflow, non UEFI that allows vmlinuz, initrd and DTB to be protected in a single FIT. The trustworthiness of the solution is higher that regular distro on pure
UEFI
systems but does not allow initrd changes as you install stuff. We need
to
keep in mind the use cases: most of the cases are for production devices where updates are not "calculated" in place but rather deployed with various means.
I'd like to define two EBBR boot flows:
- typical distro (with its weakness)
- typical embedded (as of today, addressing security and mix/match
protection)
The 1) is described in slide 4 of the deck The 2) is described in slide 5.
It seems these discussion keeps looping back to out-of-band resources. If we have to keep referring to out-of-band resources to follow discussion can you ensure there is a link to said out-of-band resources when citing modifications to them.
here it is: https://docs.google.com/presentation/d/1JK00su6e7vt8lRfwSt2C9EuuzwcBHLyoLRRr...
It's frustrating to have to go rummaging through my mail archives to find your doc.
Daniel.
The UEFI interface is still OS independent but comes with an additional opportunity: the ESP File System is "merged" with contents of a FIT (kind of overlayfs). This way the content of the FIT can be checked and EFIStub with EFI-LOAD_FILE2 the initrd. The bootXXXX will still indirectly point
to
the FIT contained .EFI application, the firmware DTB may be overwritten
by
a FIT DTB.
Is this a better scenario to establish 2)?
Cheers
FF
On Sat, 3 Oct 2020 at 15:12, Ard Biesheuvel ardb@kernel.org wrote:
On Sat, 3 Oct 2020 at 13:16, François Ozog francois.ozog@linaro.org wrote:
Le sam. 3 oct. 2020 à 13:14, François Ozog francois.ozog@linaro.org
a
écrit :
Le sam. 3 oct. 2020 à 10:51, Heinrich Schuchardt xypron.glpk@gmx.de
a
écrit :
Hello Ilias, hello Christian,
with commit ec80b4735a59 ("efi_loader: Implement FileLoad2 for
initramfs
loading") Ilias provided the possibility to specify a device path
(CONFIG_EFI_INITRD_FILESPEC) from which an initial RAM disk can be
served via the EFI_FILE_LOAD2_PROTOCOL.
Ard extended the Linux EFI stub to allow loading the initial RAM
disk
via the EFI_FILE_LOAD2_PROTOCOL with the utmost priority.
With commit ecc7fdaa9ef1 ("bootm: Add a bootm command for type
IH_OS_EFI") Cristian enabled signed FIT images that contain a device
tree and a UEFI binary (enabled by CONFIG_BOOTM_EFI=y).
In the DTE calls we have discussed that it is unfortunate that we
do not
have a method to validate initial RAM images in the UEFI context.
To me it would look like a good path forward to combine the two
ideas:
Let the signed FIT image (of type IH_OS_EFI) contain a RAM disk
Pass location and size to the UEFI subsystem and serve them via
the EFI_FILE_LOAD2_PROTOCOL.
We could also extend the bootefi command to be callable as
bootefi $kernel_addr_r $ramdisk_addr_r:$filesize $fdt_addr_r
like the booti command to serve an initial RAM disk.
What are your thoughts?
that looks super interesting. I propose something (in the latest desk preparing oct 14th) similar except the an efi application boots the FIT. I view UEFI as booting a PE coff and pass a set of config tables.
Today
we have DTB, we could just add Initrd (you command line). Bootefi
would be
responsible to valide the containing FIT before pushing initrd (and dTB?)into the table. It would be the responsibility of the efi stub
to get
the initrd from the config table (GUID to be defined).
the memory attributes of the initrd config table should be such that
it
can be recovered for normal use. That may be tricky though.
The purpose of the EFI_FILE_LOAD2_PROTOCOL based initrd loading
mechanism
is to allow the EFI stub (which is tightly coupled to the kernel arch/version/etc) to allocate the memory for the initrd, and pass it
into
the LoadFile2() request, using whichever policy it wants to adhere to
for
alignment, offset and/or vicinity of the kernel image. It also ensures
that
any measurement performed by the bootloader for attestation or authentication can be delayed to the point where the booting kernel
assumes
ownership of the initrd contents, preventing potential TOCTOU issues
where
intermediate boot stages are involved (shim+grub etc)
Creating an initrd config table would mean that the bootloader decides where to load the initrd in memory, and only passes the address and
size.
This is exactly what we wanted to avoid, because now, the bootloader
has to
know all these different rules that vary between kernel version, configurations and architectures.
For uboot's implementation of FIT based EFI_FILE_LOAD2_PROTOCOL, this might mean that the initrd is loaded into memory first, and copied to another location (and [re-]authenticated) when LoadFile2() is invoked.
I
don't think this is a problem in the general case, but we might think
about
ways to avoid this if this turns out to be a problem for memory
constrained
devices with huge initrds.
-- François-Frédéric Ozog | *Director Linaro Edge & Fog Computing Group* T: +33.67221.6485 francois.ozog@linaro.org | Skype: ffozog _______________________________________________ boot-architecture mailing list boot-architecture@lists.linaro.org https://lists.linaro.org/mailman/listinfo/boot-architecture
Hello Heinrich,
On Sat, Oct 03, 2020 at 10:51:24AM +0200, Heinrich Schuchardt wrote:
Hello Ilias, hello Christian,
with commit ec80b4735a59 ("efi_loader: Implement FileLoad2 for initramfs loading") Ilias provided the possibility to specify a device path (CONFIG_EFI_INITRD_FILESPEC) from which an initial RAM disk can be served via the EFI_FILE_LOAD2_PROTOCOL.
Ard extended the Linux EFI stub to allow loading the initial RAM disk via the EFI_FILE_LOAD2_PROTOCOL with the utmost priority.
Thanks for sharing this information, I was not aware of the work related to the EFI_FILE_LOAD2_PROTOCOL, neither in the Linux kernel nor in U-Boot.
With commit ecc7fdaa9ef1 ("bootm: Add a bootm command for type IH_OS_EFI") Cristian enabled signed FIT images that contain a device tree and a UEFI binary (enabled by CONFIG_BOOTM_EFI=y).
In the DTE calls we have discussed that it is unfortunate that we do not have a method to validate initial RAM images in the UEFI context.
To me it would look like a good path forward to combine the two ideas:
- Let the signed FIT image (of type IH_OS_EFI) contain a RAM disk
- Pass location and size to the UEFI subsystem and serve them via the EFI_FILE_LOAD2_PROTOCOL.
We could also extend the bootefi command to be callable as
bootefi $kernel_addr_r $ramdisk_addr_r:$filesize $fdt_addr_r
like the booti command to serve an initial RAM disk.
What are your thoughts?
I think having initial RAM disk support in UEFI FIT images would be a great improvement.
For the moment I had to put on hold my experiments around bootefi and verified boot scenarios, but I will do my best to resume this work in the foreseeable future.
Best regards
Heinrich
Kind regards, Cristi
On 03/10/2020 09:51, Heinrich Schuchardt wrote:
Hello Ilias, hello Christian,
with commit ec80b4735a59 ("efi_loader: Implement FileLoad2 for initramfs loading") Ilias provided the possibility to specify a device path (CONFIG_EFI_INITRD_FILESPEC) from which an initial RAM disk can be served via the EFI_FILE_LOAD2_PROTOCOL.
Ard extended the Linux EFI stub to allow loading the initial RAM disk via the EFI_FILE_LOAD2_PROTOCOL with the utmost priority.
With commit ecc7fdaa9ef1 ("bootm: Add a bootm command for type IH_OS_EFI") Cristian enabled signed FIT images that contain a device tree and a UEFI binary (enabled by CONFIG_BOOTM_EFI=y).
In the DTE calls we have discussed that it is unfortunate that we do not have a method to validate initial RAM images in the UEFI context.
To me it would look like a good path forward to combine the two ideas:
- Let the signed FIT image (of type IH_OS_EFI) contain a RAM disk
- Pass location and size to the UEFI subsystem and serve them via the EFI_FILE_LOAD2_PROTOCOL.
We could also extend the bootefi command to be callable as
bootefi $kernel_addr_r $ramdisk_addr_r:$filesize $fdt_addr_r
like the booti command to serve an initial RAM disk.
What are your thoughts?
Hi Heinrich,
I've got concerns about this approach. Even though it uses the UEFI infrastructure, images deployed in this way are U-Boot specific and won't ever be applicable on EDK2 or other UEFI implementations.
However there is another way to approach it which I think Francois touched on. If instead a UEFI stub was added to the FIT image, in the same way that the kernel has a UEFI stub, then the logic of decoding the FIT and choosing the correct DTB & initrd can be part of the image and it becomes applicable to any UEFI implementation. It would also address Ard's concern of loading the FIT into memory, and then copying due to the EFI_FILE_LOAD2 path. The FIT stub would already know the image is in RAM, that is is reserved correctly, and just pass the correct addresses to the kernel as part of the normal boot flow.
Signing would also be taken care of because the whole FIT can be signed, and that signature would be checked when it gets loaded.
Thoughts?
g.
Am 6. Oktober 2020 00:37:58 MESZ schrieb Grant Likely grant.likely@arm.com:
On 03/10/2020 09:51, Heinrich Schuchardt wrote:
Hello Ilias, hello Christian,
with commit ec80b4735a59 ("efi_loader: Implement FileLoad2 for
initramfs
loading") Ilias provided the possibility to specify a device path (CONFIG_EFI_INITRD_FILESPEC) from which an initial RAM disk can be served via the EFI_FILE_LOAD2_PROTOCOL.
Ard extended the Linux EFI stub to allow loading the initial RAM disk via the EFI_FILE_LOAD2_PROTOCOL with the utmost priority.
With commit ecc7fdaa9ef1 ("bootm: Add a bootm command for type IH_OS_EFI") Cristian enabled signed FIT images that contain a device tree and a UEFI binary (enabled by CONFIG_BOOTM_EFI=y).
In the DTE calls we have discussed that it is unfortunate that we do
not
have a method to validate initial RAM images in the UEFI context.
To me it would look like a good path forward to combine the two
ideas:
- Let the signed FIT image (of type IH_OS_EFI) contain a RAM disk
- Pass location and size to the UEFI subsystem and serve them via the EFI_FILE_LOAD2_PROTOCOL.
We could also extend the bootefi command to be callable as
bootefi $kernel_addr_r $ramdisk_addr_r:$filesize $fdt_addr_r
like the booti command to serve an initial RAM disk.
What are your thoughts?
Hi Heinrich,
I've got concerns about this approach. Even though it uses the UEFI infrastructure, images deployed in this way are U-Boot specific and won't ever be applicable on EDK2 or other UEFI implementations.
However there is another way to approach it which I think Francois touched on. If instead a UEFI stub was added to the FIT image, in the same way that the kernel has a UEFI stub, then the logic of decoding the FIT and choosing the correct DTB & initrd can be part of the image and it becomes applicable to any UEFI implementation. It would also address
Ard's concern of loading the FIT into memory, and then copying due to the EFI_FILE_LOAD2 path. The FIT stub would already know the image is in RAM, that is is reserved correctly, and just pass the correct addresses
to the kernel as part of the normal boot flow.
Signing would also be taken care of because the whole FIT can be signed, and that signature would be checked when it gets loaded.
Thoughts?
The gain of a fit image in U-Boot used for calling the Linux kernel via the EFI stub vs calling the legacy entry point comes down to providing the EFI_RNG_PROTOCOL to be used for KASLR.
For initrd a stub UEFI binary will work. But if you want to provide a kernel specific dtb with the same stub binary it will require a new service for device-tree fixups.
Both approaches are on Francois' DTE slidedeck.
When thinking of security what really is unclear to me is how we can safely provide the decryption key for the root partition. Without such a means secure boot stops being secure once Linux starts the init process. I would assume that only the secure world can provide the key.
Best regards
Heinrich
On Tue, 6 Oct 2020 at 06:35, Heinrich Schuchardt xypron.glpk@gmx.de wrote:
Am 6. Oktober 2020 00:37:58 MESZ schrieb Grant Likely grant.likely@arm.com:
On 03/10/2020 09:51, Heinrich Schuchardt wrote:
Hello Ilias, hello Christian,
with commit ec80b4735a59 ("efi_loader: Implement FileLoad2 for
initramfs
loading") Ilias provided the possibility to specify a device path (CONFIG_EFI_INITRD_FILESPEC) from which an initial RAM disk can be served via the EFI_FILE_LOAD2_PROTOCOL.
Ard extended the Linux EFI stub to allow loading the initial RAM disk via the EFI_FILE_LOAD2_PROTOCOL with the utmost priority.
With commit ecc7fdaa9ef1 ("bootm: Add a bootm command for type IH_OS_EFI") Cristian enabled signed FIT images that contain a device tree and a UEFI binary (enabled by CONFIG_BOOTM_EFI=y).
In the DTE calls we have discussed that it is unfortunate that we do
not
have a method to validate initial RAM images in the UEFI context.
To me it would look like a good path forward to combine the two
ideas:
- Let the signed FIT image (of type IH_OS_EFI) contain a RAM disk
- Pass location and size to the UEFI subsystem and serve them via the EFI_FILE_LOAD2_PROTOCOL.
We could also extend the bootefi command to be callable as
bootefi $kernel_addr_r $ramdisk_addr_r:$filesize $fdt_addr_r
like the booti command to serve an initial RAM disk.
What are your thoughts?
Hi Heinrich,
I've got concerns about this approach. Even though it uses the UEFI infrastructure, images deployed in this way are U-Boot specific and won't ever be applicable on EDK2 or other UEFI implementations.
However there is another way to approach it which I think Francois touched on. If instead a UEFI stub was added to the FIT image, in the same way that the kernel has a UEFI stub, then the logic of decoding the FIT and choosing the correct DTB & initrd can be part of the image and it becomes applicable to any UEFI implementation. It would also address
Ard's concern of loading the FIT into memory, and then copying due to the EFI_FILE_LOAD2 path. The FIT stub would already know the image is in RAM, that is is reserved correctly, and just pass the correct addresses
to the kernel as part of the normal boot flow.
Signing would also be taken care of because the whole FIT can be signed, and that signature would be checked when it gets loaded.
Thoughts?
The gain of a fit image in U-Boot used for calling the Linux kernel via the EFI stub vs calling the legacy entry point comes down to providing the EFI_RNG_PROTOCOL to be used for KASLR.
For initrd a stub UEFI binary will work. But if you want to provide a kernel specific dtb with the same stub binary it will require a new service for device-tree fixups.
Both approaches are on Francois' DTE slidedeck.
When thinking of security what really is unclear to me is how we can safely provide the decryption key for the root partition. Without such a means secure boot stops being secure once Linux starts the init process. I would assume that only the secure world can provide the key.
Secure boot only deals with authentication, which does not require any secret keys.
Encrypted file systems are a completely separate matter. Typically, this is based on TPM-based local attestation, where the decryption key has been sealed into the TPM, and is only unsealed when all the boot components check out (based on their 'measurements' [aka hashes] that are cumulatively recorded in TPM hardware registers called PCRs)
In general, keeping secrets on a device is much more difficult than authenticating executable images, and typically involves some user provided secret, or h/w support. UEFI secure boot only reasons about authentication.
Le mar. 6 oct. 2020 à 09:21, Ard Biesheuvel ardb@kernel.org a écrit :
On Tue, 6 Oct 2020 at 06:35, Heinrich Schuchardt xypron.glpk@gmx.de wrote:
Am 6. Oktober 2020 00:37:58 MESZ schrieb Grant Likely <
grant.likely@arm.com>:
On 03/10/2020 09:51, Heinrich Schuchardt wrote:
Hello Ilias, hello Christian,
with commit ec80b4735a59 ("efi_loader: Implement FileLoad2 for
initramfs
loading") Ilias provided the possibility to specify a device path (CONFIG_EFI_INITRD_FILESPEC) from which an initial RAM disk can be served via the EFI_FILE_LOAD2_PROTOCOL.
Ard extended the Linux EFI stub to allow loading the initial RAM disk via the EFI_FILE_LOAD2_PROTOCOL with the utmost priority.
With commit ecc7fdaa9ef1 ("bootm: Add a bootm command for type IH_OS_EFI") Cristian enabled signed FIT images that contain a device tree and a UEFI binary (enabled by CONFIG_BOOTM_EFI=y).
In the DTE calls we have discussed that it is unfortunate that we do
not
have a method to validate initial RAM images in the UEFI context.
To me it would look like a good path forward to combine the two
ideas:
- Let the signed FIT image (of type IH_OS_EFI) contain a RAM disk
- Pass location and size to the UEFI subsystem and serve them via the EFI_FILE_LOAD2_PROTOCOL.
We could also extend the bootefi command to be callable as
bootefi $kernel_addr_r $ramdisk_addr_r:$filesize $fdt_addr_r
like the booti command to serve an initial RAM disk.
What are your thoughts?
Hi Heinrich,
I've got concerns about this approach. Even though it uses the UEFI infrastructure, images deployed in this way are U-Boot specific and won't ever be applicable on EDK2 or other UEFI implementations.
However there is another way to approach it which I think Francois touched on. If instead a UEFI stub was added to the FIT image, in the same way that the kernel has a UEFI stub, then the logic of decoding the FIT and choosing the correct DTB & initrd can be part of the image and it becomes applicable to any UEFI implementation. It would also address
Ard's concern of loading the FIT into memory, and then copying due to the EFI_FILE_LOAD2 path. The FIT stub would already know the image is in RAM, that is is reserved correctly, and just pass the correct addresses
to the kernel as part of the normal boot flow.
Signing would also be taken care of because the whole FIT can be signed, and that signature would be checked when it gets loaded.
Thoughts?
The gain of a fit image in U-Boot used for calling the Linux kernel via
the EFI stub vs calling the legacy entry point comes down to providing the EFI_RNG_PROTOCOL to be used for KASLR.
For initrd a stub UEFI binary will work. But if you want to provide a
kernel specific dtb with the same stub binary it will require a new service for device-tree fixups.
Both approaches are on Francois' DTE slidedeck.
When thinking of security what really is unclear to me is how we can
safely provide the decryption key for the root partition. Without such a means secure boot stops being secure once Linux starts the init process. I would assume that only the secure world can provide the key.
Secure boot only deals with authentication, which does not require any secret keys.
Encrypted file systems are a completely separate matter. Typically, this is based on TPM-based local attestation, where the decryption key has been sealed into the TPM, and is only unsealed when all the boot components check out (based on their 'measurements' [aka hashes] that are cumulatively recorded in TPM hardware registers called PCRs)
In general, keeping secrets on a device is much more difficult than authenticating executable images, and typically involves some user provided secret, or h/w support. UEFI secure boot only reasons about authentication.
If SecureBoot is involving Microsoft certificate, a US governmental agency could get its code signed and insert itself in a stealth mode (efi apps or drivers -> rootkit?)
If the set of keys must include this certificate , then to achieve SecureBoot you actually need the TPM to control what signed code you accept.
If the certificate can be omitted I would either sign the shim or add the sha256 of trustable ones.
The unsealing if keys for rootfs decryption is yet another capability that is offered by TPM to protect against different nature of attacks (conuterfeit products, confidentiality...)
--
François-Frédéric Ozog | *Director Linaro Edge & Fog Computing Group* T: +33.67221.6485 francois.ozog@linaro.org | Skype: ffozog
On Tue, 6 Oct 2020 at 10:00, François Ozog francois.ozog@linaro.org wrote:
Le mar. 6 oct. 2020 à 09:21, Ard Biesheuvel ardb@kernel.org a écrit :
On Tue, 6 Oct 2020 at 06:35, Heinrich Schuchardt xypron.glpk@gmx.de wrote:
Am 6. Oktober 2020 00:37:58 MESZ schrieb Grant Likely <
grant.likely@arm.com>:
On 03/10/2020 09:51, Heinrich Schuchardt wrote:
Hello Ilias, hello Christian,
with commit ec80b4735a59 ("efi_loader: Implement FileLoad2 for
initramfs
loading") Ilias provided the possibility to specify a device path (CONFIG_EFI_INITRD_FILESPEC) from which an initial RAM disk can be served via the EFI_FILE_LOAD2_PROTOCOL.
Ard extended the Linux EFI stub to allow loading the initial RAM disk via the EFI_FILE_LOAD2_PROTOCOL with the utmost priority.
With commit ecc7fdaa9ef1 ("bootm: Add a bootm command for type IH_OS_EFI") Cristian enabled signed FIT images that contain a device tree and a UEFI binary (enabled by CONFIG_BOOTM_EFI=y).
In the DTE calls we have discussed that it is unfortunate that we do
not
have a method to validate initial RAM images in the UEFI context.
To me it would look like a good path forward to combine the two
ideas:
- Let the signed FIT image (of type IH_OS_EFI) contain a RAM disk
- Pass location and size to the UEFI subsystem and serve them via the EFI_FILE_LOAD2_PROTOCOL.
We could also extend the bootefi command to be callable as
bootefi $kernel_addr_r $ramdisk_addr_r:$filesize $fdt_addr_r
like the booti command to serve an initial RAM disk.
What are your thoughts?
Hi Heinrich,
I've got concerns about this approach. Even though it uses the UEFI infrastructure, images deployed in this way are U-Boot specific and won't ever be applicable on EDK2 or other UEFI implementations.
However there is another way to approach it which I think Francois touched on. If instead a UEFI stub was added to the FIT image, in the same way that the kernel has a UEFI stub, then the logic of decoding the FIT and choosing the correct DTB & initrd can be part of the image and it becomes applicable to any UEFI implementation. It would also address
Ard's concern of loading the FIT into memory, and then copying due to the EFI_FILE_LOAD2 path. The FIT stub would already know the image is in RAM, that is is reserved correctly, and just pass the correct addresses
to the kernel as part of the normal boot flow.
Signing would also be taken care of because the whole FIT can be signed, and that signature would be checked when it gets loaded.
Thoughts?
The gain of a fit image in U-Boot used for calling the Linux kernel via
the EFI stub vs calling the legacy entry point comes down to providing the EFI_RNG_PROTOCOL to be used for KASLR.
For initrd a stub UEFI binary will work. But if you want to provide a
kernel specific dtb with the same stub binary it will require a new service for device-tree fixups.
Both approaches are on Francois' DTE slidedeck.
When thinking of security what really is unclear to me is how we can
safely provide the decryption key for the root partition. Without such a means secure boot stops being secure once Linux starts the init process. I would assume that only the secure world can provide the key.
Secure boot only deals with authentication, which does not require any secret keys.
Encrypted file systems are a completely separate matter. Typically, this is based on TPM-based local attestation, where the decryption key has been sealed into the TPM, and is only unsealed when all the boot components check out (based on their 'measurements' [aka hashes] that are cumulatively recorded in TPM hardware registers called PCRs)
In general, keeping secrets on a device is much more difficult than authenticating executable images, and typically involves some user provided secret, or h/w support. UEFI secure boot only reasons about authentication.
If SecureBoot is involving Microsoft certificate, a US governmental agency could get its code signed and insert itself in a stealth mode (efi apps or drivers -> rootkit?)
If the set of keys must include this certificate , then to achieve SecureBoot you actually need the TPM to control what signed code you accept.
I am sorry, but this makes no sense at all. Either you trust the MS certificate or you don't - if you don't, then you cannot rely on the TPM either, as you are relying on the boot chain not to lie about the measurements it sends to the TPM. IOW, you can trick the TPM into releasing its secrets by sending the 'correct' values that it expects, rather than measurements that were taken from the actual boot stages.
If the certificate can be omitted I would either sign the shim or add the
sha256 of trustable ones.
The unsealing if keys for rootfs decryption is yet another capability that is offered by TPM to protect against different nature of attacks (conuterfeit products, confidentiality...)
--
François-Frédéric Ozog | *Director Linaro Edge & Fog Computing Group* T: +33.67221.6485 francois.ozog@linaro.org | Skype: ffozog
On Tue, 6 Oct 2020 at 10:06, Ard Biesheuvel ardb@kernel.org wrote:
On Tue, 6 Oct 2020 at 10:00, François Ozog francois.ozog@linaro.org wrote:
Le mar. 6 oct. 2020 à 09:21, Ard Biesheuvel ardb@kernel.org a écrit :
On Tue, 6 Oct 2020 at 06:35, Heinrich Schuchardt xypron.glpk@gmx.de wrote:
Am 6. Oktober 2020 00:37:58 MESZ schrieb Grant Likely <
grant.likely@arm.com>:
On 03/10/2020 09:51, Heinrich Schuchardt wrote:
Hello Ilias, hello Christian,
with commit ec80b4735a59 ("efi_loader: Implement FileLoad2 for
initramfs
loading") Ilias provided the possibility to specify a device path (CONFIG_EFI_INITRD_FILESPEC) from which an initial RAM disk can be served via the EFI_FILE_LOAD2_PROTOCOL.
Ard extended the Linux EFI stub to allow loading the initial RAM
disk
via the EFI_FILE_LOAD2_PROTOCOL with the utmost priority.
With commit ecc7fdaa9ef1 ("bootm: Add a bootm command for type IH_OS_EFI") Cristian enabled signed FIT images that contain a device tree and a UEFI binary (enabled by CONFIG_BOOTM_EFI=y).
In the DTE calls we have discussed that it is unfortunate that we do
not
have a method to validate initial RAM images in the UEFI context.
To me it would look like a good path forward to combine the two
ideas:
- Let the signed FIT image (of type IH_OS_EFI) contain a RAM disk
- Pass location and size to the UEFI subsystem and serve them via the EFI_FILE_LOAD2_PROTOCOL.
We could also extend the bootefi command to be callable as
bootefi $kernel_addr_r $ramdisk_addr_r:$filesize $fdt_addr_r
like the booti command to serve an initial RAM disk.
What are your thoughts?
Hi Heinrich,
I've got concerns about this approach. Even though it uses the UEFI infrastructure, images deployed in this way are U-Boot specific and won't ever be applicable on EDK2 or other UEFI implementations.
However there is another way to approach it which I think Francois touched on. If instead a UEFI stub was added to the FIT image, in the same way that the kernel has a UEFI stub, then the logic of decoding the FIT and choosing the correct DTB & initrd can be part of the image and it becomes applicable to any UEFI implementation. It would also
address
Ard's concern of loading the FIT into memory, and then copying due to the EFI_FILE_LOAD2 path. The FIT stub would already know the image is in RAM, that is is reserved correctly, and just pass the correct
addresses
to the kernel as part of the normal boot flow.
Signing would also be taken care of because the whole FIT can be signed, and that signature would be checked when it gets loaded.
Thoughts?
The gain of a fit image in U-Boot used for calling the Linux kernel
via the EFI stub vs calling the legacy entry point comes down to providing the EFI_RNG_PROTOCOL to be used for KASLR.
For initrd a stub UEFI binary will work. But if you want to provide a
kernel specific dtb with the same stub binary it will require a new service for device-tree fixups.
Both approaches are on Francois' DTE slidedeck.
When thinking of security what really is unclear to me is how we can
safely provide the decryption key for the root partition. Without such a means secure boot stops being secure once Linux starts the init process. I would assume that only the secure world can provide the key.
Secure boot only deals with authentication, which does not require any secret keys.
Encrypted file systems are a completely separate matter. Typically, this is based on TPM-based local attestation, where the decryption key has been sealed into the TPM, and is only unsealed when all the boot components check out (based on their 'measurements' [aka hashes] that are cumulatively recorded in TPM hardware registers called PCRs)
In general, keeping secrets on a device is much more difficult than authenticating executable images, and typically involves some user provided secret, or h/w support. UEFI secure boot only reasons about authentication.
If SecureBoot is involving Microsoft certificate, a US governmental agency could get its code signed and insert itself in a stealth mode (efi apps or drivers -> rootkit?)
If the set of keys must include this certificate , then to achieve SecureBoot you actually need the TPM to control what signed code you accept.
I am sorry, but this makes no sense at all. Either you trust the MS certificate or you don't -
I trust the certificate technology but I may not trust the signature process at Microsoft: as a consumer I am fine with it, if I were a French nuclear plant security officer, I wouldn't trust the MS certification process (because NSA can get Microsoft to sign a piece of code I don't want). So trustworthiness or trustworthiness target levels should be defined (an effort is below and was presented at DTE call)
if you don't, then you cannot rely on the TPM either, as you are relying on the boot chain not to lie about the measurements it sends to the TPM. IOW, you can trick the TPM into releasing its secrets by sending the 'correct' values that it expects, rather than measurements that were taken from the actual boot stages.
Indeed. And I think there are countermeasures. In the same spirit, there are hardware attacks: Riscure proved SecureBoot can be defeated by injecting 12V on a USB port of a platform: the pseudo code "if <signature_verified> then <continue_secure_boot> else <stop_boot_with_alert>" went on <continue_secure_boot> while signature was bad.
From the above, and based on Arm defined certification levels, I
postulate that there are three classes of "trustworthiness target levels": PSA level 1: limited security requirements, self certification PSA level 2: software attacks (local or remote) resilience, lab certified PSA level 3: hardware attacks resilience
In this context, it may be defined that: - a PSA level 2 with basic trustworthiness target level is OK with trusting the Msft process of certification (basically that is all datacenter, home computing world) - a PSA level 3 with high end trustworthiness target level is not OK with Msft certificate, will require TPM with mitigation of evasion techniques you mention, provide counter measures (hardware or software) to ensure guaranteed behavior in key decisions such as "if <signature_verified>", have non repudiable auditability of events, and a continuous assessment of measured boot in RAM (this was proposed by OpenFog group - probably by Arm BTW - while not digging in how this could actually be done).
At the end of the day, trustworthiness target level is about matching the use case with costs and complexity of management.
There will be thus many trustworthiness target levels. we should define them and their implications on technologies, processes (OTA...) and software design patterns (mitigation of hardware attacks when hardware mitigation is not available). And it may be possible that the high end trustworthiness levels will never be open source. In any case we shall define them and state what can be expected from the technologies we build so that product vendors can characterize the trustworthiness level of their products.
If the certificate can be omitted I would either sign the shim or add the
sha256 of trustable ones.
The unsealing if keys for rootfs decryption is yet another capability that is offered by TPM to protect against different nature of attacks (conuterfeit products, confidentiality...)
--
François-Frédéric Ozog | *Director Linaro Edge & Fog Computing Group* T: +33.67221.6485 francois.ozog@linaro.org | Skype: ffozog
On Tue, 6 Oct 2020 at 12:13, François Ozog francois.ozog@linaro.org wrote:
On Tue, 6 Oct 2020 at 10:06, Ard Biesheuvel ardb@kernel.org wrote:
On Tue, 6 Oct 2020 at 10:00, François Ozog francois.ozog@linaro.org wrote:
Le mar. 6 oct. 2020 à 09:21, Ard Biesheuvel ardb@kernel.org a écrit :
On Tue, 6 Oct 2020 at 06:35, Heinrich Schuchardt xypron.glpk@gmx.de wrote:
Am 6. Oktober 2020 00:37:58 MESZ schrieb Grant Likely <
grant.likely@arm.com>:
On 03/10/2020 09:51, Heinrich Schuchardt wrote: > Hello Ilias, hello Christian, > > with commit ec80b4735a59 ("efi_loader: Implement FileLoad2 for initramfs > loading") Ilias provided the possibility to specify a device path > (CONFIG_EFI_INITRD_FILESPEC) from which an initial RAM disk can be > served via the EFI_FILE_LOAD2_PROTOCOL. > > Ard extended the Linux EFI stub to allow loading the initial RAM
disk
> via the EFI_FILE_LOAD2_PROTOCOL with the utmost priority. > > With commit ecc7fdaa9ef1 ("bootm: Add a bootm command for type > IH_OS_EFI") Cristian enabled signed FIT images that contain a
device
> tree and a UEFI binary (enabled by CONFIG_BOOTM_EFI=y). > > In the DTE calls we have discussed that it is unfortunate that we
do
not > have a method to validate initial RAM images in the UEFI context. > > To me it would look like a good path forward to combine the two ideas: > > * Let the signed FIT image (of type IH_OS_EFI) contain a RAM disk > * Pass location and size to the UEFI subsystem and serve them via > the EFI_FILE_LOAD2_PROTOCOL. > > We could also extend the bootefi command to be callable as > > bootefi $kernel_addr_r $ramdisk_addr_r:$filesize $fdt_addr_r > > like the booti command to serve an initial RAM disk. > > What are your thoughts?
Hi Heinrich,
I've got concerns about this approach. Even though it uses the UEFI infrastructure, images deployed in this way are U-Boot specific and won't ever be applicable on EDK2 or other UEFI implementations.
However there is another way to approach it which I think Francois touched on. If instead a UEFI stub was added to the FIT image, in the same way that the kernel has a UEFI stub, then the logic of decoding the FIT and choosing the correct DTB & initrd can be part of the image
and
it becomes applicable to any UEFI implementation. It would also
address
Ard's concern of loading the FIT into memory, and then copying due to the EFI_FILE_LOAD2 path. The FIT stub would already know the image is in RAM, that is is reserved correctly, and just pass the correct
addresses
to the kernel as part of the normal boot flow.
Signing would also be taken care of because the whole FIT can be signed, and that signature would be checked when it gets loaded.
Thoughts?
The gain of a fit image in U-Boot used for calling the Linux kernel
via the EFI stub vs calling the legacy entry point comes down to providing the EFI_RNG_PROTOCOL to be used for KASLR.
For initrd a stub UEFI binary will work. But if you want to provide a
kernel specific dtb with the same stub binary it will require a new service for device-tree fixups.
Both approaches are on Francois' DTE slidedeck.
When thinking of security what really is unclear to me is how we can
safely provide the decryption key for the root partition. Without such a means secure boot stops being secure once Linux starts the init process. I would assume that only the secure world can provide the key.
Secure boot only deals with authentication, which does not require any secret keys.
Encrypted file systems are a completely separate matter. Typically, this is based on TPM-based local attestation, where the decryption key has been sealed into the TPM, and is only unsealed when all the boot components check out (based on their 'measurements' [aka hashes] that are cumulatively recorded in TPM hardware registers called PCRs)
In general, keeping secrets on a device is much more difficult than authenticating executable images, and typically involves some user provided secret, or h/w support. UEFI secure boot only reasons about authentication.
If SecureBoot is involving Microsoft certificate, a US governmental agency could get its code signed and insert itself in a stealth mode (efi apps or drivers -> rootkit?)
If the set of keys must include this certificate , then to achieve SecureBoot you actually need the TPM to control what signed code you accept.
I am sorry, but this makes no sense at all. Either you trust the MS certificate or you don't -
I trust the certificate technology but I may not trust the signature process at Microsoft: as a consumer I am fine with it, if I were a French nuclear plant security officer, I wouldn't trust the MS certification process (because NSA can get Microsoft to sign a piece of code I don't want). So trustworthiness or trustworthiness target levels should be defined (an effort is below and was presented at DTE call)
This is policy, and belongs in a different discussion.
I have been arguing since 2013 that there is no reason for the ARM ecosystem at large to put all their eggs in the MS basket, but the distros and the rest of the industry prefer ease of deployment over actual security. IOW, happy to debate this, but not in this email thread :-)
if you don't, then you cannot rely on the TPM either, as you are relying
on the boot chain not to lie about the measurements it sends to the TPM. IOW, you can trick the TPM into releasing its secrets by sending the 'correct' values that it expects, rather than measurements that were taken from the actual boot stages.
Indeed. And I think there are countermeasures. In the same spirit, there are hardware attacks: Riscure proved SecureBoot can be defeated by injecting 12V on a USB port of a platform: the pseudo code "if <signature_verified> then <continue_secure_boot> else <stop_boot_with_alert>" went on <continue_secure_boot> while signature was bad.
Whether this is relevant or not in a particular case depends on the threats that you are trying to defend against. Again, interesting topic, but not relevant for the discussion.
Could we please refocus the discussion on *authenticated* boot using FIT images, i.e., no encrypted root file systems, no opinions as to whether the certs in the KEK are trustworthy, and no detours into hardware that can be made to operate out of spec from the outside.
On Tue, Oct 06, 2020 at 10:00:40AM +0200, François Ozog wrote:
Le mar. 6 oct. 2020 à 09:21, Ard Biesheuvel ardb@kernel.org a écrit :
On Tue, 6 Oct 2020 at 06:35, Heinrich Schuchardt xypron.glpk@gmx.de wrote:
Am 6. Oktober 2020 00:37:58 MESZ schrieb Grant Likely <
grant.likely@arm.com>:
On 03/10/2020 09:51, Heinrich Schuchardt wrote:
Hello Ilias, hello Christian,
with commit ec80b4735a59 ("efi_loader: Implement FileLoad2 for
initramfs
loading") Ilias provided the possibility to specify a device path (CONFIG_EFI_INITRD_FILESPEC) from which an initial RAM disk can be served via the EFI_FILE_LOAD2_PROTOCOL.
Ard extended the Linux EFI stub to allow loading the initial RAM disk via the EFI_FILE_LOAD2_PROTOCOL with the utmost priority.
With commit ecc7fdaa9ef1 ("bootm: Add a bootm command for type IH_OS_EFI") Cristian enabled signed FIT images that contain a device tree and a UEFI binary (enabled by CONFIG_BOOTM_EFI=y).
In the DTE calls we have discussed that it is unfortunate that we do
not
have a method to validate initial RAM images in the UEFI context.
To me it would look like a good path forward to combine the two
ideas:
- Let the signed FIT image (of type IH_OS_EFI) contain a RAM disk
- Pass location and size to the UEFI subsystem and serve them via the EFI_FILE_LOAD2_PROTOCOL.
We could also extend the bootefi command to be callable as
bootefi $kernel_addr_r $ramdisk_addr_r:$filesize $fdt_addr_r
like the booti command to serve an initial RAM disk.
What are your thoughts?
Hi Heinrich,
I've got concerns about this approach. Even though it uses the UEFI infrastructure, images deployed in this way are U-Boot specific and won't ever be applicable on EDK2 or other UEFI implementations.
However there is another way to approach it which I think Francois touched on. If instead a UEFI stub was added to the FIT image, in the same way that the kernel has a UEFI stub, then the logic of decoding the FIT and choosing the correct DTB & initrd can be part of the image and it becomes applicable to any UEFI implementation. It would also address
Ard's concern of loading the FIT into memory, and then copying due to the EFI_FILE_LOAD2 path. The FIT stub would already know the image is in RAM, that is is reserved correctly, and just pass the correct addresses
to the kernel as part of the normal boot flow.
Signing would also be taken care of because the whole FIT can be signed, and that signature would be checked when it gets loaded.
Thoughts?
The gain of a fit image in U-Boot used for calling the Linux kernel via
the EFI stub vs calling the legacy entry point comes down to providing the EFI_RNG_PROTOCOL to be used for KASLR.
For initrd a stub UEFI binary will work. But if you want to provide a
kernel specific dtb with the same stub binary it will require a new service for device-tree fixups.
Both approaches are on Francois' DTE slidedeck.
When thinking of security what really is unclear to me is how we can
safely provide the decryption key for the root partition. Without such a means secure boot stops being secure once Linux starts the init process. I would assume that only the secure world can provide the key.
Secure boot only deals with authentication, which does not require any secret keys.
Encrypted file systems are a completely separate matter. Typically, this is based on TPM-based local attestation, where the decryption key has been sealed into the TPM, and is only unsealed when all the boot components check out (based on their 'measurements' [aka hashes] that are cumulatively recorded in TPM hardware registers called PCRs)
In general, keeping secrets on a device is much more difficult than authenticating executable images, and typically involves some user provided secret, or h/w support. UEFI secure boot only reasons about authentication.
If SecureBoot is involving Microsoft certificate, a US governmental agency could get its code signed and insert itself in a stealth mode (efi apps or drivers -> rootkit?)
It is possible that user customizable systems (EBBR booting something like a normal distro) might choose to ship with Microsoft certificates. However in the general case there is no good reason to ship a fully integrated embedded product (e.g. not user modifiable) that trusts the MS certificate.
If the set of keys must include this certificate , then to achieve SecureBoot you actually need the TPM to control what signed code you accept.
I don't quite follow here.
Why does choosing to trust MS reqiure a second signature. Surely either we do trust MS or we don't enroll the cert. Why is there a third way here?
Daniel.
If the certificate can be omitted I would either sign the shim or add the sha256 of trustable ones.
The unsealing if keys for rootfs decryption is yet another capability that is offered by TPM to protect against different nature of attacks (conuterfeit products, confidentiality...)
--
François-Frédéric Ozog | *Director Linaro Edge & Fog Computing Group* T: +33.67221.6485 francois.ozog@linaro.org | Skype: ffozog _______________________________________________ boot-architecture mailing list boot-architecture@lists.linaro.org https://lists.linaro.org/mailman/listinfo/boot-architecture
On 06/10/2020 05:35, Heinrich Schuchardt wrote:
Am 6. Oktober 2020 00:37:58 MESZ schrieb Grant Likely grant.likely@arm.com:
On 03/10/2020 09:51, Heinrich Schuchardt wrote:
Hello Ilias, hello Christian,
with commit ec80b4735a59 ("efi_loader: Implement FileLoad2 for
initramfs
loading") Ilias provided the possibility to specify a device path (CONFIG_EFI_INITRD_FILESPEC) from which an initial RAM disk can be served via the EFI_FILE_LOAD2_PROTOCOL.
Ard extended the Linux EFI stub to allow loading the initial RAM disk via the EFI_FILE_LOAD2_PROTOCOL with the utmost priority.
With commit ecc7fdaa9ef1 ("bootm: Add a bootm command for type IH_OS_EFI") Cristian enabled signed FIT images that contain a device tree and a UEFI binary (enabled by CONFIG_BOOTM_EFI=y).
In the DTE calls we have discussed that it is unfortunate that we do
not
have a method to validate initial RAM images in the UEFI context.
To me it would look like a good path forward to combine the two
ideas:
- Let the signed FIT image (of type IH_OS_EFI) contain a RAM disk
- Pass location and size to the UEFI subsystem and serve them via the EFI_FILE_LOAD2_PROTOCOL.
We could also extend the bootefi command to be callable as
bootefi $kernel_addr_r $ramdisk_addr_r:$filesize $fdt_addr_r
like the booti command to serve an initial RAM disk.
What are your thoughts?
Hi Heinrich,
I've got concerns about this approach. Even though it uses the UEFI infrastructure, images deployed in this way are U-Boot specific and won't ever be applicable on EDK2 or other UEFI implementations.
However there is another way to approach it which I think Francois touched on. If instead a UEFI stub was added to the FIT image, in the same way that the kernel has a UEFI stub, then the logic of decoding the FIT and choosing the correct DTB & initrd can be part of the image and it becomes applicable to any UEFI implementation. It would also address
Ard's concern of loading the FIT into memory, and then copying due to the EFI_FILE_LOAD2 path. The FIT stub would already know the image is in RAM, that is is reserved correctly, and just pass the correct addresses
to the kernel as part of the normal boot flow.
Signing would also be taken care of because the whole FIT can be signed, and that signature would be checked when it gets loaded.
Thoughts?
The gain of a fit image in U-Boot used for calling the Linux kernel via the EFI stub vs calling the legacy entry point comes down to providing the EFI_RNG_PROTOCOL to be used for KASLR.
I agree with that, but that is not my concern.
My concern is that the FIT image format will only be supported by U-Boot. Other UEFI implementations do not implement it.
On the other hand, adding a UEFI Stub to the FIT image format makes it a generic solution that can be used by any UEFI implementation. This would be separate from the linux kernel's UEFI stub, and should only deal with choosing the appropriate kernel/initrd/dtb from the FIT and then calling into the kernel's stub to actually boot the kernel.
For initrd a stub UEFI binary will work. But if you want to provide a kernel specific dtb with the same stub binary it will require a new service for device-tree fixups.
Devicetree fixups indeed needs to be solved. I would propose registering a new protocol for fixups. If the protocol is present, then stub can call it. If not, then the DTB from the fit should be used unmodified.
g.
As always, Ard made a good point, and I feel compelled to top post and restate stuff.
Here is the supporting deck: https://docs.google.com/presentation/d/1JK00su6e7vt8lRfwSt2C9EuuzwcBHLyoLRRr...
We have two boot flows under consideration (not saying others are bad, just to say they are on focus): A.1 typical distro (slide 2): <EFI firmware/ACPI> --> <shim> --> <grub> --> Linux; Linux is here defined as the tuple {vmlinuz}, vmlinuz is verified through EFI mechanism by either efi firmware or shim, ACPI tables are verified by firmware, initrd is not verified A.2 typical embedded (slide 3): <firmware/DT> -> Linux ; Linux is here defined as the tuple {vmlinuz, initrd, dtb} that is folded into a FIT and are verified via signature, it avoid errors/attacks about mixing vmlinuz/initrd/dtb.
We want EBBR "equivalent" flows (Equivalent meaning with the same level of security and accepting the weaknesses). B.1 typical distro (slide 4): <EFI firmware/DT> --> <shim> --> <grub> --> Linux B.2 typical embedded (slide 5): <EFI firmware/DT> -> Linux
For B.1 to be equivalent to A.1, we need the DT to be authenticated (ACPI is embedded in the firmware in A.1). For B2. to be equivalent to A.2, we need the DT and initrd to be authenticated
_____________ We can first validate this point: let's check whether we want to do this (regardless of the implementation details, focusing on the intention).
On the implementation side, last call we discussed Trusting DT and we ended up talking about trusting initrd too (probably because B.2 in the back of our minds, without being explicit about this).
After giving some additional thoughts, it sounds like a good approach is to "lead by example": let's implement what we think are the "archetype" flows for Qemu and maintain it over time. We would make all changes we think are good in all relevant projects (tfa, op-tee, u-boot, devicetree, linux kernel, qemu...). Being an "archetype" flow does not prevent systems to be EBBR compliant, we just have reference flows.
_____________ We can validate this second point: are we in agreement that leading by an end-to-end example on a platform, rather by technology layers (trusting DT PoC was in that spirit) ?
What are the implementation details of B.1 and B.2?
B.1 To trust DT the proposal is to make its use closer to ACPI: this is a platform attribute that is verified by firmware and handed over to OS. To achieve that: - we create a platform repo in devicetree.org, add the Qemu-bsa DT (coming from current Linux kernel ), and maintain it over time. We shall ensure forward/backward compatibility of relevant Linux drivers. - the resulting DTB is compiled and integrated by the platform vendor in its TF-A FIP at NT_FW_CONFIG section. - at boot time, TF-A verifies DTB, pass it to U-Boot, U-Boot passes that DTB to the shim as a config table and boot flow continues; the platform DTB can be overridden by grub (without any verification, that can be seen as a weaker than ACPI case); the Linux EFI-STUB uses EFI_LOAD_FILE2 protocol to get the initrd (unverified). Linux command line dtb= is disabled
B.2 To trust DT the proposal is to make its use closer to ACPI: this is a platform attribute that is verified by firmware and handed over to OS. To trust the initrd the proposal is to leverage the same concept as A.2: create a tuple with {vmlinuz, initrd, dtb} To achieve that: - we create a platform repo in devicetree.org, add the Qemu-bsa DT (coming from current Linux kernel ), and maintain it over time. We shall ensure forward/backward compatibility of relevant Linux drivers. - the resulting DTB is compiled and integrated by the platform vendor in its TF-A FIP at NT_FW_CONFIG section. - the platform vendor creates a FIT with the desired tuple - an EFI application is actually "booting" that FIT verifying both the initrd and the replacement DTB - at boot time, TF-A verifies DTB, pass it to U-Boot, U-Boot passes that DTB to the EFI application as a config table; The EFI application hooks the EFI BS (much like the SHIM does) so that EFI_LOAD_FILE2 of initrd goes to the FIT (uefi_merge_fs idea in the slide 5); vmlinuz is verified launched via UEFI mechanism, Linux EFI stub gets the initrd with EFI_LOAD_PROTOCOL2 which happens to be transparently redirected to the FIT (so the initrd is validated as in A.2).
_____________ Identifying the right flow is the third point to decide on. I hope we can achieve this result on the October 14th call. If we agree on the first two points, the mail thread shall be such that we find consensus on how to implement the intention, the above description and slide 4/5 in the deck being just starting points. We can go in an entire direction.
On Tue, 6 Oct 2020 at 12:38, Grant Likely grant.likely@arm.com wrote:
On 06/10/2020 05:35, Heinrich Schuchardt wrote:
Am 6. Oktober 2020 00:37:58 MESZ schrieb Grant Likely <
grant.likely@arm.com>:
On 03/10/2020 09:51, Heinrich Schuchardt wrote:
Hello Ilias, hello Christian,
with commit ec80b4735a59 ("efi_loader: Implement FileLoad2 for
initramfs
loading") Ilias provided the possibility to specify a device path (CONFIG_EFI_INITRD_FILESPEC) from which an initial RAM disk can be served via the EFI_FILE_LOAD2_PROTOCOL.
Ard extended the Linux EFI stub to allow loading the initial RAM disk via the EFI_FILE_LOAD2_PROTOCOL with the utmost priority.
With commit ecc7fdaa9ef1 ("bootm: Add a bootm command for type IH_OS_EFI") Cristian enabled signed FIT images that contain a device tree and a UEFI binary (enabled by CONFIG_BOOTM_EFI=y).
In the DTE calls we have discussed that it is unfortunate that we do
not
have a method to validate initial RAM images in the UEFI context.
To me it would look like a good path forward to combine the two
ideas:
- Let the signed FIT image (of type IH_OS_EFI) contain a RAM disk
- Pass location and size to the UEFI subsystem and serve them via the EFI_FILE_LOAD2_PROTOCOL.
We could also extend the bootefi command to be callable as
bootefi $kernel_addr_r $ramdisk_addr_r:$filesize $fdt_addr_r
like the booti command to serve an initial RAM disk.
What are your thoughts?
Hi Heinrich,
I've got concerns about this approach. Even though it uses the UEFI infrastructure, images deployed in this way are U-Boot specific and won't ever be applicable on EDK2 or other UEFI implementations.
However there is another way to approach it which I think Francois touched on. If instead a UEFI stub was added to the FIT image, in the same way that the kernel has a UEFI stub, then the logic of decoding the FIT and choosing the correct DTB & initrd can be part of the image and it becomes applicable to any UEFI implementation. It would also address
Ard's concern of loading the FIT into memory, and then copying due to the EFI_FILE_LOAD2 path. The FIT stub would already know the image is in RAM, that is is reserved correctly, and just pass the correct addresses
to the kernel as part of the normal boot flow.
Signing would also be taken care of because the whole FIT can be signed, and that signature would be checked when it gets loaded.
Thoughts?
The gain of a fit image in U-Boot used for calling the Linux kernel via
the EFI stub vs calling the legacy entry point comes down to providing the EFI_RNG_PROTOCOL to be used for KASLR.
I agree with that, but that is not my concern.
My concern is that the FIT image format will only be supported by U-Boot. Other UEFI implementations do not implement it.
On the other hand, adding a UEFI Stub to the FIT image format makes it a generic solution that can be used by any UEFI implementation. This would be separate from the linux kernel's UEFI stub, and should only deal with choosing the appropriate kernel/initrd/dtb from the FIT and then calling into the kernel's stub to actually boot the kernel.
For initrd a stub UEFI binary will work. But if you want to provide a
kernel specific dtb with the same stub binary it will require a new service for device-tree fixups.
Devicetree fixups indeed needs to be solved. I would propose registering a new protocol for fixups. If the protocol is present, then stub can call it. If not, then the DTB from the fit should be used unmodified.
g.
On 06.10.20 14:04, François Ozog wrote:
As always, Ard made a good point, and I feel compelled to top post and restate stuff.
Here is the supporting deck: https://docs.google.com/presentation/d/1JK00su6e7vt8lRfwSt2C9EuuzwcBHLyoLRRr... We have two boot flows under consideration (not saying others are bad, just to say they are on focus): A.1 typical distro (slide 2): <EFI firmware/ACPI> --> <shim> --> <grub> --> Linux; Linux is here defined as the tuple {vmlinuz}, vmlinuz is verified through EFI mechanism by either efi firmware or shim, ACPI tables are verified by firmware, initrd is not verified A.2 typical embedded (slide 3): <firmware/DT> -> Linux ; Linux is here defined as the tuple {vmlinuz, initrd, dtb} that is folded into a FIT and are verified via signature, it avoid errors/attacks about mixing vmlinuz/initrd/dtb.
We want EBBR "equivalent" flows (Equivalent meaning with the same level of security and accepting the weaknesses). B.1 typical distro (slide 4): <EFI firmware/DT> --> <shim> --> <grub> --> Linux B.2 typical embedded (slide 5): <EFI firmware/DT> -> Linux
For B.1 to be equivalent to A.1, we need the DT to be authenticated (ACPI is embedded in the firmware in A.1). For B2. to be equivalent to A.2, we need the DT and initrd to be authenticated
We can first validate this point: let's check whether we want to do this (regardless of the implementation details, focusing on the intention).
On the implementation side, last call we discussed Trusting DT and we ended up talking about trusting initrd too (probably because B.2 in the back of our minds, without being explicit about this).
After giving some additional thoughts, it sounds like a good approach is to "lead by example": let's implement what we think are the "archetype" flows for Qemu and maintain it over time. We would make all changes we think are good in all relevant projects (tfa, op-tee, u-boot, devicetree, linux kernel, qemu...). Being an "archetype" flow does not prevent systems to be EBBR compliant, we just have reference flows.
We can validate this second point: are we in agreement that leading by an end-to-end example on a platform, rather by technology layers (trusting DT PoC was in that spirit) ?
What are the implementation details of B.1 and B.2?
B.1 To trust DT the proposal is to make its use closer to ACPI: this is a platform attribute that is verified by firmware and handed over to OS. To achieve that:
- we create a platform repo in devicetree.org http://devicetree.org,
add the Qemu-bsa DT (coming from current Linux kernel ), and maintain it over time. We shall ensure forward/backward compatibility of relevant Linux drivers.
- the resulting DTB is compiled and integrated by the platform vendor in
its TF-A FIP at NT_FW_CONFIG section.
When building OpenSBI you can specify a device-tree using environment variable FW_PAYLOAD_FDT_PATH.
- at boot time, TF-A verifies DTB, pass it to U-Boot, U-Boot passes that
DTB to the shim as a config table and boot flow continues; the platform DTB can be overridden by grub (without any verification, that can be seen as a weaker than ACPI case); the Linux EFI-STUB uses EFI_LOAD_FILE2 protocol to get the initrd (unverified). Linux command line dtb= is disabled
B.2 To trust DT the proposal is to make its use closer to ACPI: this is a platform attribute that is verified by firmware and handed over to OS. To trust the initrd the proposal is to leverage the same concept as A.2: create a tuple with {vmlinuz, initrd, dtb} To achieve that:
- we create a platform repo in devicetree.org http://devicetree.org,
add the Qemu-bsa DT (coming from current Linux kernel ), and maintain it over time. We shall ensure forward/backward compatibility of relevant Linux drivers.
QEMU provides its own device-tree to the firmware. Why would we need a Linux device-tree for QEMU?
The Linux Foundation is unable to ensure that their device-trees are usable. With a Linux DTB after v5.3 I cannot start my MacchiatoBin with v5.4-v5.7.
If Linux does not run with the device tree of the same version, how can we hope for forward/backward compatibility?
Who takes care that other operating systems (e.g. BSD) are not broken by DTB changes?
- the resulting DTB is compiled and integrated by the platform vendor in
its TF-A FIP at NT_FW_CONFIG section.
- the platform vendor creates a FIT with the desired tuple
- an EFI application is actually "booting" that FIT verifying both the
initrd and the replacement DTB
- at boot time, TF-A verifies DTB, pass it to U-Boot, U-Boot passes that
DTB to the EFI application as a config table; The EFI application hooks the EFI BS (much like the SHIM does) so that EFI_LOAD_FILE2 of initrd goes to the FIT (uefi_merge_fs idea in the slide 5); vmlinuz is verified launched via UEFI mechanism, Linux EFI stub gets the initrd with EFI_LOAD_PROTOCOL2 which happens to be transparently redirected to the FIT (so the initrd is validated as in A.2).
The FIT image file format is not needed here. It is sufficient that the vendor provides a signed binary that supplies the kernel, initrd, fdt triplet. There is no need to specify how this binary works internally.
Best regards
Heinrich
_____________ Identifying the right flow is the third point to decide on. I hope we can achieve this result on the October 14th call. If we agree on the first two points, the mail thread shall be such that we find consensus on how to implement the intention, the above description and slide 4/5 in the deck being just starting points. We can go in an entire direction.
On 06/10/2020 13:36, Heinrich Schuchardt wrote:
On 06.10.20 14:04, François Ozog wrote:
As always, Ard made a good point, and I feel compelled to top post and restate stuff.
Here is the supporting deck: https://docs.google.com/presentation/d/1JK00su6e7vt8lRfwSt2C9EuuzwcBHLyoLRRr... We have two boot flows under consideration (not saying others are bad, just to say they are on focus): A.1 typical distro (slide 2): <EFI firmware/ACPI> --> <shim> --> <grub> --> Linux; Linux is here defined as the tuple {vmlinuz}, vmlinuz is verified through EFI mechanism by either efi firmware or shim, ACPI tables are verified by firmware, initrd is not verified A.2 typical embedded (slide 3): <firmware/DT> -> Linux ; Linux is here defined as the tuple {vmlinuz, initrd, dtb} that is folded into a FIT and are verified via signature, it avoid errors/attacks about mixing vmlinuz/initrd/dtb.
We want EBBR "equivalent" flows (Equivalent meaning with the same level of security and accepting the weaknesses). B.1 typical distro (slide 4): <EFI firmware/DT> --> <shim> --> <grub> --> Linux B.2 typical embedded (slide 5): <EFI firmware/DT> -> Linux
For B.1 to be equivalent to A.1, we need the DT to be authenticated (ACPI is embedded in the firmware in A.1). For B2. to be equivalent to A.2, we need the DT and initrd to be authenticated
We can first validate this point: let's check whether we want to do this (regardless of the implementation details, focusing on the intention).
On the implementation side, last call we discussed Trusting DT and we ended up talking about trusting initrd too (probably because B.2 in the back of our minds, without being explicit about this).
After giving some additional thoughts, it sounds like a good approach is to "lead by example": let's implement what we think are the "archetype" flows for Qemu and maintain it over time. We would make all changes we think are good in all relevant projects (tfa, op-tee, u-boot, devicetree, linux kernel, qemu...). Being an "archetype" flow does not prevent systems to be EBBR compliant, we just have reference flows.
We can validate this second point: are we in agreement that leading by an end-to-end example on a platform, rather by technology layers (trusting DT PoC was in that spirit) ?
What are the implementation details of B.1 and B.2?
B.1 To trust DT the proposal is to make its use closer to ACPI: this is a platform attribute that is verified by firmware and handed over to OS. To achieve that:
- we create a platform repo in devicetree.org http://devicetree.org,
add the Qemu-bsa DT (coming from current Linux kernel ), and maintain it over time. We shall ensure forward/backward compatibility of relevant Linux drivers.
- the resulting DTB is compiled and integrated by the platform vendor in
its TF-A FIP at NT_FW_CONFIG section.
When building OpenSBI you can specify a device-tree using environment variable FW_PAYLOAD_FDT_PATH.
- at boot time, TF-A verifies DTB, pass it to U-Boot, U-Boot passes that
DTB to the shim as a config table and boot flow continues; the platform DTB can be overridden by grub (without any verification, that can be seen as a weaker than ACPI case); the Linux EFI-STUB uses EFI_LOAD_FILE2 protocol to get the initrd (unverified). Linux command line dtb= is disabled
B.2 To trust DT the proposal is to make its use closer to ACPI: this is a platform attribute that is verified by firmware and handed over to OS. To trust the initrd the proposal is to leverage the same concept as A.2: create a tuple with {vmlinuz, initrd, dtb} To achieve that:
- we create a platform repo in devicetree.org http://devicetree.org,
add the Qemu-bsa DT (coming from current Linux kernel ), and maintain it over time. We shall ensure forward/backward compatibility of relevant Linux drivers.
QEMU provides its own device-tree to the firmware. Why would we need a Linux device-tree for QEMU?
The Linux Foundation is unable to ensure that their device-trees are usable. With a Linux DTB after v5.3 I cannot start my MacchiatoBin with v5.4-v5.7.
Current U-Boot by default uses the same DT image for both U-Boot internal setup and to provide to the OS. This should be split so that the U-Boot internal version has what U-Boot needs without needs to track mainline Linux DTB schema.
I've been looking into a generic config for adding a separate OS-dtb to U-Boot that is not used internally and is only passed to the OS. That would solve the problem you're seeing above.
That doesn't solve the problem of DTB schema stability, but it at least decouples the problem so we're not stuck.
g.
On 06.10.20 14:43, Grant Likely wrote:
Current U-Boot by default uses the same DT image for both U-Boot internal setup and to provide to the OS. This should be split so that the U-Boot internal version has what U-Boot needs without needs to track mainline Linux DTB schema.
I've been looking into a generic config for adding a separate OS-dtb to U-Boot that is not used internally and is only passed to the OS. That would solve the problem you're seeing above.
What would be the advantage of building said second device-tree into U-Boot instead of loading it from a (possibly signed) file?
Best regards
Heinrich
That doesn't solve the problem of DTB schema stability, but it at least decouples the problem so we're not stuck.
g.
On 06/10/2020 13:52, Heinrich Schuchardt wrote:
On 06.10.20 14:43, Grant Likely wrote:
Current U-Boot by default uses the same DT image for both U-Boot internal setup and to provide to the OS. This should be split so that the U-Boot internal version has what U-Boot needs without needs to track mainline Linux DTB schema.
I've been looking into a generic config for adding a separate OS-dtb to U-Boot that is not used internally and is only passed to the OS. That would solve the problem you're seeing above.
What would be the advantage of building said second device-tree into U-Boot instead of loading it from a (possibly signed) file?
I would see that as an implementation detail, but from the OS point of view EBBR requires the firmware to provide a DTB to the OS without the OS having any involvement in providing it. The easiest solution is to embed the OS dtb into U-Boot, but it could be loaded and verified from a file as well.
g.
Ard, there is a question for you in the below thread ;-)
On Tue, 6 Oct 2020 at 15:02, Grant Likely grant.likely@arm.com wrote:
On 06/10/2020 13:52, Heinrich Schuchardt wrote:
On 06.10.20 14:43, Grant Likely wrote:
Current U-Boot by default uses the same DT image for both U-Boot internal setup and to provide to the OS. This should be split so that the U-Boot internal version has what U-Boot needs without needs to track mainline Linux DTB schema.
I've been looking into a generic config for adding a separate OS-dtb to U-Boot that is not used internally and is only passed to the OS. That would solve the problem you're seeing above.
What would be the advantage of building said second device-tree into U-Boot instead of loading it from a (possibly signed) file?
I would see that as an implementation detail, but from the OS point of view EBBR requires the firmware to provide a DTB to the OS without the OS having any involvement in providing it. The easiest solution is to embed the OS dtb into U-Boot, but it could be loaded and verified from a file as well.
To strongly state that the DT is a hardware description entity, disconnected from open source projects consuming it, I would still build the DT for the Booted Payload in the context of devicetree.org and append it to either FIP or U-Boot.
From a hierarchical perspective FIP would make more sense (I was told by
the LinuxBoot guys that the ACPI tables are tied to PEI so that they can use them while replacing EDK2. I am not sure my understanding is correct: Ard ?) as I consider that PEI and TF-A are at the same layer I am inclined to promote this. Should the DTB cause problems, the one embedded in the FIT would be replacing the platform base one (I assume this is your "loaded and verified from a file" comment).
g.
On Tue, 6 Oct 2020 at 16:22, François Ozog francois.ozog@linaro.org wrote:
Ard, there is a question for you in the below thread ;-)
On Tue, 6 Oct 2020 at 15:02, Grant Likely grant.likely@arm.com wrote:
On 06/10/2020 13:52, Heinrich Schuchardt wrote:
On 06.10.20 14:43, Grant Likely wrote:
Current U-Boot by default uses the same DT image for both U-Boot internal setup and to provide to the OS. This should be split so that the U-Boot internal version has what U-Boot needs without needs to
track
mainline Linux DTB schema.
I've been looking into a generic config for adding a separate OS-dtb to U-Boot that is not used internally and is only passed to the OS. That would solve the problem you're seeing above.
What would be the advantage of building said second device-tree into U-Boot instead of loading it from a (possibly signed) file?
I would see that as an implementation detail, but from the OS point of view EBBR requires the firmware to provide a DTB to the OS without the OS having any involvement in providing it. The easiest solution is to embed the OS dtb into U-Boot, but it could be loaded and verified from a file as well.
To strongly state that the DT is a hardware description entity, disconnected from open source projects consuming it, I would still build the DT for the Booted Payload in the context of devicetree.org and append it to either FIP or U-Boot. From a hierarchical perspective FIP would make more sense (I was told by the LinuxBoot guys that the ACPI tables are tied to PEI so that they can use them while replacing EDK2. I am not sure my understanding is correct: Ard ?)
No that is a lie. In EDK2 based firmwares, there are DXE protocols used for publishing and manipulating ACPI tables, and for exposing them via the config table array when the boot finally occurs.
I should also point out (for anyone that hadn't noticed) that the Linuxboot guys have a highly skewed and opinionated view of UEFI boot, which seems mostly based on bad experiences with IBV provided, OEM mangled builds for proprietary code bases of which it is unknown how much they are based on EDK2 (or UEFI for that matter). The IBVs used to claim that they carried their own complete implementations of the PI and UEFI and specifications, but everybody knows that is a lie, especially for firmwares built for ARM machines.
as I consider that PEI and TF-A are at the same layer I am inclined to
promote this.
TF-A is secure firmware, PEI is non-secure firmware, so I suppose it depends on how you defined your layers. Although in the x86 context, PEI executes when the SMM execution context has not split off yet, so it s closer to a secure world firmware than it is on ARM (same applies to DXE before EndOfDxe, but the boundary line is not as clear in this case)
Should the DTB cause problems, the one embedded in the FIT would be
replacing the platform base one (I assume this is your "loaded and verified from a file" comment).
g.
-- François-Frédéric Ozog | *Director Linaro Edge & Fog Computing Group* T: +33.67221.6485 francois.ozog@linaro.org | Skype: ffozog
On Tue, 6 Oct 2020 at 16:46, Ard Biesheuvel ardb@kernel.org wrote:
On Tue, 6 Oct 2020 at 16:22, François Ozog francois.ozog@linaro.org wrote:
Ard, there is a question for you in the below thread ;-)
On Tue, 6 Oct 2020 at 15:02, Grant Likely grant.likely@arm.com wrote:
On 06/10/2020 13:52, Heinrich Schuchardt wrote:
On 06.10.20 14:43, Grant Likely wrote:
Current U-Boot by default uses the same DT image for both U-Boot internal setup and to provide to the OS. This should be split so that the U-Boot internal version has what U-Boot needs without needs to
track
mainline Linux DTB schema.
I've been looking into a generic config for adding a separate OS-dtb
to
U-Boot that is not used internally and is only passed to the OS. That would solve the problem you're seeing above.
What would be the advantage of building said second device-tree into U-Boot instead of loading it from a (possibly signed) file?
I would see that as an implementation detail, but from the OS point of view EBBR requires the firmware to provide a DTB to the OS without the OS having any involvement in providing it. The easiest solution is to embed the OS dtb into U-Boot, but it could be loaded and verified from a file as well.
To strongly state that the DT is a hardware description entity, disconnected from open source projects consuming it, I would still build the DT for the Booted Payload in the context of devicetree.org and append it to either FIP or U-Boot. From a hierarchical perspective FIP would make more sense (I was told by the LinuxBoot guys that the ACPI tables are tied to PEI so that they can use them while replacing EDK2. I am not sure my understanding is correct: Ard ?)
No that is a lie. In EDK2 based firmwares, there are DXE protocols used for publishing and manipulating ACPI tables, and for exposing them via the config table array when the boot finally occurs.
Are the ACPI tables "static" blobs that are integrated into the firmware
image with some late fixups in the DXE phase or are they entirely built programmatically during the DXE phase? In the case they are static base blobs in the firmware image, are they used (to access hardware, not manipulated) in all phases (SEC, PEI, DXE) ?
I should also point out (for anyone that hadn't noticed) that the Linuxboot guys have a highly skewed and opinionated view of UEFI boot, which seems mostly based on bad experiences with IBV provided, OEM mangled builds for proprietary code bases of which it is unknown how much they are based on EDK2 (or UEFI for that matter). The IBVs used to claim that they carried their own complete implementations of the PI and UEFI and specifications, but everybody knows that is a lie, especially for firmwares built for ARM machines.
as I consider that PEI and TF-A are at the same layer I am inclined to
promote this.
TF-A is secure firmware, PEI is non-secure firmware, so I suppose it depends on how you defined your layers. Although in the x86 context, PEI executes when the SMM execution context has not split off yet, so it s closer to a secure world firmware than it is on ARM (same applies to DXE before EndOfDxe, but the boundary line is not as clear in this case)
I was biased by the x86 model here...
Should the DTB cause problems, the one embedded in the FIT would be
replacing the platform base one (I assume this is your "loaded and verified from a file" comment).
g.
-- François-Frédéric Ozog | *Director Linaro Edge & Fog Computing Group* T: +33.67221.6485 francois.ozog@linaro.org | Skype: ffozog
On Tue, 6 Oct 2020 at 17:08, François Ozog francois.ozog@linaro.org wrote:
On Tue, 6 Oct 2020 at 16:46, Ard Biesheuvel ardb@kernel.org wrote:
On Tue, 6 Oct 2020 at 16:22, François Ozog francois.ozog@linaro.org wrote:
Ard, there is a question for you in the below thread ;-)
On Tue, 6 Oct 2020 at 15:02, Grant Likely grant.likely@arm.com wrote:
On 06/10/2020 13:52, Heinrich Schuchardt wrote:
On 06.10.20 14:43, Grant Likely wrote:
Current U-Boot by default uses the same DT image for both U-Boot internal setup and to provide to the OS. This should be split so that the U-Boot internal version has what U-Boot needs without needs to
track
mainline Linux DTB schema.
I've been looking into a generic config for adding a separate OS-dtb
to
U-Boot that is not used internally and is only passed to the OS. That would solve the problem you're seeing above.
What would be the advantage of building said second device-tree into U-Boot instead of loading it from a (possibly signed) file?
I would see that as an implementation detail, but from the OS point of view EBBR requires the firmware to provide a DTB to the OS without the OS having any involvement in providing it. The easiest solution is to embed the OS dtb into U-Boot, but it could be loaded and verified from a file as well.
To strongly state that the DT is a hardware description entity, disconnected from open source projects consuming it, I would still build the DT for the Booted Payload in the context of devicetree.org and append it to either FIP or U-Boot. From a hierarchical perspective FIP would make more sense (I was told by the LinuxBoot guys that the ACPI tables are tied to PEI so that they can use them while replacing EDK2. I am not sure my understanding is correct: Ard ?)
For TF-A, I would think having the same DT lifecycle regardless BL33
(U-Boot, LinuxBoot, Xen...) is a nice objective. hence the FIP proposal. In this context, U-Boot, LinuxBoot and Xen can have their own DTB for their operations. I am just considering the DT for the Booted Payload. Other firmware frameworks (U-Boot SPL, coreboot) may have different flows.
No that is a lie. In EDK2 based firmwares, there are DXE protocols used for publishing and manipulating ACPI tables, and for exposing them via the config table array when the boot finally occurs.
Are the ACPI tables "static" blobs that are integrated into the firmware
image with some late fixups in the DXE phase or are they entirely built programmatically during the DXE phase? In the case they are static base blobs in the firmware image, are they used (to access hardware, not manipulated) in all phases (SEC, PEI, DXE) ?
I should also point out (for anyone that hadn't noticed) that the Linuxboot guys have a highly skewed and opinionated view of UEFI boot, which seems mostly based on bad experiences with IBV provided, OEM mangled builds for proprietary code bases of which it is unknown how much they are based on EDK2 (or UEFI for that matter). The IBVs used to claim that they carried their own complete implementations of the PI and UEFI and specifications, but everybody knows that is a lie, especially for firmwares built for ARM machines.
as I consider that PEI and TF-A are at the same layer I am inclined to
promote this.
TF-A is secure firmware, PEI is non-secure firmware, so I suppose it depends on how you defined your layers. Although in the x86 context, PEI executes when the SMM execution context has not split off yet, so it s closer to a secure world firmware than it is on ARM (same applies to DXE before EndOfDxe, but the boundary line is not as clear in this case)
I was biased by the x86 model here...
Should the DTB cause problems, the one embedded in the FIT would be
replacing the platform base one (I assume this is your "loaded and verified from a file" comment).
g.
-- François-Frédéric Ozog | *Director Linaro Edge & Fog Computing Group* T: +33.67221.6485 francois.ozog@linaro.org | Skype: ffozog
-- François-Frédéric Ozog | *Director Linaro Edge & Fog Computing Group* T: +33.67221.6485 francois.ozog@linaro.org | Skype: ffozog
On Tue, 6 Oct 2020 at 17:09, François Ozog francois.ozog@linaro.org wrote:
On Tue, 6 Oct 2020 at 16:46, Ard Biesheuvel ardb@kernel.org wrote:
On Tue, 6 Oct 2020 at 16:22, François Ozog francois.ozog@linaro.org wrote:
Ard, there is a question for you in the below thread ;-)
On Tue, 6 Oct 2020 at 15:02, Grant Likely grant.likely@arm.com wrote:
On 06/10/2020 13:52, Heinrich Schuchardt wrote:
On 06.10.20 14:43, Grant Likely wrote:
Current U-Boot by default uses the same DT image for both U-Boot internal setup and to provide to the OS. This should be split so that the U-Boot internal version has what U-Boot needs without needs to
track
mainline Linux DTB schema.
I've been looking into a generic config for adding a separate OS-dtb
to
U-Boot that is not used internally and is only passed to the OS. That would solve the problem you're seeing above.
What would be the advantage of building said second device-tree into U-Boot instead of loading it from a (possibly signed) file?
I would see that as an implementation detail, but from the OS point of view EBBR requires the firmware to provide a DTB to the OS without the OS having any involvement in providing it. The easiest solution is to embed the OS dtb into U-Boot, but it could be loaded and verified from a file as well.
To strongly state that the DT is a hardware description entity, disconnected from open source projects consuming it, I would still build the DT for the Booted Payload in the context of devicetree.org and append it to either FIP or U-Boot. From a hierarchical perspective FIP would make more sense (I was told by the LinuxBoot guys that the ACPI tables are tied to PEI so that they can use them while replacing EDK2. I am not sure my understanding is correct: Ard ?)
No that is a lie. In EDK2 based firmwares, there are DXE protocols used for publishing and manipulating ACPI tables, and for exposing them via the config table array when the boot finally occurs.
Are the ACPI tables "static" blobs that are integrated into the firmware
image with some late fixups in the DXE phase or are they entirely built programmatically during the DXE phase? In the case they are static base blobs in the firmware image, are they used (to access hardware, not manipulated) in all phases (SEC, PEI, DXE) ?
They could be generated from scratch or incorporated fully baked. In either case, the firmware itself never consumes the ACPI tables, it only produces them for consumption by the OS.
I should also point out (for anyone that hadn't noticed) that the Linuxboot guys have a highly skewed and opinionated view of UEFI boot, which seems mostly based on bad experiences with IBV provided, OEM mangled builds for proprietary code bases of which it is unknown how much they are based on EDK2 (or UEFI for that matter). The IBVs used to claim that they carried their own complete implementations of the PI and UEFI and specifications, but everybody knows that is a lie, especially for firmwares built for ARM machines.
as I consider that PEI and TF-A are at the same layer I am inclined to
promote this.
TF-A is secure firmware, PEI is non-secure firmware, so I suppose it depends on how you defined your layers. Although in the x86 context, PEI executes when the SMM execution context has not split off yet, so it s closer to a secure world firmware than it is on ARM (same applies to DXE before EndOfDxe, but the boundary line is not as clear in this case)
I was biased by the x86 model here...
Should the DTB cause problems, the one embedded in the FIT would be
replacing the platform base one (I assume this is your "loaded and verified from a file" comment).
g.
-- François-Frédéric Ozog | *Director Linaro Edge & Fog Computing Group* T: +33.67221.6485 francois.ozog@linaro.org | Skype: ffozog
-- François-Frédéric Ozog | *Director Linaro Edge & Fog Computing Group* T: +33.67221.6485 francois.ozog@linaro.org | Skype: ffozog
On Tue, 6 Oct 2020 at 14:36, Heinrich Schuchardt xypron.glpk@gmx.de wrote:
On 06.10.20 14:04, François Ozog wrote:
As always, Ard made a good point, and I feel compelled to top post and restate stuff.
Here is the supporting deck:
https://docs.google.com/presentation/d/1JK00su6e7vt8lRfwSt2C9EuuzwcBHLyoLRRr...
We have two boot flows under consideration (not saying others are bad, just to say they are on focus): A.1 typical distro (slide 2): <EFI firmware/ACPI> --> <shim> --> <grub> --> Linux; Linux is here defined as the tuple {vmlinuz}, vmlinuz is verified through EFI mechanism by either efi firmware or shim, ACPI tables are verified by firmware, initrd is not verified A.2 typical embedded (slide 3): <firmware/DT> -> Linux ; Linux is here defined as the tuple {vmlinuz, initrd, dtb} that is folded into a FIT and are verified via signature, it avoid errors/attacks about mixing vmlinuz/initrd/dtb.
We want EBBR "equivalent" flows (Equivalent meaning with the same level of security and accepting the weaknesses). B.1 typical distro (slide 4): <EFI firmware/DT> --> <shim> --> <grub> --> Linux B.2 typical embedded (slide 5): <EFI firmware/DT> -> Linux
For B.1 to be equivalent to A.1, we need the DT to be authenticated (ACPI is embedded in the firmware in A.1). For B2. to be equivalent to A.2, we need the DT and initrd to be authenticated
We can first validate this point: let's check whether we want to do this (regardless of the implementation details, focusing on the intention).
On the implementation side, last call we discussed Trusting DT and we ended up talking about trusting initrd too (probably because B.2 in the back of our minds, without being explicit about this).
After giving some additional thoughts, it sounds like a good approach is to "lead by example": let's implement what we think are the "archetype" flows for Qemu and maintain it over time. We would make all changes we think are good in all relevant projects (tfa, op-tee, u-boot, devicetree, linux kernel, qemu...). Being an "archetype" flow does not prevent systems to be EBBR compliant, we just have reference flows.
We can validate this second point: are we in agreement that leading by an end-to-end example on a platform, rather by technology layers (trusting DT PoC was in that spirit) ?
What are the implementation details of B.1 and B.2?
B.1 To trust DT the proposal is to make its use closer to ACPI: this is a platform attribute that is verified by firmware and handed over to OS. To achieve that:
- we create a platform repo in devicetree.org http://devicetree.org,
add the Qemu-bsa DT (coming from current Linux kernel ), and maintain it over time. We shall ensure forward/backward compatibility of relevant Linux drivers.
- the resulting DTB is compiled and integrated by the platform vendor in
its TF-A FIP at NT_FW_CONFIG section.
When building OpenSBI you can specify a device-tree using environment variable FW_PAYLOAD_FDT_PATH.
- at boot time, TF-A verifies DTB, pass it to U-Boot, U-Boot passes that
DTB to the shim as a config table and boot flow continues; the platform DTB can be overridden by grub (without any verification, that can be seen as a weaker than ACPI case); the Linux EFI-STUB uses EFI_LOAD_FILE2 protocol to get the initrd (unverified). Linux command line dtb= is
disabled
B.2 To trust DT the proposal is to make its use closer to ACPI: this is a platform attribute that is verified by firmware and handed over to OS. To trust the initrd the proposal is to leverage the same concept as A.2: create a tuple with {vmlinuz, initrd, dtb} To achieve that:
- we create a platform repo in devicetree.org http://devicetree.org,
add the Qemu-bsa DT (coming from current Linux kernel ), and maintain it over time. We shall ensure forward/backward compatibility of relevant Linux drivers.
QEMU provides its own device-tree to the firmware. Why would we need a Linux device-tree for QEMU?
The Linux Foundation is unable to ensure that their device-trees are usable. With a Linux DTB after v5.3 I cannot start my MacchiatoBin with v5.4-v5.7.
If Linux does not run with the device tree of the same version, how can we hope for forward/backward compatibility?
Who takes care that other operating systems (e.g. BSD) are not broken by DTB changes?
Trying to address all the above with this: qemu-bsa is essentially about virtio devices which are discovered through virtio and not DT. Linaro is further involved in virtio devices for random number generator, SCMI and watchdog. The compatibility issues are limited to platform devices and services such as: GIC, PSCI and may be others (I would prefer to have virtio-console rather than PL01 for instance) So I think the scope of the proof of concept is small enough to be manageable. The proof of concept would be to allow Linux and freeBSD on arm64. Linaro and its members would be responsible to make that happen. Some platforms will be EBBR compliant, some not. Should a platform vendor want to have an EBBR flow, it should have the power to choose to make it work and not depend on other vendors to embrace the model. This is leading by example: by itself the PoC will not solve the whole problem for all platforms. Merely show the way. And with a lot of good will, situations may change over time (5 years?).
- the resulting DTB is compiled and integrated by the platform vendor in
its TF-A FIP at NT_FW_CONFIG section.
- the platform vendor creates a FIT with the desired tuple
- an EFI application is actually "booting" that FIT verifying both the
initrd and the replacement DTB
- at boot time, TF-A verifies DTB, pass it to U-Boot, U-Boot passes that
DTB to the EFI application as a config table; The EFI application hooks the EFI BS (much like the SHIM does) so that EFI_LOAD_FILE2 of initrd goes to the FIT (uefi_merge_fs idea in the slide 5); vmlinuz is verified launched via UEFI mechanism, Linux EFI stub gets the initrd with EFI_LOAD_PROTOCOL2 which happens to be transparently redirected to the FIT (so the initrd is validated as in A.2).
The FIT image file format is not needed here. It is sufficient that the vendor provides a signed binary that supplies the kernel, initrd, fdt triplet. There is no need to specify how this binary works internally.
Indeed. The idea is to have one reference model based on something
available.
Best regards
Heinrich
Identifying the right flow is the third point to decide on. I hope we can achieve this result on the October 14th call. If we agree on the first two points, the mail thread shall be such that we find consensus on how to implement the intention, the above description and slide 4/5 in the deck being just starting points. We can go in an entire direction.
On 06/10/2020 13:04, François Ozog wrote:
As always, Ard made a good point, and I feel compelled to top post and restate stuff.
Here is the supporting deck: https://docs.google.com/presentation/d/1JK00su6e7vt8lRfwSt2C9EuuzwcBHLyoLRRr...
We have two boot flows under consideration (not saying others are bad, just to say they are on focus): A.1 typical distro (slide 2): <EFI firmware/ACPI> --> <shim> --> <grub> --> Linux; Linux is here defined as the tuple {vmlinuz}, vmlinuz is verified through EFI mechanism by either efi firmware or shim, ACPI tables are verified by firmware, initrd is not verified A.2 typical embedded (slide 3): <firmware/DT> -> Linux ; Linux is here defined as the tuple {vmlinuz, initrd, dtb} that is folded into a FIT and are verified via signature, it avoid errors/attacks about mixing vmlinuz/initrd/dtb.
We want EBBR "equivalent" flows (Equivalent meaning with the same level of security and accepting the weaknesses). B.1 typical distro (slide 4): <EFI firmware/DT> --> <shim> --> <grub> --> Linux B.2 typical embedded (slide 5): <EFI firmware/DT> -> Linux
For B.1 to be equivalent to A.1, we need the DT to be authenticated (ACPI is embedded in the firmware in A.1).
Current EBBR requires DT to be embedded in firmware by default. OS has option to replace it, but the firmware provided DT can be verified with the firmware image.
For B2. to be equivalent to A.2, we need the DT and initrd to be authenticated
I'm proposing an alternative to B2: <EFI firmware/DT> -> FIT Shim (payload of kernel+initrd+dt) -> Linux
g.
On 06.10.20 12:38, Grant Likely wrote:
On 06/10/2020 05:35, Heinrich Schuchardt wrote:
Am 6. Oktober 2020 00:37:58 MESZ schrieb Grant Likely grant.likely@arm.com:
On 03/10/2020 09:51, Heinrich Schuchardt wrote:
Hello Ilias, hello Christian,
with commit ec80b4735a59 ("efi_loader: Implement FileLoad2 for
initramfs
loading") Ilias provided the possibility to specify a device path (CONFIG_EFI_INITRD_FILESPEC) from which an initial RAM disk can be served via the EFI_FILE_LOAD2_PROTOCOL.
Ard extended the Linux EFI stub to allow loading the initial RAM disk via the EFI_FILE_LOAD2_PROTOCOL with the utmost priority.
With commit ecc7fdaa9ef1 ("bootm: Add a bootm command for type IH_OS_EFI") Cristian enabled signed FIT images that contain a device tree and a UEFI binary (enabled by CONFIG_BOOTM_EFI=y).
In the DTE calls we have discussed that it is unfortunate that we do
not
have a method to validate initial RAM images in the UEFI context.
To me it would look like a good path forward to combine the two
ideas:
- Let the signed FIT image (of type IH_OS_EFI) contain a RAM disk
- Pass location and size to the UEFI subsystem and serve them via
the EFI_FILE_LOAD2_PROTOCOL.
We could also extend the bootefi command to be callable as
bootefi $kernel_addr_r $ramdisk_addr_r:$filesize $fdt_addr_r
like the booti command to serve an initial RAM disk.
What are your thoughts?
Hi Heinrich,
I've got concerns about this approach. Even though it uses the UEFI infrastructure, images deployed in this way are U-Boot specific and won't ever be applicable on EDK2 or other UEFI implementations.
However there is another way to approach it which I think Francois touched on. If instead a UEFI stub was added to the FIT image, in the same way that the kernel has a UEFI stub, then the logic of decoding the FIT and choosing the correct DTB & initrd can be part of the image and it becomes applicable to any UEFI implementation. It would also address
Ard's concern of loading the FIT into memory, and then copying due to the EFI_FILE_LOAD2 path. The FIT stub would already know the image is in RAM, that is is reserved correctly, and just pass the correct addresses
to the kernel as part of the normal boot flow.
Signing would also be taken care of because the whole FIT can be signed, and that signature would be checked when it gets loaded.
Thoughts?
The gain of a fit image in U-Boot used for calling the Linux kernel via the EFI stub vs calling the legacy entry point comes down to providing the EFI_RNG_PROTOCOL to be used for KASLR.
I agree with that, but that is not my concern.
My concern is that the FIT image format will only be supported by U-Boot. Other UEFI implementations do not implement it.
On the other hand, adding a UEFI Stub to the FIT image format makes it a generic solution that can be used by any UEFI implementation. This would be separate from the linux kernel's UEFI stub, and should only deal with choosing the appropriate kernel/initrd/dtb from the FIT and then calling into the kernel's stub to actually boot the kernel.
For initrd a stub UEFI binary will work. But if you want to provide a kernel specific dtb with the same stub binary it will require a new service for device-tree fixups.
Devicetree fixups indeed needs to be solved. I would propose registering a new protocol for fixups. If the protocol is present, then stub can call it. If not, then the DTB from the fit should be used unmodified.
For such a protocol we will need to decide who will make the memory reservation needed to encompass the increasing size of the device tree.
As the caller of the protocol does not know how much memory is needed for the fixup I think the allocation should be done by the callee.
A definition of the protocol could look like this:
#define EFI_FDT_FIXUP_PROTOCOL_GUID \ {0xfa68b9a7, 0xb5fd, 0x49f5, \ {0x87, 0x93, 0x11, 0xfd, 0xb5, 0x6a, 0x8d, 0x41}
typedef EFI_STATUS (EFIAPI *EFI_FDT_FIXUP) ( IN EFI_FDT_FIXUP_PROTOCOL *This, IN OUT VOID **Fdt, IN BOOLEAN Install, };
typedef struct _EFI_FDT_FIXUP_PROTOCOL { EFI_FIX_UP Fixup; } EFI_FDT_FIXUP_PROTOCOL;
where
* This - pointer to the calling context * Fdt - On entry pointer to the address of the original device tree, on exit pointer to the address of the new device tree. If an error is returned, the value of *Fdt is undefined. * Install - If TRUE, install the resulting device tree as configuration table.
The 'Fixup' service
* makes a memory reservation using EFI_BOOT_SERVICES.AllocatePages(), * copies the device tree to the new memory area, * applies the fixups, * installs the resulting device tree as configuration table if Install==TRUE.
In case of an error the protocol implementation releases the memory by calling EFI_BOOT_SERVICES.FreePages().
Return values:
* EFI_INVALID_PARAMETER - Fdt is NULL. * EFI_INVALID_PARAMETER - *Fdt does not point to a valid device tree. * EFI_OUT_OF_RESOURCES - Not enough memory for the operation. * EFI_SUCCESS - The fixup was successful and the device-tree was installed if requested.
Best regards
Heinrich
On Tue, 6 Oct 2020 at 14:05, Heinrich Schuchardt xypron.glpk@gmx.de wrote:
On 06.10.20 12:38, Grant Likely wrote:
On 06/10/2020 05:35, Heinrich Schuchardt wrote:
Am 6. Oktober 2020 00:37:58 MESZ schrieb Grant Likely grant.likely@arm.com:
On 03/10/2020 09:51, Heinrich Schuchardt wrote:
Hello Ilias, hello Christian,
with commit ec80b4735a59 ("efi_loader: Implement FileLoad2 for
initramfs
loading") Ilias provided the possibility to specify a device path (CONFIG_EFI_INITRD_FILESPEC) from which an initial RAM disk can be served via the EFI_FILE_LOAD2_PROTOCOL.
Ard extended the Linux EFI stub to allow loading the initial RAM disk via the EFI_FILE_LOAD2_PROTOCOL with the utmost priority.
With commit ecc7fdaa9ef1 ("bootm: Add a bootm command for type IH_OS_EFI") Cristian enabled signed FIT images that contain a device tree and a UEFI binary (enabled by CONFIG_BOOTM_EFI=y).
In the DTE calls we have discussed that it is unfortunate that we do
not
have a method to validate initial RAM images in the UEFI context.
To me it would look like a good path forward to combine the two
ideas:
- Let the signed FIT image (of type IH_OS_EFI) contain a RAM disk
- Pass location and size to the UEFI subsystem and serve them via the EFI_FILE_LOAD2_PROTOCOL.
We could also extend the bootefi command to be callable as
bootefi $kernel_addr_r $ramdisk_addr_r:$filesize $fdt_addr_r
like the booti command to serve an initial RAM disk.
What are your thoughts?
Hi Heinrich,
I've got concerns about this approach. Even though it uses the UEFI infrastructure, images deployed in this way are U-Boot specific and won't ever be applicable on EDK2 or other UEFI implementations.
However there is another way to approach it which I think Francois touched on. If instead a UEFI stub was added to the FIT image, in the same way that the kernel has a UEFI stub, then the logic of decoding the FIT and choosing the correct DTB & initrd can be part of the image and it becomes applicable to any UEFI implementation. It would also address
Ard's concern of loading the FIT into memory, and then copying due to the EFI_FILE_LOAD2 path. The FIT stub would already know the image is in RAM, that is is reserved correctly, and just pass the correct addresses
to the kernel as part of the normal boot flow.
Signing would also be taken care of because the whole FIT can be signed, and that signature would be checked when it gets loaded.
Thoughts?
The gain of a fit image in U-Boot used for calling the Linux kernel via the EFI stub vs calling the legacy entry point comes down to providing the EFI_RNG_PROTOCOL to be used for KASLR.
I agree with that, but that is not my concern.
My concern is that the FIT image format will only be supported by U-Boot. Other UEFI implementations do not implement it.
On the other hand, adding a UEFI Stub to the FIT image format makes it a generic solution that can be used by any UEFI implementation. This would be separate from the linux kernel's UEFI stub, and should only deal with choosing the appropriate kernel/initrd/dtb from the FIT and then calling into the kernel's stub to actually boot the kernel.
For initrd a stub UEFI binary will work. But if you want to provide a kernel specific dtb with the same stub binary it will require a new service for device-tree fixups.
Devicetree fixups indeed needs to be solved. I would propose registering a new protocol for fixups. If the protocol is present, then stub can call it. If not, then the DTB from the fit should be used unmodified.
For such a protocol we will need to decide who will make the memory reservation needed to encompass the increasing size of the device tree.
As the caller of the protocol does not know how much memory is needed for the fixup I think the allocation should be done by the callee.
A definition of the protocol could look like this:
#define EFI_FDT_FIXUP_PROTOCOL_GUID \ {0xfa68b9a7, 0xb5fd, 0x49f5, \ {0x87, 0x93, 0x11, 0xfd, 0xb5, 0x6a, 0x8d, 0x41}
typedef EFI_STATUS (EFIAPI *EFI_FDT_FIXUP) ( IN EFI_FDT_FIXUP_PROTOCOL *This, IN OUT VOID **Fdt, IN BOOLEAN Install, };
typedef struct _EFI_FDT_FIXUP_PROTOCOL { EFI_FIX_UP Fixup; } EFI_FDT_FIXUP_PROTOCOL;
where
- This - pointer to the calling context
- Fdt - On entry pointer to the address of the original device tree, on exit pointer to the address of the new device tree. If an error is returned, the value of *Fdt is undefined.
- Install - If TRUE, install the resulting device tree as configuration table.
The 'Fixup' service
- makes a memory reservation using EFI_BOOT_SERVICES.AllocatePages(),
- copies the device tree to the new memory area,
- applies the fixups,
- installs the resulting device tree as configuration table if Install==TRUE.
In case of an error the protocol implementation releases the memory by calling EFI_BOOT_SERVICES.FreePages().
Return values:
- EFI_INVALID_PARAMETER - Fdt is NULL.
- EFI_INVALID_PARAMETER - *Fdt does not point to a valid device tree.
- EFI_OUT_OF_RESOURCES - Not enough memory for the operation.
- EFI_SUCCESS - The fixup was successful and the device-tree was installed if requested.
I like the idea;
it can do for fixups what we have for firmware updates: UEFI update capsules reach UEFI, there are UEFI drivers for underlying firmware components to adapt the request. Platforms can append relevant drivers to call in TF-A or OP-TEE for fixups. The implementation is platform specific. For some platforms this would result in an SMC call to get the fixups done, for others, this is about reading memory locations. In addition to presenting no constraints between platforms within an architecture, it is also architecture agnostic.
Best regards
Heinrich
Hi Grant,
[...]
Hi Heinrich,
I've got concerns about this approach. Even though it uses the UEFI infrastructure, images deployed in this way are U-Boot specific and won't ever be applicable on EDK2 or other UEFI implementations.
However there is another way to approach it which I think Francois touched on. If instead a UEFI stub was added to the FIT image, in the same way that the kernel has a UEFI stub, then the logic of decoding the FIT and choosing the correct DTB & initrd can be part of the image and it becomes applicable to any UEFI implementation. It would also address
Ard's concern of loading the FIT into memory, and then copying due to the EFI_FILE_LOAD2 path. The FIT stub would already know the image is in RAM, that is is reserved correctly, and just pass the correct addresses
to the kernel as part of the normal boot flow.
Signing would also be taken care of because the whole FIT can be signed, and that signature would be checked when it gets loaded.
Thoughts?
The gain of a fit image in U-Boot used for calling the Linux kernel via the EFI stub vs calling the legacy entry point comes down to providing the EFI_RNG_PROTOCOL to be used for KASLR.
I agree with that, but that is not my concern.
My concern is that the FIT image format will only be supported by U-Boot. Other UEFI implementations do not implement it.
On the other hand, adding a UEFI Stub to the FIT image format makes it a generic solution that can be used by any UEFI implementation. This would be separate from the linux kernel's UEFI stub, and should only deal with choosing the appropriate kernel/initrd/dtb from the FIT and then calling into the kernel's stub to actually boot the kernel.
If we are considering a cross-firmware solution for this why base it on FIT? Wouldn't a single EFI application (that's aware of the signatures and how to verify them) do the job? Just to inherit the work on signatures already done in FIT?
For initrd a stub UEFI binary will work. But if you want to provide a kernel specific dtb with the same stub binary it will require a new service for device-tree fixups.
Devicetree fixups indeed needs to be solved. I would propose registering a new protocol for fixups. If the protocol is present, then stub can call it. If not, then the DTB from the fit should be used unmodified.
g.
So if you do this in a single EFI app, you wont need an extra protocol for it right?
Thanks /Ilias
On 06/10/2020 13:41, Ilias Apalodimas wrote:
Hi Grant,
[...]
Hi Heinrich,
I've got concerns about this approach. Even though it uses the UEFI infrastructure, images deployed in this way are U-Boot specific and won't ever be applicable on EDK2 or other UEFI implementations.
However there is another way to approach it which I think Francois touched on. If instead a UEFI stub was added to the FIT image, in the same way that the kernel has a UEFI stub, then the logic of decoding the FIT and choosing the correct DTB & initrd can be part of the image and it becomes applicable to any UEFI implementation. It would also address
Ard's concern of loading the FIT into memory, and then copying due to the EFI_FILE_LOAD2 path. The FIT stub would already know the image is in RAM, that is is reserved correctly, and just pass the correct addresses
to the kernel as part of the normal boot flow.
Signing would also be taken care of because the whole FIT can be signed, and that signature would be checked when it gets loaded.
Thoughts?
The gain of a fit image in U-Boot used for calling the Linux kernel via the EFI stub vs calling the legacy entry point comes down to providing the EFI_RNG_PROTOCOL to be used for KASLR.
I agree with that, but that is not my concern.
My concern is that the FIT image format will only be supported by U-Boot. Other UEFI implementations do not implement it.
On the other hand, adding a UEFI Stub to the FIT image format makes it a generic solution that can be used by any UEFI implementation. This would be separate from the linux kernel's UEFI stub, and should only deal with choosing the appropriate kernel/initrd/dtb from the FIT and then calling into the kernel's stub to actually boot the kernel.
If we are considering a cross-firmware solution for this why base it on FIT? Wouldn't a single EFI application (that's aware of the signatures and how to verify them) do the job? Just to inherit the work on signatures already done in FIT?
Hahaha! I wasn't going to bring that up because I didn't want to cause extra trouble. :-) But yes, you're right. If we have a UEFI stub on the container, then it doesn't matter what the container format is. cpio, tar.gz, zip, FAT image, etc. Any of those would work.
For initrd a stub UEFI binary will work. But if you want to provide a kernel specific dtb with the same stub binary it will require a new service for device-tree fixups.
Devicetree fixups indeed needs to be solved. I would propose registering a new protocol for fixups. If the protocol is present, then stub can call it. If not, then the DTB from the fit should be used unmodified.
g.
So if you do this in a single EFI app, you wont need an extra protocol for it right?
True, you could embed the DT fixups into the EFI stub itself, but that would end up being completely separate logic from the fixup code already in U-Boot.
g.
On 06.10.20 14:46, Grant Likely wrote:
On 06/10/2020 13:41, Ilias Apalodimas wrote:
Hi Grant,
[...]
Hi Heinrich,
I've got concerns about this approach. Even though it uses the UEFI infrastructure, images deployed in this way are U-Boot specific and won't ever be applicable on EDK2 or other UEFI implementations.
However there is another way to approach it which I think Francois touched on. If instead a UEFI stub was added to the FIT image, in the same way that the kernel has a UEFI stub, then the logic of decoding the FIT and choosing the correct DTB & initrd can be part of the image and it becomes applicable to any UEFI implementation. It would also address
Ard's concern of loading the FIT into memory, and then copying due to the EFI_FILE_LOAD2 path. The FIT stub would already know the image is in RAM, that is is reserved correctly, and just pass the correct addresses
to the kernel as part of the normal boot flow.
Signing would also be taken care of because the whole FIT can be signed, and that signature would be checked when it gets loaded.
Thoughts?
The gain of a fit image in U-Boot used for calling the Linux kernel via the EFI stub vs calling the legacy entry point comes down to providing the EFI_RNG_PROTOCOL to be used for KASLR.
I agree with that, but that is not my concern.
My concern is that the FIT image format will only be supported by U-Boot. Other UEFI implementations do not implement it.
On the other hand, adding a UEFI Stub to the FIT image format makes it a generic solution that can be used by any UEFI implementation. This would be separate from the linux kernel's UEFI stub, and should only deal with choosing the appropriate kernel/initrd/dtb from the FIT and then calling into the kernel's stub to actually boot the kernel.
If we are considering a cross-firmware solution for this why base it on FIT? Wouldn't a single EFI application (that's aware of the signatures and how to verify them) do the job? Just to inherit the work on signatures already done in FIT?
Hahaha! I wasn't going to bring that up because I didn't want to cause extra trouble. :-) But yes, you're right. If we have a UEFI stub on the container, then it doesn't matter what the container format is. cpio, tar.gz, zip, FAT image, etc. Any of those would work.
For initrd a stub UEFI binary will work. But if you want to provide a kernel specific dtb with the same stub binary it will require a new service for device-tree fixups.
Devicetree fixups indeed needs to be solved. I would propose registering a new protocol for fixups. If the protocol is present, then stub can call it. If not, then the DTB from the fit should be used unmodified.
g.
So if you do this in a single EFI app, you wont need an extra protocol for it right?
True, you could embed the DT fixups into the EFI stub itself, but that would end up being completely separate logic from the fixup code already in U-Boot.
Many fixups are hardware related. We should not write that logic twice.
You could think of copying fixups from the firmware device-tree to the stub device-tree but this too would be a very device specific solution.
Having the firmware (e.g. U-Boot) do the fixup would provide a solution that is much more generic.
Best regards
Heinrich
On Tue, 6 Oct 2020 at 15:12, Heinrich Schuchardt xypron.glpk@gmx.de wrote:
On 06.10.20 14:46, Grant Likely wrote:
On 06/10/2020 13:41, Ilias Apalodimas wrote:
Hi Grant,
[...]
Hi Heinrich,
I've got concerns about this approach. Even though it uses the UEFI infrastructure, images deployed in this way are U-Boot specific and won't ever be applicable on EDK2 or other UEFI implementations.
However there is another way to approach it which I think Francois touched on. If instead a UEFI stub was added to the FIT image, in the same way that the kernel has a UEFI stub, then the logic of decoding the FIT and choosing the correct DTB & initrd can be part of the image
and
it becomes applicable to any UEFI implementation. It would also address
Ard's concern of loading the FIT into memory, and then copying due to the EFI_FILE_LOAD2 path. The FIT stub would already know the image is in RAM, that is is reserved correctly, and just pass the correct addresses
to the kernel as part of the normal boot flow.
Signing would also be taken care of because the whole FIT can be signed, and that signature would be checked when it gets loaded.
Thoughts?
The gain of a fit image in U-Boot used for calling the Linux kernel via the EFI stub vs calling the legacy entry point comes down to providing the EFI_RNG_PROTOCOL to be used for KASLR.
I agree with that, but that is not my concern.
My concern is that the FIT image format will only be supported by U-Boot. Other UEFI implementations do not implement it.
On the other hand, adding a UEFI Stub to the FIT image format makes it
a
generic solution that can be used by any UEFI implementation. This would be separate from the linux kernel's UEFI stub, and should only deal with choosing the appropriate kernel/initrd/dtb from the FIT and then
calling
into the kernel's stub to actually boot the kernel.
If we are considering a cross-firmware solution for this why base it on FIT? Wouldn't a single EFI application (that's aware of the signatures and
how
to verify them) do the job? Just to inherit the work on signatures already done in FIT?
Hahaha! I wasn't going to bring that up because I didn't want to cause extra trouble. :-) But yes, you're right. If we have a UEFI stub on the container, then it doesn't matter what the container format is. cpio, tar.gz, zip, FAT image, etc. Any of those would work.
For initrd a stub UEFI binary will work. But if you want to provide a kernel specific dtb with the same stub binary it will require a new service for device-tree fixups.
Devicetree fixups indeed needs to be solved. I would propose registering a new protocol for fixups. If the protocol is present, then stub can call it. If not, then the DTB from the fit should be used unmodified.
g.
So if you do this in a single EFI app, you wont need an extra protocol for it right?
True, you could embed the DT fixups into the EFI stub itself, but that would end up being completely separate logic from the fixup code already in U-Boot.
Many fixups are hardware related. We should not write that logic twice.
You could think of copying fixups from the firmware device-tree to the stub device-tree but this too would be a very device specific solution.
Having the firmware (e.g. U-Boot) do the fixup would provide a solution that is much more generic.
Agreed. U-Boot actually should orchestrate fixups (the protocol you just proposed) and do its own fixups ([chosen][, serial numbers][, part numbers][, MAC addresses]...).
Best regards
Heinrich
boot-architecture@lists.linaro.org