From b0f1c728c82c25291895d66e591fa2a6851ba374 Mon Sep 17 00:00:00 2001 From: Heinrich Schuchardt Date: Fri, 6 Sep 2019 21:37:21 +0200 Subject: efi_loader: EFI_FILE_PROTOCOL.Write() check args Check the parameters passed to Write(): * cannot write to directories (UEFI SCT 2017, 5.7.3.5.15) * cannot write to file opened read only (UEFI SCT 2017, 5.7.3.5.16) Add missing comments. Signed-off-by: Heinrich Schuchardt --- lib/efi_loader/efi_file.c | 51 +++++++++++++++++++++++++++++++++++++---------- 1 file changed, 41 insertions(+), 10 deletions(-) diff --git a/lib/efi_loader/efi_file.c b/lib/efi_loader/efi_file.c index f4ca569..a13754a 100644 --- a/lib/efi_loader/efi_file.c +++ b/lib/efi_loader/efi_file.c @@ -1,8 +1,8 @@ // SPDX-License-Identifier: GPL-2.0+ /* - * EFI utils + * EFI_FILE_PROTOCOL * - * Copyright (c) 2017 Rob Clark + * Copyright (c) 2017 Rob Clark */ #include @@ -28,6 +28,7 @@ struct file_handle { struct file_system *fs; loff_t offset; /* current file position/cursor */ int isdir; + u64 open_mode; /* for reading a directory: */ struct fs_dir_stream *dirs; @@ -161,13 +162,13 @@ static int efi_create_file(struct file_handle *fh, u64 attributes) * @file_name: path of the file to be opened. '\', '.', or '..' may * be used as modifiers. A leading backslash indicates an * absolute path. - * @mode: bit mask indicating the access mode (read, write, + * @open_mode: bit mask indicating the access mode (read, write, * create) * @attributes: attributes for newly created file * Returns: handle to the opened file or NULL */ static struct efi_file_handle *file_open(struct file_system *fs, - struct file_handle *parent, u16 *file_name, u64 mode, + struct file_handle *parent, u16 *file_name, u64 open_mode, u64 attributes) { struct file_handle *fh; @@ -190,6 +191,7 @@ static struct efi_file_handle *file_open(struct file_system *fs, /* +2 is for null and '/' */ fh = calloc(1, sizeof(*fh) + plen + (flen * MAX_UTF8_PER_UTF16) + 2); + fh->open_mode = open_mode; fh->base = efi_file_handle_protocol; fh->fs = fs; @@ -218,9 +220,11 @@ static struct efi_file_handle *file_open(struct file_system *fs, goto error; if (!exists) { - if (!(mode & EFI_FILE_MODE_CREATE) || + if (!(open_mode & EFI_FILE_MODE_CREATE) || efi_create_file(fh, attributes)) goto error; + if (set_blk_dev(fh)) + goto error; } /* figure out if file is a directory: */ @@ -434,6 +438,19 @@ error: return EFI_EXIT(ret); } +/** + * efi_file_write() - write to file + * + * This function implements the Write() service of the EFI_FILE_PROTOCOL. + * + * See the Unified Extensible Firmware Interface (UEFI) specification for + * details. + * + * @file: file handle + * @buffer_size: number of bytes to write + * @buffer: buffer with the bytes to write + * Return: status code + */ static efi_status_t EFIAPI efi_file_write(struct efi_file_handle *file, efi_uintn_t *buffer_size, void *buffer) @@ -444,21 +461,35 @@ static efi_status_t EFIAPI efi_file_write(struct efi_file_handle *file, EFI_ENTRY("%p, %p, %p", file, buffer_size, buffer); + if (!file || !buffer_size || !buffer) { + ret = EFI_INVALID_PARAMETER; + goto out; + } + if (fh->isdir) { + ret = EFI_UNSUPPORTED; + goto out; + } + if (!(fh->open_mode & EFI_FILE_MODE_WRITE)) { + ret = EFI_ACCESS_DENIED; + goto out; + } + + if (!*buffer_size) + goto out; + if (set_blk_dev(fh)) { ret = EFI_DEVICE_ERROR; - goto error; + goto out; } - if (fs_write(fh->path, map_to_sysmem(buffer), fh->offset, *buffer_size, &actwrite)) { ret = EFI_DEVICE_ERROR; - goto error; + goto out; } - *buffer_size = actwrite; fh->offset += actwrite; -error: +out: return EFI_EXIT(ret); } -- cgit v1.1 From 87c4840610e037018b9df30b1a31896b0bd284a9 Mon Sep 17 00:00:00 2001 From: Heinrich Schuchardt Date: Sat, 7 Sep 2019 21:05:45 +0200 Subject: efi_loader: eliminate inline function ascii2unicode() ascii2unicode() can only convert characters 0x00-0x7f from UTF-8 to UTF-16. Use utf8_utf16_strcpy() instead. Signed-off-by: Heinrich Schuchardt --- include/efi_loader.h | 16 ---------------- lib/efi_loader/efi_device_path_to_text.c | 10 +++++----- lib/efi_loader/efi_file.c | 23 +++++++++++++++-------- 3 files changed, 20 insertions(+), 29 deletions(-) diff --git a/include/efi_loader.h b/include/efi_loader.h index 00eba8a..dd24a27 100644 --- a/include/efi_loader.h +++ b/include/efi_loader.h @@ -555,22 +555,6 @@ efi_status_t efi_dp_from_name(const char *dev, const char *devnr, (((_dp)->type == DEVICE_PATH_TYPE_##_type) && \ ((_dp)->sub_type == DEVICE_PATH_SUB_TYPE_##_subtype)) -/** - * ascii2unicode() - convert ASCII string to UTF-16 string - * - * A zero terminated ASCII string is converted to a zero terminated UTF-16 - * string. The output buffer must be preassigned. - * - * @unicode: preassigned output buffer for UTF-16 string - * @ascii: ASCII string to be converted - */ -static inline void ascii2unicode(u16 *unicode, const char *ascii) -{ - while (*ascii) - *(unicode++) = *(ascii++); - *unicode = 0; -} - static inline int guidcmp(const void *g1, const void *g2) { return memcmp(g1, g2, sizeof(efi_guid_t)); diff --git a/lib/efi_loader/efi_device_path_to_text.c b/lib/efi_loader/efi_device_path_to_text.c index b20b7c0..0f3796b 100644 --- a/lib/efi_loader/efi_device_path_to_text.c +++ b/lib/efi_loader/efi_device_path_to_text.c @@ -29,15 +29,15 @@ const efi_guid_t efi_guid_device_path_to_text_protocol = static u16 *efi_str_to_u16(char *str) { efi_uintn_t len; - u16 *out; + u16 *out, *dst; efi_status_t ret; - len = strlen(str) + 1; - ret = efi_allocate_pool(EFI_ALLOCATE_ANY_PAGES, len * sizeof(u16), - (void **)&out); + len = sizeof(u16) * (utf8_utf16_strlen(str) + 1); + ret = efi_allocate_pool(EFI_ALLOCATE_ANY_PAGES, len, (void **)&out); if (ret != EFI_SUCCESS) return NULL; - ascii2unicode(out, str); + dst = out; + utf8_utf16_strcpy(&dst, str); return out; } diff --git a/lib/efi_loader/efi_file.c b/lib/efi_loader/efi_file.c index a13754a..9f78b82 100644 --- a/lib/efi_loader/efi_file.c +++ b/lib/efi_loader/efi_file.c @@ -339,6 +339,7 @@ static efi_status_t dir_read(struct file_handle *fh, u64 *buffer_size, struct efi_file_info *info = buffer; struct fs_dirent *dent; unsigned int required_size; + u16 *dst; if (!fh->dirs) { assert(fh->offset == 0); @@ -381,7 +382,8 @@ static efi_status_t dir_read(struct file_handle *fh, u64 *buffer_size, } /* check buffer size: */ - required_size = sizeof(*info) + 2 * (strlen(dent->name) + 1); + required_size = sizeof(*info) + + 2 * (utf8_utf16_strlen(dent->name) + 1); if (*buffer_size < required_size) { *buffer_size = required_size; fh->dent = dent; @@ -398,7 +400,8 @@ static efi_status_t dir_read(struct file_handle *fh, u64 *buffer_size, if (dent->type == FS_DT_DIR) info->attribute |= EFI_FILE_DIRECTORY; - ascii2unicode(info->file_name, dent->name); + dst = info->file_name; + utf8_utf16_strcpy(&dst, dent->name); fh->offset++; @@ -577,6 +580,7 @@ static efi_status_t EFIAPI efi_file_getinfo(struct efi_file_handle *file, { struct file_handle *fh = to_fh(file); efi_status_t ret = EFI_SUCCESS; + u16 *dst; EFI_ENTRY("%p, %pUl, %p, %p", file, info_type, buffer_size, buffer); @@ -587,7 +591,8 @@ static efi_status_t EFIAPI efi_file_getinfo(struct efi_file_handle *file, loff_t file_size; /* check buffer size: */ - required_size = sizeof(*info) + 2 * (strlen(filename) + 1); + required_size = sizeof(*info) + + 2 * (utf8_utf16_strlen(filename) + 1); if (*buffer_size < required_size) { *buffer_size = required_size; ret = EFI_BUFFER_TOO_SMALL; @@ -613,7 +618,8 @@ static efi_status_t EFIAPI efi_file_getinfo(struct efi_file_handle *file, if (fh->isdir) info->attribute |= EFI_FILE_DIRECTORY; - ascii2unicode(info->file_name, filename); + dst = info->file_name; + utf8_utf16_strcpy(&dst, filename); } else if (!guidcmp(info_type, &efi_file_system_info_guid)) { struct efi_file_system_info *info = buffer; disk_partition_t part; @@ -628,8 +634,9 @@ static efi_status_t EFIAPI efi_file_getinfo(struct efi_file_handle *file, ret = EFI_DEVICE_ERROR; goto error; } - required_size = sizeof(info) + 2 * - (strlen((const char *)part.name) + 1); + required_size = sizeof(*info) + 2 * + (utf8_utf16_strlen((const char *)part.name) + + 1); if (*buffer_size < required_size) { *buffer_size = required_size; ret = EFI_BUFFER_TOO_SMALL; @@ -647,8 +654,8 @@ static efi_status_t EFIAPI efi_file_getinfo(struct efi_file_handle *file, * TODO: The volume label is not available in U-Boot. * Use the partition name as substitute. */ - ascii2unicode((u16 *)info->volume_label, - (const char *)part.name); + dst = info->volume_label; + utf8_utf16_strcpy(&dst, (const char *)part.name); } else { ret = EFI_UNSUPPORTED; } -- cgit v1.1 From 83a74ad14370b75051cabfc2eab01fd8556f3bdb Mon Sep 17 00:00:00 2001 From: Heinrich Schuchardt Date: Sat, 7 Sep 2019 22:34:07 +0200 Subject: efi_loader: correct reading of directories EFI_FILE_PROTOCOL.Read() is used both to read files and directories. When reaching the end of a directory we always have to return buffer size zero irrespective of the incoming buffer size. (The described scenario for a Shim quirk cannot arise because every directory has at least '.' and '..' as entries.) Even when the buffer_size is too small multiple times we have to keep a reference to our last read directory entry. When we return to the start of the directory via SetPosition() we must remove the reference to a previously kept directory entry. Signed-off-by: Heinrich Schuchardt --- lib/efi_loader/efi_file.c | 23 +++++------------------ 1 file changed, 5 insertions(+), 18 deletions(-) diff --git a/lib/efi_loader/efi_file.c b/lib/efi_loader/efi_file.c index 9f78b82..74ad878 100644 --- a/lib/efi_loader/efi_file.c +++ b/lib/efi_loader/efi_file.c @@ -338,7 +338,7 @@ static efi_status_t dir_read(struct file_handle *fh, u64 *buffer_size, { struct efi_file_info *info = buffer; struct fs_dirent *dent; - unsigned int required_size; + u64 required_size; u16 *dst; if (!fh->dirs) { @@ -346,6 +346,7 @@ static efi_status_t dir_read(struct file_handle *fh, u64 *buffer_size, fh->dirs = fs_opendir(fh->path); if (!fh->dirs) return EFI_DEVICE_ERROR; + fh->dent = NULL; } /* @@ -356,28 +357,13 @@ static efi_status_t dir_read(struct file_handle *fh, u64 *buffer_size, */ if (fh->dent) { dent = fh->dent; - fh->dent = NULL; } else { dent = fs_readdir(fh->dirs); } - if (!dent) { - /* no more files in directory: */ - /* workaround shim.efi bug/quirk.. as find_boot_csv() - * loops through directory contents, it initially calls - * read w/ zero length buffer to find out how much mem - * to allocate for the EFI_FILE_INFO, then allocates, - * and then calls a 2nd time. If we return size of - * zero the first time, it happily passes that to - * AllocateZeroPool(), and when that returns NULL it - * thinks it is EFI_OUT_OF_RESOURCES. So on first - * call return a non-zero size: - */ - if (*buffer_size == 0) - *buffer_size = sizeof(*info); - else - *buffer_size = 0; + /* no more files in directory */ + *buffer_size = 0; return EFI_SUCCESS; } @@ -389,6 +375,7 @@ static efi_status_t dir_read(struct file_handle *fh, u64 *buffer_size, fh->dent = dent; return EFI_BUFFER_TOO_SMALL; } + fh->dent = NULL; *buffer_size = required_size; memset(info, 0, required_size); -- cgit v1.1 From 9bb62fa63ba1e26ade9842588d98806b9fecd67e Mon Sep 17 00:00:00 2001 From: Heinrich Schuchardt Date: Sat, 7 Sep 2019 23:28:04 +0200 Subject: efi_loader: file size checks The file size has to be determined in multiple places. Factor out a common function. If on entry into EFI_FILE_PROTOCOL.Read() the current position is beyond the end of the file, return EFI_DEVICE_ERROR. Signed-off-by: Heinrich Schuchardt --- lib/efi_loader/efi_file.c | 69 +++++++++++++++++++++++++++-------------------- 1 file changed, 40 insertions(+), 29 deletions(-) diff --git a/lib/efi_loader/efi_file.c b/lib/efi_loader/efi_file.c index 74ad878..504b1d1 100644 --- a/lib/efi_loader/efi_file.c +++ b/lib/efi_loader/efi_file.c @@ -318,11 +318,42 @@ static efi_status_t EFIAPI efi_file_delete(struct efi_file_handle *file) return EFI_EXIT(ret); } +/** + * efi_get_file_size() - determine the size of a file + * + * @fh: file handle + * @file_size: pointer to receive file size + * Return: status code + */ +static efi_status_t efi_get_file_size(struct file_handle *fh, + loff_t *file_size) +{ + if (set_blk_dev(fh)) + return EFI_DEVICE_ERROR; + + if (fs_size(fh->path, file_size)) + return EFI_DEVICE_ERROR; + + return EFI_SUCCESS; +} + static efi_status_t file_read(struct file_handle *fh, u64 *buffer_size, void *buffer) { loff_t actread; + efi_status_t ret; + loff_t file_size; + + ret = efi_get_file_size(fh, &file_size); + if (ret != EFI_SUCCESS) + return ret; + if (file_size < fh->offset) { + ret = EFI_DEVICE_ERROR; + return ret; + } + if (set_blk_dev(fh)) + return EFI_DEVICE_ERROR; if (fs_read(fh->path, map_to_sysmem(buffer), fh->offset, *buffer_size, &actread)) return EFI_DEVICE_ERROR; @@ -341,6 +372,9 @@ static efi_status_t dir_read(struct file_handle *fh, u64 *buffer_size, u64 required_size; u16 *dst; + if (set_blk_dev(fh)) + return EFI_DEVICE_ERROR; + if (!fh->dirs) { assert(fh->offset == 0); fh->dirs = fs_opendir(fh->path); @@ -409,11 +443,6 @@ static efi_status_t EFIAPI efi_file_read(struct efi_file_handle *file, goto error; } - if (set_blk_dev(fh)) { - ret = EFI_DEVICE_ERROR; - goto error; - } - bs = *buffer_size; if (fh->isdir) ret = dir_read(fh, &bs, buffer); @@ -541,16 +570,9 @@ static efi_status_t EFIAPI efi_file_setpos(struct efi_file_handle *file, if (pos == ~0ULL) { loff_t file_size; - if (set_blk_dev(fh)) { - ret = EFI_DEVICE_ERROR; - goto error; - } - - if (fs_size(fh->path, &file_size)) { - ret = EFI_DEVICE_ERROR; + ret = efi_get_file_size(fh, &file_size); + if (ret != EFI_SUCCESS) goto error; - } - pos = file_size; } @@ -586,15 +608,9 @@ static efi_status_t EFIAPI efi_file_getinfo(struct efi_file_handle *file, goto error; } - if (set_blk_dev(fh)) { - ret = EFI_DEVICE_ERROR; - goto error; - } - - if (fs_size(fh->path, &file_size)) { - ret = EFI_DEVICE_ERROR; + ret = efi_get_file_size(fh, &file_size); + if (ret != EFI_SUCCESS) goto error; - } memset(info, 0, required_size); @@ -693,14 +709,9 @@ static efi_status_t EFIAPI efi_file_setinfo(struct efi_file_handle *file, } free(new_file_name); /* Check for truncation */ - if (set_blk_dev(fh)) { - ret = EFI_DEVICE_ERROR; - goto out; - } - if (fs_size(fh->path, &file_size)) { - ret = EFI_DEVICE_ERROR; + ret = efi_get_file_size(fh, &file_size); + if (ret != EFI_SUCCESS) goto out; - } if (file_size != info->file_size) { /* TODO: we do not support truncation */ EFI_PRINT("Truncation not supported\n"); -- cgit v1.1 From e692ed1d560f8d9ece0e0b9e57c91233825be7ed Mon Sep 17 00:00:00 2001 From: Heinrich Schuchardt Date: Sun, 8 Sep 2019 09:35:32 +0200 Subject: efi_loader: EFI_FILE_PROTOCOL rev 2 stub The UEFI specification requires to implement version 2 of the EFI_FILE_PROTOCOL. Provide the missing functions as stubs. Signed-off-by: Heinrich Schuchardt --- include/efi_api.h | 20 ++++++++++++++++---- lib/efi_loader/efi_file.c | 36 +++++++++++++++++++++++++++++++----- 2 files changed, 47 insertions(+), 9 deletions(-) diff --git a/include/efi_api.h b/include/efi_api.h index cb895f3..f43fb7a 100644 --- a/include/efi_api.h +++ b/include/efi_api.h @@ -1461,6 +1461,12 @@ struct efi_pxe_base_code_protocol { #define EFI_FILE_PROTOCOL_REVISION2 0x00020000 #define EFI_FILE_PROTOCOL_LATEST_REVISION EFI_FILE_PROTOCOL_REVISION2 +struct efi_file_io_token { + struct efi_event *event; + efi_status_t status; + efi_uintn_t buffer_size; + void *buffer;}; + struct efi_file_handle { u64 rev; efi_status_t (EFIAPI *open)(struct efi_file_handle *file, @@ -1483,10 +1489,16 @@ struct efi_file_handle { const efi_guid_t *info_type, efi_uintn_t buffer_size, void *buffer); efi_status_t (EFIAPI *flush)(struct efi_file_handle *file); - /* - * TODO: We currently only support EFI file protocol revision 0x00010000 - * while UEFI specs 2.4 - 2.7 prescribe revision 0x00020000. - */ + efi_status_t (EFIAPI *open_ex)(struct efi_file_handle *file, + struct efi_file_handle **new_handle, + u16 *file_name, u64 open_mode, u64 attributes, + struct efi_file_io_token *token); + efi_status_t (EFIAPI *read_ex)(struct efi_file_handle *file, + struct efi_file_io_token *token); + efi_status_t (EFIAPI *write_ex)(struct efi_file_handle *file, + struct efi_file_io_token *token); + efi_status_t (EFIAPI *flush_ex)(struct efi_file_handle *file, + struct efi_file_io_token *token); }; #define EFI_SIMPLE_FILE_SYSTEM_PROTOCOL_REVISION 0x00010000 diff --git a/lib/efi_loader/efi_file.c b/lib/efi_loader/efi_file.c index 504b1d1..4b53016 100644 --- a/lib/efi_loader/efi_file.c +++ b/lib/efi_loader/efi_file.c @@ -741,12 +741,34 @@ static efi_status_t EFIAPI efi_file_flush(struct efi_file_handle *file) return EFI_EXIT(EFI_SUCCESS); } +static efi_status_t EFIAPI efi_file_open_ex(struct efi_file_handle *file, + struct efi_file_handle **new_handle, + u16 *file_name, u64 open_mode, u64 attributes, + struct efi_file_io_token *token) +{ + return EFI_UNSUPPORTED; +} + +static efi_status_t EFIAPI efi_file_read_ex(struct efi_file_handle *file, + struct efi_file_io_token *token) +{ + return EFI_UNSUPPORTED; +} + +static efi_status_t EFIAPI efi_file_write_ex(struct efi_file_handle *file, + struct efi_file_io_token *token) +{ + return EFI_UNSUPPORTED; +} + +static efi_status_t EFIAPI efi_file_flush_ex(struct efi_file_handle *file, + struct efi_file_io_token *token) +{ + return EFI_UNSUPPORTED; +} + static const struct efi_file_handle efi_file_handle_protocol = { - /* - * TODO: We currently only support EFI file protocol revision 0x00010000 - * while UEFI specs 2.4 - 2.7 prescribe revision 0x00020000. - */ - .rev = EFI_FILE_PROTOCOL_REVISION, + .rev = EFI_FILE_PROTOCOL_REVISION2, .open = efi_file_open, .close = efi_file_close, .delete = efi_file_delete, @@ -757,6 +779,10 @@ static const struct efi_file_handle efi_file_handle_protocol = { .getinfo = efi_file_getinfo, .setinfo = efi_file_setinfo, .flush = efi_file_flush, + .open_ex = efi_file_open_ex, + .read_ex = efi_file_read_ex, + .write_ex = efi_file_write_ex, + .flush_ex = efi_file_flush_ex, }; /** -- cgit v1.1 From 632834ce6dc9905cb101c91903e8bea5224e1b72 Mon Sep 17 00:00:00 2001 From: Heinrich Schuchardt Date: Sun, 8 Sep 2019 10:32:54 +0200 Subject: efi_loader: volume name in EFI_FILE_PROTOCOL.GetInfo() We cannot determine the volume name in U-Boot. Instead of providing a dummy volume name in case of EFI_FILE_SYSTEM_INFO and EFI_UNSUPPORTED in case of EFI_FILE_SYSTEM_VOLUME_LABEL consistently return an empty string. Signed-off-by: Heinrich Schuchardt --- include/efi_api.h | 4 ++++ lib/efi_loader/efi_file.c | 18 ++++++++++++------ 2 files changed, 16 insertions(+), 6 deletions(-) diff --git a/include/efi_api.h b/include/efi_api.h index f43fb7a..37e56da 100644 --- a/include/efi_api.h +++ b/include/efi_api.h @@ -1517,6 +1517,10 @@ struct efi_simple_file_system_protocol { EFI_GUID(0x09576e93, 0x6d3f, 0x11d2, \ 0x8e, 0x39, 0x00, 0xa0, 0xc9, 0x69, 0x72, 0x3b) +#define EFI_FILE_SYSTEM_VOLUME_LABEL_ID \ + EFI_GUID(0xdb47d7d3, 0xfe81, 0x11d3, \ + 0x9a, 0x35, 0x00, 0x90, 0x27, 0x3f, 0xC1, 0x4d) + #define EFI_FILE_MODE_READ 0x0000000000000001 #define EFI_FILE_MODE_WRITE 0x0000000000000002 #define EFI_FILE_MODE_CREATE 0x8000000000000000 diff --git a/lib/efi_loader/efi_file.c b/lib/efi_loader/efi_file.c index 4b53016..3a108c6 100644 --- a/lib/efi_loader/efi_file.c +++ b/lib/efi_loader/efi_file.c @@ -15,6 +15,9 @@ /* GUID for file system information */ const efi_guid_t efi_file_system_info_guid = EFI_FILE_SYSTEM_INFO_GUID; +/* GUID to obtain the volume label */ +const efi_guid_t efi_system_volume_label_id = EFI_FILE_SYSTEM_VOLUME_LABEL_ID; + struct file_system { struct efi_simple_file_system_protocol base; struct efi_device_path *dp; @@ -637,9 +640,7 @@ static efi_status_t EFIAPI efi_file_getinfo(struct efi_file_handle *file, ret = EFI_DEVICE_ERROR; goto error; } - required_size = sizeof(*info) + 2 * - (utf8_utf16_strlen((const char *)part.name) + - 1); + required_size = sizeof(*info) + 2; if (*buffer_size < required_size) { *buffer_size = required_size; ret = EFI_BUFFER_TOO_SMALL; @@ -655,10 +656,15 @@ static efi_status_t EFIAPI efi_file_getinfo(struct efi_file_handle *file, info->block_size = part.blksz; /* * TODO: The volume label is not available in U-Boot. - * Use the partition name as substitute. */ - dst = info->volume_label; - utf8_utf16_strcpy(&dst, (const char *)part.name); + info->volume_label[0] = 0; + } else if (!guidcmp(info_type, &efi_system_volume_label_id)) { + if (*buffer_size < 2) { + *buffer_size = 2; + ret = EFI_BUFFER_TOO_SMALL; + goto error; + } + *(u16 *)buffer = 0; } else { ret = EFI_UNSUPPORTED; } -- cgit v1.1 From 11335c0439aa76bc5ed32b1ccfcab9995e2eac6b Mon Sep 17 00:00:00 2001 From: Heinrich Schuchardt Date: Sun, 8 Sep 2019 10:45:31 +0200 Subject: efi_loader: check parameters EFI_FILE_PROTOCOL.GetInfo() Check the parameters of EFI_FILE_PROTOCOL.GetInfo() to avoid possible NULL dereference. Check the buffer size for EFI_FILE_SYSTEM_INFO. Signed-off-by: Heinrich Schuchardt --- lib/efi_loader/efi_file.c | 6 ++++++ 1 file changed, 6 insertions(+) diff --git a/lib/efi_loader/efi_file.c b/lib/efi_loader/efi_file.c index 3a108c6..71582e5 100644 --- a/lib/efi_loader/efi_file.c +++ b/lib/efi_loader/efi_file.c @@ -596,6 +596,12 @@ static efi_status_t EFIAPI efi_file_getinfo(struct efi_file_handle *file, EFI_ENTRY("%p, %pUl, %p, %p", file, info_type, buffer_size, buffer); + if (!file || !info_type || !buffer_size || + (*buffer_size && !buffer)) { + ret = EFI_INVALID_PARAMETER; + goto error; + } + if (!guidcmp(info_type, &efi_file_info_guid)) { struct efi_file_info *info = buffer; char *filename = basename(fh); -- cgit v1.1 From 8262578535f18cdab95318828e6fd6464721ac54 Mon Sep 17 00:00:00 2001 From: Heinrich Schuchardt Date: Sun, 8 Sep 2019 11:37:07 +0200 Subject: efi_loader: parameter checks EFI_FILE_PROTOCOL.SetInfo() We do not support volume label changes. No parameter checks are needed here. When the info for as file is changed the buffer must always contain a file name. Signed-off-by: Heinrich Schuchardt --- lib/efi_loader/efi_file.c | 10 ++++------ 1 file changed, 4 insertions(+), 6 deletions(-) diff --git a/lib/efi_loader/efi_file.c b/lib/efi_loader/efi_file.c index 71582e5..6d3f680 100644 --- a/lib/efi_loader/efi_file.c +++ b/lib/efi_loader/efi_file.c @@ -695,7 +695,9 @@ static efi_status_t EFIAPI efi_file_setinfo(struct efi_file_handle *file, char *new_file_name, *pos; loff_t file_size; - if (buffer_size < sizeof(struct efi_file_info)) { + /* The buffer will always contain a file name. */ + if (buffer_size < sizeof(struct efi_file_info) + 2 || + buffer_size < info->size) { ret = EFI_BAD_BUFFER_SIZE; goto out; } @@ -735,12 +737,8 @@ static efi_status_t EFIAPI efi_file_setinfo(struct efi_file_handle *file, * TODO: Support read only */ ret = EFI_SUCCESS; - } else if (!guidcmp(info_type, &efi_file_system_info_guid)) { - if (buffer_size < sizeof(struct efi_file_system_info)) { - ret = EFI_BAD_BUFFER_SIZE; - goto out; - } } else { + /* TODO: We do not support changing the volume label */ ret = EFI_UNSUPPORTED; } out: -- cgit v1.1