diff options
Diffstat (limited to 'arch/arm64')
-rw-r--r-- | arch/arm64/kernel/module.c | 16 |
1 files changed, 14 insertions, 2 deletions
diff --git a/arch/arm64/kernel/module.c b/arch/arm64/kernel/module.c index 1e418e69b58c..f32359cffb01 100644 --- a/arch/arm64/kernel/module.c +++ b/arch/arm64/kernel/module.c @@ -96,15 +96,27 @@ static int reloc_data(enum aarch64_reloc_op op, void *place, u64 val, int len) { s64 sval = do_reloc(op, place, val); + /* + * The ELF psABI for AArch64 documents the 16-bit and 32-bit place + * relative relocations as having a range of [-2^15, 2^16) or + * [-2^31, 2^32), respectively. However, in order to be able to detect + * overflows reliably, we have to choose whether we interpret such + * quantities as signed or as unsigned, and stick with it. + * The way we organize our address space requires a signed + * interpretation of 32-bit relative references, so let's use that + * for all R_AARCH64_PRELxx relocations. This means our upper + * bound for overflow detection should be Sxx_MAX rather than Uxx_MAX. + */ + switch (len) { case 16: *(s16 *)place = sval; - if (sval < S16_MIN || sval > U16_MAX) + if (sval < S16_MIN || sval > S16_MAX) return -ERANGE; break; case 32: *(s32 *)place = sval; - if (sval < S32_MIN || sval > U32_MAX) + if (sval < S32_MIN || sval > S32_MAX) return -ERANGE; break; case 64: |