2.6.16-stable review
Subsystems (4)
cover 2.6.16-stable review
This is the start of the stable review cycle for the 2.6.16.25 release.
This should also flush out the last of the 2.6.16 pending patches, and the -stable team will turn this kernel over to Adrian Bunk now, unless there are any outstanding issues that people raise.
There are 3 patches in this series, all will be posted as a response to this one. If anyone has any issues with these being applied, please let us know. If anyone is a maintainer of the proper subsystem, and wants to add a Signed-off-by: line to the patch, please respond with it.
These patches are sent out with a number of different people on the Cc:
line. If you wish to be a reviewer, please email [email protected] to add your name to the list. If you want to be off the reviewer list, also email us.
Responses should be made by Saturday, July 16 22:00:00 UTC. Anything received after that time, might be too late.
thanks,
greg k-h
PATCH 1/3 IPV6: Fix source address selection.
-stable review patch. If anyone has any objections, please let us know.
------------------
From: aukasz Stelmach <[email protected]>
Two additional labels (RFC 3484, sec. 10.3) for IPv6 addreses are defined to make a distinction between global unicast addresses and Unique Local Addresses (fc00::/7, RFC 4193) and Teredo (2001::/32, RFC 4380). It is necessary to avoid attempts of connection that would either fail (eg. fec0:: to 2001:feed::) or be sub-optimal (2001:0:: to 2001:feed::).
--- net/ipv6/addrconf.c | 6 ++++++ 1 file changed, 6 insertions(+)
net/ipv6/addrconf.c +6 -0
@@ -852,6 +852,8 @@ static int inline ipv6_saddr_label(const* 2002::/16 2 * ::/96 3 * ::ffff:0:0/96 4 +* fc00::/7 5 +* 2001::/32 6 */ if (type &IPV6_ADDR_LOOPBACK )return 0 ;
@@ -859,8 +861,12 @@ static int inline ipv6_saddr_label(constreturn 3 ; else if (type & IPV6_ADDR_MAPPED) return 4; + else if (addr->s6_addr32[0] == htonl(0x20010000)) + return 6; else if (addr->s6_addr16[0] == htons(0x2002)) return 2; + else if ((addr->s6_addr[0] & 0xfe) == 0xfc) +return 5 ;return 1 ; }
--
PATCH 2/3 IPV6 ADDRCONF: Fix default source address selection without CONFIG_IPV6_PRIVACY
In reply to Greg KH-stable review patch. If anyone has any objections, please let us know.
------------------
From: YOSHIFUJI Hideaki <[email protected]>
We need to update hiscore.rule even if we don't enable CONFIG_IPV6_PRIVACY, because we have more less significant rule; longest match.
--- net/ipv6/addrconf.c | 3 +++ 1 file changed, 3 insertions(+)
net/ipv6/addrconf.c +3 -0
@@ -1065,6 +1065,9 @@ int ipv6_dev_get_saddr(struct net_deviceif (hiscore.attrs &IPV6_SADDR_SCORE_PRIVACY ) continue; } +#else +if (hiscore.rule <7 ) + hiscore.rule++;#endif /* Rule 8: Use longest matching prefix */ if (hiscore.rule <8 ) {
--
PATCH 3/3 USB serial ftdi_sio: Prevent userspace DoS (CVE-2006-2936)
In reply to Greg KH-stable review patch. If anyone has any objections, please let us know.
------------------
From: Ian Abbott <[email protected]>
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.
--- drivers/usb/serial/ftdi_sio.c | 84 +++++++++++++++++++++++++++++++++++------- 1 file changed, 71 insertions(+), 13 deletions(-)
drivers/usb/serial/ftdi_sio.c +71 -13
@@ -545,6 +545,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 */
@@ -618,6 +622,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
@@ -1149,6 +1156,7 @@ static int ftdi_sio_attach (struct usb_smemset (priv,0 ,sizeof (*priv));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 */
@@ -1365,6 +1373,7 @@ static int ftdi_write (struct usb_serialint 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);
@@ -1372,6 +1381,13 @@ static int ftdi_write (struct usb_serialdbg ("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);
@@ -1438,6 +1454,11 @@ static int ftdi_write (struct usb_serialerr ("%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
@@ -1453,7 +1474,11 @@ static int ftdi_write (struct usb_serialstatic 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);
@@ -1465,34 +1490,67 @@ static void ftdi_write_bulk_callback (streturn ; } + 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 */
--