[05/12] core/flash core/init: Fix unintended sign extension

Submitted by Cyril Bur on Aug. 3, 2017, 6:45 a.m.

Details

Message ID 20170803064551.3439-5-cyril.bur@au1.ibm.com
State Accepted
Headers show

Commit Message

Cyril Bur Aug. 3, 2017, 6:45 a.m.
According to Coverity:
le16_to_cpu(elf64->e_shnum) is promoted in
`le16_to_cpu(elf64->e_shentsize) * le16_to_cpu(elf64->e_shnum)`
to type int (32 bits, signed), then sign-extended to type
unsigned long long (64 bits, unsigned).
If `le16_to_cpu(elf64->e_shentsize) * le16_to_cpu(elf64->e_shnum)`
is greater than 0x7FFFFFFF, the upper bits of the result will all be 1.

I'm sure in practice this can't happen since this would require
either/or e_shnum and e_shentsize to be quite large.

Fixes: CID 138019, 137707, 137706, 137708
Signed-off-by: Cyril Bur <cyril.bur@au1.ibm.com>
---
I think a simple cast should solve it, so lets do that.

 core/flash.c | 4 ++--
 core/init.c  | 6 ++++--
 2 files changed, 6 insertions(+), 4 deletions(-)

Patch hide | download patch | download mbox

diff --git a/core/flash.c b/core/flash.c
index 8a908e5b..53e6eba0 100644
--- a/core/flash.c
+++ b/core/flash.c
@@ -438,8 +438,8 @@  static size_t sizeof_elf_from_hdr(void *buf)
 		if (elf->ei_class == ELF_CLASS_64) {
 			struct elf64_hdr *elf64 = (struct elf64_hdr*) buf;
 			sz = le64_to_cpu(elf64->e_shoff) +
-				(le16_to_cpu(elf64->e_shentsize) *
-				 le16_to_cpu(elf64->e_shnum));
+				((uint32_t)le16_to_cpu(elf64->e_shentsize) *
+				 (uint32_t)le16_to_cpu(elf64->e_shnum));
 		} else if (elf->ei_class == ELF_CLASS_32) {
 			struct elf32_hdr *elf32 = (struct elf32_hdr*) buf;
 			sz = le32_to_cpu(elf32->e_shoff) +
diff --git a/core/init.c b/core/init.c
index 61b531c7..a96a69c8 100644
--- a/core/init.c
+++ b/core/init.c
@@ -119,7 +119,8 @@  static bool try_load_elf64_le(struct elf_hdr *header)
 	kernel_32bit = false;
 
 	kernel_size = le64_to_cpu(kh->e_shoff) +
-		(le16_to_cpu(kh->e_shentsize) * le16_to_cpu(kh->e_shnum));
+		((uint32_t)le16_to_cpu(kh->e_shentsize) *
+		 (uint32_t)le16_to_cpu(kh->e_shnum));
 
 	prlog(PR_DEBUG, "INIT: 64-bit kernel entry at 0x%llx, size 0x%lx\n",
 	      kernel_entry, kernel_size);
@@ -196,7 +197,8 @@  static bool try_load_elf64(struct elf_hdr *header)
 	kernel_entry += load_base;
 	kernel_32bit = false;
 
-	kernel_size = kh->e_shoff + (kh->e_shentsize * kh->e_shnum);
+	kernel_size = kh->e_shoff +
+		((uint32_t)kh->e_shentsize * (uint32_t)kh->e_shnum);
 
 	printf("INIT: 64-bit kernel entry at 0x%llx, size 0x%lx\n",
 	       kernel_entry, kernel_size);