From nobody Fri May 27 16:37:17 2022 X-Original-To: dev-commits-src-all@mlmmj.nyi.freebsd.org Received: from mx1.freebsd.org (mx1.freebsd.org [IPv6:2610:1c1:1:606c::19:1]) by mlmmj.nyi.freebsd.org (Postfix) with ESMTP id 3BEDC1B52FA4; Fri, 27 May 2022 16:37:18 +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 4L8r7L17b5z3vJp; Fri, 27 May 2022 16:37:18 +0000 (UTC) (envelope-from git@FreeBSD.org) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=freebsd.org; s=dkim; t=1653669438; h=from:from:reply-to:subject:subject:date:date:message-id:message-id: to:to:cc:mime-version:mime-version:content-type:content-type: content-transfer-encoding:content-transfer-encoding; bh=rHsL7fqqkcmWEe5uORIeFOokUIsRQiF1zx1e6lRE1b0=; b=sJqtkPvQBeGk4xwjg9GlI8iozv0xsFbDsZOTEYKUVvi+OlgbOjRq/L9NhWWNdDH3oNPUUW FSjgfdmSyHQidPaHgArUvwZCUq+ER2jSfoa+3Vp4NMxSMlX7E7meZJTn6IyRb9YeEjeZgs /mZMasqijzp47U9oztWPwI52IWoOama+j/8ZtDJZc/fZZfIDGUnFTPCQwGVgMr8OJ1HCW6 54v9W9EQEzX/MPKcTSZnxWYSi3l4/PTAigh23cbSDZ7lUEhy9vP2+dF8H6JmxnoSyJexsm II6hJ4g/GJ8wIM5QL4e3/4IuRfDsdACtcU0TizN+VS+ErMRg4e/gBuciqaTdjw== 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 068D225D93; Fri, 27 May 2022 16:37:18 +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 24RGbHg7010236; Fri, 27 May 2022 16:37:17 GMT (envelope-from git@gitrepo.freebsd.org) Received: (from git@localhost) by gitrepo.freebsd.org (8.16.1/8.16.1/Submit) id 24RGbHHW010235; Fri, 27 May 2022 16:37:17 GMT (envelope-from git) Date: Fri, 27 May 2022 16:37:17 GMT Message-Id: <202205271637.24RGbHHW010235@gitrepo.freebsd.org> To: src-committers@FreeBSD.org, dev-commits-src-all@FreeBSD.org, dev-commits-src-branches@FreeBSD.org From: Kristof Provost Subject: git: 4dfd3ffc4488 - stable/13 - if: avoid interface destroy race List-Id: Commit messages for all branches of the src repository List-Archive: https://lists.freebsd.org/archives/dev-commits-src-all List-Help: List-Post: List-Subscribe: List-Unsubscribe: Sender: owner-dev-commits-src-all@freebsd.org X-BeenThere: dev-commits-src-all@freebsd.org MIME-Version: 1.0 Content-Type: text/plain; charset=utf-8 Content-Transfer-Encoding: 8bit X-Git-Committer: kp X-Git-Repository: src X-Git-Refname: refs/heads/stable/13 X-Git-Reftype: branch X-Git-Commit: 4dfd3ffc4488e5e2662cdc40deec17d82432da0b Auto-Submitted: auto-generated ARC-Message-Signature: i=1; a=rsa-sha256; c=relaxed/relaxed; d=freebsd.org; s=dkim; t=1653669438; h=from:from:reply-to:subject:subject:date:date:message-id:message-id: to:to:cc:mime-version:mime-version:content-type:content-type: content-transfer-encoding:content-transfer-encoding; bh=rHsL7fqqkcmWEe5uORIeFOokUIsRQiF1zx1e6lRE1b0=; b=vI7+060FiSQg5R730se8n/W0cmYmHgI7JL8ykexr/i3N2/gmU/6ralt0kcFKxa2L12L3ti NqqcrEcE1tn0w/aD3RnQRUlkxFku6JwdsBDPGhIffMzFK+NoRBvupFsNgrfOAoiftgAI4L 3WFNl7Bm84Xfl7vyy21nOQnLld9CJ+9QdMavJs5/Je97WWBm/u83qxVCrxnlcC4zH2esKw JLeVlPgyjFwqqChQR/D7Q8oLPR86aHjkfBt4ALzlNervtlR3Lk6GS4c6g2AGoIZZKiuPf9 6whDOjuaA+155LpwEy6YVzBOp/sg7942yRf80A4UEQu0mXpMHz/mrbQvTGkk9w== ARC-Seal: i=1; s=dkim; d=freebsd.org; t=1653669438; a=rsa-sha256; cv=none; b=PLh0v2NqZMH4un4/G2VOqCqXTUp/zjR5jxKxe24vq1fDnjzG0Ar3y9+Huc/veWnfdtrQuM O8W8wNQcOe9eWFNmNYaoUnKbYGw/NdZYjCgnq4yoW6OPrftV27BSu6Nxk75EO9NxUZgI+s Qy6KtN1JqyJ0QqLWyv0oaDjh6WW5T3CYQPobiTCgvQlrmSEBHiyse+rwctqb3yxlQJysMl R59xJeTaS5KPsZDuWSWb16XtBISDpZGIB/QUGjpIq1z8SQX7WjzP36Ntz5iSnBvCtC//C7 oGvWmi+Kvhc5PlPsuiYK5HeAhbX0bJiZYrIo3g3KNMgoiwE//hZbkl5zCpLLMA== ARC-Authentication-Results: i=1; mx1.freebsd.org; none X-ThisMailContainsUnwantedMimeParts: N The branch stable/13 has been updated by kp: URL: https://cgit.FreeBSD.org/src/commit/?id=4dfd3ffc4488e5e2662cdc40deec17d82432da0b commit 4dfd3ffc4488e5e2662cdc40deec17d82432da0b Author: Kristof Provost AuthorDate: 2022-03-27 18:23:25 +0000 Commit: Kristof Provost CommitDate: 2022-05-27 16:25:10 +0000 if: avoid interface destroy race When we destroy an interface while the jail containing it is being destroyed we risk seeing a race between if_vmove() and the destruction code, which results in us trying to move a destroyed interface. Protect against this by using the ifnet_detach_sxlock to also covert if_vmove() (and not just detach). PR: 262829 MFC after: 3 weeks Differential Revision: https://reviews.freebsd.org/D34704 (cherry picked from commit 868bf82153e8ff22f09a8860c872149e0fb6bdef) --- sys/net/if.c | 22 ++++++++++++++++++++-- tests/sys/net/if_clone_test.sh | 29 +++++++++++++++++++++++++++++ 2 files changed, 49 insertions(+), 2 deletions(-) diff --git a/sys/net/if.c b/sys/net/if.c index d4871ccbc1f7..091e9e64b99f 100644 --- a/sys/net/if.c +++ b/sys/net/if.c @@ -548,7 +548,9 @@ vnet_if_return(const void *unused __unused) IFNET_WUNLOCK(); for (int j = 0; j < i; j++) { + sx_xlock(&ifnet_detach_sxlock); if_vmove(pending[j], pending[j]->if_home_vnet); + sx_xunlock(&ifnet_detach_sxlock); } free(pending, M_IFNET); @@ -1393,6 +1395,8 @@ if_vmove_loan(struct thread *td, struct ifnet *ifp, char *ifname, int jid) bool found; bool shutdown; + MPASS(ifindex_table[ifp->if_index].ife_ifnet == ifp); + /* Try to find the prison within our visibility. */ sx_slock(&allprison_lock); pr = prison_find_child(td->td_ucred->cr_prison, jid); @@ -1417,10 +1421,12 @@ if_vmove_loan(struct thread *td, struct ifnet *ifp, char *ifname, int jid) prison_free(pr); return (EEXIST); } + sx_xlock(&ifnet_detach_sxlock); /* Make sure the VNET is stable. */ shutdown = VNET_IS_SHUTTING_DOWN(ifp->if_vnet); if (shutdown) { + sx_xunlock(&ifnet_detach_sxlock); CURVNET_RESTORE(); prison_free(pr); return (EBUSY); @@ -1428,7 +1434,12 @@ if_vmove_loan(struct thread *td, struct ifnet *ifp, char *ifname, int jid) CURVNET_RESTORE(); found = if_unlink_ifnet(ifp, true); - MPASS(found); + if (! found) { + sx_xunlock(&ifnet_detach_sxlock); + CURVNET_RESTORE(); + prison_free(pr); + return (ENODEV); + } /* Move the interface into the child jail/vnet. */ error = if_vmove(ifp, pr->pr_vnet); @@ -1437,6 +1448,8 @@ if_vmove_loan(struct thread *td, struct ifnet *ifp, char *ifname, int jid) if (error == 0) sprintf(ifname, "%s", ifp->if_xname); + sx_xunlock(&ifnet_detach_sxlock); + prison_free(pr); return (error); } @@ -1487,7 +1500,9 @@ if_vmove_reclaim(struct thread *td, char *ifname, int jid) /* Get interface back from child jail/vnet. */ found = if_unlink_ifnet(ifp, true); MPASS(found); + sx_xlock(&ifnet_detach_sxlock); error = if_vmove(ifp, vnet_dst); + sx_xunlock(&ifnet_detach_sxlock); CURVNET_RESTORE(); /* Report the new if_xname back to the userland on success. */ @@ -2397,8 +2412,11 @@ ifunit_ref(const char *name) !(ifp->if_flags & IFF_DYING)) break; } - if (ifp != NULL) + if (ifp != NULL) { if_ref(ifp); + MPASS(ifindex_table[ifp->if_index].ife_ifnet == ifp); + } + NET_EPOCH_EXIT(et); return (ifp); } diff --git a/tests/sys/net/if_clone_test.sh b/tests/sys/net/if_clone_test.sh index 0b50d741814f..60483a2da334 100755 --- a/tests/sys/net/if_clone_test.sh +++ b/tests/sys/net/if_clone_test.sh @@ -69,6 +69,34 @@ epair_up_stress_cleanup() cleanup_ifaces } +atf_test_case epair_destroy_race cleanup +epair_destroy_race_head() +{ + atf_set "descr" "Race if_detach() and if_vmove()" + atf_set "require.user" "root" +} +epair_destroy_race_body() +{ + for i in `seq 1 10` + do + epair_a=$(ifconfig epair create) + echo $epair_a >> devices_to_cleanup + epair_b=${epair_a%a}b + + jail -c vnet name="epair_destroy" nopersist path=/ \ + host.hostname="epair_destroy" vnet.interface="$epair_b" \ + command=sh -c "ifconfig $epair_b 192.0.2.1/24; sleep 0.1"& + pid=$! + ifconfig "$epair_a" destroy + wait $pid + done + true +} +epair_destroy_race_cleanup() +{ + cleanup_ifaces +} + atf_test_case epair_ipv6_up_stress cleanup epair_ipv6_up_stress_head() { @@ -405,6 +433,7 @@ atf_init_test_cases() atf_add_test_case epair_ipv6_up_stress atf_add_test_case epair_stress atf_add_test_case epair_up_stress + atf_add_test_case epair_destroy_race atf_add_test_case faith_ipv6_up_stress atf_add_test_case faith_stress atf_add_test_case faith_up_stress