diff options
Diffstat (limited to 'arch/x86/kernel/module.c')
| -rw-r--r-- | arch/x86/kernel/module.c | 13 | 
1 files changed, 13 insertions, 0 deletions
| diff --git a/arch/x86/kernel/module.c b/arch/x86/kernel/module.c index 62e7d70aadd5..da0c160e5589 100644 --- a/arch/x86/kernel/module.c +++ b/arch/x86/kernel/module.c @@ -172,19 +172,27 @@ int apply_relocate_add(Elf64_Shdr *sechdrs,  		case R_X86_64_NONE:  			break;  		case R_X86_64_64: +			if (*(u64 *)loc != 0) +				goto invalid_relocation;  			*(u64 *)loc = val;  			break;  		case R_X86_64_32: +			if (*(u32 *)loc != 0) +				goto invalid_relocation;  			*(u32 *)loc = val;  			if (val != *(u32 *)loc)  				goto overflow;  			break;  		case R_X86_64_32S: +			if (*(s32 *)loc != 0) +				goto invalid_relocation;  			*(s32 *)loc = val;  			if ((s64)val != *(s32 *)loc)  				goto overflow;  			break;  		case R_X86_64_PC32: +			if (*(u32 *)loc != 0) +				goto invalid_relocation;  			val -= (u64)loc;  			*(u32 *)loc = val;  #if 0 @@ -200,6 +208,11 @@ int apply_relocate_add(Elf64_Shdr *sechdrs,  	}  	return 0; +invalid_relocation: +	pr_err("x86/modules: Skipping invalid relocation target, existing value is nonzero for type %d, loc %p, val %Lx\n", +	       (int)ELF64_R_TYPE(rel[i].r_info), loc, val); +	return -ENOEXEC; +  overflow:  	pr_err("overflow in relocation type %d val %Lx\n",  	       (int)ELF64_R_TYPE(rel[i].r_info), val); |