livepatch: ARM 32|64: Ignore mapping symbols: $[d,a,x]
authorKonrad Rzeszutek Wilk <konrad.wilk@oracle.com>
Sat, 13 Aug 2016 03:08:32 +0000 (23:08 -0400)
committerKonrad Rzeszutek Wilk <konrad.wilk@oracle.com>
Wed, 28 Sep 2016 02:06:15 +0000 (22:06 -0400)
Those symbols are used to help final linkers to replace insn.
The ARM ELF specification mandates that they are present
to denote the start of certain CPU features. There are two
variants of it - short and long format.

Either way - we can ignore these symbols.

Reviewed-by: Ross Lagerwall <ross.lagerwall@citrix.com>
Acked-by: Julien Grall <julien.grall@arm.com>
Reviewed-by: Andrew Cooper <andrew.cooper3@citrix.com> [x86 bits]
Signed-off-by: Konrad Rzeszutek Wilk <konrad.wilk@oracle.com>
xen/arch/arm/livepatch.c
xen/arch/x86/livepatch.c
xen/common/livepatch.c
xen/include/xen/livepatch.h

index 679abf1d636148d54ec033b03a0cf14afd64a9ff..f467d9db4a7d7228b4159f0930dff9a4efa07c9d 100644 (file)
@@ -84,6 +84,39 @@ void arch_livepatch_unmask(void)
     local_abort_enable();
 }
 
+bool arch_livepatch_symbol_ok(const struct livepatch_elf *elf,
+                              const struct livepatch_elf_sym *sym)
+{
+    /*
+     * - Mapping symbols - denote the "start of a sequence of bytes of the
+     *   appropriate type" to mark certain features - such as start of region
+     *   containing data ($d); ARM ($a), or A64 ($x) instructions.
+     *   We ignore Thumb instructions ($t) as we shouldn't have them.
+     *
+     * The format is either short: '$x' or long: '$x.<any>'. We do not
+     * need this and more importantly - each payload will contain this
+     * resulting in symbol collisions.
+     */
+    if ( sym->name[0] == '$' && sym->name[1] != '\0' )
+    {
+        char p = sym->name[1];
+        size_t len = strlen(sym->name);
+
+        if ( (len >= 3 && (sym->name[2] == '.' )) || (len == 2) )
+        {
+            if ( p == 'd' ||
+#ifdef CONFIG_ARM_32
+                 p == 'a'
+#else
+                 p == 'x'
+#endif
+               )
+                return false;
+        }
+    }
+    return true;
+}
+
 int arch_livepatch_perform_rel(struct livepatch_elf *elf,
                                const struct livepatch_elf_sec *base,
                                const struct livepatch_elf_sec *rela)
index b0d81d7ceb1eafff597ef26b7e6d6be91c0d5128..7a369a004b9d47a8e8c5ed171488f8ec51d658b5 100644 (file)
@@ -124,6 +124,13 @@ int arch_livepatch_verify_elf(const struct livepatch_elf *elf)
     return 0;
 }
 
+bool arch_livepatch_symbol_ok(const struct livepatch_elf *elf,
+                              const struct livepatch_elf_sym *sym)
+{
+    /* No special checks on x86. */
+    return true;
+}
+
 int arch_livepatch_perform_rel(struct livepatch_elf *elf,
                                const struct livepatch_elf_sec *base,
                                const struct livepatch_elf_sec *rela)
index 2d08c9af6054007f2956b01e77acedd6afb225fb..fc8ef9999ad3cb67fad4f638eb048d324363774a 100644 (file)
@@ -747,7 +747,7 @@ static bool_t is_payload_symbol(const struct livepatch_elf *elf,
          !strncmp(sym->name, ".L", 2) )
         return 0;
 
-    return 1;
+    return arch_livepatch_symbol_ok(elf, sym);
 }
 
 static int build_symbol_table(struct payload *payload,
index b7b84e705f57ed209a79a0d85a2945873f31a277..e8c67d6b0193c963cb4edd679014e7e573938dd0 100644 (file)
@@ -48,6 +48,8 @@ bool_t is_patch(const void *addr);
 
 /* Arch hooks. */
 int arch_livepatch_verify_elf(const struct livepatch_elf *elf);
+bool arch_livepatch_symbol_ok(const struct livepatch_elf *elf,
+                              const struct livepatch_elf_sym *sym);
 int arch_livepatch_perform_rel(struct livepatch_elf *elf,
                                const struct livepatch_elf_sec *base,
                                const struct livepatch_elf_sec *rela);