Subject: kern/6702: Device open/close bug
To: None <gnats-bugs@gnats.netbsd.org>
From: Lennart Augustsson <augustss@cs.chalmers.se>
List: netbsd-bugs
Date: 01/02/1999 00:46:51
>Number:         6702
>Category:       kern
>Synopsis:       Device open/close bug
>Confidential:   no
>Severity:       serious
>Priority:       medium
>Responsible:    kern-bug-people (Kernel Bug People)
>State:          open
>Class:          sw-bug
>Submitter-Id:   net
>Arrival-Date:   Fri Jan  1 15:50:01 1999
>Last-Modified:
>Originator:     Lennart Augustsson
>Organization:
>Release:        NetBSD-current 990101
>Environment:
System: NetBSD dogbert.cs.chalmers.se 1.3I NetBSD 1.3I (DOGBERT) #0: Mon Dec 21 01:18:44 CET 1998 augustss@dogbert.cs.chalmers.se:/usr/src/sys/arch/i386/compile/DOGBERT i386


>Description:
	There is a bug in the device open/close protocol.  It can be observed
	in the following way.  Assume we have a foo (character) device with
	fooopen() and fooclose() routines.

	r = open("/dev/foo", O_RDONLY)
		This causes a call to fooopen(..., FREAD, ..., ...)
	w = open("/dev/foo", O_WRONLY)
		This causes a call to fooopen(..., FWRITE, ..., ...)
	close(w)
		No call to fooclose() because this is not the last
		reference to the device (spec_vnops.c line 578).
	close(r)
		This causes a call to fooclose(..., FREAD, ..., ...)

	So if the device driver keeps track of how the device has been opened
	by noting the FREAD/FWRITE flags on fooopen() it now thinks that the
	device is still opened for writing since there was no call to fooclose()
	corresponding to the fooopen().

>How-To-Repeat:
	See above
>Fix:
I'm not sure how to best solve this.  I would like to see a call
to fooclose() on the first close, but maybe this would cause
existing code to break?

But the current situation is clearly unacceptable; it's impossible to
have a device with exclusive open for read and write respectively
working properly if you allow it to be opened with separate calls to
open.

An alternative would be to "transfer" the FWRITE flag (in the example
above) to the remaining file descriptor, thus causing the last close
to be `fooclose(..., FREAD|FWRITE, ..., ...)'.  But this is a hack
rather than a solution.
>Audit-Trail:
>Unformatted: