out of bounds array access in mmap_fgets_multiline

Florian Hars hars at bik-gmbh.de
Thu Oct 2 21:14:07 CEST 2008


As noticed before
http://archive.netbsd.se/?ml=nagios-users&a=2008-05&t=7383489
nagios 3 tends to segfault while reading its config files on OpenBSD. It
always happens in the same position in the code:

| Program received signal SIGSEGV, Segmentation fault.
| [Switching to process 32062, thread 0x8511f400]
| 0x1c03c443 in mmap_fgets_multiline (temp_mmapfile=0x88b82b60) at
| utils.c:3487
| 3487                    else if(buf[end]=='\\')
| (gdb) print buf
| $1 = 0x81bc8000 "\n"
| (gdb) print end
| $2 = -1

but in different locations in the config file:

| (gdb) print *temp_mmapfile
| $3 = {path = 0x8bddf100 "/usr/local/nagios/etc/nagios.cfg",
| mode =  0,fd = 8, file_size = 42546, current_position = 4794,
| current_line = 144, mmap_buf = 0x82f46000}

| $4 = {path = 0x7ff95540 "/usr/local/nagios/etc/nagios.cfg",
| mode = 0,fd = 8, file_size = 42546, current_position = 8733,
| current_line = 260, mmap_buf = 0x89ec5000}

Sometimes it will just stop reading the config files halfway through and
claim that things look okay.

The value of -1 for end is a dead giveaway: It leads to an undefined
access to buf[-1], which suggested OpenBSDs address randomization as
the source for the curious nondeterminism.

I changed two lines in the source:

--- nagios-3.0.3-orig/base/utils.c      Mon Jun 23 22:47:41 2008
+++ nagios-3.0.3/base/utils.c   Thu Oct  2 20:15:56 2008
@@ -3472,7 +3472,8 @@
                         end=len-1;

  #ifdef DEBUG
-               printf("LEN: %d, END: %d, BUF=%s",len,end,buf);
+               printf("LEN: %d, END: %d, BUF=(%p) %s",len,end,buf,buf);
+               fflush(stdout);
  #endif

                 /* two backslashes found, so unescape first backslash
first and break */

And indeed, the segfaults happen if, and only if end is -1 and buf is
allocated at the start of a page:

| LEN: 1, END: -1, BUF=(0x7fecf000)
|
| Program received signal SIGSEGV, Segmentation fault.

The root cause lies in these lines:

3465                    /* handle Windows/DOS CR/LF */
3466                    if(len>=2 && buf[len-2]=='\r')
3467                            end=len-3;
3468                    /* normal Unix LF */
3469                    else if(len>=1 && buf[len-1]=='\n')
3470                            end=len-2;
3471                    else
3472                            end=len-1;

which result in end=-1 if buf contains just an end of line.

- Florian.

--
But our moral language is fragmented; our contemporaries reject the Kantian
hunch that choosing those things most admirable and plausible as ends in
themselves is the best practice; autonomous sources of the good are everywhere
brown and broken. Thus we have PHP. http://lambda-the-ultimate.org/node/1463


-------------------------------------------------------------------------
This SF.Net email is sponsored by the Moblin Your Move Developer's challenge
Build the coolest Linux based applications with Moblin SDK & win great prizes
Grand prize is a trip for two to an Open Source event anywhere in the world
http://moblin-contest.org/redirect.php?banner_id=100&url=/
_______________________________________________
Nagios-users mailing list
Nagios-users at lists.sourceforge.net
https://lists.sourceforge.net/lists/listinfo/nagios-users
::: Please include Nagios version, plugin version (-v) and OS when reporting any issue. 
::: Messages without supporting info will risk being sent to /dev/null





More information about the Users mailing list