[tnozaki-elftoolchain] TNF local patch for libelf - add miscellaneous integer overflow check

Issue #276 wontfix
Takehiko NOZAKI repo owner created an issue

No description provided.

Comments (5)

  1. Takehiko NOZAKI reporter

    elf_scn.c’s change:

    diff --git a/external/bsd/elftoolchain/dist/libelf/elf_scn.c b/external/bsd/elftoolchain/dist/libelf/elf_scn.c
    index 54e36a8833b..c6ae8b908bb 100644
    --- a/external/bsd/elftoolchain/dist/libelf/elf_scn.c
    +++ b/external/bsd/elftoolchain/dist/libelf/elf_scn.c
    @@ -31,6 +31,7 @@
     #include <errno.h>
     #include <gelf.h>
     #include <libelf.h>
    +#include <limits.h>
     #include <stddef.h>
     #include <stdint.h>
     #include <stdlib.h>
    @@ -91,7 +92,11 @@ _libelf_load_section_headers(Elf *e, void *ehdr)
                _libelf_elfmachine(e));
    
            swapbytes = e->e_byteorder != _libelf_host_byteorder();
    -       src = e->e_rawfile + shoff;
    +       if (shoff > SSIZE_MAX) {
    +               LIBELF_SET_ERROR(HEADER, 0);
    +               return (0);
    +       }
    +       src = e->e_rawfile + (ssize_t)shoff;
    
            /*
             * If the file is using extended numbering then section #0
    

    shoff’s range check have already done in following macro, i think.

    #define CHECK_EHDR(E,EH)        do {                            \
                    uintmax_t rawsize = (uintmax_t) e->e_rawsize;   \
                    if (shoff > (uintmax_t) e->e_rawsize ||         \
                        fsz != (EH)->e_shentsize ||                 \
                        shnum > SIZE_MAX / fsz ||                   \
                        fsz * shnum > rawsize - shoff) {            \
                            LIBELF_SET_ERROR(HEADER, 0);            \
                            return (0);                             \
                    }                                               \
            } while (/* CONSTCOND */ 0)
    

    fix done r3147 https://sourceforge.net/p/elftoolchain/code/3147/

    ticket 462 https://sourceforge.net/p/elftoolchain/tickets/462/

    N HEAD is not merged this change yet.

  2. Takehiko NOZAKI reporter

    libelf_ehdr.c’s change:

    index e012750c33b..c558dc2824d 100644
    --- a/external/bsd/elftoolchain/dist/libelf/libelf_ehdr.c
    +++ b/external/bsd/elftoolchain/dist/libelf/libelf_ehdr.c
    @@ -29,6 +29,7 @@
     #include <assert.h>
     #include <gelf.h>
     #include <libelf.h>
    +#include <limits.h>
     #include <stdlib.h>
    
     #include "_libelf.h"
    @@ -68,6 +69,11 @@ _libelf_load_extended(Elf *e, int ec, uint64_t shoff, uint16_t phnum,
            if ((scn = _libelf_allocate_scn(e, (size_t) 0)) == NULL)
                    return (0);
    
    +       if (shoff > SSIZE_MAX) {
    +               LIBELF_SET_ERROR(HEADER, 0);
    +               return (0);
    +       }
    +
            xlator = _libelf_get_translator(ELF_T_SHDR, ELF_TOMEMORY, ec,
                _libelf_elfmachine(e));
            (*xlator)((unsigned char *) &scn->s_shdr, sizeof(scn->s_shdr),
    

    shoff range check is done previous:

        if (shoff + fsz < shoff) {  /* Numeric overflow. */
            LIBELF_SET_ERROR(HEADER, 0);
            return (0);
        }
    

    fix done r3688 https://sourceforge.net/p/elftoolchain/code/3688/

    ticket 565 https://sourceforge.net/p/elftoolchain/tickets/565/

    N HEAD is not merged this change yet.

  3. Takehiko NOZAKI reporter

    libelf_ehdr.c’s change:

    diff --git a/external/bsd/elftoolchain/dist/libelf/libelf_ehdr.c b/external/bsd/elftoolchain/dist/libelf/libelf_ehdr.c
    index e012750c33b..32a9fd500ab 100644
    --- a/external/bsd/elftoolchain/dist/libelf/libelf_ehdr.c
    +++ b/external/bsd/elftoolchain/dist/libelf/libelf_ehdr.c
    @@ -29,6 +29,7 @@
     #include <assert.h>
     #include <gelf.h>
     #include <libelf.h>
    +#include <limits.h>
     #include <stdlib.h>
    
     #include "_libelf.h"
    @@ -82,6 +83,11 @@ _libelf_load_extended(Elf *e, int ec, uint64_t shoff, uint16_t phnum,
                    return (0);
            }
    
    +       if (GET_SHDR_MEMBER(sh_size) > UINT_MAX) {
    +               LIBELF_SET_ERROR(HEADER, 0);
    +               return (0);
    +       }
    +
            e->e_u.e_elf.e_nscn = (size_t) GET_SHDR_MEMBER(sh_size);
            e->e_u.e_elf.e_nphdr = (phnum != PN_XNUM) ? phnum :
                GET_SHDR_MEMBER(sh_info);
    

    but GET_SHDR_MEMBER(sh_size)'s type is uint32_t or uint64_t, this check is always false, so it is completely meaningless.

    and if this code compile with -Werror=type-limits, may cause error.

    so i don’t accept this code.

  4. Log in to comment