git: 990a6d18b0cb - main - net: Fix memory leaks in lltable_calc_llheader() error paths

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

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

commit 990a6d18b0cb1eee9e18a4220150d549b9bee753
Author:     Mark Johnston <markj@FreeBSD.org>
AuthorDate: 2022-04-08 15:47:25 +0000
Commit:     Mark Johnston <markj@FreeBSD.org>
CommitDate: 2022-04-08 15:47:25 +0000

    net: Fix memory leaks in lltable_calc_llheader() error paths
    
    Also convert raw epoch_call() calls to lltable_free_entry() calls, no
    functional change intended.  There's no need to asynchronously free the
    LLEs in that case to begin with, but we might as well use the lltable
    interfaces consistently.
    
    Noticed by code inspection; I believe lltable_calc_llheader() failures
    do not generally happen in practice.
    
    Reviewed by:    bz
    MFC after:      1 week
    Sponsored by:   The FreeBSD Foundation
    Differential Revision:  https://reviews.freebsd.org/D34832
---
 sys/net/if_llatbl.c | 4 +++-
 sys/netinet/in.c    | 2 +-
 sys/netinet6/in6.c  | 2 +-
 sys/netinet6/nd6.c  | 4 +++-
 4 files changed, 8 insertions(+), 4 deletions(-)

diff --git a/sys/net/if_llatbl.c b/sys/net/if_llatbl.c
index b82bc9fc104c..d2fb58974d3f 100644
--- a/sys/net/if_llatbl.c
+++ b/sys/net/if_llatbl.c
@@ -926,8 +926,10 @@ lla_rt_output(struct rt_msghdr *rtm, struct rt_addrinfo *info)
 
 		linkhdrsize = sizeof(linkhdr);
 		if (lltable_calc_llheader(ifp, dst->sa_family, LLADDR(dl),
-		    linkhdr, &linkhdrsize, &lladdr_off) != 0)
+		    linkhdr, &linkhdrsize, &lladdr_off) != 0) {
+			lltable_free_entry(llt, lle);
 			return (EINVAL);
+		}
 		lltable_set_entry_addr(ifp, lle, linkhdr, linkhdrsize,
 		    lladdr_off);
 		if ((rtm->rtm_flags & RTF_ANNOUNCE))
diff --git a/sys/netinet/in.c b/sys/netinet/in.c
index a504f54a026e..e427b9e92db3 100644
--- a/sys/netinet/in.c
+++ b/sys/netinet/in.c
@@ -1563,7 +1563,7 @@ in_lltable_alloc(struct lltable *llt, u_int flags, const struct sockaddr *l3addr
 		linkhdrsize = LLE_MAX_LINKHDR;
 		if (lltable_calc_llheader(ifp, AF_INET, IF_LLADDR(ifp),
 		    linkhdr, &linkhdrsize, &lladdr_off) != 0) {
-			NET_EPOCH_CALL(in_lltable_destroy_lle_unlocked, &lle->lle_epoch_ctx);
+			in_lltable_free_entry(llt, lle);
 			return (NULL);
 		}
 		lltable_set_entry_addr(ifp, lle, linkhdr, linkhdrsize,
diff --git a/sys/netinet6/in6.c b/sys/netinet6/in6.c
index 3c03c2996d9b..c273d74b565c 100644
--- a/sys/netinet6/in6.c
+++ b/sys/netinet6/in6.c
@@ -2325,7 +2325,7 @@ in6_lltable_alloc(struct lltable *llt, u_int flags,
 		linkhdrsize = LLE_MAX_LINKHDR;
 		if (lltable_calc_llheader(ifp, AF_INET6, IF_LLADDR(ifp),
 		    linkhdr, &linkhdrsize, &lladdr_off) != 0) {
-			NET_EPOCH_CALL(in6_lltable_destroy_lle_unlocked, &lle->lle_epoch_ctx);
+			in6_lltable_free_entry(llt, lle);
 			return (NULL);
 		}
 		lltable_set_entry_addr(ifp, lle, linkhdr, linkhdrsize,
diff --git a/sys/netinet6/nd6.c b/sys/netinet6/nd6.c
index 6a9e2a4fdd7c..69da61aa9c5c 100644
--- a/sys/netinet6/nd6.c
+++ b/sys/netinet6/nd6.c
@@ -2036,8 +2036,10 @@ nd6_cache_lladdr(struct ifnet *ifp, struct in6_addr *from, char *lladdr,
 		if (lladdr != NULL) {
 			linkhdrsize = sizeof(linkhdr);
 			if (lltable_calc_llheader(ifp, AF_INET6, lladdr,
-			    linkhdr, &linkhdrsize, &lladdr_off) != 0)
+			    linkhdr, &linkhdrsize, &lladdr_off) != 0) {
+				lltable_free_entry(LLTABLE6(ifp), ln);
 				return;
+			}
 			lltable_set_entry_addr(ifp, ln, linkhdr, linkhdrsize,
 			    lladdr_off);
 		}