From 37684ed22a633193cef30c5c915af9a75b8452fe Mon Sep 17 00:00:00 2001 From: Peter Jones Date: Thu, 19 May 2016 10:54:06 -0400 Subject: [PATCH] Fix some deginerate load option parsing cases. Signed-off-by: Peter Jones --- src/dp.c | 7 +++++-- src/loadopt.c | 38 +++++++++++++++++++++++--------------- 2 files changed, 28 insertions(+), 17 deletions(-) diff --git a/src/dp.c b/src/dp.c index 3fcbcee..4c45046 100644 --- a/src/dp.c +++ b/src/dp.c @@ -265,7 +265,10 @@ efidp_format_device_path(char *buf, size_t size, const_efidp dp, ssize_t limit) if (!dp) return -1; - while (1) { + if (buf && size) + memset(buf, 0, size); + + while (limit) { if (limit >= 0 && (limit < 4 || efidp_node_size(dp) > limit)) { if (off) return off; @@ -346,7 +349,7 @@ efidp_format_device_path(char *buf, size_t size, const_efidp dp, ssize_t limit) off += format(buf, size, off, ","); break; } - return off; + return off + 1; default: off += format(buf, size, off, "Path(%d,%d,", dp->type, dp->subtype); diff --git a/src/loadopt.c b/src/loadopt.c index a72a9c6..d2c655c 100644 --- a/src/loadopt.c +++ b/src/loadopt.c @@ -96,17 +96,18 @@ efi_loadopt_optional_data_size(efi_load_option *opt, size_t size) size -= sizeof(*opt); if (size < opt->file_path_list_length) return -1; + size -= opt->file_path_list_length; + /* "size" as the limit means sz will be size or less in all cases; no + * need to test it. if it /is/ size, there's no optional data. */ sz = ucs2size(opt->description, size); - if (sz >= size) // since there's no room for a file path... - return -1; p = (uint8_t *)(opt->description) + sz; size -= sz; - if (!efidp_is_valid((const_efidp)p, size)) + if (!efidp_is_valid((const_efidp)p, opt->file_path_list_length)) return -1; sz = efidp_size((const_efidp)p); - p += sz; - size -= sz; + if (sz != opt->file_path_list_length) + return -1; return size; } @@ -167,20 +168,27 @@ __attribute__((__visibility__ ("default"))) efi_loadopt_path(efi_load_option *opt, ssize_t limit) { char *p = (char *)opt; - size_t l; - ssize_t desc_limit; + size_t sz; + size_t left; efidp dp; - l = (size_t)limit; - if (l <= offsetof(efi_load_option, description)) + left = (size_t)limit; + if (left <= offsetof(efi_load_option, description)) + return NULL; + left -= offsetof(efi_load_option, description); + p += offsetof(efi_load_option, description); + + sz = ucs2size(opt->description, left); + if (sz >= left) // since there's no room for a file path... + return NULL; + p += sz; + left -= sz; + + if (left < opt->file_path_list_length) return NULL; - desc_limit = limit - offsetof(efi_load_option, description); - dp = (efidp)(p + sizeof (opt->attributes) - + sizeof (opt->file_path_list_length) - + ucs2size(opt->description, desc_limit)); - limit -= (unsigned long)dp - (unsigned long)opt; - if (!efidp_is_valid(dp, limit)) + dp = (efidp)p; + if (!efidp_is_valid(dp, opt->file_path_list_length)) return NULL; return dp; } -- 2.11.0