Skip to content

Commit 1cf24a2

Browse files
Ard Biesheuvelwildea01
authored andcommitted
arm64/module: deal with ambiguity in PRELxx relocation ranges
The R_AARCH64_PREL16 and R_AARCH64_PREL32 relocations are documented as permitting a range of [-2^15 .. 2^16), resp. [-2^31 .. 2^32). It is also documented that this means we cannot detect overflow in some cases, which is bad. Since we always interpret the targets of these relocations as signed quantities (e.g., in the ksymtab handling code), let's tighten the overflow checks so that targets that are out of range for our signed interpretation of the relocated quantity get flagged. Signed-off-by: Ard Biesheuvel <[email protected]> Signed-off-by: Will Deacon <[email protected]>
1 parent 8212688 commit 1cf24a2

File tree

1 file changed

+14
-2
lines changed

1 file changed

+14
-2
lines changed

arch/arm64/kernel/module.c

Lines changed: 14 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -96,15 +96,27 @@ static int reloc_data(enum aarch64_reloc_op op, void *place, u64 val, int len)
9696
{
9797
s64 sval = do_reloc(op, place, val);
9898

99+
/*
100+
* The ELF psABI for AArch64 documents the 16-bit and 32-bit place
101+
* relative relocations as having a range of [-2^15, 2^16) or
102+
* [-2^31, 2^32), respectively. However, in order to be able to detect
103+
* overflows reliably, we have to choose whether we interpret such
104+
* quantities as signed or as unsigned, and stick with it.
105+
* The way we organize our address space requires a signed
106+
* interpretation of 32-bit relative references, so let's use that
107+
* for all R_AARCH64_PRELxx relocations. This means our upper
108+
* bound for overflow detection should be Sxx_MAX rather than Uxx_MAX.
109+
*/
110+
99111
switch (len) {
100112
case 16:
101113
*(s16 *)place = sval;
102-
if (sval < S16_MIN || sval > U16_MAX)
114+
if (sval < S16_MIN || sval > S16_MAX)
103115
return -ERANGE;
104116
break;
105117
case 32:
106118
*(s32 *)place = sval;
107-
if (sval < S32_MIN || sval > U32_MAX)
119+
if (sval < S32_MIN || sval > S32_MAX)
108120
return -ERANGE;
109121
break;
110122
case 64:

0 commit comments

Comments
 (0)