diff mbox series

[livepatch-build-tools,part3,2/3] create-diff-object: Extend patchability verification: STN_UNDEF

Message ID 20190416122241.28342-2-wipawel@amazon.de (mailing list archive)
State New, archived
Headers show
Series [livepatch-build-tools,part3,1/3] create-diff-object: Do not create empty .livepatch.funcs section | expand

Commit Message

Wieczorkiewicz, Pawel April 16, 2019, 12:22 p.m. UTC
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>

CR: https://code.amazon.com/reviews/CR-7368645
---
 create-diff-object.c | 60 ++++++++++++++++++++++++++++++++++++++++++++++++++++
 1 file changed, 60 insertions(+)
diff mbox series

Patch

diff --git a/create-diff-object.c b/create-diff-object.c
index af2245c..96b6716 100644
--- a/create-diff-object.c
+++ b/create-diff-object.c
@@ -1448,6 +1448,31 @@  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++) {
+			/* Match sections starting with special->name prefix */
+			if (!strncmp(sec->name, special->name, strlen(special->name))) {
+				return special->group_size(kelf, 0);
+			}
+		}
+        }
+
+        return entry_size;
+}
+
 static void kpatch_verify_patchability(struct kpatch_elf *kelf)
 {
 	struct section *sec;
@@ -1471,6 +1496,41 @@  static void kpatch_verify_patchability(struct kpatch_elf *kelf)
 			errs++;
 		}
 
+		if (sec->include) {
+			if (!is_standard_section(sec) && !is_rela_section(sec) &&
+			    !is_debug_section(sec) && !is_special_section(sec)) {
+				if (!is_referenced_section(sec, kelf)) {
+					log_normal("section %s included, but not referenced\n", sec->name);
+					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)) {
+				int offset, entry_size = get_section_entry_size(sec, kelf);
+				struct rela *rela;
+
+				for ( offset = 0; offset < sec->base->data->d_size && entry_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 ? rela->sym->name : "none");
+							errs++;
+						}
+					}
+				}
+			}
+		}
+
 		/*
 		 * ensure we aren't including .data.* or .bss.*
 		 * (.data.unlikely is ok b/c it only has __warned vars)