Message ID | 20190103064224.8876-2-kai.heng.feng@canonical.com |
---|---|
State | New |
Headers | show |
Series | Fix iwlwifi's off by one bug in TFD | expand |
On 1/3/19 7:42 AM, Kai-Heng Feng wrote: > From: Emmanuel Grumbach <emmanuel.grumbach@intel.com> > > BugLink: https://bugs.launchpad.net/bugs/1801102 > > Our Transmit Frame Descriptor (TFD) is a DMA descriptor that > includes several pointers to be able to transmit a packet > which is not physically contiguous. > > Depending on the hardware being use, we can have 20 or 25 > pointers in a single TFD. In both cases, it is more than > enough and it is quite hard to hit this limit. > It has been reported that when using specific applications > (Ktorrent), we can actually use all the pointers and then > a long standing bug showed up. > > When we free the TFD, we check its number of valid pointers > and make sure it doesn't exceed the number of pointers the > hardware support. > This check had an off by one bug: it is perfectly valid to > free the 20 pointers if the TFD has 20 pointers. > > Fix that. > > https://bugzilla.kernel.org/show_bug.cgi?id=197981 > > Signed-off-by: Emmanuel Grumbach <emmanuel.grumbach@intel.com> > Signed-off-by: Luca Coelho <luciano.coelho@intel.com> > (cherry picked from commit 4437ba7ee7de7e71d11deb91c87a370e4ffd2601) > Signed-off-by: Kai-Heng Feng <kai.heng.feng@canonical.com> Clean cherry-pick, confirmed by the bug reporter to fix the issue. Acked-by: Kleber Sacilotto de Souza <kleber.souza@canonical.com> > --- > drivers/net/wireless/intel/iwlwifi/pcie/tx-gen2.c | 2 +- > drivers/net/wireless/intel/iwlwifi/pcie/tx.c | 2 +- > 2 files changed, 2 insertions(+), 2 deletions(-) > > diff --git a/drivers/net/wireless/intel/iwlwifi/pcie/tx-gen2.c b/drivers/net/wireless/intel/iwlwifi/pcie/tx-gen2.c > index 6d0a907d5ba5..fabae0f60683 100644 > --- a/drivers/net/wireless/intel/iwlwifi/pcie/tx-gen2.c > +++ b/drivers/net/wireless/intel/iwlwifi/pcie/tx-gen2.c > @@ -147,7 +147,7 @@ static void iwl_pcie_gen2_tfd_unmap(struct iwl_trans *trans, > /* Sanity check on number of chunks */ > num_tbs = iwl_pcie_gen2_get_num_tbs(trans, tfd); > > - if (num_tbs >= trans_pcie->max_tbs) { > + if (num_tbs > trans_pcie->max_tbs) { > IWL_ERR(trans, "Too many chunks: %i\n", num_tbs); > return; > } > diff --git a/drivers/net/wireless/intel/iwlwifi/pcie/tx.c b/drivers/net/wireless/intel/iwlwifi/pcie/tx.c > index 3f85713c41dc..1a566287993d 100644 > --- a/drivers/net/wireless/intel/iwlwifi/pcie/tx.c > +++ b/drivers/net/wireless/intel/iwlwifi/pcie/tx.c > @@ -378,7 +378,7 @@ static void iwl_pcie_tfd_unmap(struct iwl_trans *trans, > /* Sanity check on number of chunks */ > num_tbs = iwl_pcie_tfd_get_num_tbs(trans, tfd); > > - if (num_tbs >= trans_pcie->max_tbs) { > + if (num_tbs > trans_pcie->max_tbs) { > IWL_ERR(trans, "Too many chunks: %i\n", num_tbs); > /* @todo issue fatal error, it is quite serious situation */ > return;
On 03.01.19 07:42, Kai-Heng Feng wrote: > From: Emmanuel Grumbach <emmanuel.grumbach@intel.com> > > BugLink: https://bugs.launchpad.net/bugs/1801102 > > Our Transmit Frame Descriptor (TFD) is a DMA descriptor that > includes several pointers to be able to transmit a packet > which is not physically contiguous. > > Depending on the hardware being use, we can have 20 or 25 > pointers in a single TFD. In both cases, it is more than > enough and it is quite hard to hit this limit. > It has been reported that when using specific applications > (Ktorrent), we can actually use all the pointers and then > a long standing bug showed up. > > When we free the TFD, we check its number of valid pointers > and make sure it doesn't exceed the number of pointers the > hardware support. > This check had an off by one bug: it is perfectly valid to > free the 20 pointers if the TFD has 20 pointers. > > Fix that. > > https://bugzilla.kernel.org/show_bug.cgi?id=197981 > > Signed-off-by: Emmanuel Grumbach <emmanuel.grumbach@intel.com> > Signed-off-by: Luca Coelho <luciano.coelho@intel.com> > (cherry picked from commit 4437ba7ee7de7e71d11deb91c87a370e4ffd2601) > Signed-off-by: Kai-Heng Feng <kai.heng.feng@canonical.com> Acked-by: Stefan Bader <stefan.bader@canonical.com> > --- > drivers/net/wireless/intel/iwlwifi/pcie/tx-gen2.c | 2 +- > drivers/net/wireless/intel/iwlwifi/pcie/tx.c | 2 +- > 2 files changed, 2 insertions(+), 2 deletions(-) > > diff --git a/drivers/net/wireless/intel/iwlwifi/pcie/tx-gen2.c b/drivers/net/wireless/intel/iwlwifi/pcie/tx-gen2.c > index 6d0a907d5ba5..fabae0f60683 100644 > --- a/drivers/net/wireless/intel/iwlwifi/pcie/tx-gen2.c > +++ b/drivers/net/wireless/intel/iwlwifi/pcie/tx-gen2.c > @@ -147,7 +147,7 @@ static void iwl_pcie_gen2_tfd_unmap(struct iwl_trans *trans, > /* Sanity check on number of chunks */ > num_tbs = iwl_pcie_gen2_get_num_tbs(trans, tfd); > > - if (num_tbs >= trans_pcie->max_tbs) { > + if (num_tbs > trans_pcie->max_tbs) { > IWL_ERR(trans, "Too many chunks: %i\n", num_tbs); > return; > } > diff --git a/drivers/net/wireless/intel/iwlwifi/pcie/tx.c b/drivers/net/wireless/intel/iwlwifi/pcie/tx.c > index 3f85713c41dc..1a566287993d 100644 > --- a/drivers/net/wireless/intel/iwlwifi/pcie/tx.c > +++ b/drivers/net/wireless/intel/iwlwifi/pcie/tx.c > @@ -378,7 +378,7 @@ static void iwl_pcie_tfd_unmap(struct iwl_trans *trans, > /* Sanity check on number of chunks */ > num_tbs = iwl_pcie_tfd_get_num_tbs(trans, tfd); > > - if (num_tbs >= trans_pcie->max_tbs) { > + if (num_tbs > trans_pcie->max_tbs) { > IWL_ERR(trans, "Too many chunks: %i\n", num_tbs); > /* @todo issue fatal error, it is quite serious situation */ > return; >
diff --git a/drivers/net/wireless/intel/iwlwifi/pcie/tx-gen2.c b/drivers/net/wireless/intel/iwlwifi/pcie/tx-gen2.c index 6d0a907d5ba5..fabae0f60683 100644 --- a/drivers/net/wireless/intel/iwlwifi/pcie/tx-gen2.c +++ b/drivers/net/wireless/intel/iwlwifi/pcie/tx-gen2.c @@ -147,7 +147,7 @@ static void iwl_pcie_gen2_tfd_unmap(struct iwl_trans *trans, /* Sanity check on number of chunks */ num_tbs = iwl_pcie_gen2_get_num_tbs(trans, tfd); - if (num_tbs >= trans_pcie->max_tbs) { + if (num_tbs > trans_pcie->max_tbs) { IWL_ERR(trans, "Too many chunks: %i\n", num_tbs); return; } diff --git a/drivers/net/wireless/intel/iwlwifi/pcie/tx.c b/drivers/net/wireless/intel/iwlwifi/pcie/tx.c index 3f85713c41dc..1a566287993d 100644 --- a/drivers/net/wireless/intel/iwlwifi/pcie/tx.c +++ b/drivers/net/wireless/intel/iwlwifi/pcie/tx.c @@ -378,7 +378,7 @@ static void iwl_pcie_tfd_unmap(struct iwl_trans *trans, /* Sanity check on number of chunks */ num_tbs = iwl_pcie_tfd_get_num_tbs(trans, tfd); - if (num_tbs >= trans_pcie->max_tbs) { + if (num_tbs > trans_pcie->max_tbs) { IWL_ERR(trans, "Too many chunks: %i\n", num_tbs); /* @todo issue fatal error, it is quite serious situation */ return;