From owner-freebsd-bugs@FreeBSD.ORG Sun Aug 12 21:00:11 2007 Return-Path: Delivered-To: freebsd-bugs@hub.freebsd.org Received: from mx1.freebsd.org (mx1.freebsd.org [IPv6:2001:4f8:fff6::34]) by hub.freebsd.org (Postfix) with ESMTP id 4B59416A417 for ; Sun, 12 Aug 2007 21:00:11 +0000 (UTC) (envelope-from gnats@FreeBSD.org) Received: from freefall.freebsd.org (freefall.freebsd.org [IPv6:2001:4f8:fff6::28]) by mx1.freebsd.org (Postfix) with ESMTP id 3167713C468 for ; Sun, 12 Aug 2007 21:00:11 +0000 (UTC) (envelope-from gnats@FreeBSD.org) Received: from freefall.freebsd.org (gnats@localhost [127.0.0.1]) by freefall.freebsd.org (8.14.1/8.14.1) with ESMTP id l7CL0A2I090119 for ; Sun, 12 Aug 2007 21:00:10 GMT (envelope-from gnats@freefall.freebsd.org) Received: (from gnats@localhost) by freefall.freebsd.org (8.14.1/8.14.1/Submit) id l7CL0AxR090118; Sun, 12 Aug 2007 21:00:10 GMT (envelope-from gnats) Date: Sun, 12 Aug 2007 21:00:10 GMT Message-Id: <200708122100.l7CL0AxR090118@freefall.freebsd.org> To: freebsd-bugs@FreeBSD.org From: Maxim Konovalov Cc: Subject: Re: bin/115430: rpc.statd core dumps if unable to mmap() /var/db/statd.status file X-BeenThere: freebsd-bugs@freebsd.org X-Mailman-Version: 2.1.5 Precedence: list Reply-To: Maxim Konovalov List-Id: Bug reports List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , X-List-Received-Date: Sun, 12 Aug 2007 21:00:11 -0000 The following reply was made to PR bin/115430; it has been noted by GNATS. From: Maxim Konovalov To: "Timur I. Bakeyev" Cc: bug-followup@freebsd.org, truckman@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