The branch main has been updated by kp: URL: https://cgit.FreeBSD.org/src/commit/?id=ae2ca32781a90abe987e128ca167ab400a87f369
commit ae2ca32781a90abe987e128ca167ab400a87f369 Author: R. Christian McDonald <[email protected]> AuthorDate: 2023-10-23 11:23:55 +0000 Commit: Kristof Provost <[email protected]> CommitDate: 2023-10-23 14:24:51 +0000 netlink: fix potential llentry lock leak in newneigh handler The netlink newneigh handler has the potential to leak the lock on llentry objects in the kernel. This patch reconciles several paths through the newneigh handler that could result in a lock leak. MFC after: 1 week Reviewed by: markj, kp Sponsored by: Rubicon Communications, LLC ("Netgate") Differential Revision: https://reviews.freebsd.org/D42307 --- sys/netlink/route/neigh.c | 22 ++++++++++------------ 1 file changed, 10 insertions(+), 12 deletions(-) diff --git a/sys/netlink/route/neigh.c b/sys/netlink/route/neigh.c index 9914e7febf57..5be0c1f9d91f 100644 --- a/sys/netlink/route/neigh.c +++ b/sys/netlink/route/neigh.c @@ -436,17 +436,18 @@ rtnl_handle_newneigh(struct nlmsghdr *hdr, struct nlpcb *nlp, struct nl_pstate * struct llentry *lle_tmp = lla_lookup(llt, LLE_EXCLUSIVE, attrs.nda_dst); if (lle_tmp != NULL) { error = EEXIST; - if (hdr->nlmsg_flags & NLM_F_EXCL) { - LLE_WUNLOCK(lle_tmp); - lle_tmp = NULL; - } else if (hdr->nlmsg_flags & NLM_F_REPLACE) { + if (hdr->nlmsg_flags & NLM_F_REPLACE) { + error = EPERM; if ((lle_tmp->la_flags & LLE_IFADDR) == 0) { + error = 0; /* success */ lltable_unlink_entry(llt, lle_tmp); + llentry_free(lle_tmp); + lle_tmp = NULL; lltable_link_entry(llt, lle); - error = 0; - } else - error = EPERM; + } } + if (lle_tmp) + LLE_WUNLOCK(lle_tmp); } else { if (hdr->nlmsg_flags & NLM_F_CREATE) lltable_link_entry(llt, lle); @@ -456,14 +457,11 @@ rtnl_handle_newneigh(struct nlmsghdr *hdr, struct nlpcb *nlp, struct nl_pstate * IF_AFDATA_WUNLOCK(attrs.nda_ifp); if (error != 0) { - if (lle != NULL) - llentry_free(lle); + /* throw away the newly allocated llentry */ + llentry_free(lle); return (error); } - if (lle_tmp != NULL) - llentry_free(lle_tmp); - /* XXX: We're inside epoch */ EVENTHANDLER_INVOKE(lle_event, lle, LLENTRY_RESOLVED); LLE_WUNLOCK(lle);
