mirror of
git://git.kernel.org/pub/scm/linux/kernel/git/xiang/erofs.git
synced 2026-11-01 06:46:35 +01:00
For instrumenting global variables KASan will shadow memory backing memory for modules. So on module loading we will need to allocate memory for shadow and map it at address in shadow that corresponds to the address allocated in module_alloc(). __vmalloc_node_range() could be used for this purpose, except it puts a guard hole after allocated area. Guard hole in shadow memory should be a problem because at some future point we might need to have a shadow memory at address occupied by guard hole. So we could fail to allocate shadow for module_alloc(). Now we have VM_NO_GUARD flag disabling guard page, so we need to pass into __vmalloc_node_range(). Add new parameter 'vm_flags' to __vmalloc_node_range() function. Signed-off-by: Andrey Ryabinin <[email protected]> Cc: Dmitry Vyukov <[email protected]> Cc: Konstantin Serebryany <[email protected]> Cc: Dmitry Chernenkov <[email protected]> Signed-off-by: Andrey Konovalov <[email protected]> Cc: Yuri Gribov <[email protected]> Cc: Konstantin Khlebnikov <[email protected]> Cc: Sasha Levin <[email protected]> Cc: Christoph Lameter <[email protected]> Cc: Joonsoo Kim <[email protected]> Cc: Dave Hansen <[email protected]> Cc: Andi Kleen <[email protected]> Cc: Ingo Molnar <[email protected]> Cc: Thomas Gleixner <[email protected]> Cc: "H. Peter Anvin" <[email protected]> Cc: Christoph Lameter <[email protected]> Cc: Pekka Enberg <[email protected]> Cc: David Rientjes <[email protected]> Signed-off-by: Andrew Morton <[email protected]> Signed-off-by: Linus Torvalds <[email protected]>
110 lines
2.7 KiB
C
110 lines
2.7 KiB
C
/*
|
|
* linux/arch/unicore32/kernel/module.c
|
|
*
|
|
* Code specific to PKUnity SoC and UniCore ISA
|
|
*
|
|
* Copyright (C) 2001-2010 GUAN Xue-tao
|
|
*
|
|
* This program is free software; you can redistribute it and/or modify
|
|
* it under the terms of the GNU General Public License version 2 as
|
|
* published by the Free Software Foundation.
|
|
*/
|
|
#include <linux/module.h>
|
|
#include <linux/moduleloader.h>
|
|
#include <linux/kernel.h>
|
|
#include <linux/mm.h>
|
|
#include <linux/elf.h>
|
|
#include <linux/vmalloc.h>
|
|
#include <linux/fs.h>
|
|
#include <linux/string.h>
|
|
#include <linux/gfp.h>
|
|
|
|
#include <asm/pgtable.h>
|
|
#include <asm/sections.h>
|
|
|
|
void *module_alloc(unsigned long size)
|
|
{
|
|
return __vmalloc_node_range(size, 1, MODULES_VADDR, MODULES_END,
|
|
GFP_KERNEL, PAGE_KERNEL_EXEC, 0, NUMA_NO_NODE,
|
|
__builtin_return_address(0));
|
|
}
|
|
|
|
int
|
|
apply_relocate(Elf32_Shdr *sechdrs, const char *strtab, unsigned int symindex,
|
|
unsigned int relindex, struct module *module)
|
|
{
|
|
Elf32_Shdr *symsec = sechdrs + symindex;
|
|
Elf32_Shdr *relsec = sechdrs + relindex;
|
|
Elf32_Shdr *dstsec = sechdrs + relsec->sh_info;
|
|
Elf32_Rel *rel = (void *)relsec->sh_addr;
|
|
unsigned int i;
|
|
|
|
for (i = 0; i < relsec->sh_size / sizeof(Elf32_Rel); i++, rel++) {
|
|
unsigned long loc;
|
|
Elf32_Sym *sym;
|
|
s32 offset;
|
|
|
|
offset = ELF32_R_SYM(rel->r_info);
|
|
if (offset < 0 || offset >
|
|
(symsec->sh_size / sizeof(Elf32_Sym))) {
|
|
printk(KERN_ERR "%s: bad relocation, "
|
|
"section %d reloc %d\n",
|
|
module->name, relindex, i);
|
|
return -ENOEXEC;
|
|
}
|
|
|
|
sym = ((Elf32_Sym *)symsec->sh_addr) + offset;
|
|
|
|
if (rel->r_offset < 0 || rel->r_offset >
|
|
dstsec->sh_size - sizeof(u32)) {
|
|
printk(KERN_ERR "%s: out of bounds relocation, "
|
|
"section %d reloc %d offset %d size %d\n",
|
|
module->name, relindex, i, rel->r_offset,
|
|
dstsec->sh_size);
|
|
return -ENOEXEC;
|
|
}
|
|
|
|
loc = dstsec->sh_addr + rel->r_offset;
|
|
|
|
switch (ELF32_R_TYPE(rel->r_info)) {
|
|
case R_UNICORE_NONE:
|
|
/* ignore */
|
|
break;
|
|
|
|
case R_UNICORE_ABS32:
|
|
*(u32 *)loc += sym->st_value;
|
|
break;
|
|
|
|
case R_UNICORE_PC24:
|
|
case R_UNICORE_CALL:
|
|
case R_UNICORE_JUMP24:
|
|
offset = (*(u32 *)loc & 0x00ffffff) << 2;
|
|
if (offset & 0x02000000)
|
|
offset -= 0x04000000;
|
|
|
|
offset += sym->st_value - loc;
|
|
if (offset & 3 ||
|
|
offset <= (s32)0xfe000000 ||
|
|
offset >= (s32)0x02000000) {
|
|
printk(KERN_ERR
|
|
"%s: relocation out of range, section "
|
|
"%d reloc %d sym '%s'\n", module->name,
|
|
relindex, i, strtab + sym->st_name);
|
|
return -ENOEXEC;
|
|
}
|
|
|
|
offset >>= 2;
|
|
|
|
*(u32 *)loc &= 0xff000000;
|
|
*(u32 *)loc |= offset & 0x00ffffff;
|
|
break;
|
|
|
|
default:
|
|
printk(KERN_ERR "%s: unknown relocation: %u\n",
|
|
module->name, ELF32_R_TYPE(rel->r_info));
|
|
return -ENOEXEC;
|
|
}
|
|
}
|
|
return 0;
|
|
}
|