rpms/kernel/F-11 linux-2.6-ftdi-oops.patch, NONE, 1.1 kernel.spec, 1.1606, 1.1607

David Woodhouse dwmw2 at fedoraproject.org
Mon May 18 12:35:06 UTC 2009


Author: dwmw2

Update of /cvs/pkgs/rpms/kernel/F-11
In directory cvs1.fedora.phx.redhat.com:/tmp/cvs-serv15124

Modified Files:
	kernel.spec 
Added Files:
	linux-2.6-ftdi-oops.patch 
Log Message:
Fix oops on FTDI removal

linux-2.6-ftdi-oops.patch:

--- NEW FILE linux-2.6-ftdi-oops.patch ---
commit c45d63202fbaccef7ef7946c03f27f72c809b1cc
Author: Alan Stern <stern at rowland.harvard.edu>
Date:   Thu Apr 30 10:06:19 2009 -0400

    usb-serial: ftdi_sio: fix reference counting of ftdi_private
    
    This patch (as1238) adds proper reference counting for ftdi_sio's
    private data structure.  Without it, the driver will free the
    structure while it is still in use if the user unplugs the serial
    device before closing the device file.
    
    The patch also replaces a slightly dangerous
    cancel_delayed_work/flush_scheduled_work pair with
    cancel_delayed_work_sync, which is always safer.
    
    Signed-off-by: Alan Stern <stern at rowland.harvard.edu>
    Reported-by: Daniel Mack <daniel at caiaq.de>
    Tested-by: Daniel Mack <daniel at caiaq.de>
    Cc: stable <stable at kernel.org>
    Signed-off-by: Greg Kroah-Hartman <gregkh at suse.de>


Subject: [PATCH] Fix oops on close of hot-unplugged FTDI serial converter
Date: 	Mon, 18 May 2009 00:53:17 +0100

When the device is removed, ftdi_sio_port_remove() calls
usb_set_serial_port_data(port, NULL).

When userspace subsequently _closes_ the device, ftdi_close() oopses on
dereferencing that NULL pointer.

The fix is just not to clear the private data in ftdi_sio_port_remove().
The refcount on the structure reaches zero when the port is closed by
userspace and the final kref_put() happens in ftdi_close().

Remove a bogus comment too, while we're at it. And stop doing things
inside "if (priv)" -- it must _always_ be there.

Based loosely on an earlier patch by Daniel Mack, and suggestions by
Alan Stern.

Signed-off-by: David Woodhouse <David.Woodhouse at intel.com>

--- a/drivers/usb/serial/ftdi_sio.c.29	2009-05-18 12:18:13.000000000 +0100
+++ b/drivers/usb/serial/ftdi_sio.c	2009-05-18 12:18:18.000000000 +0100
@@ -56,6 +56,7 @@ static __u16 vendor = FTDI_VID;
 static __u16 product;
 
 struct ftdi_private {
+	struct kref kref;
 	ftdi_chip_type_t chip_type;
 				/* type of device, either SIO or FT8U232AM */
 	int baud_base;		/* baud base clock for divisor setting */
@@ -1354,6 +1355,7 @@ static int ftdi_sio_port_probe(struct us
 		return -ENOMEM;
 	}
 
+	kref_init(&priv->kref);
 	spin_lock_init(&priv->rx_lock);
 	spin_lock_init(&priv->tx_lock);
 	init_waitqueue_head(&priv->delta_msr_wait);
@@ -1470,6 +1472,13 @@ static void ftdi_shutdown(struct usb_ser
 	dbg("%s", __func__);
 }
 
+static void ftdi_sio_priv_release(struct kref *k)
+{
+	struct ftdi_private *priv = container_of(k, struct ftdi_private, kref);
+
+	kfree(priv);
+}
+
 static int ftdi_sio_port_remove(struct usb_serial_port *port)
 {
 	struct ftdi_private *priv = usb_get_serial_port_data(port);
@@ -1478,14 +1487,7 @@ static int ftdi_sio_port_remove(struct u
 
 	remove_sysfs_attrs(port);
 
-	/* all open ports are closed at this point
-	 *    (by usbserial.c:__serial_close, which calls ftdi_close)
-	 */
-
-	if (priv) {
-		usb_set_serial_port_data(port, NULL);
-		kfree(priv);
-	}
+	kref_put(&priv->kref, ftdi_sio_priv_release);
 
 	return 0;
 }
@@ -1549,7 +1551,8 @@ static int ftdi_open(struct tty_struct *
 		dev_err(&port->dev,
 			"%s - failed submitting read urb, error %d\n",
 			__func__, result);
-
+	else
+		kref_get(&priv->kref);
 
 	return result;
 } /* ftdi_open */
@@ -1591,11 +1594,11 @@ static void ftdi_close(struct tty_struct
 	mutex_unlock(&port->serial->disc_mutex);
 
 	/* cancel any scheduled reading */
-	cancel_delayed_work(&priv->rx_work);
-	flush_scheduled_work();
+	cancel_delayed_work_sync(&priv->rx_work);
 
 	/* shutdown our bulk read */
 	usb_kill_urb(port->read_urb);
+	kref_put(&priv->kref, ftdi_sio_priv_release);
 } /* ftdi_close */
 
 


Index: kernel.spec
===================================================================
RCS file: /cvs/pkgs/rpms/kernel/F-11/kernel.spec,v
retrieving revision 1.1606
retrieving revision 1.1607
diff -u -p -r1.1606 -r1.1607
--- kernel.spec	15 May 2009 21:47:55 -0000	1.1606
+++ kernel.spec	18 May 2009 12:34:36 -0000	1.1607
@@ -730,6 +730,7 @@ Patch3010: linux-2.6-relatime-by-default
 Patch3020: linux-2.6-fiemap-header-install.patch
 
 Patch4000: linux-2.6-usb-cdc-acm-remove-low-latency-flag.patch
+Patch4010: linux-2.6-ftdi-oops.patch
 
 Patch5000: linux-2.6-add-qcserial.patch
 
@@ -1217,6 +1218,7 @@ ApplyPatch linux-2.6-fiemap-header-insta
 # USB
 ApplyPatch linux-2.6-add-qcserial.patch
 ApplyPatch linux-2.6-usb-cdc-acm-remove-low-latency-flag.patch
+ApplyPatch linux-2.6-ftdi-oops.patch
 
 # ACPI
 ApplyPatch linux-2.6-defaults-acpi-video.patch
@@ -1979,6 +1981,9 @@ fi
 # and build.
 
 %changelog
+* Mon May 18 2009 David Woodhouse <David.Woodhouse at intel.com>
+- Fix oops on FTDI removal.
+
 * Fri May 15 2009 Eric Sandeen <sandeen at redhat.com>
 - ext4: corruption fixes from upstream.
 




More information about the scm-commits mailing list