]> xenbits.xensource.com Git - xen.git/commitdiff
xen/livepatch: Don't crash on encountering STN_UNDEF relocations
authorAndrew Cooper <andrew.cooper3@citrix.com>
Mon, 28 Aug 2017 09:45:45 +0000 (11:45 +0200)
committerJan Beulich <jbeulich@suse.com>
Mon, 28 Aug 2017 09:45:45 +0000 (11:45 +0200)
A symndx of STN_UNDEF is special, and means a symbol value of 0.  While
legitimate in the ELF standard, its existance in a livepatch is questionable
at best.  Until a plausible usecase presents itself, reject such a relocation
with -EOPNOTSUPP.

Additionally, fix an off-by-one error while range checking symndx, and perform
a safety check on elf->sym[symndx].sym before derefencing it, to avoid
tripping over a NULL pointer when calculating val.

Signed-off-by: Andrew Cooper <andrew.cooper3@citrix.com>
Reviewed-by: Stefano Stabellini <sstabellini@kernel.org>
Reviewed-by: Konrad Rzeszutek Wilk <konrad.wilk@oracle.com>
Tested-by: Konrad Rzeszutek Wilk <konrad.wilk@oracle.com> [x86 and arm32]
Reviewed-by: Jan Beulich <JBeulich@suse.com>
Reviewed-by: Ross Lagerwall <ross.lagerwall@citrix.com>
master commit: 2ff229643b739e2fd0cd0536ee9fca506cfa92f8
master date: 2017-06-23 15:00:37 +0100

xen/arch/arm/arm32/livepatch.c
xen/arch/arm/arm64/livepatch.c
xen/arch/x86/livepatch.c

index a7fd5e295e08cb8e74b43bf3a7848c6dd4b32959..d401ccc6f9b5231a76d2e04276e81ac392659e0d 100644 (file)
@@ -252,12 +252,24 @@ int arch_livepatch_perform(struct livepatch_elf *elf,
             dest = base->load_addr + r->r_offset; /* P */
         }
 
-        if ( symndx > elf->nsym )
+        if ( symndx == STN_UNDEF )
+        {
+            dprintk(XENLOG_ERR, LIVEPATCH "%s: Encountered STN_UNDEF\n",
+                    elf->name);
+            return -EOPNOTSUPP;
+        }
+        else if ( symndx >= elf->nsym )
         {
             dprintk(XENLOG_ERR, LIVEPATCH "%s: Relative symbol wants symbol@%u which is past end!\n",
                     elf->name, symndx);
             return -EINVAL;
         }
+        else if ( !elf->sym[symndx].sym )
+        {
+            dprintk(XENLOG_ERR, LIVEPATCH "%s: No relative symbol@%u\n",
+                    elf->name, symndx);
+            return -EINVAL;
+        }
 
         if ( !use_rela )
             addend = get_addend(type, dest);
index dae64f5869cbe57d8edf654e83a7fa5dd43a96c9..46301c350a9f4fd2e8c0fce51c05e2c83f5f7cbc 100644 (file)
@@ -255,12 +255,24 @@ int arch_livepatch_perform_rela(struct livepatch_elf *elf,
 
         symndx = ELF64_R_SYM(r->r_info);
 
-        if ( symndx > elf->nsym )
+        if ( symndx == STN_UNDEF )
+        {
+            dprintk(XENLOG_ERR, LIVEPATCH "%s: Encountered STN_UNDEF\n",
+                    elf->name);
+            return -EOPNOTSUPP;
+        }
+        else if ( symndx >= elf->nsym )
         {
             dprintk(XENLOG_ERR, LIVEPATCH "%s: Relative relocation wants symbol@%u which is past end!\n",
                     elf->name, symndx);
             return -EINVAL;
         }
+        else if ( !elf->sym[symndx].sym )
+        {
+            dprintk(XENLOG_ERR, LIVEPATCH "%s: No relative symbol@%u\n",
+                    elf->name, symndx);
+            return -EINVAL;
+        }
 
         dest = base->load_addr + r->r_offset; /* P */
         val = elf->sym[symndx].sym->st_value +  r->r_addend; /* S+A */
index 9663ef6fef6b860f6882c998e52c4d9d4a252e95..dc27fddfc7471a631ab16554ccbef4d77ba37325 100644 (file)
@@ -162,12 +162,24 @@ int arch_livepatch_perform_rela(struct livepatch_elf *elf,
 
         symndx = ELF64_R_SYM(r->r_info);
 
-        if ( symndx > elf->nsym )
+        if ( symndx == STN_UNDEF )
+        {
+            dprintk(XENLOG_ERR, LIVEPATCH "%s: Encountered STN_UNDEF\n",
+                    elf->name);
+            return -EOPNOTSUPP;
+        }
+        else if ( symndx >= elf->nsym )
         {
             dprintk(XENLOG_ERR, LIVEPATCH "%s: Relative relocation wants symbol@%u which is past end!\n",
                     elf->name, symndx);
             return -EINVAL;
         }
+        else if ( !elf->sym[symndx].sym )
+        {
+            dprintk(XENLOG_ERR, LIVEPATCH "%s: No symbol@%u\n",
+                    elf->name, symndx);
+            return -EINVAL;
+        }
 
         dest = base->load_addr + r->r_offset;
         val = r->r_addend + elf->sym[symndx].sym->st_value;