summaryrefslogtreecommitdiff
path: root/kernel
diff options
context:
space:
mode:
authorShuah Khan <skhan@linuxfoundation.org>2021-10-15 14:57:41 -0600
committerLuis Chamberlain <mcgrof@kernel.org>2021-11-05 15:13:10 -0700
commitd83d42d071b6c58e71e54b8778ca5b279be98f7d (patch)
tree11260e56b8e1e68a17bf0ac1157017e0dc4cb97b /kernel
parentfe91c4725aeed35023ba4f7a1e1adfebb6878c23 (diff)
module: fix validate_section_offset() overflow bug on 64-bit
validate_section_offset() uses unsigned long local variable to add/store shdr->sh_offset and shdr->sh_size on all platforms. unsigned long is too short when sh_offset is Elf64_Off which would be the case on 64bit ELF headers. Without this fix applied we were shorting the design of modules to have section headers placed within the 32-bit boundary (4 GiB) instead of 64-bits when on 64-bit architectures (which allows for up to 16,777,216 TiB). In practice this just meant we were limiting modules sections to below 4 GiB even on 64-bit systems. This then should not really affect any real-world use case as modules these days obviously should likely never exceed 1 GiB in size overall. A specially crafted invalid module might succeed to skip validation in validate_section_offset() due to this mistake, but in such case no impact is observed through code inspection given the correct data types are used for the copy of the module when needed on move_module() when the section type is not SHT_NOBITS (which indicates no the section occupies no space on the file). Fix the overflow problem using the right size local variable when CONFIG_64BIT is defined. Signed-off-by: Shuah Khan <skhan@linuxfoundation.org> [mcgrof: expand commit log with possible impact if not applied] Signed-off-by: Luis Chamberlain <mcgrof@kernel.org>
Diffstat (limited to 'kernel')
-rw-r--r--kernel/module.c4
1 files changed, 4 insertions, 0 deletions
diff --git a/kernel/module.c b/kernel/module.c
index 5c26a76e800b..c7ad73807446 100644
--- a/kernel/module.c
+++ b/kernel/module.c
@@ -2942,7 +2942,11 @@ static int module_sig_check(struct load_info *info, int flags)
static int validate_section_offset(struct load_info *info, Elf_Shdr *shdr)
{
+#if defined(CONFIG_64BIT)
+ unsigned long long secend;
+#else
unsigned long secend;
+#endif
/*
* Check for both overflow and offset/size being