From owner-freebsd-bugs@FreeBSD.ORG Sun Aug 12 01:40:02 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 12F8516A41B for ; Sun, 12 Aug 2007 01:40:02 +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 E921913C459 for ; Sun, 12 Aug 2007 01:40:01 +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 l7C1e1AT046077 for ; Sun, 12 Aug 2007 01:40:01 GMT (envelope-from gnats@freefall.freebsd.org) Received: (from gnats@localhost) by freefall.freebsd.org (8.14.1/8.14.1/Submit) id l7C1e1Sk046076; Sun, 12 Aug 2007 01:40:01 GMT (envelope-from gnats) Resent-Date: Sun, 12 Aug 2007 01:40:01 GMT Resent-Message-Id: <200708120140.l7C1e1Sk046076@freefall.freebsd.org> Resent-From: FreeBSD-gnats-submit@FreeBSD.org (GNATS Filer) Resent-To: freebsd-bugs@FreeBSD.org Resent-Reply-To: FreeBSD-gnats-submit@FreeBSD.org, "Timur I. Bakeyev" Received: from mx1.freebsd.org (mx1.freebsd.org [IPv6:2001:4f8:fff6::34]) by hub.freebsd.org (Postfix) with ESMTP id 2657716A41B for ; Sun, 12 Aug 2007 01:31:32 +0000 (UTC) (envelope-from timur@FreeBSD.org) Received: from mail.bat.ru (dzokonda.xs4all.nl [194.109.164.75]) by mx1.freebsd.org (Postfix) with ESMTP id 7934013C46E for ; Sun, 12 Aug 2007 01:31:31 +0000 (UTC) (envelope-from timur@FreeBSD.org) Received: from timur.home.bat.ru (account timur [192.168.0.4] verified) by mail.bat.ru (CommuniGate Pro SMTP 4.2.7) with ESMTP id 539689 for FreeBSD-gnats-submit@freebsd.org; Sun, 12 Aug 2007 03:33:27 +0200 Message-Id: <1186882289.87499@timur.home.bat.ru> Date: Sun, 12 Aug 2007 03:31:29 +0200 From: "Timur I. Bakeyev" To: "FreeBSD gnats submit" X-Send-Pr-Version: gtk-send-pr 0.4.8 Cc: Subject: 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 List-Id: Bug reports List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , X-List-Received-Date: Sun, 12 Aug 2007 01:40:02 -0000 >Number: 115430 >Category: bin >Synopsis: rpc.statd core dumps if unable to mmap() /var/db/statd.status file >Confidential: no >Severity: serious >Priority: high >Responsible: freebsd-bugs >State: open >Quarter: >Keywords: >Date-Required: >Class: sw-bug >Submitter-Id: current-users >Arrival-Date: Sun Aug 12 01:40:01 GMT 2007 >Closed-Date: >Last-Modified: >Originator: Timur I. Bakeyev >Release: FreeBSD 6.2-STABLE i386 >Organization: >Environment: System: FreeBSD 6.2-STABLE #0: Tue Jun 26 16:02:16 CEST 2007 root@timur.home.bat.ru:/usr/src/sys/i386/compile/COMMON >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. >Fix: Simplest solution would be to croak on mmap() failure, but possibly it's too taugh. The better approach would be to have a branch in the code, which executed only when mmap() is succeded. >Release-Note: >Audit-Trail: >Unformatted: