[PATCH] efi_loader: convert void* to u8* on the tcg eventlog buffer
Alex G.
mr.nuke.me at gmail.com
Mon Mar 29 20:41:37 CEST 2021
Hi Ilias,
On 3/29/21 8:59 AM, Ilias Apalodimas wrote:
> Although ptr arithmetics are allowed with extensions in gcc, they
> are not allowed by the C spec. So switch the 'void *' containing our
> eventlog buffer into 'u8 *'
NAK. This patch is in my opinion wrong.
In C, void * can point to anything. The same is not true of a u8*. You
can take a generic pointer, assign it to a void pointer, then assign
back to the original type. u8* has an alignment of 1. While the compiler
can now do math on u8*, it only has to worry about an alignment of 1. As
you can imagine, this can have unintended consequences when the data
behind the pointer is not actually an array of u8.
The correct way in C to do pointer arithmetic is to go via uintptr_t.
You still have to manually make sure you keep alignment and other
constraints, but this and only this is portable.
You can use either void * or the a pointer to the actual type. It's up
to you whether you want to use a uintptr_t in struct event_log_buffer,
or cast to uintptr_t when you do the actual pointer math, then cast back
to void *.
> Signed-off-by: Ilias Apalodimas <ilias.apalodimas at linaro.org>
> ---
> lib/efi_loader/efi_tcg2.c | 8 ++++----
> 1 file changed, 4 insertions(+), 4 deletions(-)
>
> diff --git a/lib/efi_loader/efi_tcg2.c b/lib/efi_loader/efi_tcg2.c
> index 09046844c723..d5213586cb9c 100644
> --- a/lib/efi_loader/efi_tcg2.c
> +++ b/lib/efi_loader/efi_tcg2.c
> @@ -23,8 +23,8 @@
> #include <hexdump.h>
>
> struct event_log_buffer {
> - void *buffer;
> - void *final_buffer;
> + u8 *buffer;
> + u8 *final_buffer;
> size_t pos; /* eventlog position */
> size_t final_pos; /* final events config table position */
> size_t last_event_size;
> @@ -990,12 +990,12 @@ static efi_status_t create_final_event(void)
> * EFI_CONFIGURATION_TABLE
> */
> ret = efi_allocate_pool(EFI_ACPI_MEMORY_NVS, TPM2_EVENT_LOG_SIZE,
> - &event_log.final_buffer);
> + (void **)&event_log.final_buffer);
Now this sort of cast I would rather avoid. Double pointer casts rarely
do what you want them to do. For once, if someone ever changes
final_buffer to be a const pointer, you've lost that in this cast. The
compiler likely won't warn you. So you've just exposed this code to
possible silent failures.
BTW, without looking at stack overflow would that be a (const void **),
(void * const *), or (void ** const) ?
> if (ret != EFI_SUCCESS)
> goto out;
>
> memset(event_log.final_buffer, 0xff, TPM2_EVENT_LOG_SIZE);
> - final_event = event_log.final_buffer;
> + final_event = (struct efi_tcg2_final_events_table *)event_log.final_buffer;
This sort of cast is also undefined. Why not make event_log.final_buffer
a struct efi_tcg2_final_events_table * in the first place?
> final_event->number_of_events = 0;
> final_event->version = EFI_TCG2_FINAL_EVENTS_TABLE_VERSION;
> event_log.final_pos = sizeof(*final_event);
>
More information about the U-Boot
mailing list