@@ -1886,6 +1886,23 @@ static void kpatch_verify_patchability(struct kpatch_elf *kelf)
18861886 DIFF_FATAL ("%d unsupported section change(s)" , errs );
18871887}
18881888
1889+ /*
1890+ * Do not perform symbol inclusion initially from .rela__bug_table.
1891+ *
1892+ * WARN() is converted to a static call which emits relocations that point
1893+ * directly into __bug_table+off. If the usual "include every symbol referenced
1894+ * by this rela section" rule is applied here, it could end up dragging in the
1895+ * entire __bug_table via propagation.
1896+ *
1897+ * .rela__bug_table relocations are processed later in
1898+ * kpatch_regenerate_special_section(), which also adjusts relocations
1899+ * targetting __bug_table.
1900+ */
1901+ static bool kpatch_skip_symbol_inclusion_from_relasec (struct section * relasec )
1902+ {
1903+ return !strcmp (relasec -> name , ".rela__bug_table" );
1904+ }
1905+
18891906static void kpatch_include_symbol (struct symbol * sym );
18901907
18911908static void kpatch_include_section (struct section * sec )
@@ -1906,6 +1923,8 @@ static void kpatch_include_section(struct section *sec)
19061923 if (!sec -> rela )
19071924 return ;
19081925 sec -> rela -> include = 1 ;
1926+ if (kpatch_skip_symbol_inclusion_from_relasec (sec -> rela ))
1927+ return ;
19091928 list_for_each_entry (rela , & sec -> rela -> relas , list )
19101929 kpatch_include_symbol (rela -> sym );
19111930}
@@ -2801,14 +2820,52 @@ static void kpatch_update_ex_table_addend(struct kpatch_elf *kelf,
28012820 }
28022821}
28032822
2823+ static bool is_reloc_to_bug_table (struct rela * rela )
2824+ {
2825+ return !strcmp (rela -> sym -> name , "__bug_table" );
2826+ }
2827+
2828+ static void recalculate_bug_table_rela_addend (struct kpatch_elf * kelf ,
2829+ long old_bug_offset ,
2830+ long new_bug_offset )
2831+ {
2832+ long add_offset , old_target_offset ;
2833+ struct section * relasec ;
2834+ struct rela * rela ;
2835+
2836+ list_for_each_entry (relasec , & kelf -> sections , list ) {
2837+ if (!is_rela_section (relasec ) ||
2838+ !relasec -> include ||
2839+ !strcmp (relasec -> name , ".rela__bug_table" ))
2840+ continue ;
2841+ list_for_each_entry (rela , & relasec -> relas , list ) {
2842+ if (!is_reloc_to_bug_table (rela ))
2843+ continue ;
2844+ old_target_offset = rela_target_offset (kelf , relasec , rela );
2845+ if (old_target_offset == old_bug_offset ) {
2846+ add_offset = rela_target_offset (kelf , relasec , rela ) - rela -> addend ;
2847+ rela -> addend = new_bug_offset - add_offset ;
2848+ rela -> rela .r_addend = rela -> addend ;
2849+ log_debug ("%s: adjusting rela from %s+%lx to %s+%lx\n" ,
2850+ relasec -> name ,
2851+ rela -> sym -> name ,
2852+ old_bug_offset - add_offset ,
2853+ rela -> sym -> name ,
2854+ new_bug_offset - add_offset );
2855+ }
2856+ }
2857+ }
2858+
2859+ }
2860+
28042861static void kpatch_regenerate_special_section (struct kpatch_elf * kelf ,
28052862 struct lookup_table * lookup ,
28062863 struct special_section * special ,
28072864 struct section * relasec )
28082865{
28092866 struct rela * rela , * safe ;
28102867 char * src , * dest ;
2811- unsigned int group_size , src_offset , dest_offset ;
2868+ unsigned int group_size , src_offset , dest_offset , new_offset ;
28122869
28132870 LIST_HEAD (newrelas );
28142871
@@ -2862,6 +2919,21 @@ static void kpatch_regenerate_special_section(struct kpatch_elf *kelf,
28622919 list_del (& rela -> list );
28632920 list_add_tail (& rela -> list , & newrelas );
28642921
2922+ if (!strcmp (relasec -> name , ".rela__bug_table" )) {
2923+ new_offset = rela -> offset - (src_offset - dest_offset );
2924+ /*
2925+ * When a bug table rela entry is
2926+ * reassigned to a new offset
2927+ * (rela->offset adjustment below),
2928+ * update the addends of all
2929+ * relocations targeting __bug_table so
2930+ * they continue to reference the
2931+ * updated bug entry.
2932+ */
2933+ recalculate_bug_table_rela_addend (kelf , rela -> offset ,
2934+ new_offset );
2935+ }
2936+
28652937 rela -> offset -= src_offset - dest_offset ;
28662938 rela -> rela .r_offset = rela -> offset ;
28672939
0 commit comments