diff options
author | Ard Biesheuvel <ard.biesheuvel@linaro.org> | 2016-07-25 15:16:55 +0000 |
---|---|---|
committer | android-build-merger <android-build-merger@google.com> | 2016-07-25 15:16:55 +0000 |
commit | 8e31bb4d9cf427f6a1720e975887dadb46a60057 (patch) | |
tree | d1f55e2f55f7c5eb790b609621d32652c6c35c5f | |
parent | 329293910e5b9e0d60575895d52de97b1febfa5e (diff) | |
parent | 2cd5629f66e2d55b17d9c66affeccf2eb2027ef1 (diff) | |
download | v4.4-8e31bb4d9cf427f6a1720e975887dadb46a60057.tar.gz |
UPSTREAM: arm64: module: avoid undefined shift behavior in reloc_data()
am: 2cd5629f66
Change-Id: Ia1363a813f3b5473fc8a09eac08d1bfd8a26b8a2
-rw-r--r-- | arch/arm64/kernel/module.c | 20 |
1 files changed, 4 insertions, 16 deletions
diff --git a/arch/arm64/kernel/module.c b/arch/arm64/kernel/module.c index 03464ab0fff2..93e970231ca9 100644 --- a/arch/arm64/kernel/module.c +++ b/arch/arm64/kernel/module.c @@ -72,15 +72,18 @@ static u64 do_reloc(enum aarch64_reloc_op reloc_op, void *place, u64 val) static int reloc_data(enum aarch64_reloc_op op, void *place, u64 val, int len) { - u64 imm_mask = (1 << len) - 1; s64 sval = do_reloc(op, place, val); switch (len) { case 16: *(s16 *)place = sval; + if (sval < S16_MIN || sval > U16_MAX) + return -ERANGE; break; case 32: *(s32 *)place = sval; + if (sval < S32_MIN || sval > U32_MAX) + return -ERANGE; break; case 64: *(s64 *)place = sval; @@ -89,21 +92,6 @@ static int reloc_data(enum aarch64_reloc_op op, void *place, u64 val, int len) pr_err("Invalid length (%d) for data relocation\n", len); return 0; } - - /* - * Extract the upper value bits (including the sign bit) and - * shift them to bit 0. - */ - sval = (s64)(sval & ~(imm_mask >> 1)) >> (len - 1); - - /* - * Overflow has occurred if the value is not representable in - * len bits (i.e the bottom len bits are not sign-extended and - * the top bits are not all zero). - */ - if ((u64)(sval + 1) > 2) - return -ERANGE; - return 0; } |