lists.openwall.net   lists  /  announce  owl-users  owl-dev  john-users  john-dev  passwdqc-users  yescrypt  popa3d-users  /  oss-security  kernel-hardening  musl  sabotage  tlsify  passwords  /  crypt-dev  xvendor  /  Bugtraq  Full-Disclosure  linux-kernel  linux-netdev  linux-ext4  linux-hardening  linux-cve-announce  PHC 
Open Source and information security mailing list archives
 
Hash Suite: Windows password security audit tool. GUI, reports in PDF.
[<prev] [next>] [<thread-prev] [thread-next>] [day] [month] [year] [list]
Date:	Fri, 15 Feb 2008 04:34:36 +1030
From:	David Newall <davidn@...idnewall.com>
To:	Alan Cox <alan@...rguk.ukuu.org.uk>
CC:	Greg KH <greg@...ah.com>, linux-usb@...r.kernel.org,
	Linux Kernel Mailing List <linux-kernel@...r.kernel.org>
Subject: Re: Handshaking on USB serial devices

Alan Cox wrote:
>> To make it clear: Even aside from the buffer in 2.6's pl2303.c, there's
>> a race: An in-flight write URB can fill all hardware buffers, making
>> unsafe what previously appeared to be a safe write.  I think it's
>> essential to delay submission of the URB on a stop-transmit condition.
>>     
>
> Hardware flow control *is* a race, and always will be. The remote end has
> a delay in signalling 'stop' there is a propogation delay and a response
> delay. This is why most implementations assert stop a bit *before* they
> run out.
>   

That's a very good point.  Even so: on the 2.4 driver, write_room isn't
implemented (refer to a previous message by Alan); and in 2.6, a 1k
buffer is built into the driver, with nothing to prevent it being sent
when the hardware buffer fills.  These could be bugs in the two versions
of pl2303, if you like; in fact I suppose they are; but there's a wider
problem: The same weakness can be found in aircable.c, airprime.c,
cyberjack.c, cypress_m8.c (I think), empeg.c, ftdi_sio (I think),
io_ti.c, and that's where I stop checking, and declare it's widespread.

> Given the size of transfers and the internal buffering one would hope the
> USB devices do their own flow control if told to properly.
>   

RS232 is (normally) so much slower than USB that, on an extended
transmission, the buffer internal to the local hardware can fill well
before the remote device has demanded that transmission stop.  In fact,
now that you've mentioned it, I can't see that anything to stop the
driver from overflowing the internal buffer, which is very perplexing. 
Would that be right?  That seems a pretty dramatic weakness; how do you
write a large report to a slow printer without losing data?


I'm beginning to realise that overflowing the internal buffer is the
greatest risk of data loss.  Hardware flow control almost seems
serendipitous.  It gives us a reason to stop submitting bulk writes.

This is the essence of the change that I looking at for pl2303.c. 
(Patch relative to kernel 2.6.23.14.)  Does it make sense?

--- pl2303.c	2008-01-15 07:19:56.000000000 +1030
+++ pl2303.c.new	2008-02-15 04:22:12.000000000 +1030
@@ -370,6 +370,18 @@
 
 	spin_lock_irqsave(&priv->lock, flags);
 
+	/*
+	 * there's a limit to how much we can buffer, so don't accept data while
+	 * CTS or DSR are low.  XXX I don't know what to do about XON/XOFF.
+	 */
+	if ((priv->line_control | CONTROL_RTS && !(priv->line_status & UART_CTS)) || \
+	    (priv->line_control | CONTROL_DTR && !(priv->line_status & UART_DSR))) {
+		/* 
+		spin_unlock_irqrestore(&priv->lock, flags);
+		dbg("%s: send paused by remote flow control", __FUNCTION__);
+		return;
+	}
+
 	if (priv->write_urb_in_use) {
 		spin_unlock_irqrestore(&priv->lock, flags);
 		return;
@@ -957,6 +969,9 @@
 
 	pl2303_update_line_status(port, data, actual_length);
 
+	/* send any buffered data */
+	pl2303_send(port);
+
 exit:
 	retval = usb_submit_urb(urb, GFP_ATOMIC);
 	if (retval)


--
To unsubscribe from this list: send the line "unsubscribe linux-kernel" in
the body of a message to majordomo@...r.kernel.org
More majordomo info at  http://vger.kernel.org/majordomo-info.html
Please read the FAQ at  http://www.tux.org/lkml/

Powered by blists - more mailing lists

Powered by Openwall GNU/*/Linux Powered by OpenVZ