[SCSI] sg: fix races during device removal
authorTony Battersby <tonyb@cybernetics.com>
Wed, 21 Jan 2009 19:45:50 +0000 (14:45 -0500)
committerJames Bottomley <James.Bottomley@HansenPartnership.com>
Thu, 12 Mar 2009 17:58:04 +0000 (12:58 -0500)
commitc6517b7942fad663cc1cf3235cbe4207cf769332
tree63af1b1aa434d756d7b7128f9e5d77bcdcbdf15e
parentbd5cd9cdc5379088b7e4e9a1757a1d101223a005
[SCSI] sg: fix races during device removal

sg has the following problems related to device removal:

* opening a sg fd races with removing a device
* closing a sg fd races with removing a device
* /proc/scsi/sg/* access races with removing a device
* command completion races with removing a device
* command completion races with closing a sg fd
* can rmmod sg with active commands

These problems can cause kernel oopses, memory-use-after-free, or
double-free errors.  This patch fixes these problems by using krefs
to manage the lifetime of sg_device and sg_fd.

Each command submitted to the midlevel holds a reference to sg_fd
until the completion callback.  This ensures that sg_fd doesn't go
away if the fd is closed with commands still outstanding.

sg_fd gets the reference of sg_device (with scsi_device) and also
makes sure that the sg module doesn't go away.

/proc/scsi/sg/* functions don't play nicely with krefs because they
give information about sg_fds which have been closed but not yet
freed due to still having outstanding commands and sg_devices which
have been removed but not yet freed due to still being referenced
by one or more sg_fds.  To deal with this safely without removing
functionality, /proc functions now access sg_device and sg_fd while
holding a lock instead of using kref_get()/kref_put().

Signed-off-by: Tony Battersby <tonyb@cybernetics.com>
Acked-by: Douglas Gilbert <dgilbert@interlog.com>
Signed-off-by: James Bottomley <James.Bottomley@HansenPartnership.com>
drivers/scsi/sg.c