aboutsummaryrefslogtreecommitdiffstats
path: root/arch/arm64/kernel/module.c
diff options
context:
space:
mode:
Diffstat (limited to 'arch/arm64/kernel/module.c')
-rw-r--r--arch/arm64/kernel/module.c38
1 files changed, 30 insertions, 8 deletions
diff --git a/arch/arm64/kernel/module.c b/arch/arm64/kernel/module.c
index f32359cffb01..dd080837e6a9 100644
--- a/arch/arm64/kernel/module.c
+++ b/arch/arm64/kernel/module.c
@@ -98,10 +98,10 @@ static int reloc_data(enum aarch64_reloc_op op, void *place, u64 val, int len)
98 98
99 /* 99 /*
100 * The ELF psABI for AArch64 documents the 16-bit and 32-bit place 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 101 * relative and absolute relocations as having a range of [-2^15, 2^16)
102 * [-2^31, 2^32), respectively. However, in order to be able to detect 102 * or [-2^31, 2^32), respectively. However, in order to be able to
103 * overflows reliably, we have to choose whether we interpret such 103 * detect overflows reliably, we have to choose whether we interpret
104 * quantities as signed or as unsigned, and stick with it. 104 * such quantities as signed or as unsigned, and stick with it.
105 * The way we organize our address space requires a signed 105 * The way we organize our address space requires a signed
106 * interpretation of 32-bit relative references, so let's use that 106 * interpretation of 32-bit relative references, so let's use that
107 * for all R_AARCH64_PRELxx relocations. This means our upper 107 * for all R_AARCH64_PRELxx relocations. This means our upper
@@ -111,13 +111,35 @@ static int reloc_data(enum aarch64_reloc_op op, void *place, u64 val, int len)
111 switch (len) { 111 switch (len) {
112 case 16: 112 case 16:
113 *(s16 *)place = sval; 113 *(s16 *)place = sval;
114 if (sval < S16_MIN || sval > S16_MAX) 114 switch (op) {
115 return -ERANGE; 115 case RELOC_OP_ABS:
116 if (sval < 0 || sval > U16_MAX)
117 return -ERANGE;
118 break;
119 case RELOC_OP_PREL:
120 if (sval < S16_MIN || sval > S16_MAX)
121 return -ERANGE;
122 break;
123 default:
124 pr_err("Invalid 16-bit data relocation (%d)\n", op);
125 return 0;
126 }
116 break; 127 break;
117 case 32: 128 case 32:
118 *(s32 *)place = sval; 129 *(s32 *)place = sval;
119 if (sval < S32_MIN || sval > S32_MAX) 130 switch (op) {
120 return -ERANGE; 131 case RELOC_OP_ABS:
132 if (sval < 0 || sval > U32_MAX)
133 return -ERANGE;
134 break;
135 case RELOC_OP_PREL:
136 if (sval < S32_MIN || sval > S32_MAX)
137 return -ERANGE;
138 break;
139 default:
140 pr_err("Invalid 32-bit data relocation (%d)\n", op);
141 return 0;
142 }
121 break; 143 break;
122 case 64: 144 case 64:
123 *(s64 *)place = sval; 145 *(s64 *)place = sval;