public inbox for linux-kernel@vger.kernel.org
 help / color / mirror / Atom feed
From: Greg KH <gregkh@suse.de>
To: linux-kernel@vger.kernel.org, stable@kernel.org
Cc: Justin Forbes <jmforbes@linuxtx.org>,
	Zwane Mwaikambo <zwane@arm.linux.org.uk>,
	"Theodore Ts'o" <tytso@mit.edu>,
	Randy Dunlap <rdunlap@xenotime.net>,
	Dave Jones <davej@redhat.com>,
	Chuck Wolber <chuckw@quantumlinux.com>,
	Chris Wedgwood <reviews@ml.cw.f00f.org>,
	torvalds@osdl.org, akpm@osdl.org, alan@lxorguk.ukuu.org.uk,
	Ian Abbott <abbotti@mev.co.uk>,
	Greg Kroah-Hartman <gregkh@suse.de>
Subject: [patch 26/45] USB serial ftdi_sio: Prevent userspace DoS (CVE-2006-2936)
Date: Mon, 17 Jul 2006 09:28:02 -0700	[thread overview]
Message-ID: <20060717162802.GA4829@kroah.com> (raw)
In-Reply-To: <20060717162452.GA4829@kroah.com>

[-- Attachment #1: USB-serial-ftdi_sio-Prevent-userspace-DoS.patch --]
[-- Type: text/plain, Size: 6032 bytes --]

-stable review patch.  If anyone has any objections, please let us know.

------------------
This patch limits the amount of outstanding 'write' data that can be
queued up for the ftdi_sio driver, to prevent userspace DoS attacks (or
simple accidents) that use up all the system memory by writing lots of
data to the serial port.

The original patch was by Guillaume Autran, who in turn based it on the
same mechanism implemented in the 'visor' driver.  I (Ian Abbott)
re-targeted the patch to the latest sources, fixed a couple of errors,
renamed his new structure members, and updated the implementations of
the 'write_room' and 'chars_in_buffer' methods to take account of the
number of outstanding 'write' bytes.  It seems to work fine, though at
low baud rates it is still possible to queue up an amount of data that
takes an age to shift (a job for another day!).

Signed-off-by: Ian Abbott <abbotti@mev.co.uk>
Signed-off-by: Greg Kroah-Hartman <gregkh@suse.de>


---
 drivers/usb/serial/ftdi_sio.c |   84 +++++++++++++++++++++++++++++++++++-------
 1 file changed, 71 insertions(+), 13 deletions(-)

--- linux-2.6.17.4.orig/drivers/usb/serial/ftdi_sio.c
+++ linux-2.6.17.4/drivers/usb/serial/ftdi_sio.c
@@ -553,6 +553,10 @@ struct ftdi_private {
 
 	int force_baud;		/* if non-zero, force the baud rate to this value */
 	int force_rtscts;	/* if non-zero, force RTS-CTS to always be enabled */
+
+	spinlock_t tx_lock;	/* spinlock for transmit state */
+	unsigned long tx_outstanding_bytes;
+	unsigned long tx_outstanding_urbs;
 };
 
 /* Used for TIOCMIWAIT */
@@ -626,6 +630,9 @@ static struct usb_serial_driver ftdi_sio
 #define HIGH 1
 #define LOW 0
 
+/* number of outstanding urbs to prevent userspace DoS from happening */
+#define URB_UPPER_LIMIT	42
+
 /*
  * ***************************************************************************
  * Utlity functions
@@ -1156,6 +1163,7 @@ static int ftdi_sio_attach (struct usb_s
 	}
 
 	spin_lock_init(&priv->rx_lock);
+	spin_lock_init(&priv->tx_lock);
         init_waitqueue_head(&priv->delta_msr_wait);
 	/* This will push the characters through immediately rather
 	   than queue a task to deliver them */
@@ -1372,6 +1380,7 @@ static int ftdi_write (struct usb_serial
 	int data_offset ;       /* will be 1 for the SIO and 0 otherwise */
 	int status;
 	int transfer_size;
+	unsigned long flags;
 
 	dbg("%s port %d, %d bytes", __FUNCTION__, port->number, count);
 
@@ -1379,6 +1388,13 @@ static int ftdi_write (struct usb_serial
 		dbg("write request of 0 bytes");
 		return 0;
 	}
+	spin_lock_irqsave(&priv->tx_lock, flags);
+	if (priv->tx_outstanding_urbs > URB_UPPER_LIMIT) {
+		spin_unlock_irqrestore(&priv->tx_lock, flags);
+		dbg("%s - write limit hit\n", __FUNCTION__);
+		return 0;
+	}
+	spin_unlock_irqrestore(&priv->tx_lock, flags);
 	
 	data_offset = priv->write_offset;
         dbg("data_offset set to %d",data_offset);
@@ -1445,6 +1461,11 @@ static int ftdi_write (struct usb_serial
 		err("%s - failed submitting write urb, error %d", __FUNCTION__, status);
 		count = status;
 		kfree (buffer);
+	} else {
+		spin_lock_irqsave(&priv->tx_lock, flags);
+		++priv->tx_outstanding_urbs;
+		priv->tx_outstanding_bytes += count;
+		spin_unlock_irqrestore(&priv->tx_lock, flags);
 	}
 
 	/* we are done with this urb, so let the host driver
@@ -1460,7 +1481,11 @@ static int ftdi_write (struct usb_serial
 
 static void ftdi_write_bulk_callback (struct urb *urb, struct pt_regs *regs)
 {
+	unsigned long flags;
 	struct usb_serial_port *port = (struct usb_serial_port *)urb->context;
+	struct ftdi_private *priv;
+	int data_offset;       /* will be 1 for the SIO and 0 otherwise */
+	unsigned long countback;
 
 	/* free up the transfer buffer, as usb_free_urb() does not do this */
 	kfree (urb->transfer_buffer);
@@ -1472,34 +1497,67 @@ static void ftdi_write_bulk_callback (st
 		return;
 	}
 
+	priv = usb_get_serial_port_data(port);
+	if (!priv) {
+		dbg("%s - bad port private data pointer - exiting", __FUNCTION__);
+		return;
+	}
+	/* account for transferred data */
+	countback = urb->actual_length;
+	data_offset = priv->write_offset;
+	if (data_offset > 0) {
+		/* Subtract the control bytes */
+		countback -= (data_offset * ((countback + (PKTSZ - 1)) / PKTSZ));
+	}
+	spin_lock_irqsave(&priv->tx_lock, flags);
+	--priv->tx_outstanding_urbs;
+	priv->tx_outstanding_bytes -= countback;
+	spin_unlock_irqrestore(&priv->tx_lock, flags);
+
 	schedule_work(&port->work);
 } /* ftdi_write_bulk_callback */
 
 
 static int ftdi_write_room( struct usb_serial_port *port )
 {
+	struct ftdi_private *priv = usb_get_serial_port_data(port);
+	int room;
+	unsigned long flags;
+
 	dbg("%s - port %d", __FUNCTION__, port->number);
 
-	/*
-	 * We really can take anything the user throws at us
-	 * but let's pick a nice big number to tell the tty
-	 * layer that we have lots of free space
-	 */
-	return 2048;
+	spin_lock_irqsave(&priv->tx_lock, flags);
+	if (priv->tx_outstanding_urbs < URB_UPPER_LIMIT) {
+		/*
+		 * We really can take anything the user throws at us
+		 * but let's pick a nice big number to tell the tty
+		 * layer that we have lots of free space
+		 */
+		room = 2048;
+	} else {
+		room = 0;
+	}
+	spin_unlock_irqrestore(&priv->tx_lock, flags);
+	return room;
 } /* ftdi_write_room */
 
 
 static int ftdi_chars_in_buffer (struct usb_serial_port *port)
 { /* ftdi_chars_in_buffer */
+	struct ftdi_private *priv = usb_get_serial_port_data(port);
+	int buffered;
+	unsigned long flags;
+
 	dbg("%s - port %d", __FUNCTION__, port->number);
 
-	/* 
-	 * We can't really account for how much data we
-	 * have sent out, but hasn't made it through to the
-	 * device, so just tell the tty layer that everything
-	 * is flushed.
-	 */
-	return 0;
+	spin_lock_irqsave(&priv->tx_lock, flags);
+	buffered = (int)priv->tx_outstanding_bytes;
+	spin_unlock_irqrestore(&priv->tx_lock, flags);
+	if (buffered < 0) {
+		err("%s outstanding tx bytes is negative!", __FUNCTION__);
+		buffered = 0;
+	}
+	return buffered;
 } /* ftdi_chars_in_buffer */
 
 

--

  parent reply	other threads:[~2006-07-17 16:33 UTC|newest]

Thread overview: 64+ messages / expand[flat|nested]  mbox.gz  Atom feed  top
     [not found] <20060717160652.408007000@blue.kroah.org>
2006-07-17 16:24 ` [patch 00/45] 2.6.17.y -stable review Greg KH
2006-07-17 16:25   ` [patch 01/45] XFS: corruption fix Greg KH
2006-07-17 19:10     ` Chris Wedgwood
2006-07-18 13:27     ` Jan Engelhardt
2006-07-18 22:24       ` Nathan Scott
2006-07-17 16:25   ` [patch 02/45] IB/mthca: restore missing PCI registers after reset Greg KH
2006-07-26 10:29     ` Michael S. Tsirkin
2006-07-26 16:20       ` Greg KH
2006-07-26 16:32         ` Michael S. Tsirkin
2006-07-26 16:42           ` Greg KH
2006-08-21 13:22             ` Michael S. Tsirkin
2006-07-17 16:25   ` [patch 03/45] x86_64: Fix modular pc speaker Greg KH
2006-07-17 18:02     ` Dmitry Torokhov
2006-07-17 16:25   ` [patch 04/45] BLOCK: Fix bounce limit address check Greg KH
2006-07-17 16:25   ` [patch 05/45] memory hotplug: solve config broken: undefined reference to `online_page Greg KH
2006-07-17 16:26   ` [patch 06/45] v4l/dvb: Fix budget-av frontend detection Greg KH
2006-07-17 16:26   ` [patch 07/45] v4l/dvb: Fix CI on old KNC1 DVBC cards Greg KH
2006-07-25 13:01     ` Edgar Hucek
2006-07-25 15:15       ` Michael Krufky
2006-07-25 15:22         ` Edgar Hucek
2006-07-25 17:10           ` Greg KH
2006-08-01 23:23             ` Michael Krufky
2006-07-17 16:26   ` [patch 08/45] v4l/dvb: Fix CI interface on PRO KNC1 cards Greg KH
2006-07-17 16:26   ` [patch 09/45] pnp: suppress request_irq() warning Greg KH
2006-07-17 16:26   ` [patch 10/45] Reduce ACPI verbosity on null handle condition Greg KH
2006-07-17 16:26   ` [patch 11/45] via-velocity: the link is not correctly detected when the device starts Greg KH
2006-07-17 16:26   ` [patch 12/45] 2 oopses in ethtool Greg KH
2006-07-17 20:51     ` Matthew Wilcox
2006-07-17 16:26   ` [patch 13/45] v4l/dvb: Kconfig: fix description and dependencies for saa7115 module Greg KH
2006-07-17 16:26   ` [patch 14/45] PKT_SCHED: Fix illegal memory dereferences when dumping actions Greg KH
2006-07-17 16:27   ` [patch 15/45] PKT_SCHED: Return ENOENT if action module is unavailable Greg KH
2006-07-17 16:27   ` [patch 16/45] PKT_SCHED: Fix error handling while dumping actions Greg KH
2006-07-17 16:27   ` [patch 17/45] v4l/dvb: Backport fix to artec USB DVB devices Greg KH
2006-07-17 16:27   ` [patch 18/45] v4l/dvb: Backport the DISEQC regression fix to 2.6.17.x Greg KH
2006-07-17 16:27   ` [patch 19/45] v4l/dvb: Backport the budget driver DISEQC instability fix Greg KH
2006-07-17 16:27   ` [patch 20/45] v4l/dvb: stradis: dont export MODULE_DEVICE_TABLE Greg KH
2006-07-17 16:27   ` [patch 21/45] dvb-bt8xx: fix frontend detection for DViCO FusionHDTV DVB-T Lite rev 1.2 Greg KH
2006-07-17 16:27   ` [patch 22/45] Make powernow-k7 work on SMP kernels Greg KH
2006-07-17 16:27   ` [patch 23/45] Fix powernow-k8 SMP kernel on UP hardware bug Greg KH
2006-07-17 16:27   ` [patch 24/45] cdrom: fix bad cgc.buflen assignment Greg KH
2006-07-17 16:27   ` [patch 25/45] splice: fix problems with sys_tee() Greg KH
2006-07-17 16:28   ` Greg KH [this message]
2006-07-17 16:28   ` [patch 27/45] tpm: interrupt clear fix Greg KH
2006-07-17 16:56     ` Kylene Jo Hall
2006-07-17 17:52       ` [stable] " Greg KH
2006-07-17 16:28   ` [patch 28/45] pdflush: handle resume wakeups Greg KH
2006-07-17 16:28   ` [patch 29/45] ieee80211: TKIP requires CRC32 Greg KH
2006-07-17 16:28   ` [patch 30/45] : Fix IPv4/DECnet routing rule dumping Greg KH
2006-07-17 16:28   ` [patch 31/45] : Add missing UFO initialisations Greg KH
2006-07-17 16:28   ` [patch 32/45] ALSA: Suppress irq handler mismatch messages in ALSA ISA drivers Greg KH
2006-07-17 16:28   ` [patch 33/45] ALSA: RME HDSP - fixed proc interface (missing {}) Greg KH
2006-07-17 16:28   ` [patch 34/45] ALSA: hda-intel - Fix race in remove Greg KH
2006-07-17 16:28   ` [patch 35/45] ALSA: Fix workaround for AD1988A rev2 codec Greg KH
2006-07-17 16:28   ` [patch 36/45] ALSA: Fix undefined (missing) references in ISA MIRO sound driver Greg KH
2006-07-17 16:28   ` [patch 37/45] ALSA: fix the SND_FM801_TEA575X dependencies Greg KH
2006-07-17 16:29   ` [patch 38/45] ALSA: Fix mute switch on VAIO laptops with STAC7661 Greg KH
2006-07-17 16:29   ` [patch 39/45] ALSA: Fix model for HP dc7600 Greg KH
2006-07-17 16:29   ` [patch 40/45] ALSA: Fix missing array terminators in AD1988 codec support Greg KH
2006-07-17 16:29   ` [patch 41/45] ALSA: Fix a deadlock in snd-rtctimer Greg KH
2006-07-17 16:29   ` [patch 42/45] ALSA: au88x0 - Fix 64bit address of MPU401 MMIO port Greg KH
2006-07-17 16:29   ` [patch 43/45] struct file leakage Greg KH
2006-07-17 16:29   ` [patch 44/45] serial 8250: sysrq deadlock fix Greg KH
2006-07-17 16:29   ` [patch 45/45] fix fdset leakage Greg KH
2006-07-18 13:24   ` [patch 00/45] 2.6.17.y -stable review akrout70

Reply instructions:

You may reply publicly to this message via plain-text email
using any one of the following methods:

* Save the following mbox file, import it into your mail client,
  and reply-to-all from there: mbox

  Avoid top-posting and favor interleaved quoting:
  https://en.wikipedia.org/wiki/Posting_style#Interleaved_style

* Reply using the --to, --cc, and --in-reply-to
  switches of git-send-email(1):

  git send-email \
    --in-reply-to=20060717162802.GA4829@kroah.com \
    --to=gregkh@suse.de \
    --cc=abbotti@mev.co.uk \
    --cc=akpm@osdl.org \
    --cc=alan@lxorguk.ukuu.org.uk \
    --cc=chuckw@quantumlinux.com \
    --cc=davej@redhat.com \
    --cc=jmforbes@linuxtx.org \
    --cc=linux-kernel@vger.kernel.org \
    --cc=rdunlap@xenotime.net \
    --cc=reviews@ml.cw.f00f.org \
    --cc=stable@kernel.org \
    --cc=torvalds@osdl.org \
    --cc=tytso@mit.edu \
    --cc=zwane@arm.linux.org.uk \
    /path/to/YOUR_REPLY

  https://kernel.org/pub/software/scm/git/docs/git-send-email.html

* If your mail client supports setting the In-Reply-To header
  via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line before the message body.
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox