efi_loader: Set variable attributes when EFI_BUFFER_TOO_SMALL is returned
authorIlias Apalodimas <ilias.apalodimas@linaro.org>
Wed, 16 Mar 2022 15:13:37 +0000 (17:13 +0200)
committerHeinrich Schuchardt <heinrich.schuchardt@canonical.com>
Sun, 20 Mar 2022 10:03:06 +0000 (11:03 +0100)
Starting UEFI Spec 2.8 we must fill in the variable attributes when
GetVariable() returns EFI_BUFFER_TOO_SMALL and Attributes is non-NULL.

This code was written with 2.7 in mind so let's move the code around a
bit and fill in the attributes EFI_BUFFER_TOO_SMALL is returned

Signed-off-by: Ilias Apalodimas <ilias.apalodimas@linaro.org>
Reviewed-by: Heinrich Schuchardt <heinrich.schuchardt@canonical.com>
lib/efi_loader/efi_variable_tee.c

index 58931c4..dfef184 100644 (file)
@@ -368,7 +368,7 @@ efi_status_t efi_get_variable_int(const u16 *variable_name,
        efi_uintn_t name_size;
        efi_uintn_t tmp_dsize;
        u8 *comm_buf = NULL;
-       efi_status_t ret;
+       efi_status_t ret, tmp;
 
        if (!variable_name || !vendor || !data_size) {
                ret = EFI_INVALID_PARAMETER;
@@ -407,23 +407,32 @@ efi_status_t efi_get_variable_int(const u16 *variable_name,
 
        /* Communicate */
        ret = mm_communicate(comm_buf, payload_size);
-       if (ret == EFI_SUCCESS || ret == EFI_BUFFER_TOO_SMALL) {
-               /* Update with reported data size for trimmed case */
-               *data_size = var_acc->data_size;
-       }
-       if (ret != EFI_SUCCESS)
-               goto out;
-
-       ret = get_property_int(variable_name, name_size, vendor, &var_property);
-       if (ret != EFI_SUCCESS)
+       if (ret != EFI_SUCCESS && ret != EFI_BUFFER_TOO_SMALL)
                goto out;
 
+       /* Update with reported data size for trimmed case */
+       *data_size = var_acc->data_size;
+       /*
+        * UEFI > 2.7 needs the attributes set even if the buffer is
+        * smaller
+        */
        if (attributes) {
+               tmp = get_property_int(variable_name, name_size, vendor,
+                                      &var_property);
+               if (tmp != EFI_SUCCESS) {
+                       ret = tmp;
+                       goto out;
+               }
                *attributes = var_acc->attr;
-               if (var_property.property & VAR_CHECK_VARIABLE_PROPERTY_READ_ONLY)
+               if (var_property.property &
+                   VAR_CHECK_VARIABLE_PROPERTY_READ_ONLY)
                        *attributes |= EFI_VARIABLE_READ_ONLY;
        }
 
+       /* return if ret is EFI_BUFFER_TOO_SMALL */
+       if (ret != EFI_SUCCESS)
+               goto out;
+
        if (data)
                memcpy(data, (u8 *)var_acc->name + var_acc->name_size,
                       var_acc->data_size);