1919#include <linux/kasan.h>
2020#include <linux/moduleloader.h>
2121#include <linux/bug.h>
22+ #include <linux/memory.h>
2223#include <asm/alternative.h>
2324#include <asm/nospec-branch.h>
2425#include <asm/facility.h>
@@ -174,10 +175,12 @@ int module_frob_arch_sections(Elf_Ehdr *hdr, Elf_Shdr *sechdrs,
174175}
175176
176177static int apply_rela_bits (Elf_Addr loc , Elf_Addr val ,
177- int sign , int bits , int shift )
178+ int sign , int bits , int shift ,
179+ void * (* write )(void * dest , const void * src , size_t len ))
178180{
179181 unsigned long umax ;
180182 long min , max ;
183+ void * dest = (void * )loc ;
181184
182185 if (val & ((1UL << shift ) - 1 ))
183186 return - ENOEXEC ;
@@ -194,26 +197,33 @@ static int apply_rela_bits(Elf_Addr loc, Elf_Addr val,
194197 return - ENOEXEC ;
195198 }
196199
197- if (bits == 8 )
198- * (unsigned char * ) loc = val ;
199- else if (bits == 12 )
200- * (unsigned short * ) loc = (val & 0xfff ) |
200+ if (bits == 8 ) {
201+ unsigned char tmp = val ;
202+ write (dest , & tmp , 1 );
203+ } else if (bits == 12 ) {
204+ unsigned short tmp = (val & 0xfff ) |
201205 (* (unsigned short * ) loc & 0xf000 );
202- else if (bits == 16 )
203- * (unsigned short * ) loc = val ;
204- else if (bits == 20 )
205- * (unsigned int * ) loc = (val & 0xfff ) << 16 |
206- (val & 0xff000 ) >> 4 |
207- (* (unsigned int * ) loc & 0xf00000ff );
208- else if (bits == 32 )
209- * (unsigned int * ) loc = val ;
210- else if (bits == 64 )
211- * (unsigned long * ) loc = val ;
206+ write (dest , & tmp , 2 );
207+ } else if (bits == 16 ) {
208+ unsigned short tmp = val ;
209+ write (dest , & tmp , 2 );
210+ } else if (bits == 20 ) {
211+ unsigned int tmp = (val & 0xfff ) << 16 |
212+ (val & 0xff000 ) >> 4 | (* (unsigned int * ) loc & 0xf00000ff );
213+ write (dest , & tmp , 4 );
214+ } else if (bits == 32 ) {
215+ unsigned int tmp = val ;
216+ write (dest , & tmp , 4 );
217+ } else if (bits == 64 ) {
218+ unsigned long tmp = val ;
219+ write (dest , & tmp , 8 );
220+ }
212221 return 0 ;
213222}
214223
215224static int apply_rela (Elf_Rela * rela , Elf_Addr base , Elf_Sym * symtab ,
216- const char * strtab , struct module * me )
225+ const char * strtab , struct module * me ,
226+ void * (* write )(void * dest , const void * src , size_t len ))
217227{
218228 struct mod_arch_syminfo * info ;
219229 Elf_Addr loc , val ;
@@ -241,17 +251,17 @@ static int apply_rela(Elf_Rela *rela, Elf_Addr base, Elf_Sym *symtab,
241251 case R_390_64 : /* Direct 64 bit. */
242252 val += rela -> r_addend ;
243253 if (r_type == R_390_8 )
244- rc = apply_rela_bits (loc , val , 0 , 8 , 0 );
254+ rc = apply_rela_bits (loc , val , 0 , 8 , 0 , write );
245255 else if (r_type == R_390_12 )
246- rc = apply_rela_bits (loc , val , 0 , 12 , 0 );
256+ rc = apply_rela_bits (loc , val , 0 , 12 , 0 , write );
247257 else if (r_type == R_390_16 )
248- rc = apply_rela_bits (loc , val , 0 , 16 , 0 );
258+ rc = apply_rela_bits (loc , val , 0 , 16 , 0 , write );
249259 else if (r_type == R_390_20 )
250- rc = apply_rela_bits (loc , val , 1 , 20 , 0 );
260+ rc = apply_rela_bits (loc , val , 1 , 20 , 0 , write );
251261 else if (r_type == R_390_32 )
252- rc = apply_rela_bits (loc , val , 0 , 32 , 0 );
262+ rc = apply_rela_bits (loc , val , 0 , 32 , 0 , write );
253263 else if (r_type == R_390_64 )
254- rc = apply_rela_bits (loc , val , 0 , 64 , 0 );
264+ rc = apply_rela_bits (loc , val , 0 , 64 , 0 , write );
255265 break ;
256266 case R_390_PC16 : /* PC relative 16 bit. */
257267 case R_390_PC16DBL : /* PC relative 16 bit shifted by 1. */
@@ -260,15 +270,15 @@ static int apply_rela(Elf_Rela *rela, Elf_Addr base, Elf_Sym *symtab,
260270 case R_390_PC64 : /* PC relative 64 bit. */
261271 val += rela -> r_addend - loc ;
262272 if (r_type == R_390_PC16 )
263- rc = apply_rela_bits (loc , val , 1 , 16 , 0 );
273+ rc = apply_rela_bits (loc , val , 1 , 16 , 0 , write );
264274 else if (r_type == R_390_PC16DBL )
265- rc = apply_rela_bits (loc , val , 1 , 16 , 1 );
275+ rc = apply_rela_bits (loc , val , 1 , 16 , 1 , write );
266276 else if (r_type == R_390_PC32DBL )
267- rc = apply_rela_bits (loc , val , 1 , 32 , 1 );
277+ rc = apply_rela_bits (loc , val , 1 , 32 , 1 , write );
268278 else if (r_type == R_390_PC32 )
269- rc = apply_rela_bits (loc , val , 1 , 32 , 0 );
279+ rc = apply_rela_bits (loc , val , 1 , 32 , 0 , write );
270280 else if (r_type == R_390_PC64 )
271- rc = apply_rela_bits (loc , val , 1 , 64 , 0 );
281+ rc = apply_rela_bits (loc , val , 1 , 64 , 0 , write );
272282 break ;
273283 case R_390_GOT12 : /* 12 bit GOT offset. */
274284 case R_390_GOT16 : /* 16 bit GOT offset. */
@@ -283,33 +293,33 @@ static int apply_rela(Elf_Rela *rela, Elf_Addr base, Elf_Sym *symtab,
283293 case R_390_GOTPLT64 : /* 64 bit offset to jump slot. */
284294 case R_390_GOTPLTENT : /* 32 bit rel. offset to jump slot >> 1. */
285295 if (info -> got_initialized == 0 ) {
286- Elf_Addr * gotent ;
296+ Elf_Addr * gotent = me -> core_layout .base +
297+ me -> arch .got_offset +
298+ info -> got_offset ;
287299
288- gotent = me -> core_layout .base + me -> arch .got_offset +
289- info -> got_offset ;
290- * gotent = val ;
300+ write (gotent , & val , sizeof (* gotent ));
291301 info -> got_initialized = 1 ;
292302 }
293303 val = info -> got_offset + rela -> r_addend ;
294304 if (r_type == R_390_GOT12 ||
295305 r_type == R_390_GOTPLT12 )
296- rc = apply_rela_bits (loc , val , 0 , 12 , 0 );
306+ rc = apply_rela_bits (loc , val , 0 , 12 , 0 , write );
297307 else if (r_type == R_390_GOT16 ||
298308 r_type == R_390_GOTPLT16 )
299- rc = apply_rela_bits (loc , val , 0 , 16 , 0 );
309+ rc = apply_rela_bits (loc , val , 0 , 16 , 0 , write );
300310 else if (r_type == R_390_GOT20 ||
301311 r_type == R_390_GOTPLT20 )
302- rc = apply_rela_bits (loc , val , 1 , 20 , 0 );
312+ rc = apply_rela_bits (loc , val , 1 , 20 , 0 , write );
303313 else if (r_type == R_390_GOT32 ||
304314 r_type == R_390_GOTPLT32 )
305- rc = apply_rela_bits (loc , val , 0 , 32 , 0 );
315+ rc = apply_rela_bits (loc , val , 0 , 32 , 0 , write );
306316 else if (r_type == R_390_GOT64 ||
307317 r_type == R_390_GOTPLT64 )
308- rc = apply_rela_bits (loc , val , 0 , 64 , 0 );
318+ rc = apply_rela_bits (loc , val , 0 , 64 , 0 , write );
309319 else if (r_type == R_390_GOTENT ||
310320 r_type == R_390_GOTPLTENT ) {
311321 val += (Elf_Addr ) me -> core_layout .base - loc ;
312- rc = apply_rela_bits (loc , val , 1 , 32 , 1 );
322+ rc = apply_rela_bits (loc , val , 1 , 32 , 1 , write );
313323 }
314324 break ;
315325 case R_390_PLT16DBL : /* 16 bit PC rel. PLT shifted by 1. */
@@ -320,25 +330,29 @@ static int apply_rela(Elf_Rela *rela, Elf_Addr base, Elf_Sym *symtab,
320330 case R_390_PLTOFF32 : /* 32 bit offset from GOT to PLT. */
321331 case R_390_PLTOFF64 : /* 16 bit offset from GOT to PLT. */
322332 if (info -> plt_initialized == 0 ) {
323- unsigned int * ip ;
324- ip = me -> core_layout .base + me -> arch .plt_offset +
325- info -> plt_offset ;
326- ip [0 ] = 0x0d10e310 ; /* basr 1,0 */
327- ip [1 ] = 0x100a0004 ; /* lg 1,10(1) */
333+ unsigned int insn [5 ];
334+ unsigned int * ip = me -> core_layout .base +
335+ me -> arch .plt_offset +
336+ info -> plt_offset ;
337+
338+ insn [0 ] = 0x0d10e310 ; /* basr 1,0 */
339+ insn [1 ] = 0x100a0004 ; /* lg 1,10(1) */
328340 if (IS_ENABLED (CONFIG_EXPOLINE ) && !nospec_disable ) {
329341 unsigned int * ij ;
330342 ij = me -> core_layout .base +
331343 me -> arch .plt_offset +
332344 me -> arch .plt_size - PLT_ENTRY_SIZE ;
333- ip [2 ] = 0xa7f40000 + /* j __jump_r1 */
345+ insn [2 ] = 0xa7f40000 + /* j __jump_r1 */
334346 (unsigned int )(u16 )
335347 (((unsigned long ) ij - 8 -
336348 (unsigned long ) ip ) / 2 );
337349 } else {
338- ip [2 ] = 0x07f10000 ; /* br %r1 */
350+ insn [2 ] = 0x07f10000 ; /* br %r1 */
339351 }
340- ip [3 ] = (unsigned int ) (val >> 32 );
341- ip [4 ] = (unsigned int ) val ;
352+ insn [3 ] = (unsigned int ) (val >> 32 );
353+ insn [4 ] = (unsigned int ) val ;
354+
355+ write (ip , insn , sizeof (insn ));
342356 info -> plt_initialized = 1 ;
343357 }
344358 if (r_type == R_390_PLTOFF16 ||
@@ -357,38 +371,38 @@ static int apply_rela(Elf_Rela *rela, Elf_Addr base, Elf_Sym *symtab,
357371 val += rela -> r_addend - loc ;
358372 }
359373 if (r_type == R_390_PLT16DBL )
360- rc = apply_rela_bits (loc , val , 1 , 16 , 1 );
374+ rc = apply_rela_bits (loc , val , 1 , 16 , 1 , write );
361375 else if (r_type == R_390_PLTOFF16 )
362- rc = apply_rela_bits (loc , val , 0 , 16 , 0 );
376+ rc = apply_rela_bits (loc , val , 0 , 16 , 0 , write );
363377 else if (r_type == R_390_PLT32DBL )
364- rc = apply_rela_bits (loc , val , 1 , 32 , 1 );
378+ rc = apply_rela_bits (loc , val , 1 , 32 , 1 , write );
365379 else if (r_type == R_390_PLT32 ||
366380 r_type == R_390_PLTOFF32 )
367- rc = apply_rela_bits (loc , val , 0 , 32 , 0 );
381+ rc = apply_rela_bits (loc , val , 0 , 32 , 0 , write );
368382 else if (r_type == R_390_PLT64 ||
369383 r_type == R_390_PLTOFF64 )
370- rc = apply_rela_bits (loc , val , 0 , 64 , 0 );
384+ rc = apply_rela_bits (loc , val , 0 , 64 , 0 , write );
371385 break ;
372386 case R_390_GOTOFF16 : /* 16 bit offset to GOT. */
373387 case R_390_GOTOFF32 : /* 32 bit offset to GOT. */
374388 case R_390_GOTOFF64 : /* 64 bit offset to GOT. */
375389 val = val + rela -> r_addend -
376390 ((Elf_Addr ) me -> core_layout .base + me -> arch .got_offset );
377391 if (r_type == R_390_GOTOFF16 )
378- rc = apply_rela_bits (loc , val , 0 , 16 , 0 );
392+ rc = apply_rela_bits (loc , val , 0 , 16 , 0 , write );
379393 else if (r_type == R_390_GOTOFF32 )
380- rc = apply_rela_bits (loc , val , 0 , 32 , 0 );
394+ rc = apply_rela_bits (loc , val , 0 , 32 , 0 , write );
381395 else if (r_type == R_390_GOTOFF64 )
382- rc = apply_rela_bits (loc , val , 0 , 64 , 0 );
396+ rc = apply_rela_bits (loc , val , 0 , 64 , 0 , write );
383397 break ;
384398 case R_390_GOTPC : /* 32 bit PC relative offset to GOT. */
385399 case R_390_GOTPCDBL : /* 32 bit PC rel. off. to GOT shifted by 1. */
386400 val = (Elf_Addr ) me -> core_layout .base + me -> arch .got_offset +
387401 rela -> r_addend - loc ;
388402 if (r_type == R_390_GOTPC )
389- rc = apply_rela_bits (loc , val , 1 , 32 , 0 );
403+ rc = apply_rela_bits (loc , val , 1 , 32 , 0 , write );
390404 else if (r_type == R_390_GOTPCDBL )
391- rc = apply_rela_bits (loc , val , 1 , 32 , 1 );
405+ rc = apply_rela_bits (loc , val , 1 , 32 , 1 , write );
392406 break ;
393407 case R_390_COPY :
394408 case R_390_GLOB_DAT : /* Create GOT entry. */
@@ -412,9 +426,10 @@ static int apply_rela(Elf_Rela *rela, Elf_Addr base, Elf_Sym *symtab,
412426 return 0 ;
413427}
414428
415- int apply_relocate_add (Elf_Shdr * sechdrs , const char * strtab ,
429+ static int __apply_relocate_add (Elf_Shdr * sechdrs , const char * strtab ,
416430 unsigned int symindex , unsigned int relsec ,
417- struct module * me )
431+ struct module * me ,
432+ void * (* write )(void * dest , const void * src , size_t len ))
418433{
419434 Elf_Addr base ;
420435 Elf_Sym * symtab ;
@@ -430,13 +445,27 @@ int apply_relocate_add(Elf_Shdr *sechdrs, const char *strtab,
430445 n = sechdrs [relsec ].sh_size / sizeof (Elf_Rela );
431446
432447 for (i = 0 ; i < n ; i ++ , rela ++ ) {
433- rc = apply_rela (rela , base , symtab , strtab , me );
448+ rc = apply_rela (rela , base , symtab , strtab , me , write );
434449 if (rc )
435450 return rc ;
436451 }
437452 return 0 ;
438453}
439454
455+ int apply_relocate_add (Elf_Shdr * sechdrs , const char * strtab ,
456+ unsigned int symindex , unsigned int relsec ,
457+ struct module * me )
458+ {
459+ bool early = me -> state == MODULE_STATE_UNFORMED ;
460+ void * (* write )(void * , const void * , size_t ) = memcpy ;
461+
462+ if (!early )
463+ write = s390_kernel_write ;
464+
465+ return __apply_relocate_add (sechdrs , strtab , symindex , relsec , me ,
466+ write );
467+ }
468+
440469int module_finalize (const Elf_Ehdr * hdr ,
441470 const Elf_Shdr * sechdrs ,
442471 struct module * me )
0 commit comments