Patch "modpost: remove broken calculation of exception_table_entry size" has been added to the 5.15-stable tree

[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]

 



This is a note to let you know that I've just added the patch titled

    modpost: remove broken calculation of exception_table_entry size

to the 5.15-stable tree which can be found at:
    http://www.kernel.org/git/?p=linux/kernel/git/stable/stable-queue.git;a=summary

The filename of the patch is:
     modpost-remove-broken-calculation-of-exception_table.patch
and it can be found in the queue-5.15 subdirectory.

If you, or anyone else, feels it should not be added to the stable tree,
please let <stable@xxxxxxxxxxxxxxx> know about it.



commit b2fe5982b68981b4a2bc0b4941b9407f6aadc132
Author: Masahiro Yamada <masahiroy@xxxxxxxxxx>
Date:   Mon May 15 00:27:19 2023 +0900

    modpost: remove broken calculation of exception_table_entry size
    
    [ Upstream commit d0acc76a49aa917c1a455d11d32d34a01e8b2835 ]
    
    find_extable_entry_size() is completely broken. It has awesome comments
    about how to calculate sizeof(struct exception_table_entry).
    
    It was based on these assumptions:
    
      - struct exception_table_entry has two fields
      - both of the fields have the same size
    
    Then, we came up with this equation:
    
      (offset of the second field) * 2 == (size of struct)
    
    It was true for all architectures when commit 52dc0595d540 ("modpost:
    handle relocations mismatch in __ex_table.") was applied.
    
    Our mathematics broke when commit 548acf19234d ("x86/mm: Expand the
    exception table logic to allow new handling options") introduced the
    third field.
    
    Now, the definition of exception_table_entry is highly arch-dependent.
    
    For x86, sizeof(struct exception_table_entry) is apparently 12, but
    find_extable_entry_size() sets extable_entry_size to 8.
    
    I could fix it, but I do not see much value in this code.
    
    extable_entry_size is used just for selecting a slightly different
    error message.
    
    If the first field ("insn") references to a non-executable section,
    
        The relocation at %s+0x%lx references
        section "%s" which is not executable, IOW
        it is not possible for the kernel to fault
        at that address.  Something is seriously wrong
        and should be fixed.
    
    If the second field ("fixup") references to a non-executable section,
    
        The relocation at %s+0x%lx references
        section "%s" which is not executable, IOW
        the kernel will fault if it ever tries to
        jump to it.  Something is seriously wrong
        and should be fixed.
    
    Merge the two error messages rather than adding even more complexity.
    
    Change fatal() to error() to make it continue running and catch more
    possible errors.
    
    Fixes: 548acf19234d ("x86/mm: Expand the exception table logic to allow new handling options")
    Signed-off-by: Masahiro Yamada <masahiroy@xxxxxxxxxx>
    Signed-off-by: Sasha Levin <sashal@xxxxxxxxxx>

diff --git a/scripts/mod/modpost.c b/scripts/mod/modpost.c
index b284ee01fdebb..b29af4ad08321 100644
--- a/scripts/mod/modpost.c
+++ b/scripts/mod/modpost.c
@@ -1612,43 +1612,6 @@ static int is_executable_section(struct elf_info* elf, unsigned int section_inde
 	return ((elf->sechdrs[section_index].sh_flags & SHF_EXECINSTR) == SHF_EXECINSTR);
 }
 
-/*
- * We rely on a gross hack in section_rel[a]() calling find_extable_entry_size()
- * to know the sizeof(struct exception_table_entry) for the target architecture.
- */
-static unsigned int extable_entry_size = 0;
-static void find_extable_entry_size(const char* const sec, const Elf_Rela* r)
-{
-	/*
-	 * If we're currently checking the second relocation within __ex_table,
-	 * that relocation offset tells us the offsetof(struct
-	 * exception_table_entry, fixup) which is equal to sizeof(struct
-	 * exception_table_entry) divided by two.  We use that to our advantage
-	 * since there's no portable way to get that size as every architecture
-	 * seems to go with different sized types.  Not pretty but better than
-	 * hard-coding the size for every architecture..
-	 */
-	if (!extable_entry_size)
-		extable_entry_size = r->r_offset * 2;
-}
-
-static inline bool is_extable_fault_address(Elf_Rela *r)
-{
-	/*
-	 * extable_entry_size is only discovered after we've handled the
-	 * _second_ relocation in __ex_table, so only abort when we're not
-	 * handling the first reloc and extable_entry_size is zero.
-	 */
-	if (r->r_offset && extable_entry_size == 0)
-		fatal("extable_entry size hasn't been discovered!\n");
-
-	return ((r->r_offset == 0) ||
-		(r->r_offset % extable_entry_size == 0));
-}
-
-#define is_second_extable_reloc(Start, Cur, Sec)			\
-	(((Cur) == (Start) + 1) && (strcmp("__ex_table", (Sec)) == 0))
-
 static void report_extable_warnings(const char* modname, struct elf_info* elf,
 				    const struct sectioncheck* const mismatch,
 				    Elf_Rela* r, Elf_Sym* sym,
@@ -1705,22 +1668,9 @@ static void extable_mismatch_handler(const char* modname, struct elf_info *elf,
 		      "You might get more information about where this is\n"
 		      "coming from by using scripts/check_extable.sh %s\n",
 		      fromsec, (long)r->r_offset, tosec, modname);
-	else if (!is_executable_section(elf, get_secindex(elf, sym))) {
-		if (is_extable_fault_address(r))
-			fatal("The relocation at %s+0x%lx references\n"
-			      "section \"%s\" which is not executable, IOW\n"
-			      "it is not possible for the kernel to fault\n"
-			      "at that address.  Something is seriously wrong\n"
-			      "and should be fixed.\n",
-			      fromsec, (long)r->r_offset, tosec);
-		else
-			fatal("The relocation at %s+0x%lx references\n"
-			      "section \"%s\" which is not executable, IOW\n"
-			      "the kernel will fault if it ever tries to\n"
-			      "jump to it.  Something is seriously wrong\n"
-			      "and should be fixed.\n",
-			      fromsec, (long)r->r_offset, tosec);
-	}
+	else if (!is_executable_section(elf, get_secindex(elf, sym)))
+		error("%s+0x%lx references non-executable section '%s'\n",
+		      fromsec, (long)r->r_offset, tosec);
 }
 
 static void check_section_mismatch(const char *modname, struct elf_info *elf,
@@ -1871,8 +1821,6 @@ static void section_rela(const char *modname, struct elf_info *elf,
 		/* Skip special sections */
 		if (is_shndx_special(sym->st_shndx))
 			continue;
-		if (is_second_extable_reloc(start, rela, fromsec))
-			find_extable_entry_size(fromsec, &r);
 		check_section_mismatch(modname, elf, &r, sym, fromsec);
 	}
 }
@@ -1931,8 +1879,6 @@ static void section_rel(const char *modname, struct elf_info *elf,
 		/* Skip special sections */
 		if (is_shndx_special(sym->st_shndx))
 			continue;
-		if (is_second_extable_reloc(start, rel, fromsec))
-			find_extable_entry_size(fromsec, &r);
 		check_section_mismatch(modname, elf, &r, sym, fromsec);
 	}
 }



[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]
[Index of Archives]     [Linux USB Devel]     [Linux Audio Users]     [Yosemite News]     [Linux Kernel]     [Linux SCSI]

  Powered by Linux