On 2009/08/27 18:02, Manoj Srivastava <[email protected]> wrote:
> > [...]
> > brk(0x3233000) = 0x3233000
> > mmap(NULL, 18446744073703178240, PROT_READ|PROT_WRITE,
> > MAP_PRIVATE|MAP_ANONYMOUS, -1, 0) = -1 ENOMEM (Cannot allocate memory)
> > mmap(NULL, 18446744073703313408, PROT_READ|PROT_WRITE,
> > MAP_PRIVATE|MAP_ANONYMOUS, -1, 0) = -1 ENOMEM (Cannot allocate memory)
> > mmap(NULL, 134217728, PROT_NONE, MAP_PRIVATE|MAP_ANONYMOUS|MAP_NORESERVE,
> > -1, 0) = 0x7fdfda316000
>
> So, seems like a memory issue to me.
>
> > munmap(0x7fdfda316000, 30318592) = 0
> > munmap(0x7fdfe0000000, 36790272) = 0
> > mprotect(0x7fdfdc000000, 135168, PROT_READ|PROT_WRITE) = 0
> > mmap(NULL, 18446744073703178240, PROT_READ|PROT_WRITE,
> > MAP_PRIVATE|MAP_ANONYMOUS, -1, 0) = -1 ENOMEM (Cannot allocate memory)
> > write(2, "libsepol.sepol_module_package_rea"...,
> > 36libsepol.sepol_module_package_read: ) = 36
> >
> > This looks like a buffer underflow (0xffffffffff9ec000) or an
> > uninitialized variable.
>
> Why do you think this is buffer underflow? (Also, I do not see
> 0xffffffffff9ec000 in the log fragment)
0xffffffffff9ec000 == 18446744073703178240 (the size of the first
large allocation). It's also equal to -6373376. This just looks like
an integer underflow, doesn't it?
> Unless you can provide some evidence that his is not a local
> hardware or configuration error, or if I can reproduce this, I would
> have to treat this as an out of memory error.
What kind of configuration error could make semanage allocate this
huge amount of memory?
Here is a backtrace:
Breakpoint 4, 0x00007f9bc4c05400 in mmap64 () from /lib/libc.so.6
(gdb) p $rsi
$25 = -6373376
(gdb) bt
#0 0x00007f9bc4c05400 in mmap64 () from /lib/libc.so.6
#1 0x00007f9bc4baf6bb in _int_malloc () from /lib/libc.so.6
#2 0x00007f9bc4bb0a78 in malloc () from /lib/libc.so.6
#3 0x00007f9bc5301a8e in sepol_module_package_read (mod=0xb1d170,
spf=0xb202e0, verbose=0) at module.c:533
#4 0x00007f9bc4ea7838 in ?? () from /lib/libsemanage.so.1
More debugging info:
(gdb) frame 3
#3 0x00007f9bc5301a8e in sepol_module_package_read (mod=0xb1d170,
spf=0xb202e0, verbose=0) at module.c:533
533 module.c: No such file or directory.
in module.c
(gdb) p len
$26 = 18446744073703176358
(gdb) p i
$27 = 3
(gdb) p nsec
$30 = 4
(gdb) p offsets[i+1]
$28 = 8192
(gdb) p offsets[i]
$29 = 6383450
line 456:
len = offsets[i + 1] - offsets[i];
Voila, integer underflow. Good guess, isn'it it? The function
module_package_read_offsets() reads the offsets from the input file,
but does not verify them.
for (i = 0; i < nsec; i++) {
// ...
len = offsets[i + 1] - offsets[i];
That looks obviously wrong, but it in fact isn't - because
module_package_read_offsets() allocates nsec+1 items. But the problem
is in module_package_read_offsets() itself:
off = (size_t *) malloc((nsec + 1) * sizeof(size_t));
// ...
for (i = 0; i < nsec; i++) {
off[i] = le32_to_cpu(buf[i]);
if (i && off[i] < off[i - 1]) {
// ...
That's nice so far - it verifies that the offsets are ascending. BUT:
off[nsec] = policy_file_length(file);
Here, the check is missing.
But why is the file length 8192? My base.pp has 6383597 bytes
(compressed), not 8192. Let's break in policy_file_length():
(gdb) p prev_offset
$4 = 28
(gdb) p end_offset
$5 = 8192
(gdb) p fp->fp
$6 = (FILE *) 0x1c42350
(gdb) p fileno(fp->fp)
$7 = -1
But why is the file descriptor negative? sepol_module_package_read()
is called by semanage_load_module(), which bunzips the file, closes
it, reopens it with fmemopen(). fmemopen has no file descriptor,
that's why it's negative. Is there another bug in glibc?
fmemopen_seek():
case SEEK_END:
np = c->maxpos - *p;
What is c->maxpos? Let's look it up in fmemopen():
c->size = len;
c->maxpos = strlen (c->buffer);
WTF!
Bottom line is:
- libsepol misses proper input validation, which may lead to an
integer underflow and a ridiculously huge allocation.
- in glibc, fmemopen_seek() works only with null-terminated strings.
Is that enough information?
Max
--
To UNSUBSCRIBE, email to [email protected]
with a subject of "unsubscribe". Trouble? Contact [email protected]