[Git][ghc/ghc][wip/T15808] 2 commits: rts/linker: Fix relocation overflow in PE linker

Ben Gamari gitlab at gitlab.haskell.org
Fri Oct 30 23:49:45 UTC 2020



Ben Gamari pushed to branch wip/T15808 at Glasgow Haskell Compiler / GHC


Commits:
0a435602 by Ben Gamari at 2020-10-30T19:49:37-04:00
rts/linker: Fix relocation overflow in PE linker

Previously the overflow check for the IMAGE_REL_AMD64_ADDR32NB
relocation failed to account for the signed nature of the value.
Specifically, the overflow check was:

    uint64_t v;
    v = S + A;
    if (v >> 32) { ... }

However, `v` ultimately needs to fit into 32-bits as a signed value.
Consequently, values `v > 2^31` in fact overflow yet this is not caught
by the existing overflow check.

Here we rewrite the overflow check to rather ensure that
`INT32_MIN <= v <= INT32_MAX`. There is now quite a bit of repetition
between the `IMAGE_REL_AMD64_REL32` and `IMAGE_REL_AMD64_ADDR32` cases
but I am leaving fixing this for future work.

This bug was first noticed by @awson.

Fixes #15808.

- - - - -
59c459f2 by Ben Gamari at 2020-10-30T19:49:37-04:00
rts/linker: Try using m32 to allocate PE symbol extras

- - - - -


3 changed files:

- rts/Linker.c
- rts/LinkerInternals.h
- rts/linker/PEi386.c


Changes:

=====================================
rts/Linker.c
=====================================
@@ -1351,7 +1351,7 @@ void freeObjectCode (ObjectCode *oc)
     ocDeinit_ELF(oc);
 #endif
 
-#if RTS_LINKER_USE_MMAP == 1
+#if defined(USE_M32)
     m32_allocator_free(oc->rx_m32);
     m32_allocator_free(oc->rw_m32);
 #endif
@@ -1422,7 +1422,7 @@ mkOc( pathchar *path, char *image, int imageSize,
    /* chain it onto the list of objects */
    oc->next              = NULL;
 
-#if RTS_LINKER_USE_MMAP
+#if defined(USE_M32)
    oc->rw_m32 = m32_allocator_new(false);
    oc->rx_m32 = m32_allocator_new(true);
 #endif


=====================================
rts/LinkerInternals.h
=====================================
@@ -236,7 +236,7 @@ typedef struct _ObjectCode {
        require extra information.*/
     StrHashTable *extraInfos;
 
-#if RTS_LINKER_USE_MMAP == 1
+#if defined(USE_M32)
     /* The m32 allocators used for allocating small sections and symbol extras
      * during loading. We have two: one for (writeable) data and one for
      * (read-only/executable) code. */
@@ -336,6 +336,12 @@ resolveSymbolAddr (pathchar* buffer, int size,
 #define USE_CONTIGUOUS_MMAP 0
 #endif
 
+// We use the m32 allocator on Windows and Unix platforms using mmap
+#if (RTS_LINKER_USE_MMAP == 1) || defined(PE_OBJFORMAT)
+#define USE_M32
+#endif
+
+
 HsInt isAlreadyLoaded( pathchar *path );
 HsInt loadOc( ObjectCode* oc );
 ObjectCode* mkOc( pathchar *path, char *image, int imageSize,


=====================================
rts/linker/PEi386.c
=====================================
@@ -1294,7 +1294,7 @@ ocVerifyImage_PEi386 ( ObjectCode* oc )
       = (PEi386_IMAGE_OFFSET + 2 * default_alignment
          + oc->info->secBytesTotal) & ~0x7;
     oc->info->secBytesTotal
-      = oc->info->trampoline + info->numberOfSymbols * sizeof(SymbolExtra);
+      = oc->info->trampoline;
 
    /* No further verification after this point; only debug printing.  */
    i = 0;
@@ -1792,12 +1792,15 @@ ocAllocateExtras_PEi386 ( ObjectCode* oc )
    if (!oc->info)
      return false;
 
-   const int mask = default_alignment - 1;
-   size_t origin  = oc->info->trampoline;
+   COFF_HEADER_INFO *info = oc->info->ch_info;
+   size_t extras_size = info->numberOfSymbols * sizeof(SymbolExtra);
+
    oc->symbol_extras
-     = (SymbolExtra*)((uintptr_t)(oc->info->image + origin + mask) & ~mask);
+     = (SymbolExtra*) m32_alloc(oc->rx_m32, extras_size, 8);
+   if (oc->symbol_extras == NULL)
+     return false;
+
    oc->first_symbol_extra = 0;
-   COFF_HEADER_INFO *info = oc->info->ch_info;
    oc->n_symbol_extras    = info->numberOfSymbols;
 
    return true;
@@ -1952,13 +1955,15 @@ ocResolve_PEi386 ( ObjectCode* oc )
                {
                    uint64_t v;
                    v = S + A;
-                   if (v >> 32) {
+                   // N.B. in the case of the sign-extended relocations we must ensure that v
+                   // fits in a signed 32-bit value. See #15808.
+                   if (((int64_t) v > (int64_t) INT32_MAX) || ((int64_t) v < (int64_t) INT32_MIN)) {
                        copyName (getSymShortName (info, sym), oc,
                                  symbol, sizeof(symbol)-1);
                        S = makeSymbolExtra_PEi386(oc, symIndex, S, (char *)symbol);
                        /* And retry */
                        v = S + A;
-                       if (v >> 32) {
+                       if (((int64_t) v > (int64_t) INT32_MAX) || ((int64_t) v < (int64_t) INT32_MIN)) {
                            barf("IMAGE_REL_AMD64_ADDR32[NB]: High bits are set in %zx for %s",
                                 v, (char *)symbol);
                        }
@@ -1970,14 +1975,14 @@ ocResolve_PEi386 ( ObjectCode* oc )
                {
                    intptr_t v;
                    v = S + (int32_t)A - ((intptr_t)pP) - 4;
-                   if ((v > (intptr_t) INT32_MAX) || (v < (intptr_t) INT32_MIN)) {
+                   if ((v > (int64_t) INT32_MAX) || (v < (int64_t) INT32_MIN)) {
                        /* Make the trampoline then */
                        copyName (getSymShortName (info, sym),
                                  oc, symbol, sizeof(symbol)-1);
                        S = makeSymbolExtra_PEi386(oc, symIndex, S, (char *)symbol);
                        /* And retry */
                        v = S + (int32_t)A - ((intptr_t)pP) - 4;
-                       if ((v > (intptr_t) INT32_MAX) || (v < (intptr_t) INT32_MIN)) {
+                       if ((v > (int64_t) INT32_MAX) || (v < (int64_t) INT32_MIN)) {
                            barf("IMAGE_REL_AMD64_REL32: High bits are set in %zx for %s",
                                 v, (char *)symbol);
                        }



View it on GitLab: https://gitlab.haskell.org/ghc/ghc/-/compare/7547b5b63e362a3f165fa8980e35325b7322ada4...59c459f2e0f5d5ba948bb9ea03f54f8c42c0e93e

-- 
View it on GitLab: https://gitlab.haskell.org/ghc/ghc/-/compare/7547b5b63e362a3f165fa8980e35325b7322ada4...59c459f2e0f5d5ba948bb9ea03f54f8c42c0e93e
You're receiving this email because of your account on gitlab.haskell.org.


-------------- next part --------------
An HTML attachment was scrubbed...
URL: <http://mail.haskell.org/pipermail/ghc-commits/attachments/20201030/9cc64896/attachment-0001.html>


More information about the ghc-commits mailing list