diff mbox series

neighbour: Disregard DEAD dst in neigh_update

Message ID 20201230225415.GA490@ucf43ac461c9a53.ant.amazon.com (mailing list archive)
State Changes Requested
Delegated to: Netdev Maintainers
Headers show
Series neighbour: Disregard DEAD dst in neigh_update | expand

Checks

Context Check Description
netdev/cover_letter success Link
netdev/fixes_present success Link
netdev/patch_count success Link
netdev/tree_selection success Guessed tree name to be net-next
netdev/subject_prefix warning Target tree name not specified in the subject
netdev/cc_maintainers warning 9 maintainers not CCed: mrv@mojatatu.com roopa@cumulusnetworks.com liuhangbin@gmail.com lirongqing@baidu.com jdike@akamai.com dsahern@kernel.org rdna@fb.com kuba@kernel.org nikolay@cumulusnetworks.com
netdev/source_inline success Was 0 now: 0
netdev/verify_signedoff success Link
netdev/module_param success Was 0 now: 0
netdev/build_32bit success Errors and warnings before: 3 this patch: 3
netdev/kdoc success Errors and warnings before: 0 this patch: 0
netdev/verify_fixes success Link
netdev/checkpatch success total: 0 errors, 0 warnings, 0 checks, 8 lines checked
netdev/build_allmodconfig_warn success Errors and warnings before: 3 this patch: 3
netdev/header_inline success Link
netdev/stable success Stable not CCed

Commit Message

Tong Zhu Dec. 30, 2020, 10:54 p.m. UTC
In 4.x kernel a dst in DST_OBSOLETE_DEAD state is associated
with loopback net_device and leads to loopback neighbour. It
leads to an ethernet header with all zero addresses.

A very troubling case is working with mac80211 and ath9k.
A packet with all zero source MAC address to mac80211 will
eventually fail ieee80211_find_sta_by_ifaddr in ath9k (xmit.c).
As result, ath9k flushes tx queue (ath_tx_complete_aggr) without
updating baw (block ack window), damages baw logic and disables
transmission.

Signed-off-by: Tong Zhu <zhutong@amazon.com>
---
 net/core/neighbour.c | 2 +-
 1 file changed, 1 insertion(+), 1 deletion(-)

Comments

David Miller Jan. 6, 2021, 12:05 a.m. UTC | #1
From: Tong Zhu <zhutong@amazon.com>
Date: Wed, 30 Dec 2020 17:54:23 -0500

> In 4.x kernel a dst in DST_OBSOLETE_DEAD state is associated
> with loopback net_device and leads to loopback neighbour. It
> leads to an ethernet header with all zero addresses.
> 
> A very troubling case is working with mac80211 and ath9k.
> A packet with all zero source MAC address to mac80211 will
> eventually fail ieee80211_find_sta_by_ifaddr in ath9k (xmit.c).
> As result, ath9k flushes tx queue (ath_tx_complete_aggr) without
> updating baw (block ack window), damages baw logic and disables
> transmission.
> 
> Signed-off-by: Tong Zhu <zhutong@amazon.com>

Please repost with an appropriate Fixes: tag.

Thanks.
Tong Zhu Jan. 8, 2021, 2:36 a.m. UTC | #2
On Tue, Jan 05, 2021 at 04:05:21PM -0800, David Miller wrote: 
> 
> 
> From: Tong Zhu <zhutong@amazon.com>
> Date: Wed, 30 Dec 2020 17:54:23 -0500
> 
> > In 4.x kernel a dst in DST_OBSOLETE_DEAD state is associated
> > with loopback net_device and leads to loopback neighbour. It
> > leads to an ethernet header with all zero addresses.
> >
> > A very troubling case is working with mac80211 and ath9k.
> > A packet with all zero source MAC address to mac80211 will
> > eventually fail ieee80211_find_sta_by_ifaddr in ath9k (xmit.c).
> > As result, ath9k flushes tx queue (ath_tx_complete_aggr) without
> > updating baw (block ack window), damages baw logic and disables
> > transmission.
> >
> > Signed-off-by: Tong Zhu <zhutong@amazon.com>
> 
> Please repost with an appropriate Fixes: tag.
> 
> Thanks.

I had a second thought on this. This fix should go mainline too. This is a 
case we are sending out queued packets when arp reply from the neighbour 
comes in. With 5.x kernel, a dst in DST_OBSOLETE_DEAD state leads to dropping
of this packet. It is not as bad as with 4.x kernel that may end up with an
all-zero mac address packet out to ethernet or choking up ath9k when using 
block ack. Dropping the packet is still wrong. I’ll repost as a fix to
mainline and target backport to 4.x LTS releases.

Best regards
Greg Kroah-Hartman Jan. 8, 2021, 7:34 a.m. UTC | #3
On Thu, Jan 07, 2021 at 09:36:37PM -0500, Your Real Name wrote:
> On Tue, Jan 05, 2021 at 04:05:21PM -0800, David Miller wrote: 
> > 
> > 
> > From: Tong Zhu <zhutong@amazon.com>
> > Date: Wed, 30 Dec 2020 17:54:23 -0500
> > 
> > > In 4.x kernel a dst in DST_OBSOLETE_DEAD state is associated
> > > with loopback net_device and leads to loopback neighbour. It
> > > leads to an ethernet header with all zero addresses.
> > >
> > > A very troubling case is working with mac80211 and ath9k.
> > > A packet with all zero source MAC address to mac80211 will
> > > eventually fail ieee80211_find_sta_by_ifaddr in ath9k (xmit.c).
> > > As result, ath9k flushes tx queue (ath_tx_complete_aggr) without
> > > updating baw (block ack window), damages baw logic and disables
> > > transmission.
> > >
> > > Signed-off-by: Tong Zhu <zhutong@amazon.com>
> > 
> > Please repost with an appropriate Fixes: tag.
> > 
> > Thanks.
> 
> I had a second thought on this. This fix should go mainline too. This is a 
> case we are sending out queued packets when arp reply from the neighbour 
> comes in. With 5.x kernel, a dst in DST_OBSOLETE_DEAD state leads to dropping
> of this packet. It is not as bad as with 4.x kernel that may end up with an
> all-zero mac address packet out to ethernet or choking up ath9k when using 
> block ack. Dropping the packet is still wrong. I’ll repost as a fix to
> mainline and target backport to 4.x LTS releases.

That's how kernel development works, please read
    https://www.kernel.org/doc/html/latest/process/stable-kernel-rules.html
for how stable kernels are allowed to accept patches.

good luck!

greg k-h
diff mbox series

Patch

diff --git a/net/core/neighbour.c b/net/core/neighbour.c
index 6e890f51b7d8..e471c32e448f 100644
--- a/net/core/neighbour.c
+++ b/net/core/neighbour.c
@@ -1271,7 +1271,7 @@  int neigh_update(struct neighbour *neigh, const u8 *lladdr, u8 new,
 			 * we can reinject the packet there.
 			 */
 			n2 = NULL;
-			if (dst) {
+			if (dst && dst->obsolete != DST_OBSOLETE_DEAD) {
 				n2 = dst_neigh_lookup_skb(dst, skb);
 				if (n2)
 					n1 = n2;