From owner-freebsd-bugs@FreeBSD.ORG Thu Jul 5 21:40:11 2007 Return-Path: X-Original-To: freebsd-bugs@hub.freebsd.org Delivered-To: freebsd-bugs@hub.freebsd.org Received: from mx1.freebsd.org (mx1.freebsd.org [69.147.83.52]) by hub.freebsd.org (Postfix) with ESMTP id 4FD1716A46B for ; Thu, 5 Jul 2007 21:40:11 +0000 (UTC) (envelope-from gnats@FreeBSD.org) Received: from freefall.freebsd.org (freefall.freebsd.org [69.147.83.40]) by mx1.freebsd.org (Postfix) with ESMTP id 3359313C469 for ; Thu, 5 Jul 2007 21:40:11 +0000 (UTC) (envelope-from gnats@FreeBSD.org) Received: from freefall.freebsd.org (gnats@localhost [127.0.0.1]) by freefall.freebsd.org (8.13.4/8.13.4) with ESMTP id l65LeBfc022070 for ; Thu, 5 Jul 2007 21:40:11 GMT (envelope-from gnats@freefall.freebsd.org) Received: (from gnats@localhost) by freefall.freebsd.org (8.13.4/8.13.4/Submit) id l65LeBAM022063; Thu, 5 Jul 2007 21:40:11 GMT (envelope-from gnats) Resent-Date: Thu, 5 Jul 2007 21:40:11 GMT Resent-Message-Id: <200707052140.l65LeBAM022063@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, Leif Pedersen Received: from mx1.freebsd.org (mx1.freebsd.org [69.147.83.52]) by hub.freebsd.org (Postfix) with ESMTP id 15D4A16A400 for ; Thu, 5 Jul 2007 21:35:09 +0000 (UTC) (envelope-from bilbo@hobbiton.org) Received: from smaug.hobbiton.org (smaug.hobbiton.org [67.132.216.160]) by mx1.freebsd.org (Postfix) with ESMTP id D779013C45E for ; Thu, 5 Jul 2007 21:35:08 +0000 (UTC) (envelope-from bilbo@hobbiton.org) Received: by smaug.hobbiton.org (Postfix, from userid 1001) id 31877130C7E; Thu, 5 Jul 2007 16:05:59 -0500 (CDT) Message-Id: <20070705210559.31877130C7E@smaug.hobbiton.org> Date: Thu, 5 Jul 2007 16:05:59 -0500 (CDT) From: Leif Pedersen To: FreeBSD-gnats-submit@FreeBSD.org X-Send-Pr-Version: 3.113 Cc: Subject: bin/114341: lockf(1) utility is severely broken X-BeenThere: freebsd-bugs@freebsd.org X-Mailman-Version: 2.1.5 Precedence: list Reply-To: Leif Pedersen List-Id: Bug reports List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , X-List-Received-Date: Thu, 05 Jul 2007 21:40:11 -0000 >Number: 114341 >Category: bin >Synopsis: lockf(1) utility is severely broken >Confidential: no >Severity: critical >Priority: high >Responsible: freebsd-bugs >State: open >Quarter: >Keywords: >Date-Required: >Class: sw-bug >Submitter-Id: current-users >Arrival-Date: Thu Jul 05 21:40:10 GMT 2007 >Closed-Date: >Last-Modified: >Originator: Leif Pedersen >Release: FreeBSD 6.2-RELEASE-p2 i386 >Organization: >Environment: System: FreeBSD legolas.hobbiton.org 6.2-RELEASE-p2 FreeBSD 6.2-RELEASE-p2 #0: Sun May 27 22:11:57 CDT 2007 bilbo@legolas.hobbiton.org:/tmp/work/usr/src/sys/HOBBITON_STANDARD i386 All arches. >Description: lockf(1) does not properly implement locking. The problem is that lockf calls open() with O_CREAT and O_EXLOCK, but open() does not implement creating the file and locking it atomically. Calling open in this way is the same as calling open without O_EXLOCK, then separately calling flock(). >How-To-Repeat: lockf will break under the following use case: - Alice executes lockf /tmp/test.lock foobar. - Bob executes lockf /tmp/test.lock foobar. - Alice finishes executing foobar (and lockf removes the lockfile). - Bob obtains the lock (but lockf forgets to create a lockfile to replace the removed one). - Charlie executes lockf /tmp/test.lock foobar. - Charlie immediately begins executing foobar, since there is no record of Bob's lock. - Bob and Charlie are now erroneously executing foobar at the same time. >Fix: To work around, always use the -k option to flock(1). To fix the problem, patch the code to check that the file exists after open() returns. For example: while(1) { lockfd = open(name, O_CREAT|O_RDONLY|O_EXLOCK, 0666); if(lockfd == -1) { ...abort } checkfd = open(name, O_RDONLY, 0); if(checkfd != -1) { // Successful lock. Continue execution. close(checkfd); break; } // Lock file was removed by a concurrent peer. Try again. if(errno != ENOENT) { close(lockfd); ...abort - almost can't happen } close(lockfd); } >Release-Note: >Audit-Trail: >Unformatted: