提交 861667dc 编写于 作者: R Ralf Baechle

MIPS: Fix race condition in module relocation code.

The relocation code was essentially taken from the 2.4 modutils which
perform relocation in userspace.  In 2.6 relocation of multiple modules
may be performed in parallel by the in-kernel loader so the global
variable mips_hi16_list won't fly anymore.  Fix race by moving it into
mod_arch_specific.

[ralf@linux-mips.org: folded in Tony's followup fix.  Thanks Tony!]
Signed-off-by: NRalf Baechle <ralf@linux-mips.org>
Signed-off-by: NTony Wu <tung7970@gmail.com>
Cc:  linux-mips@linux-mips.org
Patchwork: http://patchwork.linux-mips.org/patch/4189/
上级 d3cac35c
...@@ -10,6 +10,7 @@ struct mod_arch_specific { ...@@ -10,6 +10,7 @@ struct mod_arch_specific {
struct list_head dbe_list; struct list_head dbe_list;
const struct exception_table_entry *dbe_start; const struct exception_table_entry *dbe_start;
const struct exception_table_entry *dbe_end; const struct exception_table_entry *dbe_end;
struct mips_hi16 *r_mips_hi16_list;
}; };
typedef uint8_t Elf64_Byte; /* Type for a 8-bit quantity. */ typedef uint8_t Elf64_Byte; /* Type for a 8-bit quantity. */
......
...@@ -39,8 +39,6 @@ struct mips_hi16 { ...@@ -39,8 +39,6 @@ struct mips_hi16 {
Elf_Addr value; Elf_Addr value;
}; };
static struct mips_hi16 *mips_hi16_list;
static LIST_HEAD(dbe_list); static LIST_HEAD(dbe_list);
static DEFINE_SPINLOCK(dbe_lock); static DEFINE_SPINLOCK(dbe_lock);
...@@ -128,8 +126,8 @@ static int apply_r_mips_hi16_rel(struct module *me, u32 *location, Elf_Addr v) ...@@ -128,8 +126,8 @@ static int apply_r_mips_hi16_rel(struct module *me, u32 *location, Elf_Addr v)
n->addr = (Elf_Addr *)location; n->addr = (Elf_Addr *)location;
n->value = v; n->value = v;
n->next = mips_hi16_list; n->next = me->arch.r_mips_hi16_list;
mips_hi16_list = n; me->arch.r_mips_hi16_list = n;
return 0; return 0;
} }
...@@ -151,9 +149,9 @@ static int apply_r_mips_lo16_rel(struct module *me, u32 *location, Elf_Addr v) ...@@ -151,9 +149,9 @@ static int apply_r_mips_lo16_rel(struct module *me, u32 *location, Elf_Addr v)
/* Sign extend the addend we extract from the lo insn. */ /* Sign extend the addend we extract from the lo insn. */
vallo = ((insnlo & 0xffff) ^ 0x8000) - 0x8000; vallo = ((insnlo & 0xffff) ^ 0x8000) - 0x8000;
if (mips_hi16_list != NULL) { if (me->arch.r_mips_hi16_list != NULL) {
l = mips_hi16_list; l = me->arch.r_mips_hi16_list;
while (l != NULL) { while (l != NULL) {
unsigned long insn; unsigned long insn;
...@@ -187,7 +185,7 @@ static int apply_r_mips_lo16_rel(struct module *me, u32 *location, Elf_Addr v) ...@@ -187,7 +185,7 @@ static int apply_r_mips_lo16_rel(struct module *me, u32 *location, Elf_Addr v)
l = next; l = next;
} }
mips_hi16_list = NULL; me->arch.r_mips_hi16_list = NULL;
} }
/* /*
...@@ -278,6 +276,7 @@ int apply_relocate(Elf_Shdr *sechdrs, const char *strtab, ...@@ -278,6 +276,7 @@ int apply_relocate(Elf_Shdr *sechdrs, const char *strtab,
pr_debug("Applying relocate section %u to %u\n", relsec, pr_debug("Applying relocate section %u to %u\n", relsec,
sechdrs[relsec].sh_info); sechdrs[relsec].sh_info);
me->arch.r_mips_hi16_list = NULL;
for (i = 0; i < sechdrs[relsec].sh_size / sizeof(*rel); i++) { for (i = 0; i < sechdrs[relsec].sh_size / sizeof(*rel); i++) {
/* This is where to make the change */ /* This is where to make the change */
location = (void *)sechdrs[sechdrs[relsec].sh_info].sh_addr location = (void *)sechdrs[sechdrs[relsec].sh_info].sh_addr
......
Markdown is supported
0% .
You are about to add 0 people to the discussion. Proceed with caution.
先完成此消息的编辑!
想要评论请 注册