This is the mail archive of the glibc-bugs@sourceware.org mailing list for the glibc project.


Index Nav: [Date Index] [Subject Index] [Author Index] [Thread Index]
Message Nav: [Date Prev] [Date Next] [Thread Prev] [Thread Next]
Other format: [Raw text]

[Bug libc/11696] New: Some legal ELF files may generate SIGSEGV because of loader.


Some legal ELF files may generate SIGSEGV because of loader.

It happens only if three conditions are satisfied:
1. The ELF is shared library.
2. 1st segment of the ELF must have 0 in ElfW(Phdr)::p_filesz. (.bss section)
3. The ELF is not contiguous in memory.

When ld.so loads shared library into memory it mmaps the whole file into memory
and checks if it contains holes. If yes it mprotects everything, except for 1st
segment.

elf/dl-load.c, _dl_map_object_from_fd:
1202         /* Remember which part of the address space this object uses.  */
1203         l->l_map_start = (ElfW(Addr)) __mmap ((void *) mappref, maplength,
1204                                               c->prot,
1205                                               MAP_COPY|MAP_FILE,
1206                                               fd, c->mapoff);
1207         if (__builtin_expect ((void *) l->l_map_start == MAP_FAILED, 0))
1208           {
1209           map_error:
1210             errstring = N_("failed to map segment from shared object");
1211             goto call_lose_errno;
1212           }
1213 
1214         l->l_map_end = l->l_map_start + maplength;
1215         l->l_addr = l->l_map_start - c->mapstart;
1216 
1217         if (has_holes)
1218           /* Change protection on the excess portion to disallow all access;
1219              the portions we do not remap later will be inaccessible as if
1220              unallocated.  Then jump into the normal segment-mapping loop to
1221              handle the portion of the segment past the end of the file
1222              mapping.  */
1223           __mprotect ((caddr_t) (l->l_addr + c->mapend),
1224                       loadcmds[nloadcmds - 1].mapstart - c->mapend,
1225                       PROT_NONE);
1226 
1227         l->l_contiguous = 1;
1228 
1229         goto postmap;

The problem is that c ->mapend takes into account only p_filesz of the segment,
that is 0 if 1st segment is .bss. Hence the whole file will be mprotected with
PROT_NONE flag.

The following code reproduces the bug:
callee.c:
int n; //will be placed in .bss section

void f()
{
        n = 7;//SIGSEGV occurs here.
}


caller.c:
#include <dlfcn.h>
#include <stdio.h>

int main(int argc, char **argv)
{
    void *so;

    so = dlopen("callee.so", RTLD_NOW);
    if (!so)
    {
        printf("%s: %s\n", argv[0], dlerror());  
    }
    else
    {
        void (*f)();

        f = dlsym(so, "f");
        if (!f)
        {
            printf("%s: %s\n", argv[0], dlerror());  
        }
        else
        {
            f();
        }
    }

    return 0;
}

link.ld:
SECTIONS
{
        .bss 0x400000 :
        {
                *(.bss);
        }
        .text 0x500000 :
        {
                *(.text);
        }
}

I suggest the following patch:
1223           __mprotect ((caddr_t) (l->l_addr + c->mapend),
1224                       loadcmds[nloadcmds - 1].mapstart - \
1225                       c ->allocend > c ->mapend ? \
1227                       c ->allocend + GLRO(dl_pagesize) - 1) &
~(GLRO(dl_pagesize) - 1) : c->mapend,
1228                       PROT_NONE);

-- 
           Summary: Some legal ELF files may generate SIGSEGV because of
                    loader.
           Product: glibc
           Version: 2.9
            Status: NEW
          Severity: normal
          Priority: P2
         Component: libc
        AssignedTo: drepper at redhat dot com
        ReportedBy: mika0x65 at gmail dot com
                CC: glibc-bugs at sources dot redhat dot com


http://sourceware.org/bugzilla/show_bug.cgi?id=11696

------- You are receiving this mail because: -------
You are on the CC list for the bug, or are watching someone who is.


Index Nav: [Date Index] [Subject Index] [Author Index] [Thread Index]
Message Nav: [Date Prev] [Date Next] [Thread Prev] [Thread Next]