diff options
author | Mark Johnston <markj@FreeBSD.org> | 2022-04-08 15:47:25 +0000 |
---|---|---|
committer | Mark Johnston <markj@FreeBSD.org> | 2022-04-15 14:21:20 +0000 |
commit | 421c2f93a4e03da9c6ed36913916b15c170949e6 (patch) | |
tree | 911b336259c16bd1df96d7f5b64e66cf884f481b | |
parent | 8b01c3026b78152d9e0ca6f3758ea226f32e48b9 (diff) |
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
Sponsored by: The FreeBSD Foundation
(cherry picked from commit 990a6d18b0cb1eee9e18a4220150d549b9bee753)
-rw-r--r-- | sys/net/if_llatbl.c | 4 | ||||
-rw-r--r-- | sys/netinet/in.c | 2 | ||||
-rw-r--r-- | sys/netinet6/in6.c | 2 | ||||
-rw-r--r-- | 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 2303a8f10aa4..92b9c229ea5b 100644 --- a/sys/netinet/in.c +++ b/sys/netinet/in.c @@ -1554,7 +1554,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 41b05ae2ca53..b0a8c1608b6c 100644 --- a/sys/netinet6/in6.c +++ b/sys/netinet6/in6.c @@ -2304,7 +2304,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); } |