This is the mail archive of the
glibc-bugs@sourceware.org
mailing list for the glibc project.
[Bug libc/11696] New: Some legal ELF files may generate SIGSEGV because of loader.
- From: "mika0x65 at gmail dot com" <sourceware-bugzilla at sourceware dot org>
- To: glibc-bugs at sources dot redhat dot com
- Date: 11 Jun 2010 18:49:50 -0000
- Subject: [Bug libc/11696] New: Some legal ELF files may generate SIGSEGV because of loader.
- Reply-to: sourceware-bugzilla at sourceware dot org
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.