From owner-dev-commits-src-all@freebsd.org Tue Mar 2 12:56:04 2021 Return-Path: Delivered-To: dev-commits-src-all@mailman.nyi.freebsd.org Received: from mx1.freebsd.org (mx1.freebsd.org [IPv6:2610:1c1:1:606c::19:1]) by mailman.nyi.freebsd.org (Postfix) with ESMTP id A3E81568C35; Tue, 2 Mar 2021 12:56:04 +0000 (UTC) (envelope-from git@FreeBSD.org) Received: from mxrelay.nyi.freebsd.org (mxrelay.nyi.freebsd.org [IPv6:2610:1c1:1:606c::19:3]) (using TLSv1.3 with cipher TLS_AES_256_GCM_SHA384 (256/256 bits) key-exchange X25519 server-signature RSA-PSS (4096 bits) server-digest SHA256 client-signature RSA-PSS (4096 bits) client-digest SHA256) (Client CN "mxrelay.nyi.freebsd.org", Issuer "R3" (verified OK)) by mx1.freebsd.org (Postfix) with ESMTPS id 4DqcZD4FKQz3rJj; Tue, 2 Mar 2021 12:56:04 +0000 (UTC) (envelope-from git@FreeBSD.org) Received: from gitrepo.freebsd.org (gitrepo.freebsd.org [IPv6:2610:1c1:1:6068::e6a:5]) (using TLSv1.3 with cipher TLS_AES_256_GCM_SHA384 (256/256 bits) key-exchange X25519 server-signature RSA-PSS (4096 bits) server-digest SHA256) (Client did not present a certificate) by mxrelay.nyi.freebsd.org (Postfix) with ESMTPS id 8469D17229; Tue, 2 Mar 2021 12:56:04 +0000 (UTC) (envelope-from git@FreeBSD.org) Received: from gitrepo.freebsd.org ([127.0.1.44]) by gitrepo.freebsd.org (8.16.1/8.16.1) with ESMTP id 122Cu4ge051914; Tue, 2 Mar 2021 12:56:04 GMT (envelope-from git@gitrepo.freebsd.org) Received: (from git@localhost) by gitrepo.freebsd.org (8.16.1/8.16.1/Submit) id 122Cu45Z051913; Tue, 2 Mar 2021 12:56:04 GMT (envelope-from git) Date: Tue, 2 Mar 2021 12:56:04 GMT Message-Id: <202103021256.122Cu45Z051913@gitrepo.freebsd.org> To: src-committers@FreeBSD.org, dev-commits-src-all@FreeBSD.org, dev-commits-src-branches@FreeBSD.org From: Michael Tuexen Subject: git: 8cf046aff971 - stable/13 - sctp: improve computation of an alternate net MIME-Version: 1.0 Content-Type: text/plain; charset=utf-8 Content-Transfer-Encoding: 8bit X-Git-Committer: tuexen X-Git-Repository: src X-Git-Refname: refs/heads/stable/13 X-Git-Reftype: branch X-Git-Commit: 8cf046aff9719779b665f7f4f4a8bad4b3945341 Auto-Submitted: auto-generated X-BeenThere: dev-commits-src-all@freebsd.org X-Mailman-Version: 2.1.34 Precedence: list List-Id: Commit messages for all branches of the src repository List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , X-List-Received-Date: Tue, 02 Mar 2021 12:56:04 -0000 The branch stable/13 has been updated by tuexen: URL: https://cgit.FreeBSD.org/src/commit/?id=8cf046aff9719779b665f7f4f4a8bad4b3945341 commit 8cf046aff9719779b665f7f4f4a8bad4b3945341 Author: Michael Tuexen AuthorDate: 2021-02-21 16:13:06 +0000 Commit: Michael Tuexen CommitDate: 2021-03-02 12:32:21 +0000 sctp: improve computation of an alternate net Espeially handle the case where the net passed in is about to be deleted and therefore not in the list of nets anymore. Reported by: syzbot+9756917a7c8381adf5e8@syzkaller.appspotmail.com (cherry picked from commit b963ce4588b33f733aef3f7a7f3fbe5018a89728) --- sys/netinet/sctp_timer.c | 85 ++++++++++++++++++++++++++++-------------------- 1 file changed, 49 insertions(+), 36 deletions(-) diff --git a/sys/netinet/sctp_timer.c b/sys/netinet/sctp_timer.c index bce1f5cd166d..582abd8e8854 100644 --- a/sys/netinet/sctp_timer.c +++ b/sys/netinet/sctp_timer.c @@ -164,8 +164,8 @@ sctp_threshold_management(struct sctp_inpcb *inp, struct sctp_tcb *stcb, } /* - * sctp_find_alternate_net() returns a non-NULL pointer as long - * the argument net is non-NULL. + * sctp_find_alternate_net() returns a non-NULL pointer as long as there + * exists nets, which are not being deleted. */ struct sctp_nets * sctp_find_alternate_net(struct sctp_tcb *stcb, @@ -174,14 +174,14 @@ sctp_find_alternate_net(struct sctp_tcb *stcb, { /* Find and return an alternate network if possible */ struct sctp_nets *alt, *mnet, *min_errors_net = NULL, *max_cwnd_net = NULL; - int once; + bool looped; /* JRS 5/14/07 - Initialize min_errors to an impossible value. */ int min_errors = -1; uint32_t max_cwnd = 0; if (stcb->asoc.numnets == 1) { - /* No others but net */ + /* No selection can be made. */ return (TAILQ_FIRST(&stcb->asoc.nets)); } /* @@ -328,25 +328,22 @@ sctp_find_alternate_net(struct sctp_tcb *stcb, return (max_cwnd_net); } } - mnet = net; - once = 0; - - if (mnet == NULL) { - mnet = TAILQ_FIRST(&stcb->asoc.nets); - if (mnet == NULL) { - return (NULL); - } + /* Look for an alternate net, which is active. */ + if ((net != NULL) && ((net->dest_state & SCTP_ADDR_BEING_DELETED) == 0)) { + alt = TAILQ_NEXT(net, sctp_next);; + } else { + alt = TAILQ_FIRST(&stcb->asoc.nets); } + looped = false; for (;;) { - alt = TAILQ_NEXT(mnet, sctp_next); if (alt == NULL) { - once++; - if (once > 1) { - break; + if (!looped) { + alt = TAILQ_FIRST(&stcb->asoc.nets); + looped = true; } - alt = TAILQ_FIRST(&stcb->asoc.nets); + /* Definitely out of candidates. */ if (alt == NULL) { - return (NULL); + break; } } if (alt->ro.ro_nh == NULL) { @@ -358,43 +355,59 @@ sctp_find_alternate_net(struct sctp_tcb *stcb, } if (((alt->dest_state & SCTP_ADDR_REACHABLE) == SCTP_ADDR_REACHABLE) && (alt->ro.ro_nh != NULL) && - (!(alt->dest_state & SCTP_ADDR_UNCONFIRMED))) { - /* Found a reachable address */ + (!(alt->dest_state & SCTP_ADDR_UNCONFIRMED)) && + (alt != net)) { + /* Found an alternate net, which is reachable. */ break; } - mnet = alt; + alt = TAILQ_NEXT(alt, sctp_next); } if (alt == NULL) { - /* Case where NO insv network exists (dormant state) */ - /* we rotate destinations */ - once = 0; - mnet = net; + /* + * In case no active alternate net has been found, look for + * an alternate net, which is confirmed. + */ + if ((net != NULL) && ((net->dest_state & SCTP_ADDR_BEING_DELETED) == 0)) { + alt = TAILQ_NEXT(net, sctp_next);; + } else { + alt = TAILQ_FIRST(&stcb->asoc.nets); + } + looped = false; for (;;) { - if (mnet == NULL) { - return (TAILQ_FIRST(&stcb->asoc.nets)); - } - alt = TAILQ_NEXT(mnet, sctp_next); if (alt == NULL) { - once++; - if (once > 1) { - break; + if (!looped) { + alt = TAILQ_FIRST(&stcb->asoc.nets); + looped = true; } - alt = TAILQ_FIRST(&stcb->asoc.nets); + /* Definitely out of candidates. */ if (alt == NULL) { break; } } if ((!(alt->dest_state & SCTP_ADDR_UNCONFIRMED)) && (alt != net)) { - /* Found an alternate address */ + /* + * Found an alternate net, which is + * confirmed. + */ break; } - mnet = alt; + alt = TAILQ_NEXT(alt, sctp_next); } } if (alt == NULL) { - return (net); + /* + * In case no confirmed alternate net has been found, just + * return net, if it is not being deleted. In the other case + * just return the first net. + */ + if ((net != NULL) && ((net->dest_state & SCTP_ADDR_BEING_DELETED) == 0)) { + alt = net; + } + if (alt == NULL) { + alt = TAILQ_FIRST(&stcb->asoc.nets); + } } return (alt); }