1 /*
2 * Copyright (c) 2016 Oracle and/or its affiliates. All rights reserved.
3 */
4
5 #include <xen/errno.h>
6 #include <xen/kernel.h>
7 #include <xen/lib.h>
8 #include <xen/livepatch_elf.h>
9 #include <xen/livepatch.h>
10
11 #include <asm/page.h>
12 #include <asm/livepatch.h>
13
arch_livepatch_apply(struct livepatch_func * func)14 void arch_livepatch_apply(struct livepatch_func *func)
15 {
16 uint32_t insn;
17 uint32_t *new_ptr;
18 unsigned int i, len;
19
20 BUILD_BUG_ON(ARCH_PATCH_INSN_SIZE > sizeof(func->opaque));
21 BUILD_BUG_ON(ARCH_PATCH_INSN_SIZE != sizeof(insn));
22
23 ASSERT(vmap_of_xen_text);
24
25 len = livepatch_insn_len(func);
26 if ( !len )
27 return;
28
29 /* Save old ones. */
30 memcpy(func->opaque, func->old_addr, len);
31
32 if ( func->new_addr )
33 {
34 s32 delta;
35
36 /*
37 * PC is current address (old_addr) + 8 bytes. The semantics for a
38 * unconditional branch is to jump to PC + imm32 (offset).
39 *
40 * ARM DDI 0406C.c, see A2.3 (pg 45) and A8.8.18 pg (pg 334,335)
41 *
42 */
43 delta = (s32)func->new_addr - (s32)(func->old_addr + 8);
44
45 /* The arch_livepatch_symbol_ok should have caught it. */
46 ASSERT(delta >= -(s32)ARCH_LIVEPATCH_RANGE ||
47 delta < (s32)ARCH_LIVEPATCH_RANGE);
48
49 /* CPU shifts by two (left) when decoding, so we shift right by two. */
50 delta = delta >> 2;
51 /* Lets not modify the cond. */
52 delta &= 0x00FFFFFF;
53
54 insn = 0xea000000 | delta;
55 }
56 else
57 insn = 0xe1a00000; /* mov r0, r0 */
58
59 new_ptr = func->old_addr - (void *)_start + vmap_of_xen_text;
60 len = len / sizeof(uint32_t);
61
62 /* PATCH! */
63 for ( i = 0; i < len; i++ )
64 *(new_ptr + i) = insn;
65
66 /*
67 * When we upload the payload, it will go through the data cache
68 * (the region is cacheable). Until the data cache is cleaned, the data
69 * may not reach the memory. And in the case the data and instruction cache
70 * are separated, we may read invalid instruction from the memory because
71 * the data cache have not yet synced with the memory. Hence sync it.
72 */
73 if ( func->new_addr )
74 clean_and_invalidate_dcache_va_range(func->new_addr, func->new_size);
75 clean_and_invalidate_dcache_va_range(new_ptr, sizeof (*new_ptr) * len);
76 }
77
78 /* arch_livepatch_revert shared with ARM 32/ARM 64. */
79
arch_livepatch_verify_elf(const struct livepatch_elf * elf)80 int arch_livepatch_verify_elf(const struct livepatch_elf *elf)
81 {
82 const Elf_Ehdr *hdr = elf->hdr;
83
84 if ( hdr->e_machine != EM_ARM ||
85 hdr->e_ident[EI_CLASS] != ELFCLASS32 )
86 {
87 dprintk(XENLOG_ERR, LIVEPATCH "%s: Unsupported ELF Machine type!\n",
88 elf->name);
89 return -EOPNOTSUPP;
90 }
91
92 if ( (hdr->e_flags & EF_ARM_EABI_MASK) != EF_ARM_EABI_VER5 )
93 {
94 dprintk(XENLOG_ERR, LIVEPATCH "%s: Unsupported ELF EABI(%x)!\n",
95 elf->name, hdr->e_flags);
96 return -EOPNOTSUPP;
97 }
98
99 return 0;
100 }
101
arch_livepatch_symbol_deny(const struct livepatch_elf * elf,const struct livepatch_elf_sym * sym)102 bool arch_livepatch_symbol_deny(const struct livepatch_elf *elf,
103 const struct livepatch_elf_sym *sym)
104 {
105 /*
106 * Xen does not use Thumb instructions - and we should not see any of
107 * them. If we do, abort.
108 */
109 if ( sym->name && sym->name[0] == '$' && sym->name[1] == 't' )
110 return ( !sym->name[2] || sym->name[2] == '.' );
111
112 return false;
113 }
114
get_addend(unsigned char type,void * dest)115 static s32 get_addend(unsigned char type, void *dest)
116 {
117 s32 addend = 0;
118
119 switch ( type ) {
120 case R_ARM_NONE:
121 /* ignore */
122 break;
123
124 case R_ARM_ABS32:
125 addend = *(u32 *)dest;
126 break;
127
128 case R_ARM_REL32:
129 addend = *(u32 *)dest;
130 break;
131
132 case R_ARM_MOVW_ABS_NC:
133 case R_ARM_MOVT_ABS:
134 addend = (*(u32 *)dest & 0x00000FFF);
135 addend |= (*(u32 *)dest & 0x000F0000) >> 4;
136 /* Addend is to sign-extend ([19:16],[11:0]). */
137 addend = (s16)addend;
138 break;
139
140 case R_ARM_CALL:
141 case R_ARM_JUMP24:
142 /* Addend = sign_extend (insn[23:0]) << 2 */
143 addend = ((*(u32 *)dest & 0xFFFFFF) ^ 0x800000) - 0x800000;
144 addend = addend << 2;
145 break;
146 }
147
148 return addend;
149 }
150
perform_rel(unsigned char type,void * dest,uint32_t val,s32 addend)151 static int perform_rel(unsigned char type, void *dest, uint32_t val, s32 addend)
152 {
153
154 switch ( type ) {
155 case R_ARM_NONE:
156 /* ignore */
157 break;
158
159 case R_ARM_ABS32: /* (S + A) | T */
160 *(u32 *)dest = (val + addend);
161 break;
162
163 case R_ARM_REL32: /* ((S + A) | T) – P */
164 *(u32 *)dest = (val + addend) - (uint32_t)dest;
165 break;
166
167 case R_ARM_MOVW_ABS_NC: /* S + A */
168 case R_ARM_MOVT_ABS: /* S + A */
169 /* Clear addend if needed . */
170 if ( addend )
171 *(u32 *)dest &= 0xFFF0F000;
172
173 if ( type == R_ARM_MOVT_ABS )
174 {
175 /*
176 * Almost the same as MOVW except it uses the 16 bit
177 * high value. Putting it in insn requires shifting right by
178 * 16-bit (as we only have 16-bit for imm.
179 */
180 val &= 0xFFFF0000; /* ResultMask */
181 val = val >> 16;
182 }
183 else
184 {
185 /* MOVW loads 16 bits into the bottom half of a register. */
186 val &= 0xFFFF;
187 }
188 /* [11:0] = Result_Mask(X) & 0xFFF,[19:16] = Result_Mask(X) >> 12 */
189 *(u32 *)dest |= val & 0xFFF;
190 *(u32 *)dest |= (val >> 12) << 16;
191 break;
192
193 case R_ARM_CALL:
194 case R_ARM_JUMP24: /* (S + A) - P */
195 /* Clear the old addend. */
196 if ( addend )
197 *(u32 *)dest &= 0xFF000000;
198
199 val += addend - (uint32_t)dest;
200
201 /*
202 * arch_livepatch_verify_distance can't account of addend so we have
203 * to do the check here as well.
204 */
205 if ( (s32)val < -(s32)ARCH_LIVEPATCH_RANGE ||
206 (s32)val >= (s32)ARCH_LIVEPATCH_RANGE )
207 return -EOVERFLOW;
208
209 /* CPU always shifts insn by two, so complement it. */
210 val = val >> 2;
211 val &= 0x00FFFFFE;
212 *(u32 *)dest |= (uint32_t)val;
213 break;
214
215 default:
216 return -EOPNOTSUPP;
217 }
218
219 return 0;
220 }
221
arch_livepatch_perform(struct livepatch_elf * elf,const struct livepatch_elf_sec * base,const struct livepatch_elf_sec * rela,bool use_rela)222 int arch_livepatch_perform(struct livepatch_elf *elf,
223 const struct livepatch_elf_sec *base,
224 const struct livepatch_elf_sec *rela,
225 bool use_rela)
226 {
227 unsigned int i;
228 int rc = 0;
229
230 for ( i = 0; i < (rela->sec->sh_size / rela->sec->sh_entsize); i++ )
231 {
232 unsigned int symndx;
233 uint32_t val;
234 void *dest;
235 unsigned char type;
236 s32 addend;
237
238 if ( use_rela )
239 {
240 const Elf_RelA *r_a = rela->data + i * rela->sec->sh_entsize;
241
242 symndx = ELF32_R_SYM(r_a->r_info);
243 type = ELF32_R_TYPE(r_a->r_info);
244 dest = base->load_addr + r_a->r_offset; /* P */
245 addend = r_a->r_addend;
246 }
247 else
248 {
249 const Elf_Rel *r = rela->data + i * rela->sec->sh_entsize;
250
251 symndx = ELF32_R_SYM(r->r_info);
252 type = ELF32_R_TYPE(r->r_info);
253 dest = base->load_addr + r->r_offset; /* P */
254 addend = get_addend(type, dest);
255 }
256
257 if ( symndx == STN_UNDEF )
258 {
259 dprintk(XENLOG_ERR, LIVEPATCH "%s: Encountered STN_UNDEF\n",
260 elf->name);
261 return -EOPNOTSUPP;
262 }
263 else if ( symndx >= elf->nsym )
264 {
265 dprintk(XENLOG_ERR, LIVEPATCH "%s: Relative symbol wants symbol@%u which is past end!\n",
266 elf->name, symndx);
267 return -EINVAL;
268 }
269 else if ( !elf->sym[symndx].sym )
270 {
271 dprintk(XENLOG_ERR, LIVEPATCH "%s: No relative symbol@%u\n",
272 elf->name, symndx);
273 return -EINVAL;
274 }
275
276 val = elf->sym[symndx].sym->st_value; /* S */
277
278 rc = perform_rel(type, dest, val, addend);
279 switch ( rc )
280 {
281 case -EOVERFLOW:
282 dprintk(XENLOG_ERR, LIVEPATCH "%s: Overflow in relocation %u in %s for %s!\n",
283 elf->name, i, rela->name, base->name);
284 break;
285
286 case -EOPNOTSUPP:
287 dprintk(XENLOG_ERR, LIVEPATCH "%s: Unhandled relocation #%x\n",
288 elf->name, type);
289 break;
290 }
291
292 if ( rc )
293 break;
294 }
295
296 return rc;
297 }
298
arch_livepatch_perform_rel(struct livepatch_elf * elf,const struct livepatch_elf_sec * base,const struct livepatch_elf_sec * rela)299 int arch_livepatch_perform_rel(struct livepatch_elf *elf,
300 const struct livepatch_elf_sec *base,
301 const struct livepatch_elf_sec *rela)
302 {
303 return arch_livepatch_perform(elf, base, rela, false);
304 }
305
arch_livepatch_perform_rela(struct livepatch_elf * elf,const struct livepatch_elf_sec * base,const struct livepatch_elf_sec * rela)306 int arch_livepatch_perform_rela(struct livepatch_elf *elf,
307 const struct livepatch_elf_sec *base,
308 const struct livepatch_elf_sec *rela)
309 {
310 return arch_livepatch_perform(elf, base, rela, true);
311 }
312
313 /*
314 * Local variables:
315 * mode: C
316 * c-file-style: "BSD"
317 * c-basic-offset: 4
318 * tab-width: 4
319 * indent-tabs-mode: nil
320 * End:
321 */
322