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;
if (err != EFI_SUCCESS)
return err;
+ if (size == 0)
+ return EFI_BUFFER_TOO_SMALL;
+
if (ret)
*ret = *b > 0;
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);
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;
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);
return EFI_SUCCESS;
}
- if (dp_err != EFI_SUCCESS)
+ if (!dp)
return EFI_NOT_FOUND;
}
assert_not_reached();