Project

General

Profile

Actions

Bug #3926

closed

multiple extern map file definitions corrupt symbol table entry

Added by Robert Mustacchi almost 8 years ago. Updated almost 8 years ago.

Status:
Resolved
Priority:
Normal
Category:
lib - userland libraries
Start date:
2013-07-28
Due date:
% Done:

100%

Estimated time:
Difficulty:
Medium
Tags:
Gerrit CR:

Description

Take the following program:

void
bagnoogle()
{
        doogle();
}

And the following map file:

$mapfile_version 2

SYMBOL_SCOPE {
        doogle                  { TYPE = function; FLAGS = extern };
};

Compile bagnoogle.c:

% gcc -fPIC -c bagnoogle.c
%

And link with the map file:

% ld -G -dy -z text -Qy -Bdirect -o bagnoogle.so -zdefs -M bagnoogle.map bagnoogle.o

The symbol table is as expected with respect to doogle:

% elfdump -s bagnoogle.so | grep doogle
       [6]  0x00000000 0x00000000  FUNC GLOB  D    0 UNDEF          doogle
      [27]  0x00000000 0x00000000  FUNC GLOB  D    0 UNDEF          doogle

Now, link it but define bagnoogle.map twice:

% ld -G -dy -z text -Qy -Bdirect -o bagnoogle.so -zdefs -M bagnoogle.map -M bagnoogle.map bagnoogle.o

The symbol is now wrong:

% elfdump -s bagnoogle.so | grep doogle
       [6]  0x00000000 0x00000000  FUNC GLOB  D    0 ABS            doogle
      [27]  0x00000000 0x00000000  FUNC GLOB  D    0 ABS            doogle

Note that the consequences of this can be dire; take the following program:

#include <stdio.h>

extern void bagnoogle();

void
doogle()
{
        printf("doogle knows all probes!\\n");
}

void
main()
{
        bagnoogle();
}

Linking this program with the correctly-generated shared object yields the expected results:

% gcc -o doogle doogle.c ./bagnoogle.so
% ./doogle
doogle knows all probes!
%

However, running this against the corrupted .o yields a seg fault:

% ./doogle
Segmentation Fault (core dumped)
% pstack core
core 'core' of 25387:   ./doogle
 00000000 ???????? (8050f2a, feffb0a4, 8047d28, 8050c73, 1, 8047d34)
 08050ebf main     (1, 8047d34, 8047d3c, 8047d28, 8050c12, 8050f30) + b
 08050c73 _start   (1, 8047e00, 0, 8047e09, 8047e9b, 8047eac) + 83

The problem, of course, is that we have resolved doogle() incorrectly in bagnoogle.so to be 0 – and attempting to jump through it crashes the program.

The problem is in ld_map_sym_enter() (or, more accurately, ld32_map_sym_enter() and ld64_map_sym_enter()): when we have a symbol that is not found, we execute the following logic:

...
                /*
                 * Make sure any parent or external declarations
                 * fall back to references.
                 */
                if (ms->ms_sdflags & (FLG_SY_PARENT | FLG_SY_EXTERN)) {
                        /*
                         * Turn it into a reference by setting
                         * the section index to UNDEF.
                         */
                        sym->st_shndx = ms->ms_shndx = SHN_UNDEF;
                        ...
                } else {
                        sym->st_shndx = (Half)ms->ms_shndx;
                }

But if the symbol is found, we neglect to perform this check against the ms_sdflags; we simply do this:

...
                if (sym->st_shndx != SHN_UNDEF) {
                        if ((ms->ms_shndx != SHN_UNDEF) &&
                            (sym->st_shndx != ms->ms_shndx))
                                conflict = MSG_INTL(MSG_MAP_DIFF_SYMNDX);
                } else {
                        sym->st_shndx = sdp->sd_shndx = ms->ms_shndx;
                }

The st_shndx is in fact SHN_UNDEF, so we simply assign ms_shndx to st_shndx without consulting ms_sdflags – and we mistakenly assign the (bogus) SHN_ABS to st_shndx. The fix is to always check ms_sdflags and adjust ms_shndx accordingly.

Actions #1

Updated by Robert Mustacchi almost 8 years ago

  • Status changed from New to Resolved
  • % Done changed from 90 to 100

Resolved in c56b380c394069fe4abc1010960870ca8b2726a8.

Actions

Also available in: Atom PDF