]> xenbits.xensource.com Git - people/wipawel/livepatch-build-tools/commitdiff
create-diff-object: Extend patchability verification: STN_UNDEF
authorPawel Wieczorkiewicz <wipawel@amazon.de>
Mon, 1 Oct 2018 12:36:26 +0000 (12:36 +0000)
committerPawel Wieczorkiewicz <wipawel@amazon.de>
Thu, 8 Aug 2019 09:53:13 +0000 (09:53 +0000)
During verification check if all sections do not contain any entries
with undefined symbols (STN_UNDEF). This situation can happen when a
section is copied over from its original object to a patched object,
but various symbols related to the section are not copied along.
This scenario happens typically during stacked hotpatches creation
(between 2 different hotpatch modules).

Signed-off-by: Pawel Wieczorkiewicz <wipawel@amazon.de>
Reviewed-by: Martin Pohlack <mpohlack@amazon.de>
Reviewed-by: Bjoern Doebel <doebel@amazon.de>
Reviewed-by: Norbert Manthey <nmanthey@amazon.de>
Reviewed-by: Andra-Irina Paraschiv <andraprs@amazon.com>
create-diff-object.c

index 41adb09b88c920e8608e519de0947a122d28c185..e9051315b50387df923f584d62bd031f1d24c4fe 100644 (file)
@@ -1531,6 +1531,61 @@ static void kpatch_print_changes(struct kpatch_elf *kelf)
        }
 }
 
+static inline int get_section_entry_size(const struct section *sec,
+                                        struct kpatch_elf *kelf)
+{
+       int entry_size;
+
+       /*
+        * Base sections typically do not define fixed size elements.
+        * Detect section's element size in case it's a special section.
+        * Otherwise, skip it due to an unknown sh_entsize.
+        */
+       entry_size = sec->sh.sh_entsize;
+       if (entry_size == 0) {
+               struct special_section *special;
+
+               /* Find special section group_size. */
+               for (special = special_sections; special->name; special++) {
+                       if (!strcmp(sec->name, special->name))
+                               return special->group_size(kelf, 0);
+               }
+        }
+
+       return entry_size;
+}
+
+static int kpatch_section_has_undef_symbols(struct kpatch_elf *kelf,
+                                           const struct section *sec)
+{
+       int offset, entry_size;
+       struct rela *rela;
+       size_t d_size;
+
+       entry_size = get_section_entry_size(sec, kelf);
+       if (entry_size == 0)
+               return false;
+
+       d_size = sec->base->data->d_size;
+       for ( offset = 0; offset < d_size; offset += entry_size ) {
+               list_for_each_entry(rela, &sec->relas, list) {
+                       if (rela->offset < offset ||
+                           rela->offset >= offset + entry_size) {
+                               continue;
+                       }
+
+                       if ((GELF_R_SYM(rela->rela.r_info) == STN_UNDEF) ||
+                           (!rela->sym->include && rela->sym->status == SAME)) {
+                               log_normal("section %s has an entry with a STN_UNDEF symbol: %s\n",
+                                          sec->name, rela->sym->name ?: "none");
+                               return true;
+                       }
+               }
+       }
+
+       return false;
+}
+
 static void kpatch_verify_patchability(struct kpatch_elf *kelf)
 {
        struct section *sec;
@@ -1563,6 +1618,17 @@ static void kpatch_verify_patchability(struct kpatch_elf *kelf)
                                        errs++;
                                }
                        }
+
+                       /* Check if a RELA section does not contain any entries with
+                        * undefined symbols (STN_UNDEF). This situation can happen
+                        * when a section is copied over from its original object to
+                        * a patched object, but various symbols related to the section
+                        * are not copied along.
+                        */
+                       if (is_rela_section(sec)) {
+                               if (kpatch_section_has_undef_symbols(kelf, sec))
+                                       errs++;
+                       }
                }
 
                /*