git: dd91d8448665 - main - net: Fix LLE lock leaks

From: Mark Johnston <markj_at_FreeBSD.org>
Date: Fri, 08 Apr 2022 16:10:24 UTC
The branch main has been updated by markj:

URL: https://cgit.FreeBSD.org/src/commit/?id=dd91d8448665dd31df5be7341756394293c6e36c

commit dd91d8448665dd31df5be7341756394293c6e36c
Author:     Mark Johnston <markj@FreeBSD.org>
AuthorDate: 2022-04-08 15:46:19 +0000
Commit:     Mark Johnston <markj@FreeBSD.org>
CommitDate: 2022-04-08 15:46:19 +0000

    net: Fix LLE lock leaks
    
    Historically, lltable_try_set_entry_addr() would release the LLE lock
    upon failure.  After some refactoring, it no longer does so, but
    consumers were not adjusted accordingly.
    
    Also fix a leak that can occur if lltable_calc_llheader() fails in the
    ARP code, but I suspect that such a failure can only occur due to a code
    bug.
    
    Reviewed by:    bz, melifaro
    Reported by:    pho
    Fixes:          0b79b007ebfc ("[lltable] Restructure nd6 code.")
    MFC after:      3 days
    Sponsored by:   The FreeBSD Foundation
    Differential Revision:  https://reviews.freebsd.org/D34831
---
 sys/netinet/if_ether.c | 8 ++++++--
 sys/netinet6/nd6_nbr.c | 4 +---
 2 files changed, 7 insertions(+), 5 deletions(-)

diff --git a/sys/netinet/if_ether.c b/sys/netinet/if_ether.c
index f54df9937936..fd0423858bb8 100644
--- a/sys/netinet/if_ether.c
+++ b/sys/netinet/if_ether.c
@@ -1228,16 +1228,20 @@ arp_check_update_lle(struct arphdr *ah, struct in_addr isaddr, struct ifnet *ifp
 	/* Calculate full link prepend to use in lle */
 	linkhdrsize = sizeof(linkhdr);
 	if (lltable_calc_llheader(ifp, AF_INET, ar_sha(ah), linkhdr,
-	    &linkhdrsize, &lladdr_off) != 0)
+	    &linkhdrsize, &lladdr_off) != 0) {
+		LLE_WUNLOCK(la);
 		return;
+	}
 
 	/* Check if something has changed */
 	if (memcmp(la->r_linkdata, linkhdr, linkhdrsize) != 0 ||
 	    (la->la_flags & LLE_VALID) == 0) {
 		/* Try to perform LLE update */
 		if (lltable_try_set_entry_addr(ifp, la, linkhdr, linkhdrsize,
-		    lladdr_off) == 0)
+		    lladdr_off) == 0) {
+			LLE_WUNLOCK(la);
 			return;
+		}
 
 		/* Clear fast path feedback request if set */
 		llentry_mark_used(la);
diff --git a/sys/netinet6/nd6_nbr.c b/sys/netinet6/nd6_nbr.c
index 0c6dd9e0361f..3a56964f8eb3 100644
--- a/sys/netinet6/nd6_nbr.c
+++ b/sys/netinet6/nd6_nbr.c
@@ -855,10 +855,8 @@ nd6_na_input(struct mbuf *m, int off, int icmp6len)
 				    linkhdr, &linkhdrsize, &lladdr_off) != 0)
 					goto freeit;
 				if (lltable_try_set_entry_addr(ifp, ln, linkhdr,
-				    linkhdrsize, lladdr_off) == 0) {
-					ln = NULL;
+				    linkhdrsize, lladdr_off) == 0)
 					goto freeit;
-				}
 				EVENTHANDLER_INVOKE(lle_event, ln,
 				    LLENTRY_RESOLVED);
 			}