bin/115430: rpc.statd core dumps if unable to mmap()
/var/db/statd.status file
Maxim Konovalov
maxim at macomnet.ru
Sun Aug 12 14:00:11 PDT 2007
The following reply was made to PR bin/115430; it has been noted by GNATS.
From: Maxim Konovalov <maxim at macomnet.ru>
To: "Timur I. Bakeyev" <timur at freebsd.org>
Cc: bug-followup at freebsd.org, truckman at freebsd.org
Subject: Re: bin/115430: rpc.statd core dumps if unable to mmap()
/var/db/statd.status file
Date: Mon, 13 Aug 2007 00:23:23 +0400 (MSD)
[...]
> >Release: FreeBSD 6.2-STABLE i386
> >Organization:
> >Environment:
>
> >Description:
>
> Somehow with my recent enough build rpc.statd is unable to mmap() "/var/db/statd.status" file and core dumps. Possibly, the failure of mmap() is fixed in latest STABLE, but this problem revealed a race condition in the rpc.statd. Here is the stack trace and piece of offending code:
>
> timur# gdb `which rpc.statd` rpc.statd.0.1092.core
> GNU gdb 6.1.1 [FreeBSD]
> Copyright 2004 Free Software Foundation, Inc.
> GDB is free software, covered by the GNU General Public License, and you are
> welcome to change it and/or distribute copies of it under certain conditions.
> Type "show copying" to see the conditions.
> There is absolutely no warranty for GDB. Type "show warranty" for details.
> This GDB was configured as "i386-marcel-freebsd"...
> Core was generated by `rpc.statd'.
> Program terminated with signal 11, Segmentation fault.
> Reading symbols from /usr/lib/librpcsvc.so.3...done.
> Loaded symbols for /usr/lib/librpcsvc.so.3
> Reading symbols from /lib/libc.so.6...done.
> Loaded symbols for /lib/libc.so.6
> Reading symbols from /libexec/ld-elf.so.1...done.
> Loaded symbols for /libexec/ld-elf.so.1
> #0 0x08049531 in init_file (filename=0x804a880 "/var/db/statd.status") at /usr/src/usr.sbin/rpc.statd/file.c:170
> (gdb) l 150
> 145
> 146 /* try to open existing file - if not present, create one */
> 147 status_fd = open(filename, O_RDWR);
> 148 if ((status_fd < 0) && (errno == ENOENT))
> 149 {
> 150 status_fd = open(filename, O_RDWR | O_CREAT, 0644);
> 151 new_file = TRUE;
> 152 }
> 153 if (status_fd < 0)
> 154 errx(1, "unable to open status file %s", filename);
> 155
> 156 /* File now open. mmap() it, with a generous size to allow for */
> 157 /* later growth, where we will extend the file but not re-map it. */
> 158 status_info = (FileLayout *)
> 159 mmap(NULL, 0x10000000, PROT_READ | PROT_WRITE, MAP_SHARED, status_fd, 0);
> 160
> 161 if (status_info == (FileLayout *) MAP_FAILED)
> 162 warn("unable to mmap() status file");
> 163
> 164 status_file_len = lseek(status_fd, 0L, SEEK_END);
> 165
> 166 /* If the file was not newly created, validate the contents, and if */
> 167 /* defective, re-create from scratch. */
> 168 if (!new_file)
> 169 {
> 170 if ((status_file_len < HEADER_LEN) || (status_file_len
> 171 < (HEADER_LEN + sizeof(HostInfo) * status_info->noOfHosts)) )
> 172 {
> 173 warnx("status file is corrupt");
> 174 new_file = TRUE;
>
> On line 170 we have a guardian condition:
>
> 170 if ((status_file_len < HEADER_LEN) ||
>
> But it doesn't work after second invokation of rpc.statd, when status file was already created.
>
> statd.h:#define HEADER_LEN (sizeof(FileLayout) - sizeof(HostInfo))
>
> (gdb) p status_file_len
> $1 = 256
> (gdb) p sizeof(FileLayout) - sizeof(HostInfo)
> $2 = 256
>
> As it's seen on line 161, in case of mmap() failure status_info variable takes special value MAP_FAILED:
>
> mman.h:#define MAP_FAILED ((void *)-1)
>
> And a warning issued. Possibly, such a failure shouldn't be a fatal event, we just loose some speed in processing. But the fact of a failure isn't taken into account on line 171, when we try to dereference status_info unconditionally:
>
> sizeof(HostInfo) * status_info->noOfHosts
>
> which leads to the core dump. I don't think, this bug is
> exploitable, but definetly, it have to be fixed one way or another.
>
> >How-To-Repeat:
>
> I wish I know what's wrong with mmap() functino in my build. If it
> is reproduced then rpc.statd will crash for sure. But the bug is
> visible on a first glance.
>
Could it be fixed by the latest truckman@ work?
--
Maxim Konovalov
More information about the freebsd-bugs
mailing list