boot: initialize return parameters on zero-length EFI variable read
When a variable exists but is empty, the initial size-query
GetVariable() in efivar_get_raw_full() returns EFI_SUCCESS instead of
EFI_BUFFER_TOO_SMALL: the zero-length payload already "fits" the
zero-length query buffer. The helper returns success, but does not
initialize the return parameters.
Handle a couple of corner cases by checking the return size.
Follow-up for a409607489
This commit is contained in:
@@ -191,6 +191,16 @@ EFI_STATUS efivar_get_raw_full(
|
||||
|
||||
size_t size = 0;
|
||||
err = RT->GetVariable((char16_t *) name, (EFI_GUID *) vendor, NULL, &size, NULL);
|
||||
if (err == EFI_SUCCESS) {
|
||||
/* The variable exists but is empty, initialize return parameters */
|
||||
if (ret_attributes)
|
||||
*ret_attributes = 0;
|
||||
if (ret_data)
|
||||
*ret_data = NULL;
|
||||
if (ret_size)
|
||||
*ret_size = 0;
|
||||
return EFI_SUCCESS;
|
||||
}
|
||||
if (err != EFI_BUFFER_TOO_SMALL)
|
||||
return err;
|
||||
|
||||
@@ -222,6 +232,9 @@ EFI_STATUS efivar_get_boolean_u8(const EFI_GUID *vendor, const char16_t *name, b
|
||||
if (err != EFI_SUCCESS)
|
||||
return err;
|
||||
|
||||
if (size == 0)
|
||||
return EFI_BUFFER_TOO_SMALL;
|
||||
|
||||
if (ret)
|
||||
*ret = *b > 0;
|
||||
|
||||
|
||||
+11
-5
@@ -62,7 +62,7 @@ bool is_direct_boot(EFI_HANDLE device) {
|
||||
EFI_STATUS vmm_open(EFI_HANDLE *ret_vmm_dev, EFI_FILE **ret_vmm_dir) {
|
||||
_cleanup_free_ EFI_HANDLE *handles = NULL;
|
||||
size_t n_handles;
|
||||
EFI_STATUS err, dp_err;
|
||||
EFI_STATUS err;
|
||||
|
||||
assert(ret_vmm_dev);
|
||||
assert(ret_vmm_dir);
|
||||
@@ -79,9 +79,15 @@ EFI_STATUS vmm_open(EFI_HANDLE *ret_vmm_dev, EFI_FILE **ret_vmm_dir) {
|
||||
|
||||
for (size_t order = 0;; order++) {
|
||||
_cleanup_free_ EFI_DEVICE_PATH *dp = NULL;
|
||||
size_t dp_size = 0;
|
||||
|
||||
_cleanup_free_ char16_t *order_str = xasprintf("VMMBootOrder%04zx", order);
|
||||
dp_err = efivar_get_raw(MAKE_GUID_PTR(VMM_BOOT_ORDER), order_str, (void**) &dp, NULL);
|
||||
err = efivar_get_raw(MAKE_GUID_PTR(VMM_BOOT_ORDER), order_str, (void**) &dp, &dp_size);
|
||||
|
||||
/* Drop the device path from the (untrusted) EFI variable if it doesn't validate, so the
|
||||
* check below simply has to test whether it is set. */
|
||||
if (err == EFI_SUCCESS && !device_path_is_valid(dp, dp_size))
|
||||
dp = mfree(dp);
|
||||
|
||||
for (size_t i = 0; i < n_handles; i++) {
|
||||
_cleanup_file_close_ EFI_FILE *root_dir = NULL, *efi_dir = NULL;
|
||||
@@ -92,8 +98,8 @@ EFI_STATUS vmm_open(EFI_HANDLE *ret_vmm_dev, EFI_FILE **ret_vmm_dir) {
|
||||
if (err != EFI_SUCCESS)
|
||||
return err;
|
||||
|
||||
/* check against VMMBootOrderNNNN (if set) */
|
||||
if (dp_err == EFI_SUCCESS && !device_path_startswith(fs, dp))
|
||||
/* check against VMMBootOrderNNNN (if set and valid) */
|
||||
if (dp && !device_path_startswith(fs, dp))
|
||||
continue;
|
||||
|
||||
err = open_volume(handles[i], &root_dir);
|
||||
@@ -112,7 +118,7 @@ EFI_STATUS vmm_open(EFI_HANDLE *ret_vmm_dev, EFI_FILE **ret_vmm_dir) {
|
||||
return EFI_SUCCESS;
|
||||
}
|
||||
|
||||
if (dp_err != EFI_SUCCESS)
|
||||
if (!dp)
|
||||
return EFI_NOT_FOUND;
|
||||
}
|
||||
assert_not_reached();
|
||||
|
||||
Reference in New Issue
Block a user