From: Greg Kroah-Hartman Date: Tue, 28 Jul 2009 22:47:32 +0000 (-0700) Subject: .27 patches X-Git-Tag: v2.6.30.4~5 X-Git-Url: http://git.ipfire.org/?a=commitdiff_plain;h=a40e926226fa4c16916fd74ca7c01a296b2d35fa;p=thirdparty%2Fkernel%2Fstable-queue.git .27 patches --- diff --git a/queue-2.6.27/e100-work-around-the-driver-using-streaming-dma-mapping-for-rx-descriptors.patch b/queue-2.6.27/e100-work-around-the-driver-using-streaming-dma-mapping-for-rx-descriptors.patch new file mode 100644 index 00000000000..e118bb7e7e7 --- /dev/null +++ b/queue-2.6.27/e100-work-around-the-driver-using-streaming-dma-mapping-for-rx-descriptors.patch @@ -0,0 +1,37 @@ +From dc82c02c693c02cec8dc1cc6ecdb602ee5558b23 Mon Sep 17 00:00:00 2001 +From: Krzysztof Halasa +Date: Tue, 14 Jul 2009 11:01:54 +0000 +Subject: E100: work around the driver using streaming DMA mapping for RX descriptors. + + +From: Krzysztof Halasa + +[ Upstream commit 303d67c288319768b19ed8dbed429fef7eb7c275 ] + +E100 places it's RX packet descriptors inside skb->data and uses them +with bidirectional streaming DMA mapping. Unfortunately it fails to +transfer skb->data ownership to the device after it reads the +descriptor's status, breaking on non-coherent (e.g., ARM) platforms. + +This have to be converted to use coherent memory for the descriptors. + +Signed-off-by: Krzysztof Halasa +Acked-by: Jeff Kirsher +Signed-off-by: David S. Miller +Signed-off-by: Greg Kroah-Hartman +--- + drivers/net/e100.c | 3 +++ + 1 file changed, 3 insertions(+) + +--- a/drivers/net/e100.c ++++ b/drivers/net/e100.c +@@ -1840,6 +1840,9 @@ static int e100_rx_indicate(struct nic * + + if (ioread8(&nic->csr->scb.status) & rus_no_res) + nic->ru_running = RU_SUSPENDED; ++ pci_dma_sync_single_for_device(nic->pdev, rx->dma_addr, ++ sizeof(struct rfd), ++ PCI_DMA_BIDIRECTIONAL); + return -ENODATA; + } + diff --git a/queue-2.6.27/ecryptfs-check-tag-11-literal-data-buffer-size.patch b/queue-2.6.27/ecryptfs-check-tag-11-literal-data-buffer-size.patch new file mode 100644 index 00000000000..c5017f108c3 --- /dev/null +++ b/queue-2.6.27/ecryptfs-check-tag-11-literal-data-buffer-size.patch @@ -0,0 +1,40 @@ +From 6352a29305373ae6196491e6d4669f301e26492e Mon Sep 17 00:00:00 2001 +From: Tyler Hicks +Date: Tue, 28 Jul 2009 13:57:01 -0500 +Subject: eCryptfs: Check Tag 11 literal data buffer size (CVE-2009-2406) + +From: Tyler Hicks + +commit 6352a29305373ae6196491e6d4669f301e26492e upstream. + +Tag 11 packets are stored in the metadata section of an eCryptfs file to +store the key signature(s) used to encrypt the file encryption key. +After extracting the packet length field to determine the key signature +length, a check is not performed to see if the length would exceed the +key signature buffer size that was passed into parse_tag_11_packet(). + +Thanks to Ramon de Carvalho Valle for finding this bug using fsfuzzer. + +Signed-off-by: Tyler Hicks +Signed-off-by: Linus Torvalds +Signed-off-by: Greg Kroah-Hartman + +--- + fs/ecryptfs/keystore.c | 6 ++++++ + 1 file changed, 6 insertions(+) + +--- a/fs/ecryptfs/keystore.c ++++ b/fs/ecryptfs/keystore.c +@@ -876,6 +876,12 @@ parse_tag_11_packet(unsigned char *data, + rc = -EINVAL; + goto out; + } ++ if (unlikely((*tag_11_contents_size) > max_contents_bytes)) { ++ printk(KERN_ERR "Literal data section in tag 11 packet exceeds " ++ "expected size\n"); ++ rc = -EINVAL; ++ goto out; ++ } + if (data[(*packet_size)++] != 0x62) { + printk(KERN_WARNING "Unrecognizable packet\n"); + rc = -EINVAL; diff --git a/queue-2.6.27/ecryptfs-parse_tag_3_packet-check-tag-3-packet-encrypted-key-size.patch b/queue-2.6.27/ecryptfs-parse_tag_3_packet-check-tag-3-packet-encrypted-key-size.patch new file mode 100644 index 00000000000..2bd3a3171b0 --- /dev/null +++ b/queue-2.6.27/ecryptfs-parse_tag_3_packet-check-tag-3-packet-encrypted-key-size.patch @@ -0,0 +1,38 @@ +From f151cd2c54ddc7714e2f740681350476cda03a28 Mon Sep 17 00:00:00 2001 +From: Ramon de Carvalho Valle +Date: Tue, 28 Jul 2009 13:58:22 -0500 +Subject: eCryptfs: parse_tag_3_packet check tag 3 packet encrypted key size (CVE-2009-2407) + +From: Ramon de Carvalho Valle + +commit f151cd2c54ddc7714e2f740681350476cda03a28 upstream. + +The parse_tag_3_packet function does not check if the tag 3 packet contains a +encrypted key size larger than ECRYPTFS_MAX_ENCRYPTED_KEY_BYTES. + +Signed-off-by: Ramon de Carvalho Valle +[tyhicks@linux.vnet.ibm.com: Added printk newline and changed goto to out_free] +Signed-off-by: Tyler Hicks +Signed-off-by: Linus Torvalds +Signed-off-by: Greg Kroah-Hartman + +--- + fs/ecryptfs/keystore.c | 7 +++++++ + 1 file changed, 7 insertions(+) + +--- a/fs/ecryptfs/keystore.c ++++ b/fs/ecryptfs/keystore.c +@@ -730,6 +730,13 @@ parse_tag_3_packet(struct ecryptfs_crypt + } + (*new_auth_tok)->session_key.encrypted_key_size = + (body_size - (ECRYPTFS_SALT_SIZE + 5)); ++ if ((*new_auth_tok)->session_key.encrypted_key_size ++ > ECRYPTFS_MAX_ENCRYPTED_KEY_BYTES) { ++ printk(KERN_WARNING "Tag 3 packet contains key larger " ++ "than ECRYPTFS_MAX_ENCRYPTED_KEY_BYTES\n"); ++ rc = -EINVAL; ++ goto out_free; ++ } + if (unlikely(data[(*packet_size)++] != 0x04)) { + printk(KERN_WARNING "Unknown version number [%d]\n", + data[(*packet_size) - 1]); diff --git a/queue-2.6.27/ipsec-fix-name-of-cast-algorithm.patch b/queue-2.6.27/ipsec-fix-name-of-cast-algorithm.patch new file mode 100644 index 00000000000..5545e6ee593 --- /dev/null +++ b/queue-2.6.27/ipsec-fix-name-of-cast-algorithm.patch @@ -0,0 +1,33 @@ +From e771d997f2460ef215a8a8662b1c84ad464d9d1a Mon Sep 17 00:00:00 2001 +From: Herbert Xu +Date: Wed, 24 Jun 2009 03:55:41 -0700 +Subject: ipsec: Fix name of CAST algorithm + + +From: Herbert Xu + +[ Upstream commit 245acb87729bc76ba65c7476665c01837e0cdccb ] + +Our CAST algorithm is called cast5, not cast128. Clearly nobody +has ever used it :) + +Signed-off-by: Herbert Xu +Signed-off-by: David S. Miller +Signed-off-by: Greg Kroah-Hartman +--- + net/xfrm/xfrm_algo.c | 4 ++-- + 1 file changed, 2 insertions(+), 2 deletions(-) + +--- a/net/xfrm/xfrm_algo.c ++++ b/net/xfrm/xfrm_algo.c +@@ -292,8 +292,8 @@ static struct xfrm_algo_desc ealg_list[] + } + }, + { +- .name = "cbc(cast128)", +- .compat = "cast128", ++ .name = "cbc(cast5)", ++ .compat = "cast5", + + .uinfo = { + .encr = { diff --git a/queue-2.6.27/net-fix-locking-issues-in-ppp-6pack-mkiss-and-strip-line-disciplines.patch b/queue-2.6.27/net-fix-locking-issues-in-ppp-6pack-mkiss-and-strip-line-disciplines.patch new file mode 100644 index 00000000000..83d61056cdc --- /dev/null +++ b/queue-2.6.27/net-fix-locking-issues-in-ppp-6pack-mkiss-and-strip-line-disciplines.patch @@ -0,0 +1,545 @@ +From 972df98afa31a4e28894f030a80cef9d86d412bd Mon Sep 17 00:00:00 2001 +From: Ralf Baechle +Date: Tue, 28 Jul 2009 13:59:36 -0700 +Subject: NET: Fix locking issues in PPP, 6pack, mkiss and strip line disciplines. + + +From: Ralf Baechle + +[ Upstream commit adeab1afb7de89555c69aab5ca21300c14af6369 ] + +Guido Trentalancia reports: + +I am trying to use the kiss driver in the Linux kernel that is being +shipped with Fedora 10 but unfortunately I get the following oops: + +mkiss: AX.25 Multikiss, Hans Albas PE1AYX +mkiss: ax0: crc mode is auto. +ADDRCONF(NETDEV_CHANGE): ax0: link becomes ready +------------[ cut here ]------------ +WARNING: at kernel/softirq.c:77 __local_bh_disable+0x2f/0x83() (Not +tainted) +[...] +unloaded: microcode] +Pid: 0, comm: swapper Not tainted 2.6.27.25-170.2.72.fc10.i686 #1 + [] warn_on_slowpath+0x65/0x8b + [] ? _spin_unlock_irqrestore+0x22/0x38 + [] ? __enqueue_entity+0xe3/0xeb + [] ? enqueue_entity+0x203/0x20b + [] ? enqueue_task_fair+0x3b/0x3f + [] ? resched_task+0x3a/0x6e + [] ? _spin_unlock_irqrestore+0x22/0x38 + [] ? _spin_lock_bh+0xb/0x16 + [] __local_bh_disable+0x2f/0x83 + [] local_bh_disable+0xb/0xd + [] _spin_lock_bh+0xb/0x16 + [] mkiss_receive_buf+0x2fb/0x3a6 [mkiss] + [] flush_to_ldisc+0xf7/0x198 + [] tty_flip_buffer_push+0x41/0x51 + [] ftdi_process_read+0x375/0x4ad [ftdi_sio] + [] ftdi_read_bulk_callback+0x130/0x138 [ftdi_sio] + [] usb_hcd_giveback_urb+0x63/0x93 + [] uhci_giveback_urb+0xe5/0x15f + [] uhci_scan_schedule+0x52e/0x767 + [] ? psmouse_handle_byte+0xc/0xe5 + [] ? acpi_ev_gpe_detect+0xd6/0xe1 + [] uhci_irq+0x110/0x125 + [] usb_hcd_irq+0x40/0xa3 + [] handle_IRQ_event+0x2f/0x64 + [] handle_level_irq+0x74/0xbe + [] ? handle_level_irq+0x0/0xbe + [] do_IRQ+0xc7/0xfe + [] common_interrupt+0x28/0x30 + [] ? acpi_idle_enter_simple+0x162/0x19d + [] cpuidle_idle_call+0x60/0x92 + [] cpu_idle+0x101/0x134 + [] rest_init+0x4e/0x50 + ======================= +---[ end trace b7cc8076093467ad ]--- +------------[ cut here ]------------ +WARNING: at kernel/softirq.c:136 _local_bh_enable_ip+0x3d/0xc4() +[...] +Pid: 0, comm: swapper Tainted: G W 2.6.27.25-170.2.72.fc10.i686 + [] warn_on_slowpath+0x65/0x8b + [] ? _spin_unlock_irqrestore+0x22/0x38 + [] ? __enqueue_entity+0xe3/0xeb + [] ? enqueue_entity+0x203/0x20b + [] ? enqueue_task_fair+0x3b/0x3f + [] ? resched_task+0x3a/0x6e + [] ? _spin_unlock_irqrestore+0x22/0x38 + [] ? _spin_lock_bh+0xb/0x16 + [] ? mkiss_receive_buf+0x33d/0x3a6 [mkiss] + [] _local_bh_enable_ip+0x3d/0xc4 + [] local_bh_enable_ip+0x8/0xa + [] _spin_unlock_bh+0x11/0x13 + [] mkiss_receive_buf+0x33d/0x3a6 [mkiss] + [] flush_to_ldisc+0xf7/0x198 + [] tty_flip_buffer_push+0x41/0x51 + [] ftdi_process_read+0x375/0x4ad [ftdi_sio] + [] ftdi_read_bulk_callback+0x130/0x138 [ftdi_sio] + [] usb_hcd_giveback_urb+0x63/0x93 + [] uhci_giveback_urb+0xe5/0x15f + [] uhci_scan_schedule+0x52e/0x767 + [] ? psmouse_handle_byte+0xc/0xe5 + [] ? acpi_ev_gpe_detect+0xd6/0xe1 + [] uhci_irq+0x110/0x125 + [] usb_hcd_irq+0x40/0xa3 + [] handle_IRQ_event+0x2f/0x64 + [] handle_level_irq+0x74/0xbe + [] ? handle_level_irq+0x0/0xbe + [] do_IRQ+0xc7/0xfe + [] common_interrupt+0x28/0x30 + [] ? acpi_idle_enter_simple+0x162/0x19d + [] cpuidle_idle_call+0x60/0x92 + [] cpu_idle+0x101/0x134 + [] rest_init+0x4e/0x50 + ======================= +---[ end trace b7cc8076093467ad ]--- +mkiss: ax0: Trying crc-smack +mkiss: ax0: Trying crc-flexnet + +The issue was, that the locking code in mkiss was assuming it was only +ever being called in process or bh context. Fixed by converting the +involved locking code to use irq-safe locks. + +Review of other networking line disciplines shows that 6pack, both sync +and async PPP and STRIP have similar issues. The ppp_async one is the +most interesting one as it sorts out half of the issue as far back as +2004 in commit http://git.kernel.org/?p=linux/kernel/git/tglx/history.git;a=commitdiff;h=2996d8deaeddd01820691a872550dc0cfba0c37d + +Signed-off-by: Ralf Baechle +Reported-by: Guido Trentalancia +Signed-off-by: David S. Miller +Signed-off-by: Greg Kroah-Hartman +--- + drivers/net/hamradio/6pack.c | 10 ++++++---- + drivers/net/hamradio/mkiss.c | 41 ++++++++++++++++++++++++----------------- + drivers/net/ppp_async.c | 11 +++++++---- + drivers/net/ppp_synctty.c | 11 +++++++---- + drivers/net/wireless/strip.c | 39 ++++++++++++++++++++++++--------------- + 5 files changed, 68 insertions(+), 44 deletions(-) + +--- a/drivers/net/hamradio/6pack.c ++++ b/drivers/net/hamradio/6pack.c +@@ -397,13 +397,14 @@ static DEFINE_RWLOCK(disc_data_lock); + + static struct sixpack *sp_get(struct tty_struct *tty) + { ++ unsigned long flags; + struct sixpack *sp; + +- read_lock(&disc_data_lock); ++ read_lock_irqsave(&disc_data_lock, flags); + sp = tty->disc_data; + if (sp) + atomic_inc(&sp->refcnt); +- read_unlock(&disc_data_lock); ++ read_unlock_irqrestore(&disc_data_lock, flags); + + return sp; + } +@@ -687,12 +688,13 @@ out: + */ + static void sixpack_close(struct tty_struct *tty) + { ++ unsigned long flags; + struct sixpack *sp; + +- write_lock(&disc_data_lock); ++ write_lock_irqsave(&disc_data_lock, flags); + sp = tty->disc_data; + tty->disc_data = NULL; +- write_unlock(&disc_data_lock); ++ write_unlock_irqrestore(&disc_data_lock, flags); + if (!sp) + return; + +--- a/drivers/net/hamradio/mkiss.c ++++ b/drivers/net/hamradio/mkiss.c +@@ -246,15 +246,16 @@ static int kiss_esc_crc(unsigned char *s + /* Send one completely decapsulated AX.25 packet to the AX.25 layer. */ + static void ax_bump(struct mkiss *ax) + { ++ unsigned long flags; + struct sk_buff *skb; + int count; + +- spin_lock_bh(&ax->buflock); ++ spin_lock_irqsave(&ax->buflock, flags); + if (ax->rbuff[0] > 0x0f) { + if (ax->rbuff[0] & 0x80) { + if (check_crc_16(ax->rbuff, ax->rcount) < 0) { + ax->stats.rx_errors++; +- spin_unlock_bh(&ax->buflock); ++ spin_unlock_irqrestore(&ax->buflock, flags); + + return; + } +@@ -269,7 +270,7 @@ static void ax_bump(struct mkiss *ax) + } else if (ax->rbuff[0] & 0x20) { + if (check_crc_flex(ax->rbuff, ax->rcount) < 0) { + ax->stats.rx_errors++; +- spin_unlock_bh(&ax->buflock); ++ spin_unlock_irqrestore(&ax->buflock, flags); + return; + } + if (ax->crcmode != CRC_MODE_FLEX && ax->crcauto) { +@@ -296,7 +297,7 @@ static void ax_bump(struct mkiss *ax) + printk(KERN_ERR "mkiss: %s: memory squeeze, dropping packet.\n", + ax->dev->name); + ax->stats.rx_dropped++; +- spin_unlock_bh(&ax->buflock); ++ spin_unlock_irqrestore(&ax->buflock, flags); + return; + } + +@@ -306,11 +307,13 @@ static void ax_bump(struct mkiss *ax) + ax->dev->last_rx = jiffies; + ax->stats.rx_packets++; + ax->stats.rx_bytes += count; +- spin_unlock_bh(&ax->buflock); ++ spin_unlock_irqrestore(&ax->buflock, flags); + } + + static void kiss_unesc(struct mkiss *ax, unsigned char s) + { ++ unsigned long flags; ++ + switch (s) { + case END: + /* drop keeptest bit = VSV */ +@@ -337,18 +340,18 @@ static void kiss_unesc(struct mkiss *ax, + break; + } + +- spin_lock_bh(&ax->buflock); ++ spin_lock_irqsave(&ax->buflock, flags); + if (!test_bit(AXF_ERROR, &ax->flags)) { + if (ax->rcount < ax->buffsize) { + ax->rbuff[ax->rcount++] = s; +- spin_unlock_bh(&ax->buflock); ++ spin_unlock_irqrestore(&ax->buflock, flags); + return; + } + + ax->stats.rx_over_errors++; + set_bit(AXF_ERROR, &ax->flags); + } +- spin_unlock_bh(&ax->buflock); ++ spin_unlock_irqrestore(&ax->buflock, flags); + } + + static int ax_set_mac_address(struct net_device *dev, void *addr) +@@ -370,6 +373,7 @@ static void ax_changedmtu(struct mkiss * + { + struct net_device *dev = ax->dev; + unsigned char *xbuff, *rbuff, *oxbuff, *orbuff; ++ unsigned long flags; + int len; + + len = dev->mtu * 2; +@@ -395,7 +399,7 @@ static void ax_changedmtu(struct mkiss * + return; + } + +- spin_lock_bh(&ax->buflock); ++ spin_lock_irqsave(&ax->buflock, flags); + + oxbuff = ax->xbuff; + ax->xbuff = xbuff; +@@ -426,7 +430,7 @@ static void ax_changedmtu(struct mkiss * + ax->mtu = dev->mtu + 73; + ax->buffsize = len; + +- spin_unlock_bh(&ax->buflock); ++ spin_unlock_irqrestore(&ax->buflock, flags); + + kfree(oxbuff); + kfree(orbuff); +@@ -436,6 +440,7 @@ static void ax_changedmtu(struct mkiss * + static void ax_encaps(struct net_device *dev, unsigned char *icp, int len) + { + struct mkiss *ax = netdev_priv(dev); ++ unsigned long flags; + unsigned char *p; + int actual, count; + +@@ -452,7 +457,7 @@ static void ax_encaps(struct net_device + + p = icp; + +- spin_lock_bh(&ax->buflock); ++ spin_lock_irqsave(&ax->buflock, flags); + if ((*p & 0x0f) != 0) { + /* Configuration Command (kissparms(1). + * Protocol spec says: never append CRC. +@@ -482,7 +487,7 @@ static void ax_encaps(struct net_device + ax->crcauto = (cmd ? 0 : 1); + printk(KERN_INFO "mkiss: %s: crc mode %s %d\n", ax->dev->name, (len) ? "set to" : "is", cmd); + } +- spin_unlock_bh(&ax->buflock); ++ spin_unlock_irqrestore(&ax->buflock, flags); + netif_start_queue(dev); + + return; +@@ -515,7 +520,7 @@ static void ax_encaps(struct net_device + count = kiss_esc(p, (unsigned char *)ax->xbuff, len); + } + } +- spin_unlock_bh(&ax->buflock); ++ spin_unlock_irqrestore(&ax->buflock, flags); + + set_bit(TTY_DO_WRITE_WAKEUP, &ax->tty->flags); + actual = ax->tty->ops->write(ax->tty, ax->xbuff, count); +@@ -711,13 +716,14 @@ static DEFINE_RWLOCK(disc_data_lock); + + static struct mkiss *mkiss_get(struct tty_struct *tty) + { ++ unsigned long flags; + struct mkiss *ax; + +- read_lock(&disc_data_lock); ++ read_lock_irqsave(&disc_data_lock, flags); + ax = tty->disc_data; + if (ax) + atomic_inc(&ax->refcnt); +- read_unlock(&disc_data_lock); ++ read_unlock_irqrestore(&disc_data_lock, flags); + + return ax; + } +@@ -816,12 +822,13 @@ out: + + static void mkiss_close(struct tty_struct *tty) + { ++ unsigned long flags; + struct mkiss *ax; + +- write_lock(&disc_data_lock); ++ write_lock_irqsave(&disc_data_lock, flags); + ax = tty->disc_data; + tty->disc_data = NULL; +- write_unlock(&disc_data_lock); ++ write_unlock_irqrestore(&disc_data_lock, flags); + + if (!ax) + return; +--- a/drivers/net/ppp_async.c ++++ b/drivers/net/ppp_async.c +@@ -132,13 +132,15 @@ static DEFINE_RWLOCK(disc_data_lock); + + static struct asyncppp *ap_get(struct tty_struct *tty) + { ++ unsigned long flags; + struct asyncppp *ap; + +- read_lock(&disc_data_lock); ++ read_lock_irqsave(&disc_data_lock, flags); + ap = tty->disc_data; + if (ap != NULL) + atomic_inc(&ap->refcnt); +- read_unlock(&disc_data_lock); ++ read_unlock_irqrestore(&disc_data_lock, flags); ++ + return ap; + } + +@@ -212,12 +214,13 @@ ppp_asynctty_open(struct tty_struct *tty + static void + ppp_asynctty_close(struct tty_struct *tty) + { ++ unsigned long flags; + struct asyncppp *ap; + +- write_lock_irq(&disc_data_lock); ++ write_lock_irqsave(&disc_data_lock, flags); + ap = tty->disc_data; + tty->disc_data = NULL; +- write_unlock_irq(&disc_data_lock); ++ write_unlock_irqrestore(&disc_data_lock, flags); + if (!ap) + return; + +--- a/drivers/net/ppp_synctty.c ++++ b/drivers/net/ppp_synctty.c +@@ -182,13 +182,15 @@ static DEFINE_RWLOCK(disc_data_lock); + + static struct syncppp *sp_get(struct tty_struct *tty) + { ++ unsigned long flags; + struct syncppp *ap; + +- read_lock(&disc_data_lock); ++ read_lock_irqsave(&disc_data_lock, flags); + ap = tty->disc_data; + if (ap != NULL) + atomic_inc(&ap->refcnt); +- read_unlock(&disc_data_lock); ++ read_unlock_irqrestore(&disc_data_lock, flags); ++ + return ap; + } + +@@ -259,12 +261,13 @@ ppp_sync_open(struct tty_struct *tty) + static void + ppp_sync_close(struct tty_struct *tty) + { ++ unsigned long flags; + struct syncppp *ap; + +- write_lock_irq(&disc_data_lock); ++ write_lock_irqsave(&disc_data_lock, flags); + ap = tty->disc_data; + tty->disc_data = NULL; +- write_unlock_irq(&disc_data_lock); ++ write_unlock_irqrestore(&disc_data_lock, flags); + if (!ap) + return; + +--- a/drivers/net/wireless/strip.c ++++ b/drivers/net/wireless/strip.c +@@ -856,6 +856,7 @@ static int strip_change_mtu(struct net_d + unsigned char *orbuff = strip_info->rx_buff; + unsigned char *osbuff = strip_info->sx_buff; + unsigned char *otbuff = strip_info->tx_buff; ++ unsigned long flags; + + if (new_mtu > MAX_SEND_MTU) { + printk(KERN_ERR +@@ -864,11 +865,11 @@ static int strip_change_mtu(struct net_d + return -EINVAL; + } + +- spin_lock_bh(&strip_lock); ++ spin_lock_irqsave(&strip_lock, flags); + if (!allocate_buffers(strip_info, new_mtu)) { + printk(KERN_ERR "%s: unable to grow strip buffers, MTU change cancelled.\n", + strip_info->dev->name); +- spin_unlock_bh(&strip_lock); ++ spin_unlock_irqrestore(&strip_lock, flags); + return -ENOMEM; + } + +@@ -892,7 +893,7 @@ static int strip_change_mtu(struct net_d + } + } + strip_info->tx_head = strip_info->tx_buff; +- spin_unlock_bh(&strip_lock); ++ spin_unlock_irqrestore(&strip_lock, flags); + + printk(KERN_NOTICE "%s: strip MTU changed fom %d to %d.\n", + strip_info->dev->name, old_mtu, strip_info->mtu); +@@ -981,10 +982,13 @@ static void strip_seq_neighbours(struct + const MetricomNodeTable * table, + const char *title) + { +- /* We wrap this in a do/while loop, so if the table changes */ +- /* while we're reading it, we just go around and try again. */ ++ unsigned long flags; + struct timeval t; + ++ /* ++ * We wrap this in a do/while loop, so if the table changes ++ * while we're reading it, we just go around and try again. ++ */ + do { + int i; + t = table->timestamp; +@@ -993,9 +997,9 @@ static void strip_seq_neighbours(struct + for (i = 0; i < table->num_nodes; i++) { + MetricomNode node; + +- spin_lock_bh(&strip_lock); ++ spin_lock_irqsave(&strip_lock, flags); + node = table->node[i]; +- spin_unlock_bh(&strip_lock); ++ spin_unlock_irqrestore(&strip_lock, flags); + seq_printf(seq, " %s\n", node.c); + } + } while (table->timestamp.tv_sec != t.tv_sec +@@ -1535,6 +1539,7 @@ static void strip_send(struct strip *str + static int strip_xmit(struct sk_buff *skb, struct net_device *dev) + { + struct strip *strip_info = netdev_priv(dev); ++ unsigned long flags; + + if (!netif_running(dev)) { + printk(KERN_ERR "%s: xmit call when iface is down\n", +@@ -1573,11 +1578,11 @@ static int strip_xmit(struct sk_buff *sk + strip_info->dev->name, sx_pps_count / 8); + } + +- spin_lock_bh(&strip_lock); ++ spin_lock_irqsave(&strip_lock, flags); + + strip_send(strip_info, skb); + +- spin_unlock_bh(&strip_lock); ++ spin_unlock_irqrestore(&strip_lock, flags); + + if (skb) + dev_kfree_skb(skb); +@@ -2263,12 +2268,13 @@ static void strip_receive_buf(struct tty + { + struct strip *strip_info = (struct strip *) tty->disc_data; + const unsigned char *end = cp + count; ++ unsigned long flags; + + if (!strip_info || strip_info->magic != STRIP_MAGIC + || !netif_running(strip_info->dev)) + return; + +- spin_lock_bh(&strip_lock); ++ spin_lock_irqsave(&strip_lock, flags); + #if 0 + { + struct timeval tv; +@@ -2335,7 +2341,7 @@ static void strip_receive_buf(struct tty + } + cp++; + } +- spin_unlock_bh(&strip_lock); ++ spin_unlock_irqrestore(&strip_lock, flags); + } + + +@@ -2525,9 +2531,11 @@ static void strip_dev_setup(struct net_d + + static void strip_free(struct strip *strip_info) + { +- spin_lock_bh(&strip_lock); ++ unsigned long flags; ++ ++ spin_lock_irqsave(&strip_lock, flags); + list_del_rcu(&strip_info->list); +- spin_unlock_bh(&strip_lock); ++ spin_unlock_irqrestore(&strip_lock, flags); + + strip_info->magic = 0; + +@@ -2541,6 +2549,7 @@ static void strip_free(struct strip *str + static struct strip *strip_alloc(void) + { + struct list_head *n; ++ unsigned long flags; + struct net_device *dev; + struct strip *strip_info; + +@@ -2564,7 +2573,7 @@ static struct strip *strip_alloc(void) + strip_info->idle_timer.function = strip_IdleTask; + + +- spin_lock_bh(&strip_lock); ++ spin_lock_irqsave(&strip_lock, flags); + rescan: + /* + * Search the list to find where to put our new entry +@@ -2583,7 +2592,7 @@ static struct strip *strip_alloc(void) + sprintf(dev->name, "st%ld", dev->base_addr); + + list_add_tail_rcu(&strip_info->list, &strip_list); +- spin_unlock_bh(&strip_lock); ++ spin_unlock_irqrestore(&strip_lock, flags); + + return strip_info; + } diff --git a/queue-2.6.27/pegasus-usb-net-fix-endianness-bugs.patch b/queue-2.6.27/pegasus-usb-net-fix-endianness-bugs.patch new file mode 100644 index 00000000000..412eb29bfba --- /dev/null +++ b/queue-2.6.27/pegasus-usb-net-fix-endianness-bugs.patch @@ -0,0 +1,97 @@ +From 141cad230a6fb069eb226048398708c29d260358 Mon Sep 17 00:00:00 2001 +From: Michael Buesch +Date: Thu, 18 Jun 2009 07:03:47 +0000 +Subject: pegasus usb-net: Fix endianness bugs + + +From: Michael Buesch + +[ Upstream commit e3453f6342110d60edb37be92c4a4f668ca8b0c4 ] + +This fixes various endianness bugs. Some harmless and some real ones. +This is tested on a PowerPC-64 machine. + +Signed-off-by: Michael Buesch +Signed-off-by: David S. Miller +Signed-off-by: Greg Kroah-Hartman +--- + drivers/net/usb/pegasus.c | 29 +++++++++++++++++------------ + 1 file changed, 17 insertions(+), 12 deletions(-) + +--- a/drivers/net/usb/pegasus.c ++++ b/drivers/net/usb/pegasus.c +@@ -295,7 +295,7 @@ static int update_eth_regs_async(pegasus + + pegasus->dr.bRequestType = PEGASUS_REQT_WRITE; + pegasus->dr.bRequest = PEGASUS_REQ_SET_REGS; +- pegasus->dr.wValue = 0; ++ pegasus->dr.wValue = cpu_to_le16(0); + pegasus->dr.wIndex = cpu_to_le16(EthCtrl0); + pegasus->dr.wLength = cpu_to_le16(3); + pegasus->ctrl_urb->transfer_buffer_length = 3; +@@ -444,11 +444,12 @@ static int write_eprom_word(pegasus_t * + int i; + __u8 tmp, d[4] = { 0x3f, 0, 0, EPROM_WRITE }; + int ret; ++ __le16 le_data = cpu_to_le16(data); + + set_registers(pegasus, EpromOffset, 4, d); + enable_eprom_write(pegasus); + set_register(pegasus, EpromOffset, index); +- set_registers(pegasus, EpromData, 2, &data); ++ set_registers(pegasus, EpromData, 2, &le_data); + set_register(pegasus, EpromCtrl, EPROM_WRITE); + + for (i = 0; i < REG_TIMEOUT; i++) { +@@ -918,29 +919,32 @@ static struct net_device_stats *pegasus_ + + static inline void disable_net_traffic(pegasus_t * pegasus) + { +- int tmp = 0; ++ __le16 tmp = cpu_to_le16(0); + +- set_registers(pegasus, EthCtrl0, 2, &tmp); ++ set_registers(pegasus, EthCtrl0, sizeof(tmp), &tmp); + } + + static inline void get_interrupt_interval(pegasus_t * pegasus) + { +- __u8 data[2]; ++ u16 data; ++ u8 interval; + +- read_eprom_word(pegasus, 4, (__u16 *) data); ++ read_eprom_word(pegasus, 4, &data); ++ interval = data >> 8; + if (pegasus->usb->speed != USB_SPEED_HIGH) { +- if (data[1] < 0x80) { ++ if (interval < 0x80) { + if (netif_msg_timer(pegasus)) + dev_info(&pegasus->intf->dev, "intr interval " + "changed from %ums to %ums\n", +- data[1], 0x80); +- data[1] = 0x80; ++ interval, 0x80); ++ interval = 0x80; ++ data = (data & 0x00FF) | ((u16)interval << 8); + #ifdef PEGASUS_WRITE_EEPROM +- write_eprom_word(pegasus, 4, *(__u16 *) data); ++ write_eprom_word(pegasus, 4, data); + #endif + } + } +- pegasus->intr_interval = data[1]; ++ pegasus->intr_interval = interval; + } + + static void set_carrier(struct net_device *net) +@@ -1293,7 +1297,8 @@ static int pegasus_blacklisted(struct us + /* Special quirk to keep the driver from handling the Belkin Bluetooth + * dongle which happens to have the same ID. + */ +- if ((udd->idVendor == VENDOR_BELKIN && udd->idProduct == 0x0121) && ++ if ((udd->idVendor == cpu_to_le16(VENDOR_BELKIN)) && ++ (udd->idProduct == cpu_to_le16(0x0121)) && + (udd->bDeviceClass == USB_CLASS_WIRELESS_CONTROLLER) && + (udd->bDeviceProtocol == 1)) + return 1; diff --git a/queue-2.6.27/r8169-avoid-losing-msi-interrupts.patch b/queue-2.6.27/r8169-avoid-losing-msi-interrupts.patch new file mode 100644 index 00000000000..610cc5e92cd --- /dev/null +++ b/queue-2.6.27/r8169-avoid-losing-msi-interrupts.patch @@ -0,0 +1,159 @@ +From 9fb17ab2221d5d285f98e0fdc171fea3ddf984d7 Mon Sep 17 00:00:00 2001 +From: David Dillow +Date: Wed, 22 Jul 2009 09:17:06 -0700 +Subject: r8169: avoid losing MSI interrupts + + +From: David Dillow + +[ Upstream commit f11a377b3f4e897d11f0e8d1fc688667e2f19708 ] + +The 8169 chip only generates MSI interrupts when all enabled event +sources are quiescent and one or more sources transition to active. If +not all of the active events are acknowledged, or a new event becomes +active while the existing ones are cleared in the handler, we will not +see a new interrupt. + +The current interrupt handler masks off the Rx and Tx events once the +NAPI handler has been scheduled, which opens a race window in which we +can get another Rx or Tx event and never ACK'ing it, stopping all +activity until the link is reset (ifconfig down/up). Fix this by always +ACK'ing all event sources, and loop in the handler until we have all +sources quiescent. + +Signed-off-by: David Dillow +Tested-by: Michael Buesch +Signed-off-by: David S. Miller +Signed-off-by: Greg Kroah-Hartman +--- + drivers/net/r8169.c | 102 +++++++++++++++++++++++++++++----------------------- + 1 file changed, 57 insertions(+), 45 deletions(-) + +--- a/drivers/net/r8169.c ++++ b/drivers/net/r8169.c +@@ -2850,54 +2850,64 @@ static irqreturn_t rtl8169_interrupt(int + int handled = 0; + int status; + ++ /* loop handling interrupts until we have no new ones or ++ * we hit a invalid/hotplug case. ++ */ + status = RTL_R16(IntrStatus); ++ while (status && status != 0xffff) { ++ handled = 1; + +- /* hotplug/major error/no more work/shared irq */ +- if ((status == 0xffff) || !status) +- goto out; +- +- handled = 1; ++ /* Handle all of the error cases first. These will reset ++ * the chip, so just exit the loop. ++ */ ++ if (unlikely(!netif_running(dev))) { ++ rtl8169_asic_down(ioaddr); ++ break; ++ } + +- if (unlikely(!netif_running(dev))) { +- rtl8169_asic_down(ioaddr); +- goto out; +- } ++ /* Work around for rx fifo overflow */ ++ if (unlikely(status & RxFIFOOver) && ++ (tp->mac_version == RTL_GIGA_MAC_VER_11)) { ++ netif_stop_queue(dev); ++ rtl8169_tx_timeout(dev); ++ break; ++ } + +- status &= tp->intr_mask; +- RTL_W16(IntrStatus, +- (status & RxFIFOOver) ? (status | RxOverflow) : status); ++ if (unlikely(status & SYSErr)) { ++ rtl8169_pcierr_interrupt(dev); ++ break; ++ } + +- if (!(status & tp->intr_event)) +- goto out; ++ if (status & LinkChg) ++ rtl8169_check_link_status(dev, tp, ioaddr); + +- /* Work around for rx fifo overflow */ +- if (unlikely(status & RxFIFOOver) && +- (tp->mac_version == RTL_GIGA_MAC_VER_11)) { +- netif_stop_queue(dev); +- rtl8169_tx_timeout(dev); +- goto out; +- } ++ /* We need to see the lastest version of tp->intr_mask to ++ * avoid ignoring an MSI interrupt and having to wait for ++ * another event which may never come. ++ */ ++ smp_rmb(); ++ if (status & tp->intr_mask & tp->napi_event) { ++ RTL_W16(IntrMask, tp->intr_event & ~tp->napi_event); ++ tp->intr_mask = ~tp->napi_event; ++ ++ if (likely(napi_schedule_prep(&tp->napi))) ++ __napi_schedule(&tp->napi); ++ else if (netif_msg_intr(tp)) { ++ printk(KERN_INFO "%s: interrupt %04x in poll\n", ++ dev->name, status); ++ } ++ } + +- if (unlikely(status & SYSErr)) { +- rtl8169_pcierr_interrupt(dev); +- goto out; ++ /* We only get a new MSI interrupt when all active irq ++ * sources on the chip have been acknowledged. So, ack ++ * everything we've seen and check if new sources have become ++ * active to avoid blocking all interrupts from the chip. ++ */ ++ RTL_W16(IntrStatus, ++ (status & RxFIFOOver) ? (status | RxOverflow) : status); ++ status = RTL_R16(IntrStatus); + } + +- if (status & LinkChg) +- rtl8169_check_link_status(dev, tp, ioaddr); +- +- if (status & tp->napi_event) { +- RTL_W16(IntrMask, tp->intr_event & ~tp->napi_event); +- tp->intr_mask = ~tp->napi_event; +- +- if (likely(netif_rx_schedule_prep(dev, &tp->napi))) +- __netif_rx_schedule(dev, &tp->napi); +- else if (netif_msg_intr(tp)) { +- printk(KERN_INFO "%s: interrupt %04x in poll\n", +- dev->name, status); +- } +- } +-out: + return IRQ_RETVAL(handled); + } + +@@ -2913,13 +2923,15 @@ static int rtl8169_poll(struct napi_stru + + if (work_done < budget) { + netif_rx_complete(dev, napi); +- tp->intr_mask = 0xffff; +- /* +- * 20040426: the barrier is not strictly required but the +- * behavior of the irq handler could be less predictable +- * without it. Btw, the lack of flush for the posted pci +- * write is safe - FR ++ ++ /* We need for force the visibility of tp->intr_mask ++ * for other CPUs, as we can loose an MSI interrupt ++ * and potentially wait for a retransmit timeout if we don't. ++ * The posted write to IntrMask is safe, as it will ++ * eventually make it to the chip and we won't loose anything ++ * until it does. + */ ++ tp->intr_mask = 0xffff; + smp_wmb(); + RTL_W16(IntrMask, tp->intr_event); + } diff --git a/queue-2.6.27/series b/queue-2.6.27/series index 8a5c6a6edc7..4ccfff43636 100644 --- a/queue-2.6.27/series +++ b/queue-2.6.27/series @@ -25,3 +25,13 @@ acpi-ec-limit-workaround-for-asus-notebooks-even-more.patch enable-pnpacpi-_psx-support-v3.patch acpi-suspend-don-t-let-device-_ps3-failure-prevent-suspend.patch input-wistron_btns-recognize-maxdata-pro-7000-notebooks.patch +ecryptfs-check-tag-11-literal-data-buffer-size.patch +ecryptfs-parse_tag_3_packet-check-tag-3-packet-encrypted-key-size.patch +ipsec-fix-name-of-cast-algorithm.patch +pegasus-usb-net-fix-endianness-bugs.patch +sky2-fix-checksum-endianness.patch +x25-fix-sleep-from-timer-on-socket-destroy.patch +usbnet-cdc_subset-fix-issues-talking-to-pxa-gadgets.patch +r8169-avoid-losing-msi-interrupts.patch +e100-work-around-the-driver-using-streaming-dma-mapping-for-rx-descriptors.patch +net-fix-locking-issues-in-ppp-6pack-mkiss-and-strip-line-disciplines.patch diff --git a/queue-2.6.27/sky2-fix-checksum-endianness.patch b/queue-2.6.27/sky2-fix-checksum-endianness.patch new file mode 100644 index 00000000000..4745d0bb0de --- /dev/null +++ b/queue-2.6.27/sky2-fix-checksum-endianness.patch @@ -0,0 +1,47 @@ +From 73bba29c5976b4b49fbcd5c09856dd1642944150 Mon Sep 17 00:00:00 2001 +From: Anton Vorontsov +Date: Fri, 26 Jun 2009 09:28:42 -0700 +Subject: sky2: Fix checksum endianness + + +From: Anton Vorontsov + +[ Upstream commit b9389796fa4c87fbdff33816e317cdae5f36dd0b ] + +sky2 driver on PowerPC targets floods kernel log with following errors: + + eth1: hw csum failure. + Call Trace: + [ef84b8a0] [c00075e4] show_stack+0x50/0x160 (unreliable) + [ef84b8d0] [c02fa178] netdev_rx_csum_fault+0x3c/0x5c + [ef84b8f0] [c02f6920] __skb_checksum_complete_head+0x7c/0x84 + [ef84b900] [c02f693c] __skb_checksum_complete+0x14/0x24 + [ef84b910] [c0337e08] tcp_v4_rcv+0x4c8/0x6f8 + [ef84b940] [c031a9c8] ip_local_deliver+0x98/0x210 + [ef84b960] [c031a788] ip_rcv+0x38c/0x534 + [ef84b990] [c0300338] netif_receive_skb+0x260/0x36c + [ef84b9c0] [c025de00] sky2_poll+0x5dc/0xcf8 + [ef84ba20] [c02fb7fc] net_rx_action+0xc0/0x144 + +The NIC is Yukon-2 EC chip revision 1. + +Converting checksum field from le16 to CPU byte order fixes the issue. + +Signed-off-by: Anton Vorontsov +Signed-off-by: David S. Miller +Signed-off-by: Greg Kroah-Hartman +--- + drivers/net/sky2.c | 2 +- + 1 file changed, 1 insertion(+), 1 deletion(-) + +--- a/drivers/net/sky2.c ++++ b/drivers/net/sky2.c +@@ -2393,7 +2393,7 @@ static int sky2_status_intr(struct sky2_ + if (likely(status >> 16 == (status & 0xffff))) { + skb = sky2->rx_ring[sky2->rx_next].skb; + skb->ip_summed = CHECKSUM_COMPLETE; +- skb->csum = status & 0xffff; ++ skb->csum = le16_to_cpu(status); + } else { + printk(KERN_NOTICE PFX "%s: hardware receive " + "checksum problem (status = %#x)\n", diff --git a/queue-2.6.27/usbnet-cdc_subset-fix-issues-talking-to-pxa-gadgets.patch b/queue-2.6.27/usbnet-cdc_subset-fix-issues-talking-to-pxa-gadgets.patch new file mode 100644 index 00000000000..4b754d118e4 --- /dev/null +++ b/queue-2.6.27/usbnet-cdc_subset-fix-issues-talking-to-pxa-gadgets.patch @@ -0,0 +1,41 @@ +From a3629a044fa9570522d4cb640a6f85ca26c6ce2a Mon Sep 17 00:00:00 2001 +From: David Brownell +Date: Sat, 20 Jun 2009 01:21:53 -0700 +Subject: usbnet cdc_subset: fix issues talking to PXA gadgets + + +From: David Brownell + +[ Upstream commit 6be832529a8129c9d90a1d3a78c5d503a710b6fc ] + +The host-side CDC subset driver is binding more specifically +than it should ... only to PXA 210/25x/26x Linux-USB gadgets. + +Loosen that restriction to match the gadget driver driver. +This will various PXA 27x and PXA 3xx devices happier when +talking to Linux hosts, potentially others. + +Signed-off-by: David Brownell +Tested-by: Aric D. Blumer +Signed-off-by: David S. Miller +Signed-off-by: Greg Kroah-Hartman +--- + drivers/net/usb/cdc_subset.c | 7 ++++--- + 1 file changed, 4 insertions(+), 3 deletions(-) + +--- a/drivers/net/usb/cdc_subset.c ++++ b/drivers/net/usb/cdc_subset.c +@@ -307,9 +307,10 @@ static const struct usb_device_id produc + USB_DEVICE (0x1286, 0x8001), // "blob" bootloader + .driver_info = (unsigned long) &blob_info, + }, { +- // Linux Ethernet/RNDIS gadget on pxa210/25x/26x, second config +- // e.g. Gumstix, current OpenZaurus, ... +- USB_DEVICE_VER (0x0525, 0xa4a2, 0x0203, 0x0203), ++ // Linux Ethernet/RNDIS gadget, mostly on PXA, second config ++ // e.g. Gumstix, current OpenZaurus, ... or anything else ++ // that just enables this gadget option. ++ USB_DEVICE (0x0525, 0xa4a2), + .driver_info = (unsigned long) &linuxdev_info, + }, + #endif diff --git a/queue-2.6.27/x25-fix-sleep-from-timer-on-socket-destroy.patch b/queue-2.6.27/x25-fix-sleep-from-timer-on-socket-destroy.patch new file mode 100644 index 00000000000..db9fd3ba8f9 --- /dev/null +++ b/queue-2.6.27/x25-fix-sleep-from-timer-on-socket-destroy.patch @@ -0,0 +1,102 @@ +From 8b300863e7aa6123ec1011978e506c74bc3128f2 Mon Sep 17 00:00:00 2001 +From: David S. Miller +Date: Tue, 16 Jun 2009 05:40:30 -0700 +Subject: x25: Fix sleep from timer on socket destroy. + + +From: David S. Miller + +[ Upstream commit 14ebaf81e13ce66bff275380b246796fd16cbfa1 ] + +If socket destuction gets delayed to a timer, we try to +lock_sock() from that timer which won't work. + +Use bh_lock_sock() in that case. + +Signed-off-by: David S. Miller +Tested-by: Ingo Molnar +Signed-off-by: Greg Kroah-Hartman +--- + include/net/x25.h | 2 +- + net/x25/af_x25.c | 23 ++++++++++++++++++----- + net/x25/x25_timer.c | 2 +- + 3 files changed, 20 insertions(+), 7 deletions(-) + +--- a/include/net/x25.h ++++ b/include/net/x25.h +@@ -187,7 +187,7 @@ extern int x25_addr_ntoa(unsigned char + extern int x25_addr_aton(unsigned char *, struct x25_address *, + struct x25_address *); + extern struct sock *x25_find_socket(unsigned int, struct x25_neigh *); +-extern void x25_destroy_socket(struct sock *); ++extern void x25_destroy_socket_from_timer(struct sock *); + extern int x25_rx_call_request(struct sk_buff *, struct x25_neigh *, unsigned int); + extern void x25_kill_by_neigh(struct x25_neigh *); + +--- a/net/x25/af_x25.c ++++ b/net/x25/af_x25.c +@@ -332,14 +332,14 @@ static unsigned int x25_new_lci(struct x + /* + * Deferred destroy. + */ +-void x25_destroy_socket(struct sock *); ++static void __x25_destroy_socket(struct sock *); + + /* + * handler for deferred kills. + */ + static void x25_destroy_timer(unsigned long data) + { +- x25_destroy_socket((struct sock *)data); ++ x25_destroy_socket_from_timer((struct sock *)data); + } + + /* +@@ -349,12 +349,10 @@ static void x25_destroy_timer(unsigned l + * will touch it and we are (fairly 8-) ) safe. + * Not static as it's used by the timer + */ +-void x25_destroy_socket(struct sock *sk) ++static void __x25_destroy_socket(struct sock *sk) + { + struct sk_buff *skb; + +- sock_hold(sk); +- lock_sock(sk); + x25_stop_heartbeat(sk); + x25_stop_timer(sk); + +@@ -385,7 +383,22 @@ void x25_destroy_socket(struct sock *sk) + /* drop last reference so sock_put will free */ + __sock_put(sk); + } ++} + ++void x25_destroy_socket_from_timer(struct sock *sk) ++{ ++ sock_hold(sk); ++ bh_lock_sock(sk); ++ __x25_destroy_socket(sk); ++ bh_unlock_sock(sk); ++ sock_put(sk); ++} ++ ++static void x25_destroy_socket(struct sock *sk) ++{ ++ sock_hold(sk); ++ lock_sock(sk); ++ __x25_destroy_socket(sk); + release_sock(sk); + sock_put(sk); + } +--- a/net/x25/x25_timer.c ++++ b/net/x25/x25_timer.c +@@ -113,7 +113,7 @@ static void x25_heartbeat_expiry(unsigne + (sk->sk_state == TCP_LISTEN && + sock_flag(sk, SOCK_DEAD))) { + bh_unlock_sock(sk); +- x25_destroy_socket(sk); ++ x25_destroy_socket_from_timer(sk); + return; + } + break;