@@ -40,15 +40,6 @@ struct relocation_handlers {
4040 long buffer );
4141};
4242
43- unsigned int initialize_relocation_hashtable (unsigned int num_relocations );
44- void process_accumulated_relocations (struct module * me );
45- int add_relocation_to_accumulate (struct module * me , int type , void * location ,
46- unsigned int hashtable_bits , Elf_Addr v );
47-
48- struct hlist_head * relocation_hashtable ;
49-
50- struct list_head used_buckets_list ;
51-
5243/*
5344 * The auipc+jalr instruction pair can reach any PC-relative offset
5445 * in the range [-2^31 - 2^11, 2^31 - 2^11)
@@ -64,7 +55,7 @@ static bool riscv_insn_valid_32bit_offset(ptrdiff_t val)
6455
6556static int riscv_insn_rmw (void * location , u32 keep , u32 set )
6657{
67- u16 * parcel = location ;
58+ __le16 * parcel = location ;
6859 u32 insn = (u32 )le16_to_cpu (parcel [0 ]) | (u32 )le16_to_cpu (parcel [1 ]) << 16 ;
6960
7061 insn &= keep ;
@@ -77,7 +68,7 @@ static int riscv_insn_rmw(void *location, u32 keep, u32 set)
7768
7869static int riscv_insn_rvc_rmw (void * location , u16 keep , u16 set )
7970{
80- u16 * parcel = location ;
71+ __le16 * parcel = location ;
8172 u16 insn = le16_to_cpu (* parcel );
8273
8374 insn &= keep ;
@@ -604,7 +595,10 @@ static const struct relocation_handlers reloc_handlers[] = {
604595 /* 192-255 nonstandard ABI extensions */
605596};
606597
607- void process_accumulated_relocations (struct module * me )
598+ static void
599+ process_accumulated_relocations (struct module * me ,
600+ struct hlist_head * * relocation_hashtable ,
601+ struct list_head * used_buckets_list )
608602{
609603 /*
610604 * Only ADD/SUB/SET/ULEB128 should end up here.
@@ -624,18 +618,25 @@ void process_accumulated_relocations(struct module *me)
624618 * - Each relocation entry for a location address
625619 */
626620 struct used_bucket * bucket_iter ;
621+ struct used_bucket * bucket_iter_tmp ;
627622 struct relocation_head * rel_head_iter ;
623+ struct hlist_node * rel_head_iter_tmp ;
628624 struct relocation_entry * rel_entry_iter ;
625+ struct relocation_entry * rel_entry_iter_tmp ;
629626 int curr_type ;
630627 void * location ;
631628 long buffer ;
632629
633- list_for_each_entry (bucket_iter , & used_buckets_list , head ) {
634- hlist_for_each_entry (rel_head_iter , bucket_iter -> bucket , node ) {
630+ list_for_each_entry_safe (bucket_iter , bucket_iter_tmp ,
631+ used_buckets_list , head ) {
632+ hlist_for_each_entry_safe (rel_head_iter , rel_head_iter_tmp ,
633+ bucket_iter -> bucket , node ) {
635634 buffer = 0 ;
636635 location = rel_head_iter -> location ;
637- list_for_each_entry (rel_entry_iter ,
638- rel_head_iter -> rel_entry , head ) {
636+ list_for_each_entry_safe (rel_entry_iter ,
637+ rel_entry_iter_tmp ,
638+ rel_head_iter -> rel_entry ,
639+ head ) {
639640 curr_type = rel_entry_iter -> type ;
640641 reloc_handlers [curr_type ].reloc_handler (
641642 me , & buffer , rel_entry_iter -> value );
@@ -648,11 +649,14 @@ void process_accumulated_relocations(struct module *me)
648649 kfree (bucket_iter );
649650 }
650651
651- kfree (relocation_hashtable );
652+ kfree (* relocation_hashtable );
652653}
653654
654- int add_relocation_to_accumulate (struct module * me , int type , void * location ,
655- unsigned int hashtable_bits , Elf_Addr v )
655+ static int add_relocation_to_accumulate (struct module * me , int type ,
656+ void * location ,
657+ unsigned int hashtable_bits , Elf_Addr v ,
658+ struct hlist_head * relocation_hashtable ,
659+ struct list_head * used_buckets_list )
656660{
657661 struct relocation_entry * entry ;
658662 struct relocation_head * rel_head ;
@@ -661,6 +665,10 @@ int add_relocation_to_accumulate(struct module *me, int type, void *location,
661665 unsigned long hash ;
662666
663667 entry = kmalloc (sizeof (* entry ), GFP_KERNEL );
668+
669+ if (!entry )
670+ return - ENOMEM ;
671+
664672 INIT_LIST_HEAD (& entry -> head );
665673 entry -> type = type ;
666674 entry -> value = v ;
@@ -669,7 +677,10 @@ int add_relocation_to_accumulate(struct module *me, int type, void *location,
669677
670678 current_head = & relocation_hashtable [hash ];
671679
672- /* Find matching location (if any) */
680+ /*
681+ * Search for the relocation_head for the relocations that happen at the
682+ * provided location
683+ */
673684 bool found = false;
674685 struct relocation_head * rel_head_iter ;
675686
@@ -681,19 +692,45 @@ int add_relocation_to_accumulate(struct module *me, int type, void *location,
681692 }
682693 }
683694
695+ /*
696+ * If there has not yet been any relocations at the provided location,
697+ * create a relocation_head for that location and populate it with this
698+ * relocation_entry.
699+ */
684700 if (!found ) {
685701 rel_head = kmalloc (sizeof (* rel_head ), GFP_KERNEL );
702+
703+ if (!rel_head ) {
704+ kfree (entry );
705+ return - ENOMEM ;
706+ }
707+
686708 rel_head -> rel_entry =
687709 kmalloc (sizeof (struct list_head ), GFP_KERNEL );
710+
711+ if (!rel_head -> rel_entry ) {
712+ kfree (entry );
713+ kfree (rel_head );
714+ return - ENOMEM ;
715+ }
716+
688717 INIT_LIST_HEAD (rel_head -> rel_entry );
689718 rel_head -> location = location ;
690719 INIT_HLIST_NODE (& rel_head -> node );
691720 if (!current_head -> first ) {
692721 bucket =
693722 kmalloc (sizeof (struct used_bucket ), GFP_KERNEL );
723+
724+ if (!bucket ) {
725+ kfree (entry );
726+ kfree (rel_head );
727+ kfree (rel_head -> rel_entry );
728+ return - ENOMEM ;
729+ }
730+
694731 INIT_LIST_HEAD (& bucket -> head );
695732 bucket -> bucket = current_head ;
696- list_add (& bucket -> head , & used_buckets_list );
733+ list_add (& bucket -> head , used_buckets_list );
697734 }
698735 hlist_add_head (& rel_head -> node , current_head );
699736 }
@@ -704,7 +741,9 @@ int add_relocation_to_accumulate(struct module *me, int type, void *location,
704741 return 0 ;
705742}
706743
707- unsigned int initialize_relocation_hashtable (unsigned int num_relocations )
744+ static unsigned int
745+ initialize_relocation_hashtable (unsigned int num_relocations ,
746+ struct hlist_head * * relocation_hashtable )
708747{
709748 /* Can safely assume that bits is not greater than sizeof(long) */
710749 unsigned long hashtable_size = roundup_pow_of_two (num_relocations );
@@ -720,12 +759,13 @@ unsigned int initialize_relocation_hashtable(unsigned int num_relocations)
720759
721760 hashtable_size <<= should_double_size ;
722761
723- relocation_hashtable = kmalloc_array (hashtable_size ,
724- sizeof (* relocation_hashtable ),
725- GFP_KERNEL );
726- __hash_init (relocation_hashtable , hashtable_size );
762+ * relocation_hashtable = kmalloc_array (hashtable_size ,
763+ sizeof (* relocation_hashtable ),
764+ GFP_KERNEL );
765+ if (!* relocation_hashtable )
766+ return - ENOMEM ;
727767
728- INIT_LIST_HEAD ( & used_buckets_list );
768+ __hash_init ( * relocation_hashtable , hashtable_size );
729769
730770 return hashtable_bits ;
731771}
@@ -742,7 +782,17 @@ int apply_relocate_add(Elf_Shdr *sechdrs, const char *strtab,
742782 Elf_Addr v ;
743783 int res ;
744784 unsigned int num_relocations = sechdrs [relsec ].sh_size / sizeof (* rel );
745- unsigned int hashtable_bits = initialize_relocation_hashtable (num_relocations );
785+ struct hlist_head * relocation_hashtable ;
786+ struct list_head used_buckets_list ;
787+ unsigned int hashtable_bits ;
788+
789+ hashtable_bits = initialize_relocation_hashtable (num_relocations ,
790+ & relocation_hashtable );
791+
792+ if (hashtable_bits < 0 )
793+ return hashtable_bits ;
794+
795+ INIT_LIST_HEAD (& used_buckets_list );
746796
747797 pr_debug ("Applying relocate section %u to %u\n" , relsec ,
748798 sechdrs [relsec ].sh_info );
@@ -823,14 +873,18 @@ int apply_relocate_add(Elf_Shdr *sechdrs, const char *strtab,
823873 }
824874
825875 if (reloc_handlers [type ].accumulate_handler )
826- res = add_relocation_to_accumulate (me , type , location , hashtable_bits , v );
876+ res = add_relocation_to_accumulate (me , type , location ,
877+ hashtable_bits , v ,
878+ relocation_hashtable ,
879+ & used_buckets_list );
827880 else
828881 res = handler (me , location , v );
829882 if (res )
830883 return res ;
831884 }
832885
833- process_accumulated_relocations (me );
886+ process_accumulated_relocations (me , & relocation_hashtable ,
887+ & used_buckets_list );
834888
835889 return 0 ;
836890}
0 commit comments