On Wed, Nov 03, 2010 at 02:33:12PM +0200, Alexey Suslikov wrote:

> This is somewhat ports related, but I decided to ask here before going
> further with diff.
> 
> Well, we have Asterisk 1.6.2.14-rc1 going segfault:
> 
> #0  generic_http_callback (format=FORMAT_XML, remote_address=0x4001,
>     uri=0x4001 <Address 0x4001 out of bounds>, method=205216842,
>     params=0x20eb5bc00, status=0x2057b2c74, title=0x2057b2c78,
>     contentlength=0x2057b2c84) at manager.c:4005
> 4005
> 
> #0  generic_http_callback (format=FORMAT_XML, remote_address=0x4001,
>     uri=0x4001 <Address 0x4001 out of bounds>, method=205216842,
>     params=0x20eb5bc00, status=0x2057b2c74, title=0x2057b2c78,
>     contentlength=0x2057b2c84) at manager.c:4005
>       buf = 0x208dd5000 <Address 0x208dd5000 out of bounds>
>       l = 16384
>       s = {session = 0x203382800, f = 0x2036d3440, fd = 245}
>       session = (struct mansession_session *) 0x203382800
>       ident = 390437576
>       blastaway = 0
>       v = (struct ast_variable *) 0x4000
>       template = "/tmp/ast-http-U9afaz"
>       out = (struct ast_str *) 0x207fd7800
>       m = {hdrcount = 2, headers = {0x2057b2470 "Action: CoreShowChannels",
>     0x2057b2450 "mansession_id: 17459ac8", 0x0 <repeats 126 times>}}
>       x = 16385
>       hdrlen = 0
> 
> Relevant lines are:
> 
>         if (s.f != NULL) {      /* have temporary output */
>                 char *buf;
>                 size_t l;
> 
>                 if ((l = ftell(s.f))) {
>                         if (MAP_FAILED == (buf = mmap(NULL, l + 1,
> PROT_READ | PROT_WRITE, MAP_PRIVATE, s.fd, 0))) {
>                                 ast_log(LOG_WARNING, "mmap failed.
> Manager output was not processed\n");
>                         } else {
> =>4005:                    buf[l] = '\0';
>                                 if (format == FORMAT_XML || format ==
> FORMAT_HTML) {
>                                         xml_translate(&out, buf,
> params, format);
>                                 } else {
>                                         ast_str_append(&out, 0, "%s", buf);
>                                 }
>                                 munmap(buf, l + 1);
>                         }
>                 } else if (format == FORMAT_XML || format == FORMAT_HTML) {
>                         xml_translate(&out, "", params, format);
>                 }
>                 fclose(s.f);
>                 s.f = NULL;
>                 s.fd = -1;
>         }
> 
> So if ftell() returns value of l exactly at the end of file, accessing
> l + 1 leads to segfault while mmaping l + 1 is ok, right?

Right. And if l is on a page boundary, you have a problem.

        -Otto

> 
> On Wed, Nov 3, 2010 at 14:23, Otto Moerbeek <[email protected]> wrote:
> > On Wed, Nov 03, 2010 at 01:12:20PM +0100, Otto Moerbeek wrote:
> >
> >> On Wed, Nov 03, 2010 at 01:18:51PM +0200, Alexey Suslikov wrote:
> >>
> >> > Hello t...@.
> >> >
> >> > On OpenBSD/amd64, doing something like
> >> >     char *buf = mmap(NULL, len + 1, PROT_READ | PROT_WRITE,
> >> > MAP_PRIVATE, some.fd, 0);
> >> >     buf[len] = '\0';
> >> > causes segfault on buf[len] = '\0' assignment if len = 16384.
> >> >
> >> > However doing
> >> >     char *buf = mmap(NULL, len + 1, PROT_READ | PROT_WRITE,
> >> > MAP_PRIVATE, some.fd, 0);
> >> >     char *nbuf = malloc(len + 1);
> >> >     memcpy(nbuf, buf, len);
> >> >     nbuf[len] = '\0';
> >> > does not lead to a crash.
> >> >
> >> > Is it expected behavior of mmap (alignment?) or usage of mmap is wrong?
> >> >
> >> > Thanks.
> >> >
> >> > Alexey
> >>
> >> This (complete!) program does not show the behahaviour. Please post a
> >> complete testcase. Did you include sys/mman.h?
> >
> > BTW, accesses beyond the file do cause a segfault, and that is correct.
> >
> > Note that your firts case accesses buf[16384], while your memcpy does
> > not access that address.
> >
> >        -Otto
> >
> >>
> >> #include <sys/types.h>
> >> #include <sys/mman.h>
> >>
> >> #include <err.h>
> >> #include <fcntl.h>
> >> #include <stdio.h>
> >> #include <stdlib.h>
> >>
> >>
> >> int
> >> main()
> >> {
> >>       int fd;
> >>       char *buf;
> >>       size_t len;
> >>
> >>       fd = open("file", O_RDWR, 0);
> >>       if (fd == -1)
> >>               err(1, NULL);
> >>
> >>       len = 16384;
> >>       buf = mmap(NULL, len + 1, PROT_READ | PROT_WRITE, MAP_PRIVATE,
> >>           fd, (off_t)0);
> >>       if (buf == MAP_FAILED)
> >>               err(1, NULL);
> >>       buf[len] = '\0';
> >> }

Reply via email to