From bilbo@hobbiton.org  Thu Jul  5 21:35:09 2007
Return-Path: <bilbo@hobbiton.org>
Received: from mx1.freebsd.org (mx1.freebsd.org [69.147.83.52])
	by hub.freebsd.org (Postfix) with ESMTP id 15D4A16A400
	for <FreeBSD-gnats-submit@freebsd.org>; 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 <FreeBSD-gnats-submit@freebsd.org>; 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 <bilbo@hobbiton.org>
Reply-To: Leif Pedersen <bilbo@hobbiton.org>
To: FreeBSD-gnats-submit@freebsd.org
Cc:
Subject: lockf(1) utility is severely broken
X-Send-Pr-Version: 3.113
X-GNATS-Notify:

>Number:         114341
>Category:       bin
>Synopsis:       lockf(1) utility is severely broken
>Confidential:   no
>Severity:       serious
>Priority:       high
>Responsible:    csjp
>State:          closed
>Quarter:        
>Keywords:       
>Date-Required:  
>Class:          sw-bug
>Submitter-Id:   current-users
>Arrival-Date:   Thu Jul 05 21:40:10 GMT 2007
>Closed-Date:    Sat Nov 03 15:42:48 UTC 2007
>Last-Modified:  Sat Nov 03 15:42:48 UTC 2007
>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:
State-Changed-From-To: open->analyzed 
State-Changed-By: csjp 
State-Changed-When: Mon Sep 24 22:51:39 UTC 2007 
State-Changed-Why:  
I will take this PR. I made this change. Currently its behaving 
the way it should be. If you want to use lockf for mutual 
exclusion, then  you must use -k. There is no way it can 
mutually exclude if you let lockf delete the lock object 
from visibility to other processes. 

This is also being tracked under another PR: 

http://www.freebsd.org/cgi/query-pr.cgi?pr=116543 


Responsible-Changed-From-To: freebsd-bugs->csjp 
Responsible-Changed-By: csjp 
Responsible-Changed-When: Mon Sep 24 22:51:39 UTC 2007 
Responsible-Changed-Why:  
I will take this PR. I made this change. Currently its behaving 
the way it should be. If you want to use lockf for mutual 
exclusion, then  you must use -k. There is no way it can 
mutually exclude if you let lockf delete the lock object 
from visibility to other processes. 

This is also being tracked under another PR: 

http://www.freebsd.org/cgi/query-pr.cgi?pr=116543 

http://www.freebsd.org/cgi/query-pr.cgi?pr=114341 

From: dfilter@FreeBSD.ORG (dfilter service)
To: bug-followup@FreeBSD.org
Cc:  
Subject: Re: bin/114341: commit references a PR
Date: Fri, 12 Oct 2007 14:57:00 +0000 (UTC)

 csjp        2007-10-12 14:56:52 UTC
 
   FreeBSD src repository
 
   Modified files:
     usr.bin/lockf        lockf.1 lockf.c 
   Log:
   Revision 1.12 of lockf.c fixed a "thundering herd" scenario when the
   lock experienced contention a number of processes would race to acquire
   lock when it was released.  This problem resulted in a lot of CPU
   load as well as locks being picked up out of order.
   
   Unfortunately, a regression snuck in which allowed multiple threads
   to pickup the same lock when -k was not used.  This could occur when
   multiple processes open a file descriptor to inode X (one process
   will be blocked) and the file is unlinked on unlock (thereby removing
   the directory entry allow another process to create a new directory
   entry for the same file name and lock it).
   
   This changes restores the old algorithm of: wait for the lock, then
   acquire lock when we want to unlink the file on exit (specifically
   when -k is not used) and keeps the new algorithm for when -k is used,
   which yields fairness and improved performance.
   
   Also, update the man page to inform users that if lockf(1) is being
   used to facilitate concurrency between a number of processes, it
   is recommended that -k be used to reduce CPU load and yeld
   fairness with regard to lock ordering.
   
   Collaborated with:      jdp
   PR:             bin/114341
   PR:             bin/116543
   PR:             bin/111101
   MFC after:      1 week
   
   Revision  Changes    Path
   1.19      +13 -1     src/usr.bin/lockf/lockf.1
   1.17      +59 -10    src/usr.bin/lockf/lockf.c
 _______________________________________________
 cvs-all@freebsd.org mailing list
 http://lists.freebsd.org/mailman/listinfo/cvs-all
 To unsubscribe, send any mail to "cvs-all-unsubscribe@freebsd.org"
 
State-Changed-From-To: analyzed->patched 
State-Changed-By: csjp 
State-Changed-When: Fri Oct 12 15:12:24 UTC 2007 
State-Changed-Why:  
The fix has been merged into HEAD and will be MFCed 
when the testing period has expired. 

Thanks. 

http://www.freebsd.org/cgi/query-pr.cgi?pr=114341 
State-Changed-From-To: patched->closed 
State-Changed-By: csjp 
State-Changed-When: Sat Nov 3 15:42:03 UTC 2007 
State-Changed-Why:  
Fix has been committed to the -STABLE branch 

Thanks.  

http://www.freebsd.org/cgi/query-pr.cgi?pr=114341 
>Unformatted:
