bin/114341: lockf(1) utility is severely broken
Leif Pedersen
bilbo at hobbiton.org
Thu Jul 5 21:40:11 UTC 2007
>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 at 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:
More information about the freebsd-bugs
mailing list