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>] [day] [month] [year] [list]
Date:	Wed, 27 Jul 2016 10:59:05 -0500
From:	Tom Walsh <tomwalsh73@...il.com>
To:	netdev@...r.kernel.org
Subject: Patch: fix rotting packet OKI PCH_GBE switch

This is against torvalds 4.7.0 repo
This resolves a rotting SYN-ACK packet issue with
the OKI PCH_GBE switch.  The problem showed up
intermittently where a client would attempt to
establish a TCP connection to the host on an
otherwise quiet network.  No other activity had
occurred for a significant time.

This was a race condition that was finally duplicated
using a controlled set of timings between the SYN /
ACK / SYN-ACK sequence.  We found that by adjusting
the timing between the host ACK and the client
transmission of the SYN-ACK that we had the SYN-ACK
"stuck" in the switch data register.

The problem is that pch_gbe_irq_enable() is called
when the transmit of the ACK has completed, then
pch_gbe_irq_enable() will enable the interrupts of
the switch, followed by a read of the INT_ST which
results in clearing the status bits.

While the device would still issue an interrupt,
the pch_gbe_intr() handler would not see any pending
requests as the status register had been cleared.
Thus, the packet remains "stuck".

Signed-off-by: Tom Walsh <tomwalsh73@...il.com>

diff --git a/drivers/net/ethernet/oki-semi/pch_gbe/pch_gbe_main.c
b/drivers/net/ethernet/oki-semi/pch_gbe/pch_gbe_main.c
index 3cd87a4..baba31d 100644
--- a/drivers/net/ethernet/oki-semi/pch_gbe/pch_gbe_main.c
+++ b/drivers/net/ethernet/oki-semi/pch_gbe/pch_gbe_main.c
@@ -809,13 +809,16 @@ static void pch_gbe_irq_disable(struct
pch_gbe_adapter *adapter)
  * pch_gbe_irq_enable - Enable default interrupt generation settings
  * @adapter:  Board private structure
  */
-static void pch_gbe_irq_enable(struct pch_gbe_adapter *adapter)
+static void pch_gbe_irq_enable(struct pch_gbe_adapter *adapter,
+       bool reset_status_register)
 {
  struct pch_gbe_hw *hw = &adapter->hw;

- if (likely(atomic_dec_and_test(&adapter->irq_sem)))
+ if (likely(atomic_dec_and_test(&adapter->irq_sem))) {
  iowrite32(PCH_GBE_INT_ENABLE_MASK, &hw->reg->INT_EN);
- ioread32(&hw->reg->INT_ST);
+ if (reset_status_register)
+ ioread32(&hw->reg->INT_ST);
+ }
  netdev_dbg(adapter->netdev, "INT_EN reg : 0x%08x\n",
    ioread32(&hw->reg->INT_EN));
 }
@@ -1976,7 +1979,7 @@ int pch_gbe_up(struct pch_gbe_adapter *adapter)
  mod_timer(&adapter->watchdog_timer, jiffies);

  napi_enable(&adapter->napi);
- pch_gbe_irq_enable(adapter);
+ pch_gbe_irq_enable(adapter, true);
  netif_start_queue(adapter->netdev);

  return 0;
@@ -2392,7 +2395,7 @@ static int pch_gbe_napi_poll(struct napi_struct
*napi, int budget)

  if (poll_end_flag) {
  napi_complete(napi);
- pch_gbe_irq_enable(adapter);
+ pch_gbe_irq_enable(adapter, false);
  }

  if (adapter->rx_stop_flag) {

Powered by blists - more mailing lists

Powered by Openwall GNU/*/Linux Powered by OpenVZ