On 12.08.21 13:45, Christian Storm wrote:
> Hi,
>
>> a heads up and public documentation after a very useful internal
>> discussion yesterday:
>>
>> EFI Boot Guard roughly falls into two pieces, namely the EFI loader and
>> the Linux tools/libs. As one purpose of the loader is to compensate
>> incomplete or possibly unsafe boot path selections/rollbacks via the
>> firmware, the loader is not part of (safe) OTA updates. The userland
>> tools may reside in updateable rootfs images, thus could move forward
>> without breaking a rollback.
>>
>> Now, this may lead to userland becoming much more recent than the loader
>> on concrete system in the field. The interface between both is the
>> BGENV.DAT on the respective boot partitions. Luckily, it's format
>> (BG_ENVDATA) didn't change in structure and semantic since release v0.2.
>> So you may mix an older (not prehistoric) loader version with newer
>> userland - if you have good reasons to do so.
>>
>> However, that compatibility may not always be givin in the future - who
>> knows. The challenge will then be that our current structure does not
>> foresee any versioning of the structure itself ("revision" is that of
>> the managed boot partition). We should therefore change this in order to
>> become extensible.
>>
>> How to do that without breaking existing installations from today?
>> Luckily, there is one variable that we can use for this, and that is the
>> file size of BGENV.DAT. We will have to grow it, at least by a word that
>> holds the structure version, and loader as well as userland tools need
>> to check via the size if they see version 1 (current file size) or
>> version 2 (extended struct with version field).
>
> Well, it's rather implicit specifying the environment version by file
> size.... However, if you can ensure the environment file size is
> strictly monotonically increasing on changes (and as well on changes not
> increasing the file size by an artificial increase), you don't need
...and the semantic of no existing field will never change - so, no,
better add a struct revision.
> the extra struct field 'version' as there's already a bijective mapping
> between file size and version.
>
> Having an environment 'version' field is not an end in itself though, so
> what's to be added to the "core" struct fields (BG_ENVDATA) besides 'version'?
>
> That said, we do have "user-defined variables" in the environment
> exactly for this use case: to store more information in the environment
> than the "core" struct fields allow for. Can't this mechanism be
> leveraged?
That's an alternative hack to the file size. It's not an official
revision of the struct, though, as it's "user-defined".
>
> Granted, even if, this mechanism is also (compile-time) limited (in
> space), per default to #define ENV_MEM_USERVARS 131072.
> So, to be truly extensible, the environment file format should be
> converted from a fixed-length to a run-length encoded format, then
> making a 'version' field mandatory to know which particular struct
> version to read from the environment file ― if you stick to the binary
> format, that is...
Right, we may use the chance to encode the actual struct size as well,
in order to decouple that from a file size.
>
>
>> The plan is to add such an extension soon, possibly before the next
>> release. That shall come in a backward-compatible manner for userland. A
>> newer loader may simply demand the extended structure, though, to make
>> things simpler.
>
> The (implicit) assumption here is that userspace is always newer than
> the EFI loader binary, right? Otherwise, if a new(er) EFI loader binary
> demands a particular environment version that the old(er) userspace
> does not know of, you're again in the weeds. This may happen, e.g., for
> old(er) rescue media or the like.
>
Right, that would have been the assumption - but the rescue use case
indeed questions this.
>
>> One feature request from the internal discussion remains open so far:
>> How to read out the version of the installed loader from the userland
>> tools (and display it)? Unsure about this one so far, if BGENV.DAT
>> should carry it (risk of becoming stale) or if userland should add
>> support for extracting it from the installed loader binary or if we
>> should skip that.
>
> The only source of truth for this information is the EFI loader binary
> itself. So, assuming you can read the EFI loader binary from userspace,
> you can leverage the ― for the purpose of UEFI unused ― PE header fields
> for this by encoding the version in, e.g., the MajorImageVersion and
> MinorImageVersion fields. Of course, you have to have precautionary
> measures in place in the userspace tools so not to write information to
> the environment that the EFI loader binary cannot handle ― judged on by
> the EFI loader binary's encoded version.
> Currently, the EFI binary binary's MajorImageVersion and
> MinorImageVersion are both 0 which then indicates compatibility with the
> initial and currently only environment version.
>
> You may also encode the expected environment file size (if you want to
> go that route) a.k.a. 'version' in some PE header field so that the
> EFI loader binary can judge on whether the loaded environment file is
> digestible for it or not...
>
Well, that is much easier managed in the code itself because the logic
there need to know the size(s) it supports anyway.
Jan
--
Siemens AG, T RDA IOT
Corporate Competence Center Embedded Linux
--
You received this message because you are subscribed to the Google Groups "EFI
Boot Guard" group.
To unsubscribe from this group and stop receiving emails from it, send an email
to [email protected].
To view this discussion on the web visit
https://groups.google.com/d/msgid/efibootguard-dev/54c370bb-0e1c-4579-d7b6-6ed844a9388a%40siemens.com.