Date: Wed, 8 Mar 2006 21:16:36 -0500 (EST) From: Kris Kennaway <kris@FreeBSD.org> To: FreeBSD-gnats-submit@FreeBSD.org Subject: kern/94256: nfs locking/rpc.lockd doesn't understand file descriptor sharing Message-ID: <20060309021636.99CFB52058@obsecurity.dyndns.org> Resent-Message-ID: <200603090220.k292K6jE082800@freefall.freebsd.org>
next in thread | raw e-mail | index | archive | help
>Number: 94256 >Category: kern >Synopsis: nfs locking/rpc.lockd doesn't understand file descriptor sharing >Confidential: no >Severity: serious >Priority: medium >Responsible: freebsd-bugs >State: open >Quarter: >Keywords: >Date-Required: >Class: sw-bug >Submitter-Id: current-users >Arrival-Date: Thu Mar 09 02:20:06 GMT 2006 >Closed-Date: >Last-Modified: >Originator: Kris Kennaway >Release: FreeBSD 6.0-STABLE i386 >Organization: FreeBSD >Environment: System: FreeBSD xor.obsecurity.org 6.0-STABLE FreeBSD 6.0-STABLE #13: Sun Nov 6 12:45:25 EST 2005 kkenn@xor.obsecurity.org:/mnt/src/sys/i386/compile/XOR i386 >Description: NFS locking uses an 'svid' field for indicating ownership of lock requests. In the FreeBSD implementation this is the pid of the process performing the lock request on the NFS client. The rpc.lockd server uses this field to decide whether a process requesting an unlock operation is holding a lock. i.e. it assumes that the pid that locks a file is the only process that can legitimately perform the corresponding unlock operation. This is false in a UNIX world, because file descriptors may be passed between processes. For example, a process may lock a file, fork, and the child process inherits the file descriptor table and may legitimately unlock the file. When rpc.lockd receives an unlock request with svid that does not match the recorded svid of the corresponding lock, it returns an "unlock granted" to the client but does not actually pass the unlock operation to the kernel. Presumably this is for purposes of crash recovery, in which the lock state may have been lost by the rpc.lockd server and the client process really did own the lock. The result of this is that locks may be "leaked" by the server, e.g.: >How-To-Repeat: On the NFS client: haessal# daemon -p pid sleep 100000 <-- the daemon process creates and locks pid haessal# kill -KILL `cat pid` <-- the unlock request is generated by the child pid haessal# lockf -t 0 -k pid echo Yay <-- the server ignored it since it doesn't know the child inherited the lock lockf: pid: already locked On the NFS server: dosirak# lockf -t 0 -k pid echo Yay lockf: pid: already locked >Fix: Probably difficult. >Release-Note: >Audit-Trail: >Unformatted:
Want to link to this message? Use this URL: <https://mail-archive.FreeBSD.org/cgi/mid.cgi?20060309021636.99CFB52058>