Your message dated Sun, 30 Aug 2009 10:19:33 -0500
with message-id <[email protected]>
has caused the   report #543915,
regarding "libsepol.sepol_module_package_read: out of memory"
to be marked as having been forwarded to the upstream software
author(s) [email protected]

(NB: If you are a system administrator and have no idea what this
message is talking about, this may indicate a serious mail system
misconfiguration somewhere. Please contact [email protected]
immediately.)


-- 
543915: http://bugs.debian.org/cgi-bin/bugreport.cgi?bug=543915
Debian Bug Tracking System
Contact [email protected] with problems
--- Begin Message ---
Hi,

        This bug was discovered, and the analysis done, buy Max
 Kellermann. I have never been able to replicate the problem, so I can't
 help debug this error.

 Strace:
--8<---------------cut here---------------start------------->8---
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
--8<---------------cut here---------------end--------------->8---

> 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?

--8<---------------cut here---------------start------------->8---
 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

 (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
--8<---------------cut here---------------end--------------->8---

> line 456:
> len = offsets[i + 1] - offsets[i];

> Voila, integer underflow.  The function module_package_read_offsets()
> reads the offsets from the input file, but does not verify them.
>         off[nsec] = policy_file_length(file);
> Here, the check is missing.

        We should probably have:
--8<---------------cut here---------------start------------->8---
        off[nsec] = policy_file_length(file);
        if (off[nsec] < off[nsec-1]) {
                ERR(file->handle, "file size smaller than previous offset (at 
%u, "
                    "offset %zu -> %zu", nsec, off[nsec - 1],
                    off[nsec]);
                return -1;
        }
--8<---------------cut here---------------end--------------->8---

> But why is the file length 8192?  My base.pp has 6383597 bytes
> (compressed), not 8192.  Let's break in policy_file_length():

--8<---------------cut here---------------start------------->8---
 (gdb) p prev_offset 
 $4 = 28
 (gdb) p end_offset 
 $5 = 8192
 (gdb) p fp->fp
 $6 = (FILE *) 0x1c42350
 $7 = -1
--8<---------------cut here---------------end--------------->8---

> 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().

        I don't understand this part. Upon successful completion
 fmemopen() returns a FILE pointer.  Otherwise, NULL is returned, and
 that is checked for in In semanage_store.c:
--8<---------------cut here---------------start------------->8---
        ssize_t size;
        char *data = NULL;

        if ((size = bunzip(sh, fp, &data)) > 0) {
                fclose(fp);
                fp = fmemopen(data, size, "rb");
                if (!fp) {
                        ERR(sh, "Out of memory!");
                        goto cleanup;
                }
        }
--8<---------------cut here---------------end--------------->8---

         According to the man page, ever since glibc 2.9, the letter 'b'
 may be specified as the second character in mode.  This provides
 "binary" mode: writes don't implicitly add a terminating null byte, and
 fseek(3) SEEK_END is relative to the end of the buffer (i.e., the value
 specified by the size argument), rather than the current string length.

        Anyway, I think that adding a defensive check when we set
 off[nsec] seems to be in order, and would not harm anything; and would
 have prevented the huge memory allocation issue, and perhaps given a
 better error message.

        manoj

-- 
Manoj Srivastava <[email protected]> <http://www.golden-gryphon.com/>  
1024D/BF24424C print 4966 F272 D093 B493 410B  924B 21BA DABB BF24 424C


--- End Message ---

Reply via email to