diff options
author | Heinrich Schuchardt <xypron.glpk@gmx.de> | 2020-05-31 22:46:09 +0200 |
---|---|---|
committer | Heinrich Schuchardt <xypron.glpk@gmx.de> | 2020-06-03 17:19:17 +0200 |
commit | 0e69bcfb27644f9e7c575aa3565bcff922c7dec2 (patch) | |
tree | 1560106fb519adf2d1ac3f6214cc4383df2b0b49 /lib | |
parent | ecd4d99f654f3f7bfb96001891d69c3125e70b69 (diff) |
efi_loader: validate load option
For passing the optional data of the load option to the loaded imaged
protocol we need its size.
efi_deserialize_load_option() is changed to return the size of the optional
data.
As a by-product we get a partial validation of the load option.
Checking the length of the device path remains to be implemented.
Some Coverity defects identified the load options as user input because
get_unaligned_le32() and get_unaligned_le16() is called. But non of these
Coverity defects can be resolved without marking functions with Coverity
specific tags.
Reported-by: Coverity (CID 303760)
Reported-by: Coverity (CID 303768)
Reported-by: Coverity (CID 303776)
Signed-off-by: Heinrich Schuchardt <xypron.glpk@gmx.de>
Diffstat (limited to 'lib')
-rw-r--r-- | lib/efi_loader/efi_bootmgr.c | 48 |
1 files changed, 39 insertions, 9 deletions
diff --git a/lib/efi_loader/efi_bootmgr.c b/lib/efi_loader/efi_bootmgr.c index b112f5d81e..e144b3e7f4 100644 --- a/lib/efi_loader/efi_bootmgr.c +++ b/lib/efi_loader/efi_bootmgr.c @@ -36,24 +36,50 @@ static const struct efi_runtime_services *rs; * * @lo: pointer to target * @data: serialized data + * @size: size of the load option, on return size of the optional data + * Return: status code */ -void efi_deserialize_load_option(struct efi_load_option *lo, u8 *data) +efi_status_t efi_deserialize_load_option(struct efi_load_option *lo, u8 *data, + efi_uintn_t *size) { + efi_uintn_t len; + + len = sizeof(u32); + if (*size < len + 2 * sizeof(u16)) + return EFI_INVALID_PARAMETER; lo->attributes = get_unaligned_le32(data); - data += sizeof(u32); + data += len; + *size -= len; + len = sizeof(u16); lo->file_path_length = get_unaligned_le16(data); - data += sizeof(u16); + data += len; + *size -= len; - /* FIXME */ lo->label = (u16 *)data; - data += (u16_strlen(lo->label) + 1) * sizeof(u16); - - /* FIXME */ + len = u16_strnlen(lo->label, *size / sizeof(u16) - 1); + if (lo->label[len]) + return EFI_INVALID_PARAMETER; + len = (len + 1) * sizeof(u16); + if (*size < len) + return EFI_INVALID_PARAMETER; + data += len; + *size -= len; + + len = lo->file_path_length; + if (*size < len) + return EFI_INVALID_PARAMETER; lo->file_path = (struct efi_device_path *)data; - data += lo->file_path_length; + /* + * TODO: validate device path. There should be an end node within + * the indicated file_path_length. + */ + data += len; + *size -= len; lo->optional_data = data; + + return EFI_SUCCESS; } /** @@ -168,7 +194,11 @@ static efi_status_t try_load_entry(u16 n, efi_handle_t *handle) if (!load_option) return EFI_LOAD_ERROR; - efi_deserialize_load_option(&lo, load_option); + ret = efi_deserialize_load_option(&lo, load_option, &size); + if (ret != EFI_SUCCESS) { + log_warning("Invalid load option for %ls\n", varname); + goto error; + } if (lo.attributes & LOAD_OPTION_ACTIVE) { u32 attributes; |