git: 0ea32f0e8376 - stable/13 - inpcb: Remove a PCB from its LB group upon a subsequent error

From: Mark Johnston <markj_at_FreeBSD.org>
Date: Mon, 22 Jan 2024 18:45:26 UTC
The branch stable/13 has been updated by markj:

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

commit 0ea32f0e83769ca1c6ebc40fb0a3a0e64a24e7a0
Author:     Mark Johnston <markj@FreeBSD.org>
AuthorDate: 2022-11-02 17:05:14 +0000
Commit:     Mark Johnston <markj@FreeBSD.org>
CommitDate: 2024-01-22 18:45:03 +0000

    inpcb: Remove a PCB from its LB group upon a subsequent error
    
    If a memory allocation failure causes bind to fail, we should take the
    inpcb back out of its LB group since it's not prepared to handle
    connections.
    
    Reviewed by:    glebius
    MFC after:      2 weeks
    Sponsored by:   Modirum MDPay
    Sponsored by:   Klara, Inc.
    Differential Revision:  https://reviews.freebsd.org/D37027
    
    (cherry picked from commit a152dd863418638c3eb08b5c101b10b82f8072f5)
---
 sys/netinet/in_pcb.c | 17 ++++++++---------
 1 file changed, 8 insertions(+), 9 deletions(-)

diff --git a/sys/netinet/in_pcb.c b/sys/netinet/in_pcb.c
index 3f4ad6752aae..3f8db305d3c9 100644
--- a/sys/netinet/in_pcb.c
+++ b/sys/netinet/in_pcb.c
@@ -2646,7 +2646,6 @@ in_pcbinshash_internal(struct inpcb *inp, struct mbuf *m)
 	struct inpcbinfo *pcbinfo = inp->inp_pcbinfo;
 	struct inpcbport *phd;
 	u_int32_t hashkey_faddr;
-	int so_options;
 
 	INP_WLOCK_ASSERT(inp);
 	INP_HASH_WLOCK_ASSERT(pcbinfo);
@@ -2671,13 +2670,10 @@ in_pcbinshash_internal(struct inpcb *inp, struct mbuf *m)
 	 * Add entry to load balance group.
 	 * Only do this if SO_REUSEPORT_LB is set.
 	 */
-	so_options = inp_so_options(inp);
-	if (so_options & SO_REUSEPORT_LB) {
-		int ret = in_pcbinslbgrouphash(inp, M_NODOM);
-		if (ret) {
-			/* pcb lb group malloc fail (ret=ENOBUFS). */
-			return (ret);
-		}
+	if ((inp->inp_flags2 & INP_REUSEPORT_LB) != 0) {
+		int error = in_pcbinslbgrouphash(inp, M_NODOM);
+		if (error != 0)
+			return (error);
 	}
 
 	/*
@@ -2687,13 +2683,16 @@ in_pcbinshash_internal(struct inpcb *inp, struct mbuf *m)
 		if (phd->phd_port == inp->inp_lport)
 			break;
 	}
+
 	/*
 	 * If none exists, malloc one and tack it on.
 	 */
 	if (phd == NULL) {
 		phd = malloc(sizeof(struct inpcbport), M_PCB, M_NOWAIT);
 		if (phd == NULL) {
-			return (ENOBUFS); /* XXX */
+			if ((inp->inp_flags2 & INP_REUSEPORT_LB) != 0)
+				in_pcbremlbgrouphash(inp);
+			return (ENOMEM);
 		}
 		bzero(&phd->phd_epoch_ctx, sizeof(struct epoch_context));
 		phd->phd_port = inp->inp_lport;