From nobody Thu Sep 24 17:02:13 2026 Received: from mail-oi2-f26.google.com (mail-oi2-f26.google.com [74.125.231.218]) (using TLSv1.2 with cipher ECDHE-RSA-AES128-GCM-SHA256 (128/128 bits)) (No client certificate requested) by smtp.subspace.kernel.org (Postfix) with ESMTPS id 902B537269A for ; Tue, 22 Sep 2026 01:18:22 +0000 (UTC) Authentication-Results: smtp.subspace.kernel.org; arc=none smtp.client-ip=74.125.231.218 ARC-Seal: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1790039904; cv=none; b=fJRf+vvgPNvoEkX9ap77LMjDG6AiRw0Uq7IUlv1dt4q3cGckTxlmFioWppVMpyYy+qS4wD37T7T4h/4uf+pz+iZ5f56kg6heulnZ6vhN7KPLRacLL1MMn4cq7HTTiqvHFcDYQz1uqQ25I4uPjHgp3yOB1ASykIy9/Wiz7NIgq+I= ARC-Message-Signature: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1790039904; c=relaxed/simple; bh=cS9vNKu7FK5uQuQp6x72bj2FugS7mq6eGvzVjip2oIs=; h=From:Date:Subject:MIME-Version:Content-Type:Message-Id:References: In-Reply-To:To:Cc; b=lePtGMojhhell2PPesgAyx7c79fpZGTdhbEhtY3/e7Rda5eRx6yKI6V6b9MRaiM2xo42y8/pG0uqqSYYH6Bs8BiDZNkH/OTkVA4iwqPatj8mLfrtsuoODeqyjK31LLMD2+g1VI0v21IeWv69zdkmfMg1f0nlFJTEugnkGRfjqN0= ARC-Authentication-Results: i=1; smtp.subspace.kernel.org; dmarc=pass (p=none dis=none) header.from=gmail.com; spf=pass smtp.mailfrom=gmail.com; dkim=pass (2048-bit key) header.d=gmail.com header.i=@gmail.com header.b=XAgYGnV8; arc=none smtp.client-ip=74.125.231.218 Authentication-Results: smtp.subspace.kernel.org; dmarc=pass (p=none dis=none) header.from=gmail.com Authentication-Results: smtp.subspace.kernel.org; spf=pass smtp.mailfrom=gmail.com Authentication-Results: smtp.subspace.kernel.org; dkim=pass (2048-bit key) header.d=gmail.com header.i=@gmail.com header.b="XAgYGnV8" Received: by mail-oi2-f26.google.com with SMTP id 46e09a7af769-80a18990c76so2573905a34.2 for ; Mon, 21 Sep 2026 18:18:22 -0700 (PDT) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=gmail.com; s=20251104; t=1790039901; x=1790644701; darn=vger.kernel.org; h=cc:to:in-reply-to:references:message-id:content-transfer-encoding :content-type:mime-version:subject:date:from:from:to:cc:subject:date :message-id:reply-to:content-type; bh=eOcxxxCAKSQioxaCmq9VVEr3ww8ELRw40nRpvvXToPE=; b=XAgYGnV83DZzPD98Sv48z1rn5c9hysvhHdi0L0zfgjlCntlPiV1WEvsP+DdJ9SjFKd PKQly6wMCabbqzajOQzf3CWWfs9ZEnVDHRz86TmCr53Jrcqr7ry7uCWUX/azcupUPaTZ MhNb4WC7pVNjP2+7ZRJM17BnGIRRihfjincD38po/XttMVLFLJfgQaDOZgdERcJMswSi yHGrQuJX1zkgfDmzL5EBYWlJNwQMt1SZ+KKjw2XZw9rLxrWwUC/zZ2oOoc2Hl0asLS1L XtxPVegOuZrxcZZfsNvM/uhuSuVMZin5bhxdo05uzs4c3umbGXZh1Cwv13Yv15YWu1xI ddiw== X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20260707; t=1790039901; x=1790644701; h=cc:to:in-reply-to:references:message-id:content-transfer-encoding :content-type:mime-version:subject:date:from:x-gm-gg :x-gm-message-state:from:to:cc:subject:date:message-id:reply-to :content-type; bh=eOcxxxCAKSQioxaCmq9VVEr3ww8ELRw40nRpvvXToPE=; b=deAtqxAISbSWLtjMut0e6Mt9LBCyUefRm7/uIFJaLrJ42/mm7W8785zQt/K8vEz1Ad dKfnW1q7oZ5Jkv9/gcBKnE2bTUJWtHRt1otEbVSHeK7OgWU7m3BxeBn6ujuOMv9l1vLx cvO/+dMKqYr6eXrgVYN++qhRCK1klb7IveKDzZxGhPTOBGdzgovO51bw96Nhp+QvH4qs 2QaiOjIb2DG8ZPg7F1XVbdhy5gR+kx+i0SNx/61g2WUzCVV/O01jHyFcpYW627vadVY6 xg89v2rotuJMJ81bOJy2dMMmCfUQgMZJeOvPL/8604mzIi9lYOcmI+dB41+qwTd56Mnt XobQ== X-Forwarded-Encrypted: i=1; AKwUvBwbmhWoEhjgoxmP4xs704HfscUM4CQaNshf460QKJhHbeXMjn2zDMaPCdpoWijJ6A6Vl8/HbebeN4nkmHI=@vger.kernel.org X-Gm-Message-State: AFuF++k91CeUrW0Ju/LvPVA6U5KWfW+oCBjpBiphO7wLonIEthtGHDwW 4K9Yap0Vs/sQcMgsMGyjwJzsgeq/a9DVO/oHLIwGc+GvnSkPJYQGZfvu X-Gm-Gg: AYBFou1XPqcMxn8BAeX+doqjs0MSnEA0p+r2CYJeicfrjroBzOeDDXHBLaJT6VVEqag wn6h20fkIUnqAJxkGUOGqLQOkfaDERndB9zgJmElV8Gyi/0iB9DH4Jmrewl7+VX1VPK2g5IO39G I8wQjOfXggZCi4MWDkOhneDIRDNMGzP5kkVLHbQWRGyxKfD0Rth30nS0YdovrvY5vmJO3iZ/G96 paTwwlXqyiKcvjU9mAJUwLcA1ql8awLLewlVFw9U+9BGUjm/JKUCsrFeVyhk+3KCweaIq2ToxOX 2sqy0qv0fJZ21rxEcLCk8IB4xFXTnlOEi0HbQ0aLBa2tBk+0pE8B2ImXhL4nCwZer3lEA8gm+Ek LpGZZ/DC5oAV+4ma5w/Jv28P1rSDrURP2MdHL3MqweMDAsAZ50kPtjlAm1s1gIdHFseLOcEdQ/q 9GyO3gu1i0hU+ZeX4GTzZF7MELeD7KIbnB5Q054TkjOR7Q0u1Ex49E/U3G6AH5tLkZFNk= X-Received: by 2002:a05:6830:4905:b0:7e6:d384:459e with SMTP id 46e09a7af769-80ddff5b5f6mr12954905a34.3.1790039901424; Mon, 21 Sep 2026 18:18:21 -0700 (PDT) Received: from localhost ([2a03:2880:ff:48::]) by smtp.gmail.com with ESMTPSA id 46e09a7af769-814e5983e4dsm608478a34.6.2026.09.21.18.18.18 (version=TLS1_3 cipher=TLS_AES_256_GCM_SHA384 bits=256/256); Mon, 21 Sep 2026 18:18:20 -0700 (PDT) From: Bobby Eshleman Date: Mon, 21 Sep 2026 18:18:04 -0700 Subject: [PATCH net-next v2 1/6] vsock: constify the transport in vsock_for_each_connected_socket() Precedence: bulk X-Mailing-List: linux-kernel@vger.kernel.org List-Id: List-Subscribe: List-Unsubscribe: MIME-Version: 1.0 Content-Type: text/plain; charset="utf-8" Content-Transfer-Encoding: quoted-printable Message-Id: <20260921-vsock-guest-ns-v2-1-693bd78fde9e@meta.com> References: <20260921-vsock-guest-ns-v2-0-693bd78fde9e@meta.com> In-Reply-To: <20260921-vsock-guest-ns-v2-0-693bd78fde9e@meta.com> To: Stefano Garzarella , "David S. Miller" , Eric Dumazet , Jakub Kicinski , Paolo Abeni , Simon Horman , Jonathan Corbet , Shuah Khan , Stefan Hajnoczi , "Michael S. Tsirkin" , Jason Wang , Xuan Zhuo , =?utf-8?q?Eugenio_P=C3=A9rez?= , Shuah Khan , Randy Dunlap , Donald Hunter Cc: virtualization@lists.linux.dev, netdev@vger.kernel.org, linux-kernel@vger.kernel.org, linux-doc@vger.kernel.org, kvm@vger.kernel.org, linux-kselftest@vger.kernel.org, sargun@sargun.me, jlinbox@meta.com, Stanislav Fomichev , Bobby Eshleman X-Mailer: b4 0.14.3 From: Bobby Eshleman Allow const transports to be passed too. The function only compares the pointer against vsk->transport, which is itself const, and never writes through it. No functional change. Reviewed-by: Stefano Garzarella Signed-off-by: Bobby Eshleman Suggested-by: Stefano Garzarella --- include/net/af_vsock.h | 2 +- net/vmw_vsock/af_vsock.c | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/include/net/af_vsock.h b/include/net/af_vsock.h index 5549298c1ec6..370fcd3ddabc 100644 --- a/include/net/af_vsock.h +++ b/include/net/af_vsock.h @@ -233,7 +233,7 @@ bool vsock_check_source(const struct vsock_sock *vsk, const struct vsock_transport *transport, const struct sockaddr_vm *src); void vsock_remove_sock(struct vsock_sock *vsk); -void vsock_for_each_connected_socket(struct vsock_transport *transport, +void vsock_for_each_connected_socket(const struct vsock_transport *transpo= rt, void (*fn)(struct sock *sk)); int vsock_assign_transport(struct vsock_sock *vsk, struct vsock_sock *psk); bool vsock_find_cid(unsigned int cid); diff --git a/net/vmw_vsock/af_vsock.c b/net/vmw_vsock/af_vsock.c index f840498b58af..8d6b705f8640 100644 --- a/net/vmw_vsock/af_vsock.c +++ b/net/vmw_vsock/af_vsock.c @@ -480,7 +480,7 @@ void vsock_remove_sock(struct vsock_sock *vsk) } EXPORT_SYMBOL_GPL(vsock_remove_sock); =20 -void vsock_for_each_connected_socket(struct vsock_transport *transport, +void vsock_for_each_connected_socket(const struct vsock_transport *transpo= rt, void (*fn)(struct sock *sk)) { int i; --=20 2.53.0-Meta From nobody Thu Sep 24 17:02:13 2026 Received: from mail-oi2-f20.google.com (mail-oi2-f20.google.com [74.125.231.212]) (using TLSv1.2 with cipher ECDHE-RSA-AES128-GCM-SHA256 (128/128 bits)) (No client certificate requested) by smtp.subspace.kernel.org (Postfix) with ESMTPS id 5C09B35B63D for ; Tue, 22 Sep 2026 01:18:25 +0000 (UTC) Authentication-Results: smtp.subspace.kernel.org; arc=none smtp.client-ip=74.125.231.212 ARC-Seal: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1790039907; cv=none; b=OVUcIze23Lqv6olbgHQimzR3wxbSP4YADlwFegBWnThCO+Wz7rNU1mjQjOvOlzFdHDbNJRDc6LFVV4gyvVE9eCr+sjMlaZWinpN2j0vevAZXJWVO1Ufva12AqTIW4IN0n4u3xER6F1Ek5UExIdTUGHCEG83loIP5iimQKXD9Ld0= ARC-Message-Signature: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1790039907; c=relaxed/simple; bh=6+1OlWggIwcOyMWnxSKHvIBN5o/ar+FZaJVwUICSkfw=; h=From:Date:Subject:MIME-Version:Content-Type:Message-Id:References: In-Reply-To:To:Cc; b=urF1urxgvWiBiz11q7Pt0SL592oveKZLCKpn+uZttBNbNrULDWPNMx+DxgW5yy7d4A21vSYAMS1me8kLuvQOLYcFtW1gNLXnQ/U6O6h1NGebNRWqpy53Muvf6KAmXgv+ZC6GF5m2sD7xN++7TcWCtTqXGUJhuoY+3F4w2iHcTY8= ARC-Authentication-Results: i=1; smtp.subspace.kernel.org; dmarc=pass (p=none dis=none) header.from=gmail.com; spf=pass smtp.mailfrom=gmail.com; dkim=pass (2048-bit key) header.d=gmail.com header.i=@gmail.com header.b=DV3egPpH; arc=none smtp.client-ip=74.125.231.212 Authentication-Results: smtp.subspace.kernel.org; dmarc=pass (p=none dis=none) header.from=gmail.com Authentication-Results: smtp.subspace.kernel.org; spf=pass smtp.mailfrom=gmail.com Authentication-Results: smtp.subspace.kernel.org; dkim=pass (2048-bit key) header.d=gmail.com header.i=@gmail.com header.b="DV3egPpH" Received: by mail-oi2-f20.google.com with SMTP id 46e09a7af769-7f4f1354076so853035a34.1 for ; Mon, 21 Sep 2026 18:18:25 -0700 (PDT) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=gmail.com; s=20251104; t=1790039904; x=1790644704; darn=vger.kernel.org; h=cc:to:in-reply-to:references:message-id:content-transfer-encoding :content-type:mime-version:subject:date:from:from:to:cc:subject:date :message-id:reply-to:content-type; bh=+uW+WsuQLmfydKrFyIa5Cn6MVzEK6YuLCP3KSD2va7w=; b=DV3egPpHCwRRtStrb6Ng0e17oLh+j0TUSCLP2o/cZ/uSxxL3AAqd/1x7wCHFUf7d5Z uUjkgcyjBgFbD+9bHtkRt0qtRkIF5Yg/kDdePwy/tCGTvf7M+jWSoofKikJ3bjtxd8LO gMwrpSEz4eaKj6OQlNyTwy+chikhpb/XnKxRS51RUXvautpNd6IpcOPDm4zz0blge43Y 1Pd+axD4a0LgfyFvgzdE2/r4Knsg364CyUTBW7fvO+nNU4Aj7PNUq6AvR0bl4qnyiS2N 5Z0jm82kt++fHjhy7fOWNsljMCHDOKPEn9g744RNLAkmVw43cC8nMjpLoMqXCXzYd2ns ndNA== X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20260707; t=1790039904; x=1790644704; h=cc:to:in-reply-to:references:message-id:content-transfer-encoding :content-type:mime-version:subject:date:from:x-gm-gg :x-gm-message-state:from:to:cc:subject:date:message-id:reply-to :content-type; bh=+uW+WsuQLmfydKrFyIa5Cn6MVzEK6YuLCP3KSD2va7w=; b=F0Xm8xWRuTVD/39EaA7NGUe14zbZr3BnHrdQC6cwVlfaHHq5f+qJys8bxdrXDdIkdY antjPNNiwvQJ/RRaHtaxZS13ECIvtdxfXetz2Yvfn39yhyqn599O9DvyXozc+dgIVAAJ 6yPMYcEfcWCGg7lq7gKGP/B8OsDzrubNM9h6uSwd5Yab1kth4Ia9kPjO+Yx+7fZcXjhc 9+oh9ZiHY4apM9DtPTxtRxBbvq+9WigOOld+86jpoWpUhfZGBA77oKQ3S0d7Kbbt5aE/ L+ICTNoDFo2wx/UPW5JXNHFiyRJhit5jWvQ9gHgeI3//U1aoWLgBJ1EhPwLpGtnnD41G 9Bfg== X-Forwarded-Encrypted: i=1; AKwUvBzAkBnQqvulCwf+Ee0TCMbIT03o+hOW8Jegkw2fEcHKcpOYVYs4ChTrT+s1TPpzYG3RSO+pVyrwJBXeA/0=@vger.kernel.org X-Gm-Message-State: AFuF++knGCK6Of3LwP087EaVwH2tkzGoSi9E/Bb/gQDIVPQC0SBS97Gn 0ia6ZSBGFkPno1zz60zS3yk148dMpfFDw4/YxPXKEONj5hVkzSy2ENuH X-Gm-Gg: AYBFou0H7m+DjJEl9cY6YE+kSeAE2H5e6oeZ3s8mN+34mODDEetUdjuOjdG6NEOTuzn suOfEtc3nyVeTRLs13sFDZ9H6qoVL/5sAnGIeERsMPupcVMZCg00hfsw8q18nBK7idJ95wqR72D XFNQ5f1bI+UGG3HIZ3pRS+joHBvuaNxfLG9D+9eU5rj5EXiQ7JVlbnlS4B6MDs6XD6jZGBClI99 ppeCYyxpAXWJHDgpRz+RKK8qUzQ9k6CNhs7EPWOrxdB1cTIsHyBm4ePIqrdJkgj6p5ZV1pj1w5y mcbgOk2nIlg7WkOcc5uuUtsv7Cpt652L4IkznRIJKc12O1erQiLhDlvzXRzGF5vOShNTYzS7Xjk HL8SFK/npJVnYxCfQYhTX+KmircvjV/qjckAuDCWhUDgdPz4OFNf5RQsc0HODRVw0LEtjFgH5hK Zo8uBHtqkwQ0aOra0uouHApKlAXoB6xOnHPPKn5cONOyi8YvaT71y+Oipd90mFin9pmgc= X-Received: by 2002:a05:6830:b16:b0:805:aa3f:fff6 with SMTP id 46e09a7af769-81489cdff11mr1426321a34.17.1790039904129; Mon, 21 Sep 2026 18:18:24 -0700 (PDT) Received: from localhost ([2a03:2880:ff:56::]) by smtp.gmail.com with ESMTPSA id 46e09a7af769-814e648bd3asm555996a34.17.2026.09.21.18.18.22 (version=TLS1_3 cipher=TLS_AES_256_GCM_SHA384 bits=256/256); Mon, 21 Sep 2026 18:18:22 -0700 (PDT) From: Bobby Eshleman Date: Mon, 21 Sep 2026 18:18:05 -0700 Subject: [PATCH net-next v2 2/6] vsock: rename the vsock pernet operations Precedence: bulk X-Mailing-List: linux-kernel@vger.kernel.org List-Id: List-Subscribe: List-Unsubscribe: MIME-Version: 1.0 Content-Type: text/plain; charset="utf-8" Content-Transfer-Encoding: quoted-printable Message-Id: <20260921-vsock-guest-ns-v2-2-693bd78fde9e@meta.com> References: <20260921-vsock-guest-ns-v2-0-693bd78fde9e@meta.com> In-Reply-To: <20260921-vsock-guest-ns-v2-0-693bd78fde9e@meta.com> To: Stefano Garzarella , "David S. Miller" , Eric Dumazet , Jakub Kicinski , Paolo Abeni , Simon Horman , Jonathan Corbet , Shuah Khan , Stefan Hajnoczi , "Michael S. Tsirkin" , Jason Wang , Xuan Zhuo , =?utf-8?q?Eugenio_P=C3=A9rez?= , Shuah Khan , Randy Dunlap , Donald Hunter Cc: virtualization@lists.linux.dev, netdev@vger.kernel.org, linux-kernel@vger.kernel.org, linux-doc@vger.kernel.org, kvm@vger.kernel.org, linux-kselftest@vger.kernel.org, sargun@sargun.me, jlinbox@meta.com, Stanislav Fomichev , Bobby Eshleman X-Mailer: b4 0.14.3 From: Bobby Eshleman vsock_sysctl_ops and its two callbacks are named for the sysctl tables they register, but the init callback already does more than that: it also initialises the per-namespace vsock state through vsock_net_init(). Rename them to vsock_pernet_ops, vsock_pernet_init and vsock_pernet_exit, so that later per-namespace work has somewhere to go that does not read as sysctl handling. No functional change. Signed-off-by: Bobby Eshleman Suggested-by: Stefano Garzarella --- Changes in v2: - New patch --- net/vmw_vsock/af_vsock.c | 14 +++++++------- 1 file changed, 7 insertions(+), 7 deletions(-) diff --git a/net/vmw_vsock/af_vsock.c b/net/vmw_vsock/af_vsock.c index 8d6b705f8640..95a435aef512 100644 --- a/net/vmw_vsock/af_vsock.c +++ b/net/vmw_vsock/af_vsock.c @@ -2998,7 +2998,7 @@ static void vsock_net_init(struct net *net) net->vsock.g2h_fallback =3D 1; } =20 -static __net_init int vsock_sysctl_init_net(struct net *net) +static __net_init int vsock_pernet_init(struct net *net) { vsock_net_init(net); =20 @@ -3008,14 +3008,14 @@ static __net_init int vsock_sysctl_init_net(struct = net *net) return 0; } =20 -static __net_exit void vsock_sysctl_exit_net(struct net *net) +static __net_exit void vsock_pernet_exit(struct net *net) { vsock_sysctl_unregister(net); } =20 -static struct pernet_operations vsock_sysctl_ops =3D { - .init =3D vsock_sysctl_init_net, - .exit =3D vsock_sysctl_exit_net, +static struct pernet_operations vsock_pernet_ops =3D { + .init =3D vsock_pernet_init, + .exit =3D vsock_pernet_exit, }; =20 static int __init vsock_init(void) @@ -3045,7 +3045,7 @@ static int __init vsock_init(void) goto err_unregister_proto; } =20 - if (register_pernet_subsys(&vsock_sysctl_ops)) { + if (register_pernet_subsys(&vsock_pernet_ops)) { err =3D -ENOMEM; goto err_unregister_sock; } @@ -3069,7 +3069,7 @@ static void __exit vsock_exit(void) misc_deregister(&vsock_device); sock_unregister(AF_VSOCK); proto_unregister(&vsock_proto); - unregister_pernet_subsys(&vsock_sysctl_ops); + unregister_pernet_subsys(&vsock_pernet_ops); } =20 const struct vsock_transport *vsock_core_get_transport(struct vsock_sock *= vsk) --=20 2.53.0-Meta From nobody Thu Sep 24 17:02:13 2026 Received: from mail-oi2-f43.google.com (mail-oi2-f43.google.com [74.125.231.235]) (using TLSv1.2 with cipher ECDHE-RSA-AES128-GCM-SHA256 (128/128 bits)) (No client certificate requested) by smtp.subspace.kernel.org (Postfix) with ESMTPS id 68DB8372B45 for ; Tue, 22 Sep 2026 01:18:29 +0000 (UTC) Authentication-Results: smtp.subspace.kernel.org; arc=none smtp.client-ip=74.125.231.235 ARC-Seal: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1790039918; cv=none; b=Lfpn0Ll3keedWTOOu7tQwR2uzxEFOjzgZ8GGIsl5AqWUTQEo7HGIVjDzlNV6Ou+efeM7TwNfppTvbjljhj+HhlPr92b66aMs2mUBhdCIPC+g+TtJ3v/Xu2zhqT0xgMXx7/tsm8Oz8KN5a7EyC7sDLVEJx/CG/8GjgUtgEd531os= ARC-Message-Signature: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1790039918; c=relaxed/simple; bh=Bnn99i8wdAGOwRGMZsJMp82H2cZoGX8Ko2zwcJ450zY=; h=From:Date:Subject:MIME-Version:Content-Type:Message-Id:References: In-Reply-To:To:Cc; b=O7w5Ui+gC1j/NMcLniz5Z1fdX7nbbuN0LH4/10D0BrQ0oCs73VW11vn7TF7ytERkt4kl9r5ptTNGN6C4IFtJ6aDJ+n211BLIwl6OxzDDCPOAl/kQZLfrQVHbZd8L1uVjhljdrHr1p4kemHL9Lmv4NVLxh/iJimPY/KGTHyNnIvs= ARC-Authentication-Results: i=1; smtp.subspace.kernel.org; dmarc=pass (p=none dis=none) header.from=gmail.com; spf=pass smtp.mailfrom=gmail.com; dkim=pass (2048-bit key) header.d=gmail.com header.i=@gmail.com header.b=nvGJ+Vi+; arc=none smtp.client-ip=74.125.231.235 Authentication-Results: smtp.subspace.kernel.org; dmarc=pass (p=none dis=none) header.from=gmail.com Authentication-Results: smtp.subspace.kernel.org; spf=pass smtp.mailfrom=gmail.com Authentication-Results: smtp.subspace.kernel.org; dkim=pass (2048-bit key) header.d=gmail.com header.i=@gmail.com header.b="nvGJ+Vi+" Received: by mail-oi2-f43.google.com with SMTP id 46e09a7af769-80a4e050a12so2426970a34.3 for ; Mon, 21 Sep 2026 18:18:29 -0700 (PDT) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=gmail.com; s=20251104; t=1790039908; x=1790644708; darn=vger.kernel.org; h=cc:to:in-reply-to:references:message-id:content-transfer-encoding :content-type:mime-version:subject:date:from:from:to:cc:subject:date :message-id:reply-to:content-type; bh=qooHmNPsO9wsi0saRmI1c1ln7c0iLHMc8ijb018ShDY=; b=nvGJ+Vi+X+LtAZ7nz+NGoqQvA+YFbucJZA03cB8H7wuUw0dKnhl7f3nZkNxXL7XfJM 6oAIaQCPPsK5UOGi+zyrF9pVXQKwx4HboU1bhj3TYZKJBvRFAFTcd32QbeWYEgXlaWPR Pp6qaad59mbuUenR9tJk+UpRBPz5JBQln2QeAl/keR1OF4cVfd3Uoiwa1Aoq/4Zj5K2l O9TXKwcOu3WCeWf3zMeOHk/cQs3TmtdwGLsdorknij/RElxJ7nGKEEW1Jc8eu6E2R8IQ b+Vcrizw1cXcR2u9Tz2VWdjvCGA69Q7+xU+9aKGqiBSzn39HuS5NrON6r7rzqi4nwvFN Ytdg== X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20260707; t=1790039908; x=1790644708; h=cc:to:in-reply-to:references:message-id:content-transfer-encoding :content-type:mime-version:subject:date:from:x-gm-gg :x-gm-message-state:from:to:cc:subject:date:message-id:reply-to :content-type; bh=qooHmNPsO9wsi0saRmI1c1ln7c0iLHMc8ijb018ShDY=; b=Nz6DyQ7ZhvRtXUIGLlf4WrNg7duI66UNq3qVsR2FEI/EC6rk530TfiiDJExlTdM96c SZRubwV7TmTDkIxoNP+S2zjHPUWwCX3PTGbRHAtZTdqhiASekLZLr5MVzNgieo5pHLtN voxNkZ8LU4A/ea4Mk7VLgBCKPVn2qF24t9KHuh3Zx8+O/gbadYm4lzkOgTzJgQOwsbZV 27CyKhJZwha58KRIxCtuy6FFNNCsyKl9Zq9BboYhVyB3opDL+czX9MBafKMKaNVfwOPS wekWg/MBdxNAlHVgIY7he8NgeoUBCLWowOEtnP6uPmMBuYPjU69rLrq25MK4MsXSva2g 2cmA== X-Forwarded-Encrypted: i=1; AKwUvByten/8cWRRe5D11yxxN2SwG74W6ehx5/lEtfkHY1pxhKaU8ZABcjUfxSx5Rl+lKasBG1kYmgoCkj4l7bQ=@vger.kernel.org X-Gm-Message-State: AFuF++mYBCcpIwTokhik38gzBbUxhInklKPO6WSqs+k8S1uHM+ZX6dR5 yh3aIDtw5i9cVh7dQCJthxPYJGEbdhOV/jTePRPfwA35ICpbFMk3bIYQ X-Gm-Gg: AYBFou13MKHoJ5W520uIFtxjgvDQvK7bB8iBfXmpI2NqQ2kuhie2S313z+WPmFN8o0g uCmPKtg+kBM0++OMeIJM+ln2uC8zfrn3b6PT8qGMnJXpakKexU2tQBXMVn5l27AaSfCrWF0d7ru V9a4KV+kvsoFrM662tVZtXtyI4M94A6CgXC4obWgZe6POVFS51llwf8oDVCNhJUsRh6cuhk4I5E yR28TXB9RpzkZNB1rquE0CyXoQBuknNSS37NXyG/lFVAxSyqPzQbFB63SuoaYKwrga0WETgLB/S 6dbIwyGzub1Ir+tejddOj/ipMR7i9PXnnC1zDJvlHg0kZzqxws6z8QG3fBjAO/F5NoeDY9KzE4r 9bchIEmFvP75KQJX04hAYYnffsRJ894hBbe64Ezscj5v3Aq+vsz2mkDH3ahZPclOCoiUQECRro/ qIPpfWx7outtno3PXjIgeVHO++PgQIF0fxtAjdEDGC7YsFme2DIVaJePas6xR+UAt4W6g= X-Received: by 2002:a05:6830:25c2:b0:7f6:7110:1f83 with SMTP id 46e09a7af769-80ddf969756mr13489366a34.4.1790039907909; Mon, 21 Sep 2026 18:18:27 -0700 (PDT) Received: from localhost ([2a03:2880:ff:50::]) by smtp.gmail.com with ESMTPSA id 46e09a7af769-814e5f8c48dsm646578a34.13.2026.09.21.18.18.25 (version=TLS1_3 cipher=TLS_AES_256_GCM_SHA384 bits=256/256); Mon, 21 Sep 2026 18:18:26 -0700 (PDT) From: Bobby Eshleman Date: Mon, 21 Sep 2026 18:18:06 -0700 Subject: [PATCH net-next v2 3/6] vsock: add a netlink command to assign the g2h device to a netns Precedence: bulk X-Mailing-List: linux-kernel@vger.kernel.org List-Id: List-Subscribe: List-Unsubscribe: MIME-Version: 1.0 Content-Type: text/plain; charset="utf-8" Content-Transfer-Encoding: quoted-printable Message-Id: <20260921-vsock-guest-ns-v2-3-693bd78fde9e@meta.com> References: <20260921-vsock-guest-ns-v2-0-693bd78fde9e@meta.com> In-Reply-To: <20260921-vsock-guest-ns-v2-0-693bd78fde9e@meta.com> To: Stefano Garzarella , "David S. Miller" , Eric Dumazet , Jakub Kicinski , Paolo Abeni , Simon Horman , Jonathan Corbet , Shuah Khan , Stefan Hajnoczi , "Michael S. Tsirkin" , Jason Wang , Xuan Zhuo , =?utf-8?q?Eugenio_P=C3=A9rez?= , Shuah Khan , Randy Dunlap , Donald Hunter Cc: virtualization@lists.linux.dev, netdev@vger.kernel.org, linux-kernel@vger.kernel.org, linux-doc@vger.kernel.org, kvm@vger.kernel.org, linux-kselftest@vger.kernel.org, sargun@sargun.me, jlinbox@meta.com, Stanislav Fomichev , Bobby Eshleman X-Mailer: b4 0.14.3 From: Bobby Eshleman Namespaces let a host isolate a VM's vsock traffic to a specific namespace, but in a guest vsock traffic cannot be isolated to a namespace. The vsock device is hardcoded to global mode and can't be moved into a local-mode namespace. Introduce a vsock generic netlink family whose one command, VSOCK_CMD_DEV_NETNS_SET, moves the device to the namespace the request was sent from. VSOCK_CMD_DEV_NETNS_GET reads the assignment back, reporting the namespace as an nsid relative to the caller. The command requires CAP_NET_ADMIN in the initial user namespace. A privileged user wishing to "unassign" the device can move it to the init_net, which is hardcoded to global mode (so no unassign call is necessary). Add a transport flag to indicate support for guest namespacing, so that transports may opt in/out. A transport that opts out keeps the reachability rules it had before this command existed. Sockets are reset when the underlying device moves to a different namespace, so as to prevent reachability from the previous and now disallowed namespace. The device's CID must not be observable from such a namespace either. It is reached through three paths: IOCTL_VM_SOCKETS_GET_LOCAL_CID reports it, bind() accepts it because vsock_find_cid() matches it, and connect() to it selects the loopback transport because vsock_use_local_transport() compares against it. All three read it through vsock_registered_transport_cid(), which now takes the namespace asking and reports VMADDR_CID_ANY for the g2h slot when that namespace cannot reach the device. Following the approach of netdevs, the device returns to init_net when its namespace is removed. Care is taken to not break flows when the device is inside a global namespace that is being torn down and alive sockets are in a different global namespace. In this scenario, the device's netns getter pre-emptively falls back to the init_net (always global) so that these flows are not disrupted. If init_net ever supports local-mode in the future, this logic will have to be changed. Suggested-by: Stefano Garzarella Link: https://lore.kernel.org/all/20200427142518.uwssa6dtasrp3bfc@steredhat/ Signed-off-by: Bobby Eshleman --- Changes in v2: - New patch, replaces the ioctl with a genl family and VSOCK_CMD_DEV_NETNS_SET (Stefano) - Make netns_assign_allow a bool, not a callback (Stefano) - One vsock_netns_assignable(t) helper for both call sites (Stefano) - Make vsock_g2h_reachable_sk() static, drop the export (Stefano) - RST the peer when socket loses access to the device's net (Stefano) - Move the netns reset out of the sysctl exit hook, into the renamed vsock_pernet_ops (Stefano). - Remove the synchronize_rcu() from the pernet exit path. The net_namespace documentation states that synchronize_rcu() should be avoided in the pernet exit path. - Run the socket reset in the pernet pre_exit() hook, as the net_namespace management code (and documentation) guarantees synchronize_rcu() between pre_exit() and exit() - Drop the conditional synchronize_rcu() in vsock_core_unregister() (Stefano) - Specifically state "G2H transport" in the netns_assign_allow comment (Ste= fano) - Avoid leaking the g2h CID to a namespace that cannot reach it; GET_LOCAL_CID, bind() and loopback transport selection all read it through vsock_registered_transport_cid(), which now takes a netns - Add VSOCK_CMD_DEV_NETNS_GET --- Documentation/admin-guide/sysctl/net.rst | 23 ++ Documentation/netlink/specs/vsock.yaml | 68 ++++++ MAINTAINERS | 2 + drivers/vhost/vsock.c | 6 +- include/net/af_vsock.h | 17 +- include/uapi/linux/vsock.h | 28 +++ net/vmw_vsock/Makefile | 2 +- net/vmw_vsock/af_vsock.c | 358 +++++++++++++++++++++++++++= ++-- net/vmw_vsock/vsock_nl_gen.c | 36 ++++ net/vmw_vsock/vsock_nl_gen.h | 20 ++ tools/net/ynl/Makefile.deps | 1 + 11 files changed, 543 insertions(+), 18 deletions(-) diff --git a/Documentation/admin-guide/sysctl/net.rst b/Documentation/admin= -guide/sysctl/net.rst index fe43e8595958..f2d8e4e84f89 100644 --- a/Documentation/admin-guide/sysctl/net.rst +++ b/Documentation/admin-guide/sysctl/net.rst @@ -529,6 +529,29 @@ their hosts. The behavior of VSOCK sockets in a networ= k namespace is determined by the namespace's mode (``global`` or ``local``), which controls how CIDs (Context IDs) are allocated and how sockets interact across namespaces. =20 +In a guest, the vsock device owned by the guest-to-host (G2H) transport be= longs +to one network namespace at a time. The ``VSOCK_CMD_DEV_NETNS_SET`` comman= d of +the ``vsock`` netlink family, described in +Documentation/netlink/specs/vsock.yaml, moves it to the namespace the requ= est +was sent from, which requires ``CAP_NET_ADMIN`` in the initial user namesp= ace. +The namespace's mode decides who may then use the device: + +- ``global`` - every ``global`` mode namespace may use it. +- ``local`` - only that namespace may use it, which reserves the connectio= n to + the host for it alone. + +The device starts out in the initial namespace, so until the command is is= sued +nothing has moved and no mode has changed. + +Support is transport dependent. A G2H transport that does not implement the +move refuses the command with ``EOPNOTSUPP``; of the in-tree guest transpo= rts +only virtio-vsock implements it. + +Connections made before the move, from a namespace that can no longer reac= h the +device, are reset. The device returns to the initial namespace when the +namespace it was moved to is deleted, so assigning it to the initial names= pace +is how an assignment is undone. + ns_mode ------- =20 diff --git a/Documentation/netlink/specs/vsock.yaml b/Documentation/netlink= /specs/vsock.yaml new file mode 100644 index 000000000000..a33e02cb6f34 --- /dev/null +++ b/Documentation/netlink/specs/vsock.yaml @@ -0,0 +1,68 @@ +# SPDX-License-Identifier: ((GPL-2.0 WITH Linux-syscall-note) OR BSD-3-Cla= use) +# +# Copyright (c) 2026 Meta Platforms, Inc. and affiliates +# +--- +name: vsock + +doc: | + Control interface for the vsock (AF_VSOCK) core. + +protocol: genetlink + +uapi-header: linux/vsock.h + +attribute-sets: + - + name: vsock + attributes: + - + name: netns-id + type: s32 + doc: | + Network namespace the guest's vsock device is assigned to, as an + nsid relative to the caller. + + Absent when the device is in the caller's own namespace, and + NETNSA_NSID_NOT_ASSIGNED when the caller's namespace cannot reach + the device under the mode rules, or when no nsid could be + allocated for it. + +operations: + list: + - + name: dev-netns-set + doc: | + Set the network namespace of the guest's vsock device, the one own= ed + by the guest-to-host transport. + + The device is moved to the namespace the request was sent from. It + starts out in the initial namespace, and moving it back there is h= ow + an assignment is undone. + + Support is transport dependent: a guest-to-host transport that does + not implement the move refuses the request with EOPNOTSUPP. + + The namespace's mode decides who may then use the device: a global + mode namespace shares it with every other global mode namespace, + while a local mode namespace reserves it for itself. + + Connections made before the assignment, from a namespace that can = no + longer reach the device, are reset. + attribute-set: vsock + flags: [admin-perm] + do: {} + - + name: dev-netns-get + doc: | + Get the network namespace the guest's vsock device is assigned to. + + The namespace is reported as an nsid relative to the caller, so the + attribute is absent when the device is already in the caller's own + namespace. A caller whose namespace cannot reach the device is told + NETNSA_NSID_NOT_ASSIGNED rather than where the device went. + attribute-set: vsock + do: + reply: + attributes: + - netns-id diff --git a/MAINTAINERS b/MAINTAINERS index df8ab9b82402..e30e6f8d71e2 100644 --- a/MAINTAINERS +++ b/MAINTAINERS @@ -29143,10 +29143,12 @@ M: Stefano Garzarella L: virtualization@lists.linux.dev L: netdev@vger.kernel.org S: Maintained +F: Documentation/netlink/specs/vsock.yaml F: drivers/net/vsockmon.c F: include/net/af_vsock.h F: include/uapi/linux/vm_sockets.h F: include/uapi/linux/vm_sockets_diag.h +F: include/uapi/linux/vsock.h F: include/uapi/linux/vsockmon.h F: net/vmw_vsock/ F: tools/testing/selftests/vsock/ diff --git a/drivers/vhost/vsock.c b/drivers/vhost/vsock.c index abed1fbcf66c..badc064964b3 100644 --- a/drivers/vhost/vsock.c +++ b/drivers/vhost/vsock.c @@ -828,9 +828,11 @@ static int vhost_vsock_set_cid(struct vhost_vsock *vso= ck, u64 guest_cid) return -EINVAL; =20 /* Refuse if CID is assigned to the guest->host transport (i.e. nested - * VM), to make the loopback work. + * VM), to make the loopback work. Only when that device is reachable + * from this VM's namespace, which is the same test the guest CID + * collision check below applies. */ - if (vsock_find_cid(guest_cid)) + if (vsock_find_cid(vsock->net, guest_cid)) return -EADDRINUSE; =20 /* Refuse if CID is already in use */ diff --git a/include/net/af_vsock.h b/include/net/af_vsock.h index 370fcd3ddabc..dbf1a6aa367f 100644 --- a/include/net/af_vsock.h +++ b/include/net/af_vsock.h @@ -35,6 +35,8 @@ struct vsock_sock { /* Links for the global tables of bound and connected sockets. */ struct list_head bound_table; struct list_head connected_table; + /* Protected by vsock_register_mutex. */ + struct list_head pending_reset; /* Accessed without the socket lock held. This means it can never be * modified outsided of socket create or destruct. */ @@ -190,6 +192,16 @@ struct vsock_transport { =20 /* Zero-copy. */ bool (*msgzerocopy_allow)(void); + + /* True if the G2H transport honours VSOCK_CMD_DEV_NETNS_SET. A + * transport that sets this must also implement reset. + */ + bool netns_assign_allow; + + /* Send a reset to @vsk's peer. @skb is the packet being replied to, or + * NULL when the reset is not a reply. May sleep. + */ + int (*reset)(struct vsock_sock *vsk, struct sk_buff *skb); }; =20 /**** CORE ****/ @@ -236,8 +248,11 @@ void vsock_remove_sock(struct vsock_sock *vsk); void vsock_for_each_connected_socket(const struct vsock_transport *transpo= rt, void (*fn)(struct sock *sk)); int vsock_assign_transport(struct vsock_sock *vsk, struct vsock_sock *psk); -bool vsock_find_cid(unsigned int cid); +bool vsock_find_cid(struct net *net, unsigned int cid); void vsock_linger(struct sock *sk); +struct net *vsock_g2h_net_get(void); +bool vsock_g2h_net_reachable(struct net *net); +bool vsock_maybe_set_connected(struct vsock_sock *vsk); =20 /**** TAP ****/ =20 diff --git a/include/uapi/linux/vsock.h b/include/uapi/linux/vsock.h new file mode 100644 index 000000000000..803b9aa1f0b3 --- /dev/null +++ b/include/uapi/linux/vsock.h @@ -0,0 +1,28 @@ +/* SPDX-License-Identifier: ((GPL-2.0 WITH Linux-syscall-note) OR BSD-3-Cl= ause) */ +/* Do not edit directly, auto-generated from: */ +/* Documentation/netlink/specs/vsock.yaml */ +/* YNL-GEN uapi header */ +/* To regenerate run: tools/net/ynl/ynl-regen.sh */ + +#ifndef _UAPI_LINUX_VSOCK_H +#define _UAPI_LINUX_VSOCK_H + +#define VSOCK_FAMILY_NAME "vsock" +#define VSOCK_FAMILY_VERSION 1 + +enum { + VSOCK_A_NETNS_ID =3D 1, + + __VSOCK_A_MAX, + VSOCK_A_MAX =3D (__VSOCK_A_MAX - 1) +}; + +enum { + VSOCK_CMD_DEV_NETNS_SET =3D 1, + VSOCK_CMD_DEV_NETNS_GET, + + __VSOCK_CMD_MAX, + VSOCK_CMD_MAX =3D (__VSOCK_CMD_MAX - 1) +}; + +#endif /* _UAPI_LINUX_VSOCK_H */ diff --git a/net/vmw_vsock/Makefile b/net/vmw_vsock/Makefile index 5da74c4a9f1d..97e2a559e2bf 100644 --- a/net/vmw_vsock/Makefile +++ b/net/vmw_vsock/Makefile @@ -7,7 +7,7 @@ obj-$(CONFIG_VIRTIO_VSOCKETS_COMMON) +=3D vmw_vsock_virtio_= transport_common.o obj-$(CONFIG_HYPERV_VSOCKETS) +=3D hv_sock.o obj-$(CONFIG_VSOCKETS_LOOPBACK) +=3D vsock_loopback.o =20 -vsock-y +=3D af_vsock.o af_vsock_tap.o vsock_addr.o +vsock-y +=3D af_vsock.o af_vsock_tap.o vsock_addr.o vsock_nl_gen.o vsock-$(CONFIG_BPF_SYSCALL) +=3D vsock_bpf.o =20 vsock_diag-y +=3D diag.o diff --git a/net/vmw_vsock/af_vsock.c b/net/vmw_vsock/af_vsock.c index 95a435aef512..9938dd501019 100644 --- a/net/vmw_vsock/af_vsock.c +++ b/net/vmw_vsock/af_vsock.c @@ -130,6 +130,24 @@ * a different transport that *does* support local mode. For * example, virtio-vsock may not support local mode, but the socket * may still accept a connection from vhost-vsock which does. + * + * - A guest has a single vsock device, owned by the guest->host transport. + * The VSOCK_CMD_DEV_NETNS_SET netlink command moves it to the namespace= the + * request was sent from. It starts out in init_net. The mode rules then + * decide who may use it, and which namespace packets from the host are + * delivered to: + * + * - assigned to a global mode namespace - every global mode namespace m= ay + * use it. Until the command is issued nothing has moved and no mode h= as + * changed, so the default is the behaviour that predates it. + * - assigned to a local mode namespace - only that namespace may use it. + * This is how a nested VM is isolated from the rest of the guest. + * + * Connections made before an assignment, from a namespace that can no + * longer reach the device, are reset. + * + * No reference is taken on the assigned namespace. As is done for netde= vs, + * the device is moved back to init_net when that namespace is destroyed. */ =20 #include @@ -161,10 +179,14 @@ #include #include #include +#include +#include #include #include #include =20 +#include "vsock_nl_gen.h" + #define VSOCK_NET_MODE_STR_GLOBAL "global" #define VSOCK_NET_MODE_STR_LOCAL "local" =20 @@ -208,6 +230,11 @@ static const struct vsock_transport *transport_dgram; static const struct vsock_transport *transport_local; static DEFINE_MUTEX(vsock_register_mutex); =20 +/* Network namespace of the g2h device. Protected by + * vsock_register_mutex/RCU. + */ +static struct net __rcu *vsock_g2h_net =3D RCU_INITIALIZER(&init_net); + /**** UTILS ****/ =20 /* Each bound VSocket is stored in the bind hash table and each connected @@ -553,7 +580,37 @@ void vsock_enqueue_accept(struct sock *listener, struc= t sock *connected) } EXPORT_SYMBOL_GPL(vsock_enqueue_accept); =20 -static bool vsock_use_local_transport(unsigned int remote_cid) +/* Return true if @t honours namespace assignment. One that does not keeps= the + * reachability rules it had before VSOCK_CMD_DEV_NETNS_SET existed. + */ +static bool vsock_netns_assignable(const struct vsock_transport *t) +{ + return t && t->netns_assign_allow && t->reset; +} + +/* Return the CID of the transport in @transport, as seen from @net. + * + * The g2h device is the one that can move between namespaces, so a @net t= hat + * cannot reach it is told VMADDR_CID_ANY: the same answer it would get if= no + * g2h transport were registered at all. + */ +static u32 +__vsock_registered_transport_cid(const struct vsock_transport **transport, + struct net *net) +{ + lockdep_assert_held(&vsock_register_mutex); + + if (!*transport) + return VMADDR_CID_ANY; + + if (transport =3D=3D &transport_g2h && vsock_netns_assignable(*transport)= && + !vsock_g2h_net_reachable(net)) + return VMADDR_CID_ANY; + + return (*transport)->get_local_cid(); +} + +static bool vsock_use_local_transport(struct net *net, unsigned int remote= _cid) { lockdep_assert_held(&vsock_register_mutex); =20 @@ -564,7 +621,12 @@ static bool vsock_use_local_transport(unsigned int rem= ote_cid) return true; =20 if (transport_g2h) { - return remote_cid =3D=3D transport_g2h->get_local_cid(); + u32 cid =3D __vsock_registered_transport_cid(&transport_g2h, net); + + /* The device may be unreachable from @net, in which case + * @remote_cid is not the local CID. + */ + return cid !=3D VMADDR_CID_ANY && remote_cid =3D=3D cid; } else { return remote_cid =3D=3D VMADDR_CID_HOST; } @@ -626,7 +688,7 @@ int vsock_assign_transport(struct vsock_sock *vsk, stru= ct vsock_sock *psk) break; case SOCK_STREAM: case SOCK_SEQPACKET: - if (vsock_use_local_transport(remote_cid)) + if (vsock_use_local_transport(sock_net(sk), remote_cid)) new_transport =3D transport_local; else if (remote_cid <=3D VMADDR_CID_HOST || (remote_flags & VMADDR_FLAG_TO_HOST)) @@ -654,6 +716,13 @@ int vsock_assign_transport(struct vsock_sock *vsk, str= uct vsock_sock *psk) goto err; } =20 + if (new_transport && new_transport =3D=3D transport_g2h && + vsock_netns_assignable(new_transport) && + !vsock_g2h_net_reachable(sock_net(sk))) { + ret =3D -ENETUNREACH; + goto err; + } + /* We increase the module refcnt to prevent the transport unloading * while there are open sockets assigned to it. */ @@ -715,21 +784,22 @@ EXPORT_SYMBOL_GPL(vsock_assign_transport); * Provide safe access to static transport_{h2g,g2h,dgram,local} callbacks. * Otherwise we may race with module removal. Do not use on `vsk->transpor= t`. */ -static u32 vsock_registered_transport_cid(const struct vsock_transport **t= ransport) +static u32 +vsock_registered_transport_cid(const struct vsock_transport **transport, + struct net *net) { - u32 cid =3D VMADDR_CID_ANY; + u32 cid; =20 mutex_lock(&vsock_register_mutex); - if (*transport) - cid =3D (*transport)->get_local_cid(); + cid =3D __vsock_registered_transport_cid(transport, net); mutex_unlock(&vsock_register_mutex); =20 return cid; } =20 -bool vsock_find_cid(unsigned int cid) +bool vsock_find_cid(struct net *net, unsigned int cid) { - if (cid =3D=3D vsock_registered_transport_cid(&transport_g2h)) + if (cid =3D=3D vsock_registered_transport_cid(&transport_g2h, net)) return true; =20 if (transport_h2g && cid =3D=3D VMADDR_CID_HOST) @@ -742,6 +812,173 @@ bool vsock_find_cid(unsigned int cid) } EXPORT_SYMBOL_GPL(vsock_find_cid); =20 +/* Return the namespace the g2h device is assigned to, with a reference he= ld, + * or NULL when that namespace is going away and the init_net cannot stand= in + * for it. + */ +struct net *vsock_g2h_net_get(void) +{ + struct net *assigned; + struct net *net; + + rcu_read_lock(); + assigned =3D rcu_dereference(vsock_g2h_net); + net =3D maybe_get_net(assigned); + + /* !net means the net is about to be destroyed, at which point the g2h + * device will move to the init_net. If the init_net and the dying net + * are both global mode, we use the init_net as a fallback to avoid + * disrupting global-mode flows. The per-net destructor hook will + * eventually move the g2h device to the init_net anyway. + * + * vsock_net_check_mode() is safe here because 'assigned' is pointing + * to a net that won't be freed until the following rcu grace period. + */ + if (!net && vsock_net_check_mode(&init_net, assigned)) + net =3D get_net(&init_net); + rcu_read_unlock(); + + return net; +} +EXPORT_SYMBOL_GPL(vsock_g2h_net_get); + +bool vsock_g2h_net_reachable(struct net *net) +{ + bool reachable; + + rcu_read_lock(); + reachable =3D vsock_net_check_mode(net, rcu_dereference(vsock_g2h_net)); + rcu_read_unlock(); + + return reachable; +} +EXPORT_SYMBOL_GPL(vsock_g2h_net_reachable); + +static bool vsock_g2h_reachable_sk(struct vsock_sock *vsk) +{ + if (!vsock_netns_assignable(vsk->transport)) + return true; + + return vsock_g2h_net_reachable(sock_net(sk_vsock(vsk))); +} + +/* Move @vsk to TCP_ESTABLISHED and into the connected table, unless the d= evice + * has moved to a namespace @vsk cannot reach. Returns false without doing + * either in that case. + * + * The reset sweep walks the same table under the same lock, so an assign + * cannot land between the check and the insert: either the sweep finds @v= sk + * and resets it, or @vsk is never added. + */ +bool vsock_maybe_set_connected(struct vsock_sock *vsk) +{ + struct list_head *list; + bool reachable; + + list =3D vsock_connected_sockets(&vsk->remote_addr, &vsk->local_addr); + + spin_lock_bh(&vsock_table_lock); + reachable =3D vsock_g2h_reachable_sk(vsk); + if (reachable) { + sk_vsock(vsk)->sk_state =3D TCP_ESTABLISHED; + __vsock_insert_connected(list, vsk); + } + spin_unlock_bh(&vsock_table_lock); + + return reachable; +} +EXPORT_SYMBOL_GPL(vsock_maybe_set_connected); + +/* Reset every connected socket of @t that can no longer reach the g2h dev= ice, + * and let the transport tell each peer. + */ +static void vsock_g2h_reset_unreachable(const struct vsock_transport *t) +{ + struct vsock_sock *vsk, *tmp; + LIST_HEAD(reset_list); + struct sock *sk; + int i; + + /* The calling context must hold vsock_register_mutex, which serializes + * concurrent netns assignments' use of vsk->pending_reset. + */ + lockdep_assert_held(&vsock_register_mutex); + + spin_lock_bh(&vsock_table_lock); + + for (i =3D 0; i < ARRAY_SIZE(vsock_connected_table); i++) { + list_for_each_entry(vsk, &vsock_connected_table[i], + connected_table) { + sk =3D sk_vsock(vsk); + + if (vsk->transport !=3D t || + sk->sk_state =3D=3D TCP_CLOSE || + vsock_g2h_reachable_sk(vsk)) + continue; + + sk->sk_state =3D TCP_CLOSE; + sk->sk_err =3D ECONNRESET; + sk_error_report(sk); + + sock_hold(sk); + list_add_tail(&vsk->pending_reset, &reset_list); + } + } + + spin_unlock_bh(&vsock_table_lock); + + /* Reset outside of spinlock because the transport may sleep + * (e.g., GFP_KERNEL alloc). + */ + list_for_each_entry_safe(vsk, tmp, &reset_list, pending_reset) { + list_del_init(&vsk->pending_reset); + t->reset(vsk, NULL); + sock_put(sk_vsock(vsk)); + } +} + +/* Move the g2h device to @net. Returns -ENODEV if no g2h transport is loa= ded + * and -EOPNOTSUPP if the loaded one cannot be moved. + */ +static int vsock_g2h_net_assign(struct net *net) +{ + int ret =3D 0; + + mutex_lock(&vsock_register_mutex); + if (!transport_g2h) { + ret =3D -ENODEV; + } else if (!vsock_netns_assignable(transport_g2h)) { + ret =3D -EOPNOTSUPP; + } else { + /* See vsock_maybe_set_connected() comment about synchronizing + * with connecting sockets. + */ + rcu_assign_pointer(vsock_g2h_net, net); + vsock_g2h_reset_unreachable(transport_g2h); + } + mutex_unlock(&vsock_register_mutex); + + return ret; +} + +/* Move the g2h device back to init_net if it lives in @net, which is abou= t to + * be destroyed. + */ +/* Runs as .pre_exit: pernet_operations guarantees a synchronize_rcu() + * between pre_exit() and exit(), which drains the readers this drops. + */ +static void __net_exit vsock_g2h_net_reset(struct net *net) +{ + /* Avoid taking the mutex if the namespaces don't match. */ + if (likely(rcu_access_pointer(vsock_g2h_net) !=3D net)) + return; + + mutex_lock(&vsock_register_mutex); + if (rcu_access_pointer(vsock_g2h_net) =3D=3D net) + rcu_assign_pointer(vsock_g2h_net, &init_net); + mutex_unlock(&vsock_register_mutex); +} + static struct sock *vsock_dequeue_accept(struct sock *listener) { struct vsock_sock *vlistener; @@ -908,7 +1145,8 @@ static int __vsock_bind(struct sock *sk, struct sockad= dr_vm *addr) * like AF_INET prevents binding to a non-local IP address (in most * cases), we only allow binding to a local CID. */ - if (addr->svm_cid !=3D VMADDR_CID_ANY && !vsock_find_cid(addr->svm_cid)) + if (addr->svm_cid !=3D VMADDR_CID_ANY && + !vsock_find_cid(sock_net(sk_vsock(vsk)), addr->svm_cid)) return -EADDRNOTAVAIL; =20 switch (sk->sk_socket->type) { @@ -967,6 +1205,7 @@ static struct sock *__vsock_create(struct net *net, =20 INIT_LIST_HEAD(&vsk->bound_table); INIT_LIST_HEAD(&vsk->connected_table); + INIT_LIST_HEAD(&vsk->pending_reset); vsk->listener =3D NULL; INIT_LIST_HEAD(&vsk->pending_links); INIT_LIST_HEAD(&vsk->accept_queue); @@ -2760,6 +2999,7 @@ static long vsock_dev_do_ioctl(struct file *filp, { u32 __user *p =3D ptr; int retval =3D 0; + struct net *net; u32 cid; =20 switch (cmd) { @@ -2767,11 +3007,14 @@ static long vsock_dev_do_ioctl(struct file *filp, /* To be compatible with the VMCI behavior, we prioritize the * guest CID instead of well-know host CID (VMADDR_CID_HOST). */ - cid =3D vsock_registered_transport_cid(&transport_g2h); + net =3D current->nsproxy->net_ns; + cid =3D vsock_registered_transport_cid(&transport_g2h, net); if (cid =3D=3D VMADDR_CID_ANY) - cid =3D vsock_registered_transport_cid(&transport_h2g); + cid =3D vsock_registered_transport_cid(&transport_h2g, + net); if (cid =3D=3D VMADDR_CID_ANY) - cid =3D vsock_registered_transport_cid(&transport_local); + cid =3D vsock_registered_transport_cid(&transport_local, + net); =20 if (put_user(cid, p) !=3D 0) retval =3D -EFAULT; @@ -2812,6 +3055,81 @@ static struct miscdevice vsock_device =3D { .fops =3D &vsock_device_ops, }; =20 +int vsock_nl_dev_netns_get_doit(struct sk_buff *skb, struct genl_info *inf= o) +{ + struct net *net =3D genl_info_net(info); + struct net *assigned; + struct sk_buff *msg; + bool report; + void *hdr; + s32 id; + int err; + + mutex_lock(&vsock_register_mutex); + if (!transport_g2h) { + mutex_unlock(&vsock_register_mutex); + NL_SET_ERR_MSG(info->extack, + "no guest-to-host transport is loaded"); + return -ENODEV; + } + + rcu_read_lock(); + assigned =3D rcu_dereference(vsock_g2h_net); + report =3D !net_eq(net, assigned); + if (report) { + /* Hide the assignment on the same terms the CID is hidden: + * only a transport that honours namespace assignment keeps it + * from a namespace that cannot reach the device. + */ + if (vsock_netns_assignable(transport_g2h) && + !vsock_net_check_mode(net, assigned)) + id =3D NETNSA_NSID_NOT_ASSIGNED; + else + id =3D peernet2id_alloc(net, assigned, GFP_ATOMIC); + } + rcu_read_unlock(); + mutex_unlock(&vsock_register_mutex); + + msg =3D genlmsg_new(NLMSG_GOODSIZE, GFP_KERNEL); + if (!msg) + return -ENOMEM; + + hdr =3D genlmsg_iput(msg, info); + if (!hdr) { + err =3D -EMSGSIZE; + goto err_free; + } + + if (report && nla_put_s32(msg, VSOCK_A_NETNS_ID, id)) { + err =3D -EMSGSIZE; + goto err_cancel; + } + + genlmsg_end(msg, hdr); + + return genlmsg_reply(msg, info); + +err_cancel: + genlmsg_cancel(msg, hdr); +err_free: + nlmsg_free(msg); + return err; +} + +int vsock_nl_dev_netns_set_doit(struct sk_buff *skb, struct genl_info *inf= o) +{ + int err =3D vsock_g2h_net_assign(genl_info_net(info)); + + if (err =3D=3D -ENODEV) + NL_SET_ERR_MSG(info->extack, + "no guest-to-host transport is loaded"); + else if (err =3D=3D -EOPNOTSUPP) + NL_SET_ERR_MSG(info->extack, + "the loaded guest-to-host transport does not support namespace a= ssignment"); + + return err; +} + static int __vsock_net_mode_string(const struct ctl_table *table, int writ= e, void *buffer, size_t *lenp, loff_t *ppos, enum vsock_net_mode mode, @@ -3015,6 +3333,7 @@ static __net_exit void vsock_pernet_exit(struct net *= net) =20 static struct pernet_operations vsock_pernet_ops =3D { .init =3D vsock_pernet_init, + .pre_exit =3D vsock_g2h_net_reset, .exit =3D vsock_pernet_exit, }; =20 @@ -3050,10 +3369,18 @@ static int __init vsock_init(void) goto err_unregister_sock; } =20 + err =3D genl_register_family(&vsock_nl_family); + if (err) { + pr_err("Cannot register vsock netlink family: %d\n", err); + goto err_unregister_pernet; + } + vsock_bpf_build_proto(); =20 return 0; =20 +err_unregister_pernet: + unregister_pernet_subsys(&vsock_pernet_ops); err_unregister_sock: sock_unregister(AF_VSOCK); err_unregister_proto: @@ -3066,6 +3393,7 @@ static int __init vsock_init(void) =20 static void __exit vsock_exit(void) { + genl_unregister_family(&vsock_nl_family); misc_deregister(&vsock_device); sock_unregister(AF_VSOCK); proto_unregister(&vsock_proto); @@ -3141,8 +3469,10 @@ void vsock_core_unregister(const struct vsock_transp= ort *t) if (transport_h2g =3D=3D t) transport_h2g =3D NULL; =20 - if (transport_g2h =3D=3D t) + if (transport_g2h =3D=3D t) { transport_g2h =3D NULL; + rcu_assign_pointer(vsock_g2h_net, &init_net); + } =20 if (transport_dgram =3D=3D t) transport_dgram =3D NULL; diff --git a/net/vmw_vsock/vsock_nl_gen.c b/net/vmw_vsock/vsock_nl_gen.c new file mode 100644 index 000000000000..81db4c61d7bb --- /dev/null +++ b/net/vmw_vsock/vsock_nl_gen.c @@ -0,0 +1,36 @@ +// SPDX-License-Identifier: ((GPL-2.0 WITH Linux-syscall-note) OR BSD-3-Cl= ause) +/* Do not edit directly, auto-generated from: */ +/* Documentation/netlink/specs/vsock.yaml */ +/* YNL-GEN kernel source */ +/* To regenerate run: tools/net/ynl/ynl-regen.sh */ + +#include +#include + +#include "vsock_nl_gen.h" + +#include + +/* Ops table for vsock */ +static const struct genl_split_ops vsock_nl_ops[] =3D { + { + .cmd =3D VSOCK_CMD_DEV_NETNS_SET, + .doit =3D vsock_nl_dev_netns_set_doit, + .flags =3D GENL_ADMIN_PERM | GENL_CMD_CAP_DO, + }, + { + .cmd =3D VSOCK_CMD_DEV_NETNS_GET, + .doit =3D vsock_nl_dev_netns_get_doit, + .flags =3D GENL_CMD_CAP_DO, + }, +}; + +struct genl_family vsock_nl_family __ro_after_init =3D { + .name =3D VSOCK_FAMILY_NAME, + .version =3D VSOCK_FAMILY_VERSION, + .netnsok =3D true, + .parallel_ops =3D true, + .module =3D THIS_MODULE, + .split_ops =3D vsock_nl_ops, + .n_split_ops =3D ARRAY_SIZE(vsock_nl_ops), +}; diff --git a/net/vmw_vsock/vsock_nl_gen.h b/net/vmw_vsock/vsock_nl_gen.h new file mode 100644 index 000000000000..c041195584a0 --- /dev/null +++ b/net/vmw_vsock/vsock_nl_gen.h @@ -0,0 +1,20 @@ +/* SPDX-License-Identifier: ((GPL-2.0 WITH Linux-syscall-note) OR BSD-3-Cl= ause) */ +/* Do not edit directly, auto-generated from: */ +/* Documentation/netlink/specs/vsock.yaml */ +/* YNL-GEN kernel header */ +/* To regenerate run: tools/net/ynl/ynl-regen.sh */ + +#ifndef _LINUX_VSOCK_GEN_H +#define _LINUX_VSOCK_GEN_H + +#include +#include + +#include + +int vsock_nl_dev_netns_set_doit(struct sk_buff *skb, struct genl_info *inf= o); +int vsock_nl_dev_netns_get_doit(struct sk_buff *skb, struct genl_info *inf= o); + +extern struct genl_family vsock_nl_family; + +#endif /* _LINUX_VSOCK_GEN_H */ diff --git a/tools/net/ynl/Makefile.deps b/tools/net/ynl/Makefile.deps index 1e746e25e2bc..fa51108c43d4 100644 --- a/tools/net/ynl/Makefile.deps +++ b/tools/net/ynl/Makefile.deps @@ -55,4 +55,5 @@ CFLAGS_tc:=3D $(call get_hdr_inc,__LINUX_RTNETLINK_H,rtne= tlink.h) \ $(call get_hdr_inc,_TC_SKBEDIT_H,tc_act/tc_skbedit.h) \ $(call get_hdr_inc,_TC_TUNNEL_KEY_H,tc_act/tc_tunnel_key.h) CFLAGS_tcp_metrics:=3D$(call get_hdr_inc,_LINUX_TCP_METRICS_H,tcp_metrics.= h) +CFLAGS_vsock:=3D$(call get_hdr_inc,_LINUX_VSOCK_H,vsock.h) CFLAGS_wireguard:=3D$(call get_hdr_inc2,_LINUX_WIREGUARD_H,_WG_UAPI_WIREGU= ARD_H,wireguard.h) --=20 2.53.0-Meta From nobody Thu Sep 24 17:02:13 2026 Received: from mail-oa2-f12.google.com (mail-oa2-f12.google.com [74.125.231.76]) (using TLSv1.2 with cipher ECDHE-RSA-AES128-GCM-SHA256 (128/128 bits)) (No client certificate requested) by smtp.subspace.kernel.org (Postfix) with ESMTPS id 84E1126ED41 for ; Tue, 22 Sep 2026 01:18:32 +0000 (UTC) Authentication-Results: smtp.subspace.kernel.org; arc=none smtp.client-ip=74.125.231.76 ARC-Seal: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1790039916; cv=none; b=cspKRy+q1MAIOK7sWADPXTL1GfVJZNySudPu99YOxG+YbxMvziaBCfO/1NDPQiqKQV0u85J1T475C7e+y2Sr1N1D28nWBRCbDXOw4v0VGtGkrlBbNRVBMFTNwFZ0CKYv0QZrhdkTrX21CxhNl813lduTDTqwYQHXOf6myj/2hVs= ARC-Message-Signature: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1790039916; c=relaxed/simple; bh=Nlv14tlU9uNpBq5PQObxLvoOri0Y3sW5xPbKOk7Qmhk=; h=From:Date:Subject:MIME-Version:Content-Type:Message-Id:References: In-Reply-To:To:Cc; b=h6P3KLKu2mAk+3dDr4o1xL7ylC/rOg6EYeZEwkBv6cpP6DFX0SGzjhuNGgl93modIG60sUxyjAEJyVAKYK2MQpg7UJebWLBIR5PbSMOnjhrk2cSojERk2GgU/J7dLg02qzLv2lF6Ht62C5Czmozij3qR6R+y/zZEf7yVuGHqcdM= ARC-Authentication-Results: i=1; smtp.subspace.kernel.org; dmarc=pass (p=none dis=none) header.from=gmail.com; spf=pass smtp.mailfrom=gmail.com; dkim=pass (2048-bit key) header.d=gmail.com header.i=@gmail.com header.b=M6VxZYcF; arc=none smtp.client-ip=74.125.231.76 Authentication-Results: smtp.subspace.kernel.org; dmarc=pass (p=none dis=none) header.from=gmail.com Authentication-Results: smtp.subspace.kernel.org; spf=pass smtp.mailfrom=gmail.com Authentication-Results: smtp.subspace.kernel.org; dkim=pass (2048-bit key) header.d=gmail.com header.i=@gmail.com header.b="M6VxZYcF" Received: by mail-oa2-f12.google.com with SMTP id 586e51a60fabf-466ccdd76a9so3253896fac.0 for ; Mon, 21 Sep 2026 18:18:32 -0700 (PDT) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=gmail.com; s=20251104; t=1790039911; x=1790644711; darn=vger.kernel.org; h=cc:to:in-reply-to:references:message-id:content-transfer-encoding :content-type:mime-version:subject:date:from:from:to:cc:subject:date :message-id:reply-to:content-type; bh=hjGK+4py2zVYb4dYSS+MAdawD9WQdT1El8lmBwvFvgc=; b=M6VxZYcFp4GwHOSk9wN2SFVzV7wGxFsFYUUWdRctY2+peGsDIB2Awkxk2JL2go3kfO e4uUchO4gSyogCMgxOSO76FrgeQ7G5gooof4ss9Tl85PRCenVxf3oa5AhivwTkrdEOB2 iVl1qZrhfIufdh3Nk4CG7Wysgxz+NZ9Hi8XqfUL1OQ8N4tV+tlh6C+CCmU0GEfNIzCtJ J/rSQdo5OldJ75m0fTvWOPbuKEQZfa9QGviNRJKEDnBX9HyhFTo21EbOFyuGALCgKxon /ANh/TIs5dWBDaOQaQM5Bvlr9O+D/OLwZJgHr9j+o782K0FjdghQ6iZjH+AujJNMDWRz duUw== X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20260707; t=1790039911; x=1790644711; h=cc:to:in-reply-to:references:message-id:content-transfer-encoding :content-type:mime-version:subject:date:from:x-gm-gg :x-gm-message-state:from:to:cc:subject:date:message-id:reply-to :content-type; bh=hjGK+4py2zVYb4dYSS+MAdawD9WQdT1El8lmBwvFvgc=; b=pVAWdVizhIdmxsCvyayNwy4yIhQpdFC9NhK0S8qMHNyoWplU4nqdzoT4TRn6v61FbQ Vh227+D/Xiydw6+gV8N5vAhHozmpGD8OqSQJA/82Q6lNZ8wll6pJ+g6jpmW9eHz791qB xIQvYuM17CtzCYmW5p1nAhw58U9zTkRFaAK4YX+m95UoNXGP2ZA/L5TmxyuGgPDlnO46 4oT84Ci5FDpSUubtwW8rfosnIUfmIwdzlz2UQ5/m0aMQebKIh83bHJQp6Zc9LLJpZ0CO AviXkQZLqODNA9cffNptAG6xTrDH6OUJRG2uSNvFI1yqzErT/k6wD+nkBJGTBZ6ixVn8 0z5A== X-Forwarded-Encrypted: i=1; AKwUvBwaob4lrr5ep767DhfxzpwaZqOX0I2sJqLYBwAcsDR7Cwdorfsq6+3fW7IP3pKuQscX4zRnwiK5S9q0waE=@vger.kernel.org X-Gm-Message-State: AFuF++nsOP21MQzSFrXgSj4BUvwjlCulGoE3C1aQjpJHeTswZGem3v2I /OlB/DuUhYznjFoHDbB17Jp3mOR6RvArJp103lLBTo6pcKshreClzX6U X-Gm-Gg: AYBFou3PTICNi873wWG5c9mO7fXkJ/dpHgdU8noT7wLWj10u07OMRG1hl+zktBmPCtN iADDaG/B6t1h9dpHVuVMrbQr4h258nEM9LK8aF/c1yTowtzblNNU+o20pjpVaLZCxrhO3o6BQYp 9icfN9MUtp83xz7gMxqeJ0JArOi6e0Ze/tHCYz4x7CoriYUxU9PM19tkhk6roWeMc94wdIWnufk cTIIzMS0YcRr5FkwQUzsS6V9UVG8Wo7858AZZuq6kF/p7NnXyfkMXx7LJbbK6VcQocNDhy7m8dU RAI5HcIShT4aaWEB34rasoZ5UNWaFRH9ukUo1JS3MMW+zMJU/0qVSqh+K23rA9E0YbfiJgQWzl/ U/dzABmriCgb2/PdLBUkkQS8TbSInwmtWvBQzXTu5ZGDhZNtKkg9WsZMqFyTIa9FpNSCBQA1Ii7 T9T3A/4A+sGvdVouQdRZ78ot4brdSZUWC7AtTMm60NVx/tBUtLm99a0b7w+poegYe0Aq+m3EIdj b/gDA== X-Received: by 2002:a05:6820:4c14:b0:6b7:46e9:9700 with SMTP id 006d021491bc7-6ca9c84db7emr10939338eaf.48.1790039911395; Mon, 21 Sep 2026 18:18:31 -0700 (PDT) Received: from localhost ([2a03:2880:ff:55::]) by smtp.gmail.com with ESMTPSA id 586e51a60fabf-48fbcb5a9afsm93283fac.1.2026.09.21.18.18.28 (version=TLS1_3 cipher=TLS_AES_256_GCM_SHA384 bits=256/256); Mon, 21 Sep 2026 18:18:30 -0700 (PDT) From: Bobby Eshleman Date: Mon, 21 Sep 2026 18:18:07 -0700 Subject: [PATCH net-next v2 4/6] vsock/virtio: support guest device network namespace Precedence: bulk X-Mailing-List: linux-kernel@vger.kernel.org List-Id: List-Subscribe: List-Unsubscribe: MIME-Version: 1.0 Content-Type: text/plain; charset="utf-8" Content-Transfer-Encoding: quoted-printable Message-Id: <20260921-vsock-guest-ns-v2-4-693bd78fde9e@meta.com> References: <20260921-vsock-guest-ns-v2-0-693bd78fde9e@meta.com> In-Reply-To: <20260921-vsock-guest-ns-v2-0-693bd78fde9e@meta.com> To: Stefano Garzarella , "David S. Miller" , Eric Dumazet , Jakub Kicinski , Paolo Abeni , Simon Horman , Jonathan Corbet , Shuah Khan , Stefan Hajnoczi , "Michael S. Tsirkin" , Jason Wang , Xuan Zhuo , =?utf-8?q?Eugenio_P=C3=A9rez?= , Shuah Khan , Randy Dunlap , Donald Hunter Cc: virtualization@lists.linux.dev, netdev@vger.kernel.org, linux-kernel@vger.kernel.org, linux-doc@vger.kernel.org, kvm@vger.kernel.org, linux-kselftest@vger.kernel.org, sargun@sargun.me, jlinbox@meta.com, Stanislav Fomichev , Bobby Eshleman X-Mailer: b4 0.14.3 From: Bobby Eshleman virtio-vsock did not have namespace support (the device was always accessible to any global namespace). Make the virtio-vsock device assignable to a namespace and initialize it to init_net. Because virtio-vsock and init_net are both hardcoded to global mode, nothing changes until the assign command is issued. When the device's local-mode namespace is being destroyed, received packets are reset until a new valid namespace has been assigned and/or automatically returned to, and the next RX batch begins (in virtio_transport_rx_work). They are reset rather than dropped because vsock does not retransmit, so a silent drop would leave the host waiting for a timeout, and a connection request arriving in that window has no socket whose teardown would tell it otherwise. This requires making virtio_transport_reset_no_sock() available outside of the common code. When a device is assigned to a namespace, every already established vsock socket that is no longer able to reach the device is forcibly reset. For that reason, adding new sockets to the connected table must be performed atomically with regards to namespace assignment. This ensures that when the socket is added to the connected table that it actually passes the new reachability conditions set by ns assignment. If it wins the race to the table and does NOT pass the reachability tests, then it will be reset. This is the purpose of the new helper 'vsock_maybe_set_connected()'. Signed-off-by: Bobby Eshleman Suggested-by: Stefano Garzarella --- Changes in v2: - Export virtio_transport_reset(), wire it to the new .reset op (Stefano) - netns_assign_allow is now a bool (Stefano) - Pass NULL, not &init_net, in virtio_transport_rx_work(), and comment why (Stefano) - Drop the if (net) guard around put_net() (Stefano) - Drop the comments at the vsock_maybe_set_connected() call sites, the commit msg seems sufficient --- include/linux/virtio_vsock.h | 3 +++ net/vmw_vsock/virtio_transport.c | 24 ++++++++++++++++++------ net/vmw_vsock/virtio_transport_common.c | 27 ++++++++++++++++++--------- 3 files changed, 39 insertions(+), 15 deletions(-) diff --git a/include/linux/virtio_vsock.h b/include/linux/virtio_vsock.h index f91704731057..5d15b6d6bdf7 100644 --- a/include/linux/virtio_vsock.h +++ b/include/linux/virtio_vsock.h @@ -286,6 +286,9 @@ void virtio_transport_inc_tx_pkt(struct virtio_vsock_so= ck *vvs, struct sk_buff * u32 virtio_transport_get_credit(struct virtio_vsock_sock *vvs, u32 wanted); void virtio_transport_put_credit(struct virtio_vsock_sock *vvs, u32 credit= ); void virtio_transport_deliver_tap_pkt(struct sk_buff *skb); +int virtio_transport_reset(struct vsock_sock *vsk, struct sk_buff *skb); +int virtio_transport_reset_no_sock(const struct virtio_transport *t, + struct sk_buff *skb, struct net *net); int virtio_transport_purge_skbs(void *vsk, struct sk_buff_head *list); int virtio_transport_read_skb(struct vsock_sock *vsk, skb_read_actor_t rea= d_actor); int virtio_transport_notify_set_rcvlowat(struct vsock_sock *vsk, int val); diff --git a/net/vmw_vsock/virtio_transport.c b/net/vmw_vsock/virtio_transp= ort.c index 4f9aa9c4c3aa..5ad93af4bd2b 100644 --- a/net/vmw_vsock/virtio_transport.c +++ b/net/vmw_vsock/virtio_transport.c @@ -542,7 +542,7 @@ static bool virtio_transport_msgzerocopy_allow(void) =20 bool virtio_transport_stream_allow(struct vsock_sock *vsk, u32 cid, u32 po= rt) { - return vsock_net_mode_global(vsk); + return vsock_g2h_net_reachable(sock_net(sk_vsock(vsk))); } =20 static bool virtio_transport_seqpacket_allow(struct vsock_sock *vsk, @@ -587,6 +587,8 @@ static struct virtio_transport virtio_transport =3D { .seqpacket_has_data =3D virtio_transport_seqpacket_has_data, =20 .msgzerocopy_allow =3D virtio_transport_msgzerocopy_allow, + .netns_assign_allow =3D true, + .reset =3D virtio_transport_reset, =20 .notify_poll_in =3D virtio_transport_notify_poll_in, .notify_poll_out =3D virtio_transport_notify_poll_out, @@ -616,7 +618,7 @@ virtio_transport_seqpacket_allow(struct vsock_sock *vsk= , u32 remote_cid) struct virtio_vsock *vsock; bool seqpacket_allow; =20 - if (!vsock_net_mode_global(vsk)) + if (!vsock_g2h_net_reachable(sock_net(sk_vsock(vsk)))) return false; =20 seqpacket_allow =3D false; @@ -633,7 +635,11 @@ static void virtio_transport_rx_work(struct work_struc= t *work) { struct virtio_vsock *vsock =3D container_of(work, struct virtio_vsock, rx_work); + struct virtio_transport *t =3D &virtio_transport; struct virtqueue *vq; + struct net *net; + + net =3D vsock_g2h_net_get(); =20 mutex_lock(&vsock->rx_lock); =20 @@ -682,10 +688,14 @@ static void virtio_transport_rx_work(struct work_stru= ct *work) =20 virtio_transport_deliver_tap_pkt(skb); =20 - /* Force virtio-transport into global mode since it - * does not yet support local-mode namespacing. - */ - virtio_transport_recv_pkt(&virtio_transport, skb, NULL); + /* The virtio send path does not use @net. */ + if (unlikely(!net)) { + virtio_transport_reset_no_sock(t, skb, NULL); + kfree_skb(skb); + continue; + } + + virtio_transport_recv_pkt(t, skb, net); } } while (!virtqueue_enable_cb(vq)); =20 @@ -694,6 +704,8 @@ static void virtio_transport_rx_work(struct work_struct= *work) virtio_vsock_rx_fill(vsock); out_nofill: mutex_unlock(&vsock->rx_lock); + + put_net(net); } =20 static int virtio_vsock_vqs_init(struct virtio_vsock *vsock) diff --git a/net/vmw_vsock/virtio_transport_common.c b/net/vmw_vsock/virtio= _transport_common.c index f225f53ed4ba..c24049b2a386 100644 --- a/net/vmw_vsock/virtio_transport_common.c +++ b/net/vmw_vsock/virtio_transport_common.c @@ -1291,8 +1291,7 @@ ssize_t virtio_transport_unsent_bytes(struct vsock_so= ck *vsk) } EXPORT_SYMBOL_GPL(virtio_transport_unsent_bytes); =20 -static int virtio_transport_reset(struct vsock_sock *vsk, - struct sk_buff *skb) +int virtio_transport_reset(struct vsock_sock *vsk, struct sk_buff *skb) { struct virtio_vsock_pkt_info info =3D { .op =3D VIRTIO_VSOCK_OP_RST, @@ -1307,6 +1306,7 @@ static int virtio_transport_reset(struct vsock_sock *= vsk, =20 return virtio_transport_send_pkt_info(vsk, &info); } +EXPORT_SYMBOL_GPL(virtio_transport_reset); =20 /* Normally packets are associated with a socket. There may be no socket = if an * attempt was made to connect to a socket that does not exist. @@ -1315,8 +1315,8 @@ static int virtio_transport_reset(struct vsock_sock *= vsk, * loopback, this is the namespace of the socket. For vhost, this is the * namespace of the VM (i.e., vhost_vsock). */ -static int virtio_transport_reset_no_sock(const struct virtio_transport *t, - struct sk_buff *skb, struct net *net) +int virtio_transport_reset_no_sock(const struct virtio_transport *t, + struct sk_buff *skb, struct net *net) { struct virtio_vsock_hdr *hdr =3D virtio_vsock_hdr(skb); struct virtio_vsock_pkt_info info =3D { @@ -1355,6 +1355,7 @@ static int virtio_transport_reset_no_sock(const struc= t virtio_transport *t, =20 return t->send_pkt(reply, net); } +EXPORT_SYMBOL_GPL(virtio_transport_reset_no_sock); =20 /* This function should be called with sk_lock held and SOCK_DONE set */ static void virtio_transport_remove_sock(struct vsock_sock *vsk) @@ -1478,9 +1479,13 @@ virtio_transport_recv_connecting(struct sock *sk, =20 switch (le16_to_cpu(hdr->op)) { case VIRTIO_VSOCK_OP_RESPONSE: - sk->sk_state =3D TCP_ESTABLISHED; + if (!vsock_maybe_set_connected(vsk)) { + skerr =3D ECONNRESET; + err =3D -ENETUNREACH; + goto destroy; + } + sk->sk_socket->state =3D SS_CONNECTED; - vsock_insert_connected(vsk); sk->sk_state_change(sk); break; case VIRTIO_VSOCK_OP_INVALID: @@ -1736,8 +1741,6 @@ virtio_transport_recv_listen(struct sock *sk, struct = sk_buff *skb, =20 lock_sock_nested(child, SINGLE_DEPTH_NESTING); =20 - child->sk_state =3D TCP_ESTABLISHED; - vchild =3D vsock_sk(child); vsock_addr_init(&vchild->local_addr, le64_to_cpu(hdr->dst_cid), le32_to_cpu(hdr->dst_port)); @@ -1758,7 +1761,13 @@ virtio_transport_recv_listen(struct sock *sk, struct= sk_buff *skb, if (virtio_transport_space_update(child, skb)) child->sk_write_space(child); =20 - vsock_insert_connected(vchild); + if (!vsock_maybe_set_connected(vchild)) { + release_sock(child); + virtio_transport_reset_no_sock(t, skb, sock_net(sk)); + sock_put(child); + return -ENETUNREACH; + } + vsock_enqueue_accept(sk, child); virtio_transport_send_response(vchild, skb); =20 --=20 2.53.0-Meta From nobody Thu Sep 24 17:02:13 2026 Received: from mail-oa2-f35.google.com (mail-oa2-f35.google.com [74.125.231.99]) (using TLSv1.2 with cipher ECDHE-RSA-AES128-GCM-SHA256 (128/128 bits)) (No client certificate requested) by smtp.subspace.kernel.org (Postfix) with ESMTPS id A3908356750 for ; Tue, 22 Sep 2026 01:18:36 +0000 (UTC) Authentication-Results: smtp.subspace.kernel.org; arc=none smtp.client-ip=74.125.231.99 ARC-Seal: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1790039920; cv=none; b=mgK+GLPgAmyIQt6KfIChINsLNMqcXRQ3dFea+5YA37iTPWD1ZY7n6PQqnMF7JZJ0sIOh89ryz3s+LHDImyDMvM7uUcRxe+HiqZfkflIk1U2CpCdfxqhBMIVVZU1LTqB7+o8rSDm0Tb/XfccOMHXjRqYpSi5hxUNaHXZEMY6+w+U= ARC-Message-Signature: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1790039920; c=relaxed/simple; bh=O2u2pSj9Qz/3jUWj1+DPrF71Or2viln4RrS+4V/syQ4=; h=From:Date:Subject:MIME-Version:Content-Type:Message-Id:References: In-Reply-To:To:Cc; b=Q2YfQ0H6KbMxgTLPaCMTyxVA65PCt2KZogSNbWmp/YeYU6aKGi1JdfG6priJpRQ6nlPcRrGPJmOKqZ2hWcqtZjAixPVqzR/5XxPAo5gOxEZHJ3qVaEzXi0Bs0ZmxQYy0fKp4XGzqmdo7L4Wbt81wDL3A3DxdOa6mXLsF5RjNXXw= ARC-Authentication-Results: i=1; smtp.subspace.kernel.org; dmarc=pass (p=none dis=none) header.from=gmail.com; spf=pass smtp.mailfrom=gmail.com; dkim=pass (2048-bit key) header.d=gmail.com header.i=@gmail.com header.b=WzTyl4nT; arc=none smtp.client-ip=74.125.231.99 Authentication-Results: smtp.subspace.kernel.org; dmarc=pass (p=none dis=none) header.from=gmail.com Authentication-Results: smtp.subspace.kernel.org; spf=pass smtp.mailfrom=gmail.com Authentication-Results: smtp.subspace.kernel.org; dkim=pass (2048-bit key) header.d=gmail.com header.i=@gmail.com header.b="WzTyl4nT" Received: by mail-oa2-f35.google.com with SMTP id 586e51a60fabf-486e0f56cddso1432157fac.3 for ; Mon, 21 Sep 2026 18:18:36 -0700 (PDT) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=gmail.com; s=20251104; t=1790039915; x=1790644715; darn=vger.kernel.org; h=cc:to:in-reply-to:references:message-id:content-transfer-encoding :content-type:mime-version:subject:date:from:from:to:cc:subject:date :message-id:reply-to:content-type; bh=CQRMHNrBZb4fE3a5puaoEKZQMJld9V6GAqGwvxaywF4=; b=WzTyl4nTMuQ5r96C7QC4Eo50Cq6M7IbPhcRacPojlC9rkiiUCDmr8YLx3Z1ownqa1x TqPt+Vjrdy4qyYx7eGmzi0rEc4C25vx3E+A42JIoER6DorArF/AV+5PxEOU9AZEePXM2 G9pSC1nMguXeQm/E09Ls7mqGl1aLXge+qBKKAOgaAbyyWIxATRFUe5UqmHZcLo4rPe9D 65msCe5r+Sb1GbDvd1Zk+UVxzljWT6gaW5Zng6N79fuuJ+6bpz0qqoiJNnYUjwdxMhF4 G35awawIYm7/ZuX2eIzWJ6BHuuTrsx+VFgISWeDNwWTT/d0ohnOd8FD6aQShrfIscMwW +pag== X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20260707; t=1790039915; x=1790644715; h=cc:to:in-reply-to:references:message-id:content-transfer-encoding :content-type:mime-version:subject:date:from:x-gm-gg :x-gm-message-state:from:to:cc:subject:date:message-id:reply-to :content-type; bh=CQRMHNrBZb4fE3a5puaoEKZQMJld9V6GAqGwvxaywF4=; b=MQy6ZhXWeb4S/zBvGP5/q5GqHZaPlMz28YyXLKKA8y2s3tdoFXOT/zpR7nTIxZOgYp yIylIJCreBQCqAz7qrNweDa2Ib1WajdmFPYKtIXX6o51B4AyiVR/WzIzoANL/4qHf3DU usXa65NAE5+ddmg66cVsiesqmAkv7jzOXxI90+7PhM8gv8gsEi8SJHrZaW8a9SLbMal/ PRWGDDwF6nbVqUPSgG1i+Sht6rGr1Wt5oMzFMDrWPoKNscN2K1jSEsr6e8wnj8BMJrOd AFNR9tUg+VCiHZaGV1WcgQtHoJWpl/Y+XkrAAE9HeKCJYwfmA8ZKI9aRdWzx+6fAhFom MRJw== X-Forwarded-Encrypted: i=1; AKwUvByyug/CDLewx/IvkEqIpTDHeD7rGshq2FqB4qBxgUoByCipP1lK7IDp74E1/FNmawO1k4d+iBHFK8TARzU=@vger.kernel.org X-Gm-Message-State: AFuF++nORN+qI/VHVvFysl/H1pVYkx8AzMwVhKruJOqGG8xXJQ7xiNqs ucHal96QojDZsK6rImUg+IVhpEz87d+V9n/QiMZlo32TbPRR6utihhYC X-Gm-Gg: AYBFou1giB+sgmP2SdCk6Z0JIftErnL2+v8e+YHnzIuyu9zwc3uwqbDnTbqKhad57Kj tZqYFa7RssQYjCYljX9yFbhNNG7dKaw/karmTE8c7bU8hhDXaJxUh3l72Vs6hVgZ8G58QrMCk6d e9+OPcW1qCxR6aXc+lMZcmZZ1cr4CCI442FNlDt1YlX6PVEKplnyKB3XKYZ71px+Zgy8imehjzx aibpRWM0rTcrYT+2WgtrQUU9uG58Fs0NJmP5UuEgAofgVzY0cPbtjyY1qKUI1kuL32bIxvJguTI aTBJxoWoXvUnirhPveK1fPa6HLR+wAkH2drlIUW1EyrtCi/06ZDfamIfsASlPULTShOMNDa5Z7o ssckgVg/5rJP5tqpVC1ZqcnjdzsvcaVR/oIqm5fRoGnksg+A2MapFn+hsS562Y8gzpBlaenvudU 8JwGg86qDB27Xv5B6aYfMnhQJY7RZAs14ZqCW6cubj2qrEPqZo7btYho2m6CcYbrNFNFs= X-Received: by 2002:a05:6820:81c9:b0:6cd:3fdc:a931 with SMTP id 006d021491bc7-6cd3fecdef2mr8158701eaf.78.1790039915084; Mon, 21 Sep 2026 18:18:35 -0700 (PDT) Received: from localhost ([2a03:2880:ff:4a::]) by smtp.gmail.com with ESMTPSA id 006d021491bc7-6d1dbd52475sm117564eaf.1.2026.09.21.18.18.32 (version=TLS1_3 cipher=TLS_AES_256_GCM_SHA384 bits=256/256); Mon, 21 Sep 2026 18:18:33 -0700 (PDT) From: Bobby Eshleman Date: Mon, 21 Sep 2026 18:18:08 -0700 Subject: [PATCH net-next v2 5/6] selftests/vsock: test the guest vsock device network namespace Precedence: bulk X-Mailing-List: linux-kernel@vger.kernel.org List-Id: List-Subscribe: List-Unsubscribe: MIME-Version: 1.0 Content-Type: text/plain; charset="utf-8" Content-Transfer-Encoding: quoted-printable Message-Id: <20260921-vsock-guest-ns-v2-5-693bd78fde9e@meta.com> References: <20260921-vsock-guest-ns-v2-0-693bd78fde9e@meta.com> In-Reply-To: <20260921-vsock-guest-ns-v2-0-693bd78fde9e@meta.com> To: Stefano Garzarella , "David S. Miller" , Eric Dumazet , Jakub Kicinski , Paolo Abeni , Simon Horman , Jonathan Corbet , Shuah Khan , Stefan Hajnoczi , "Michael S. Tsirkin" , Jason Wang , Xuan Zhuo , =?utf-8?q?Eugenio_P=C3=A9rez?= , Shuah Khan , Randy Dunlap , Donald Hunter Cc: virtualization@lists.linux.dev, netdev@vger.kernel.org, linux-kernel@vger.kernel.org, linux-doc@vger.kernel.org, kvm@vger.kernel.org, linux-kselftest@vger.kernel.org, sargun@sargun.me, jlinbox@meta.com, Stanislav Fomichev , Bobby Eshleman X-Mailer: b4 0.14.3 From: Bobby Eshleman Add tests for guest vsock device namespace assignment, including ns destruction and the device moving between namespaces. We do add ynl/cli.py, so have added python3 and PyYAML to the dependency checks. Signed-off-by: Bobby Eshleman Suggested-by: Stefano Garzarella --- Changes in v2: - Drive the assign with ynl cli.py, drop the vsock_assign_g2h_netns ioctl helper and its patch - Terminate the guest socat sender too, it sometimes outlived the test and kept holding on to a port the next test binds --- tools/testing/selftests/vsock/vmtest.sh | 421 ++++++++++++++++++++++++++++= +++- 1 file changed, 416 insertions(+), 5 deletions(-) diff --git a/tools/testing/selftests/vsock/vmtest.sh b/tools/testing/selfte= sts/vsock/vmtest.sh index 310dfc2a39ad..e94cc2fd90cc 100755 --- a/tools/testing/selftests/vsock/vmtest.sh +++ b/tools/testing/selftests/vsock/vmtest.sh @@ -17,6 +17,8 @@ readonly KERNEL_CHECKOUT=3D$(realpath "${SCRIPT_DIR}"/../= ../../../) source "${SCRIPT_DIR}"/../kselftest/ktap_helpers.sh =20 readonly VSOCK_TEST=3D"${SCRIPT_DIR}"/vsock_test +readonly YNL_CLI=3D"${KERNEL_CHECKOUT}"/tools/net/ynl/pyynl/cli.py +readonly VSOCK_SPEC=3D"${KERNEL_CHECKOUT}"/Documentation/netlink/specs/vso= ck.yaml readonly TEST_GUEST_PORT=3D51000 readonly TEST_HOST_PORT=3D50000 readonly TEST_HOST_PORT_LISTENER=3D50001 @@ -73,6 +75,12 @@ readonly TEST_NAMES=3D( ns_delete_vm_ok ns_delete_host_ok ns_delete_both_ok + ns_guest_local_connect_to_host_fails + ns_guest_assign_g2h_netns_connect_to_host_ok + ns_guest_assign_g2h_netns_init_ns_connect_fails + ns_guest_assign_g2h_netns_host_connect_ok + ns_guest_assign_g2h_netns_reset_on_ns_delete_ok + ns_guest_assign_g2h_netns_old_conn_send_fails ) readonly TEST_DESCS=3D( # vm_server_host_client @@ -149,12 +157,36 @@ readonly TEST_DESCS=3D( =20 # ns_delete_both_ok "Check that deleting the VM and host's namespaces does not break the sock= et connection" + + # ns_guest_local_connect_to_host_fails + "Check a guest process in a local ns cannot reach the host without the ne= tns assign." + + # ns_guest_assign_g2h_netns_connect_to_host_ok + "Check a guest process in a local ns reaches the host once the vsock devi= ce is assigned to it." + + # ns_guest_assign_g2h_netns_init_ns_connect_fails + "Check the guest's initial ns loses vsock once the device is assigned to = another ns." + + # ns_guest_assign_g2h_netns_host_connect_ok + "Check the host reaches a guest listener in the ns the vsock device is as= signed to." + + # ns_guest_assign_g2h_netns_reset_on_ns_delete_ok + "Check the guest's vsock device returns to the initial ns when its ns is = deleted." + + # ns_guest_assign_g2h_netns_old_conn_send_fails + "Check connections made before the assign stop sending once they lose the= device." ) =20 readonly USE_SHARED_VM=3D( vm_server_host_client vm_client_host_server vm_loopback + ns_guest_local_connect_to_host_fails + ns_guest_assign_g2h_netns_connect_to_host_ok + ns_guest_assign_g2h_netns_init_ns_connect_fails + ns_guest_assign_g2h_netns_host_connect_ok + ns_guest_assign_g2h_netns_reset_on_ns_delete_ok + ns_guest_assign_g2h_netns_old_conn_send_fails ) readonly NS_MODES=3D("local" "global") =20 @@ -302,7 +334,8 @@ check_args() { } =20 check_deps() { - for dep in vng ${QEMU} busybox pkill ssh ss socat nsenter; do + for dep in vng ${QEMU} busybox pkill ssh ss socat nsenter unshare \ + python3; do if [[ ! -x $(command -v "${dep}") ]]; then echo -e "skip: dependency ${dep} not found!\n" exit "${KSFT_SKIP}" @@ -314,6 +347,18 @@ check_deps() { printf " Please build the kselftest vsock target.\n" exit "${KSFT_SKIP}" fi + + if ! python3 -c "import yaml" &>/dev/null; then + echo -e "skip: python3 yaml module not found!\n" + exit "${KSFT_SKIP}" + fi + + for dep in "${YNL_CLI}" "${VSOCK_SPEC}"; do + if [[ ! -r "${dep}" ]]; then + printf "skip: %s not found!\n" "${dep}" + exit "${KSFT_SKIP}" + fi + done } =20 check_netns() { @@ -401,6 +446,17 @@ setup_home() { mkdir -p "$(dirname "${SSH_KEY_PATH}")" ssh-keygen -t ed25519 -f "${SSH_KEY_PATH}" -N "" -q cp "${VSOCK_TEST}" "${TEST_HOME}"/vsock_test + + mkdir -p "${TEST_HOME}"/ynl + cp "${YNL_CLI}" "${TEST_HOME}"/ynl/ + cp -r "$(dirname "${YNL_CLI}")"/lib "${TEST_HOME}"/ynl/ + cp "${VSOCK_SPEC}" "${TEST_HOME}"/ynl/ + + # One of the tests runs the CLI as an unprivileged user, so the CLI + # has to be reachable by one. + chmod -R a+rX "${TEST_HOME}"/ynl + + chmod 755 "${TEST_HOME}" } =20 create_pidfile() { @@ -528,6 +584,59 @@ vm_wait_for_ssh() { done } =20 +# Create a local mode namespace in the VM and echo the pid holding it open. +vm_ns_start() { + local ns=3D$1 + + vm_ssh "${ns}" -- \ + "echo local > /proc/sys/net/vsock/child_ns_mode" &>/dev/null + + vm_ssh "${ns}" -- "unshare -n sleep infinity" \ + '>/dev/null 2>&1 & echo $!' +} + +# Returns once the holder is gone, so that the namespace is unreferenced a= nd +# the kernel can start tearing it down. +vm_ns_stop() { + local ns=3D$1 + local nspid=3D$2 + + vm_ssh "${ns}" <<-EOF &>/dev/null + kill ${nspid} + for ((i =3D 0; i < ${WAIT_PERIOD_MAX}; i++)); do + kill -0 ${nspid} 2>/dev/null || break + sleep 1 + done + EOF +} + +# Runs in the guest's initial namespace when is empty. The command= must +# not contain single quotes. +vm_ns_exec() { + local ns=3D$1 + local nspid=3D$2 + local cmd=3D$3 + + if [[ -z "${nspid}" ]]; then + vm_ssh "${ns}" -- "${cmd}" + return + fi + + vm_ssh "${ns}" -- nsenter -t "${nspid}" -n sh -c "'${cmd}'" +} + +vm_ns_assign_g2h() { + local ns=3D$1 + local nspid=3D$2 + + vm_ns_exec "${ns}" "${nspid}" "python3 /root/ynl/cli.py --no-schema \ + --spec /root/ynl/vsock.yaml --do dev-netns-set" +} + +vm_reset_g2h() { + vm_ns_assign_g2h "init_ns" "" &>/dev/null +} + # derived from selftests/net/net_helper.sh wait_for_listener() { @@ -564,17 +673,33 @@ wait_for_listener() done } =20 -vm_wait_for_listener() { +# Runs in the guest's initial namespace when is empty. +vm_ns_wait_for_listener() { local ns=3D$1 - local port=3D$2 - local protocol=3D$3 + local nspid=3D$2 + local port=3D$3 + local protocol=3D$4 + local nsenter=3D + local args + + [[ -n "${nspid}" ]] && nsenter=3D"nsenter -t ${nspid} -n" + args=3D"${port} ${WAIT_PERIOD} ${WAIT_PERIOD_MAX} ${protocol}" =20 vm_ssh "${ns}" <. +guest_send_to_host() { + local ns=3D$1 + local nspid=3D$2 + local port=3D$3 + local outfile=3D$4 + local cmd=3D"echo TEST | socat -u STDIN VSOCK-CONNECT:2:${port}" + local pid + + socat -u VSOCK-LISTEN:"${port}" STDOUT > "${outfile}" 2>/dev/null & + pid=3D$! + host_wait_for_listener "${ns}" "${port}" "vsock" + + vm_ns_exec "${ns}" "${nspid}" "${cmd}" 2>/dev/null + + timeout "${WAIT_PERIOD}" \ + bash -c 'while [[ ! -s '"${outfile}"' ]]; do sleep 1; done' + + terminate_pids "${pid}" +} + +# Send a string from the host to a listener in the guest and leave what the +# guest received in . +host_send_to_guest() { + local ns=3D$1 + local nspid=3D$2 + local port=3D$3 + local outfile=3D$4 + local cmd=3D"socat -u VSOCK-LISTEN:${port} STDOUT" + local dst=3D"VSOCK-CONNECT:${VSOCK_CID}:${port}" + local pid + + vm_ns_exec "${ns}" "${nspid}" "${cmd}" > "${outfile}" 2>/dev/null & + pid=3D$! + vm_ns_wait_for_listener "${ns}" "${nspid}" "${port}" "vsock" + + echo TEST | socat -u STDIN "${dst}" 2>/dev/null + + timeout "${WAIT_PERIOD}" \ + bash -c 'while [[ ! -s '"${outfile}"' ]]; do sleep 1; done' + + terminate_pids "${pid}" +} + +test_ns_guest_assign_g2h_netns_old_conn_send_fails() { + local gap=3D$(( WAIT_PERIOD * 3 )) + local port=3D12346 + local outfile + local result + local sender + local nspid + local pid + + nspid=3D$(vm_ns_start "init_ns") + if [[ -z "${nspid}" ]]; then + log_host "failed to create a namespace inside the guest" + return "${KSFT_FAIL}" + fi + + outfile=3D$(mktemp) + socat -u VSOCK-LISTEN:"${port}" STDOUT > "${outfile}" 2>/dev/null & + pid=3D$! + host_wait_for_listener "init_ns" "${port}" "vsock" + + # Send a message, wait, then send another. While waiting, assign the + # device to a namespace. Confirm the second message does not arrive. + vm_ssh "init_ns" -- \ + "(echo FIRST; sleep ${gap}; echo SECOND) |" \ + "socat -u STDIN VSOCK-CONNECT:2:${port}" &>/dev/null & + sender=3D$! + + sleep "${WAIT_PERIOD}" + + if ! vm_ns_assign_g2h "init_ns" "${nspid}"; then + log_host "failed to assign the vsock device to the guest ns" + terminate_pids "${pid}" "${sender}" + rm -f "${outfile}" + vm_ns_stop "init_ns" "${nspid}" + vm_reset_g2h + return "${KSFT_FAIL}" + fi + + # Let the second write happen and land, if it is going to. + sleep $(( gap + WAIT_PERIOD )) + + terminate_pids "${pid}" "${sender}" + result=3D$(cat "${outfile}") + rm -f "${outfile}" + + vm_ns_stop "init_ns" "${nspid}" + vm_reset_g2h + + if [[ "${result}" !=3D *FIRST* ]]; then + log_host "no connection before the assign: [${result}]" + return "${KSFT_FAIL}" + fi + + if [[ "${result}" =3D=3D *SECOND* ]]; then + log_host "old connection still delivered after the assign" + return "${KSFT_FAIL}" + fi + + return "${KSFT_PASS}" +} + +test_ns_guest_local_connect_to_host_fails() { + local port=3D12345 + local outfile + local result + local nspid + + nspid=3D$(vm_ns_start "init_ns") + if [[ -z "${nspid}" ]]; then + log_host "failed to create a namespace inside the guest" + return "${KSFT_FAIL}" + fi + + outfile=3D$(mktemp) + guest_send_to_host "init_ns" "${nspid}" "${port}" "${outfile}" + + vm_ns_stop "init_ns" "${nspid}" + vm_reset_g2h + + result=3D$(cat "${outfile}") + rm -f "${outfile}" + + if [[ "${result}" =3D=3D TEST ]]; then + return "${KSFT_FAIL}" + fi + + return "${KSFT_PASS}" +} + +test_ns_guest_assign_g2h_netns_connect_to_host_ok() { + local port=3D12345 + local outfile + local result + local nspid + + nspid=3D$(vm_ns_start "init_ns") + if [[ -z "${nspid}" ]]; then + log_host "failed to create a namespace inside the guest" + return "${KSFT_FAIL}" + fi + + if ! vm_ns_assign_g2h "init_ns" "${nspid}"; then + log_host "failed to assign the vsock device to the guest ns" + vm_ns_stop "init_ns" "${nspid}" + vm_reset_g2h + return "${KSFT_FAIL}" + fi + + outfile=3D$(mktemp) + guest_send_to_host "init_ns" "${nspid}" "${port}" "${outfile}" + + vm_ns_stop "init_ns" "${nspid}" + vm_reset_g2h + + result=3D$(cat "${outfile}") + rm -f "${outfile}" + + if [[ "${result}" !=3D TEST ]]; then + return "${KSFT_FAIL}" + fi + + return "${KSFT_PASS}" +} + +test_ns_guest_assign_g2h_netns_init_ns_connect_fails() { + local port=3D12345 + local outfile + local result + local nspid + + nspid=3D$(vm_ns_start "init_ns") + if [[ -z "${nspid}" ]]; then + log_host "failed to create a namespace inside the guest" + return "${KSFT_FAIL}" + fi + + if ! vm_ns_assign_g2h "init_ns" "${nspid}"; then + log_host "failed to assign the vsock device to the guest ns" + vm_ns_stop "init_ns" "${nspid}" + vm_reset_g2h + return "${KSFT_FAIL}" + fi + + # The device now belongs to a local-mode namespace, so the guest's + # initial namespace must no longer reach the host. + outfile=3D$(mktemp) + guest_send_to_host "init_ns" "" "${port}" "${outfile}" + + vm_ns_stop "init_ns" "${nspid}" + vm_reset_g2h + + result=3D$(cat "${outfile}") + rm -f "${outfile}" + + if [[ "${result}" =3D=3D TEST ]]; then + return "${KSFT_FAIL}" + fi + + return "${KSFT_PASS}" +} + +test_ns_guest_assign_g2h_netns_host_connect_ok() { + local port=3D12345 + local outfile + local result + local nspid + + nspid=3D$(vm_ns_start "init_ns") + if [[ -z "${nspid}" ]]; then + log_host "failed to create a namespace inside the guest" + return "${KSFT_FAIL}" + fi + + if ! vm_ns_assign_g2h "init_ns" "${nspid}"; then + log_host "failed to assign the vsock device to the guest ns" + vm_ns_stop "init_ns" "${nspid}" + vm_reset_g2h + return "${KSFT_FAIL}" + fi + + outfile=3D$(mktemp) + host_send_to_guest "init_ns" "${nspid}" "${port}" "${outfile}" + + vm_ns_stop "init_ns" "${nspid}" + vm_reset_g2h + + result=3D$(cat "${outfile}") + rm -f "${outfile}" + + if [[ "${result}" !=3D TEST ]]; then + return "${KSFT_FAIL}" + fi + + return "${KSFT_PASS}" +} + +test_ns_guest_assign_g2h_netns_reset_on_ns_delete_ok() { + local port=3D12345 + local outfile + local result + local nspid + local i + + nspid=3D$(vm_ns_start "init_ns") + if [[ -z "${nspid}" ]]; then + log_host "failed to create a namespace inside the guest" + return "${KSFT_FAIL}" + fi + + if ! vm_ns_assign_g2h "init_ns" "${nspid}"; then + log_host "failed to assign the vsock device to the guest ns" + vm_ns_stop "init_ns" "${nspid}" + vm_reset_g2h + return "${KSFT_FAIL}" + fi + + vm_ns_stop "init_ns" "${nspid}" + + # The holder is gone, but the namespace itself is dismantled from a + # workqueue, so the device does not come back the same instant. Retry + # until it does, rather than expecting the first send to succeed. + outfile=3D$(mktemp) + for ((i =3D 0; i < 5; i++)); do + sleep "${WAIT_PERIOD}" + guest_send_to_host "init_ns" "" "$(( port + i ))" "${outfile}" + result=3D$(cat "${outfile}") + if [[ "${result}" =3D=3D TEST ]]; then + break + fi + done + + rm -f "${outfile}" + vm_reset_g2h + + if [[ "${result}" !=3D TEST ]]; then + return "${KSFT_FAIL}" + fi + + return "${KSFT_PASS}" +} + shared_vm_test() { local tname =20 --=20 2.53.0-Meta From nobody Thu Sep 24 17:02:13 2026 Received: from mail-ot1-f41.google.com (mail-ot1-f41.google.com [209.85.210.41]) (using TLSv1.2 with cipher ECDHE-RSA-AES128-GCM-SHA256 (128/128 bits)) (No client certificate requested) by smtp.subspace.kernel.org (Postfix) with ESMTPS id EEDDA367280 for ; Tue, 22 Sep 2026 01:18:39 +0000 (UTC) Authentication-Results: smtp.subspace.kernel.org; arc=none smtp.client-ip=209.85.210.41 ARC-Seal: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1790039922; cv=none; b=Up2yz15tfFH4znZwtki5pZwgzdf5sPJkg3xfr9LQKXivxr7UgStai4uYu7pSNaCzT28Wo8A8oKD8ui/QUcsldqnSi0cvsvcZcoGN7S5zmCfvf5CSYTswT2Q9M0iT08+Qao8Oj35cf7ZKqQXHXAahulZxkx7ESO1BI8q4K0yoWvs= ARC-Message-Signature: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1790039922; c=relaxed/simple; bh=iVYKuJ2DcdFXVTgCRt4VjQYmkYPGzA6mYOOB5aRIk7c=; h=From:Date:Subject:MIME-Version:Content-Type:Message-Id:References: In-Reply-To:To:Cc; b=sJvDGtuqwZ5CdmXduz3QiRGm530sGejA8oiB/u1TDzdS2f6liMQ1ozviMszWbbT0XsZ0FpNpTJXhGvnpuLEcg1XmuOmQUwwmsTdcEkek9KZiVwUIki+jd7kCqLWl3XYygj0IBT8By7K0C60WoTb+HxBW1kbeRV0mr8ZaWTEwiaE= ARC-Authentication-Results: i=1; smtp.subspace.kernel.org; dmarc=pass (p=none dis=none) header.from=gmail.com; spf=pass smtp.mailfrom=gmail.com; dkim=pass (2048-bit key) header.d=gmail.com header.i=@gmail.com header.b=nqGY5VQH; arc=none smtp.client-ip=209.85.210.41 Authentication-Results: smtp.subspace.kernel.org; dmarc=pass (p=none dis=none) header.from=gmail.com Authentication-Results: smtp.subspace.kernel.org; spf=pass smtp.mailfrom=gmail.com Authentication-Results: smtp.subspace.kernel.org; dkim=pass (2048-bit key) header.d=gmail.com header.i=@gmail.com header.b="nqGY5VQH" Received: by mail-ot1-f41.google.com with SMTP id 46e09a7af769-7fccba9c675so421131a34.0 for ; Mon, 21 Sep 2026 18:18:39 -0700 (PDT) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=gmail.com; s=20251104; t=1790039919; x=1790644719; darn=vger.kernel.org; h=cc:to:in-reply-to:references:message-id:content-transfer-encoding :content-type:mime-version:subject:date:from:from:to:cc:subject:date :message-id:reply-to:content-type; bh=45Bl+e2P9YwHGQJKKsleiX3YXi1lYrJXOyTW+Ow8cCQ=; b=nqGY5VQHingWkjqz8rdHQazhI1p2mM16VrhuO0xQaz81oHN/TP+OoUNzyB/aLuuU// tzCy0dKHbaLLREIw/fXGxnQER0k3SarDCQZz38biP9bBFjaHjQj8/+Bzg2yZphjROzFE H2iEb/9Jw5DgRFfUG615DEPB8HZ9DuAhnvpLAikgc1MIMdaRf8th3j6xpqeKrOeoJcXH /vG60R/D2g+IYlvfg6tvkjZ+pF1CNfW+qpIWdN+xzFlC8b2bgKhZ2115hcaCCCmN6AqJ Bf21rkaspTs7tN3qJY4C8EdecMERH3uMBJFTwKWSYjiTDsOlIe5+HiNJL8w2aJP7Zdr2 RA7Q== X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20260707; t=1790039919; x=1790644719; h=cc:to:in-reply-to:references:message-id:content-transfer-encoding :content-type:mime-version:subject:date:from:x-gm-gg :x-gm-message-state:from:to:cc:subject:date:message-id:reply-to :content-type; bh=45Bl+e2P9YwHGQJKKsleiX3YXi1lYrJXOyTW+Ow8cCQ=; b=Z+nHqnwrk4kClRZyvdbw65pvHhwShip1zr7fUw5hDmFn8YAbm9LxiZgBRCcijkhvu1 lB5ynvTOXFDHuB3NRifo3UOA7RhBNahP/r/S/zE++bRL0GgFxIDpqCvm/sXCANhhx/8N pNld2wCbvNa3bYooJo7vnb2mcLEOGW883KWyn9rYPrzKkneP4AuNTT46kfhbjOwOf4LP 7MxpCGTRR4/PYPmWMErXRdb/0gqK9PhPVwuEHsCKZVDVHVYMde7h8hMEG4QNBLR54q5r ubrH99xyPASZ+fGGyuy6T+Txa3G6kBkQ/w1igtk3DPlJCDCElmIJZkmLinKcRpR8mR+r ReLA== X-Forwarded-Encrypted: i=1; AKwUvBzX52iScSzPS7AGmBG/LgvMq+Sn4aIprXCMTHBON4ZuIGGEUczM0v0Czk3UwYa7kwlNghNQwHWXhiOjQWM=@vger.kernel.org X-Gm-Message-State: AFuF++n2B4l4Is80E/n3fO9ld38/XVyauNRf3F/gS5MwyfmwGbAVPD45 4AbTK1XsACYPgQnUpwZbnTFrcFnPId0WHsnhpfYgzRuChEcqD87+1WPn X-Gm-Gg: AYBFou1thzY2ReCjXckbX0QPW+3x6v+iS0IAMaqC5QMuEQAtovSRMOpm08aXbc96QrB Qj/47OFvt/OtUXiA5P8tGLYZPmIPCAeCFE7E6FpBgrfiAK3qNsRJzMLFyDjPa07m6aiA3rAj1kc jeIjRwOpedSolmSDGbJGu9MbONvdBNWH9KsDY2bAlKu3lT6ycozpU3t+XAE2/SdFLKo/+rjedR0 dg3U9X8e+NwgxHeEbNXEmOUaOohk2O2B5BbaFK4S8TtNvaY7h+i/9e3tIjj5ZOosS4awT9JqfJN KGwpg2fOjH54Ehbx6qaSvcgNMmq/qdnAEssW+colVSGTGdsaNLB4XbTuGQl//BrhJxbijv+H1W2 qEiam08vvge2XzmzMvXYcuIqjiWFmxgu0DZyX6tRNUo5ssblTVsI7bOGlFytgyatjjgr1mbwAa9 OY8TbclZizcGzpeGjoL4hTIdL3odoqYG0mexS8L6eja9TQ11RiuDA6lpEu/1IQuD5jDcQ= X-Received: by 2002:a05:6808:1818:b0:4b8:4703:db88 with SMTP id 5614622812f47-4d4388a7358mr1277287b6e.17.1790039918606; Mon, 21 Sep 2026 18:18:38 -0700 (PDT) Received: from localhost ([2a03:2880:ff:5e::]) by smtp.gmail.com with ESMTPSA id 5614622812f47-4d4bb6be7b3sm129951b6e.0.2026.09.21.18.18.36 (version=TLS1_3 cipher=TLS_AES_256_GCM_SHA384 bits=256/256); Mon, 21 Sep 2026 18:18:37 -0700 (PDT) From: Bobby Eshleman Date: Mon, 21 Sep 2026 18:18:09 -0700 Subject: [PATCH net-next v2 6/6] selftests/vsock: test the netns assign privilege checks Precedence: bulk X-Mailing-List: linux-kernel@vger.kernel.org List-Id: List-Subscribe: List-Unsubscribe: MIME-Version: 1.0 Content-Type: text/plain; charset="utf-8" Content-Transfer-Encoding: quoted-printable Message-Id: <20260921-vsock-guest-ns-v2-6-693bd78fde9e@meta.com> References: <20260921-vsock-guest-ns-v2-0-693bd78fde9e@meta.com> In-Reply-To: <20260921-vsock-guest-ns-v2-0-693bd78fde9e@meta.com> To: Stefano Garzarella , "David S. Miller" , Eric Dumazet , Jakub Kicinski , Paolo Abeni , Simon Horman , Jonathan Corbet , Shuah Khan , Stefan Hajnoczi , "Michael S. Tsirkin" , Jason Wang , Xuan Zhuo , =?utf-8?q?Eugenio_P=C3=A9rez?= , Shuah Khan , Randy Dunlap , Donald Hunter Cc: virtualization@lists.linux.dev, netdev@vger.kernel.org, linux-kernel@vger.kernel.org, linux-doc@vger.kernel.org, kvm@vger.kernel.org, linux-kselftest@vger.kernel.org, sargun@sargun.me, jlinbox@meta.com, Stanislav Fomichev , Bobby Eshleman X-Mailer: b4 0.14.3 From: Bobby Eshleman VSOCK_CMD_DEV_NETNS_SET refuses callers without CAP_NET_ADMIN in the init user namespace. Add two tests: one confirms that CAP_NET_ADMIN is required even by a privileged user and the other confirms that CAP_NET_ADMIN in an unprivileged user ns alone is insufficient. CONFIG_USER_NS is needed to test the CAP_NET_ADMIN + unprivileged user ns case. Signed-off-by: Bobby Eshleman Suggested-by: Stefano Garzarella --- Changes in v2: - Assert only that the command fails, not EPERM: ynl's cli.py does not report the errno (Sashiko) - Use ynl cli.py for the assign --- tools/testing/selftests/vsock/config | 1 + tools/testing/selftests/vsock/vmtest.sh | 54 +++++++++++++++++++++++++++++= +++- 2 files changed, 54 insertions(+), 1 deletion(-) diff --git a/tools/testing/selftests/vsock/config b/tools/testing/selftests= /vsock/config index 5f0a4f17dfc9..4b31085558fa 100644 --- a/tools/testing/selftests/vsock/config +++ b/tools/testing/selftests/vsock/config @@ -109,3 +109,4 @@ CONFIG_FS_DAX=3Dy CONFIG_MEMORY_HOTPLUG=3Dy CONFIG_MEMORY_HOTREMOVE=3Dy CONFIG_ZONE_DEVICE=3Dy +CONFIG_USER_NS=3Dy diff --git a/tools/testing/selftests/vsock/vmtest.sh b/tools/testing/selfte= sts/vsock/vmtest.sh index e94cc2fd90cc..4f42bcdac3f6 100755 --- a/tools/testing/selftests/vsock/vmtest.sh +++ b/tools/testing/selftests/vsock/vmtest.sh @@ -81,6 +81,8 @@ readonly TEST_NAMES=3D( ns_guest_assign_g2h_netns_host_connect_ok ns_guest_assign_g2h_netns_reset_on_ns_delete_ok ns_guest_assign_g2h_netns_old_conn_send_fails + ns_guest_assign_g2h_netns_no_cap_net_admin_fails + ns_guest_assign_g2h_netns_unpriv_user_ns_fails ) readonly TEST_DESCS=3D( # vm_server_host_client @@ -175,6 +177,12 @@ readonly TEST_DESCS=3D( =20 # ns_guest_assign_g2h_netns_old_conn_send_fails "Check connections made before the assign stop sending once they lose the= device." + + # ns_guest_assign_g2h_netns_no_cap_net_admin_fails + "Check assigning the guest's vsock device to a namespace needs CAP_NET_AD= MIN." + + # ns_guest_assign_g2h_netns_unpriv_user_ns_fails + "Check an unprivileged user cannot claim the guest's vsock device via a u= ser ns." ) =20 readonly USE_SHARED_VM=3D( @@ -187,6 +195,8 @@ readonly USE_SHARED_VM=3D( ns_guest_assign_g2h_netns_host_connect_ok ns_guest_assign_g2h_netns_reset_on_ns_delete_ok ns_guest_assign_g2h_netns_old_conn_send_fails + ns_guest_assign_g2h_netns_no_cap_net_admin_fails + ns_guest_assign_g2h_netns_unpriv_user_ns_fails ) readonly NS_MODES=3D("local" "global") =20 @@ -335,7 +345,7 @@ check_args() { =20 check_deps() { for dep in vng ${QEMU} busybox pkill ssh ss socat nsenter unshare \ - python3; do + setpriv python3; do if [[ ! -x $(command -v "${dep}") ]]; then echo -e "skip: dependency ${dep} not found!\n" exit "${KSFT_SKIP}" @@ -1832,6 +1842,48 @@ test_ns_guest_assign_g2h_netns_reset_on_ns_delete_ok= () { return "${KSFT_PASS}" } =20 +test_ns_guest_assign_g2h_netns_no_cap_net_admin_fails() { + local cmd=3D"unshare -n setpriv --bounding-set=3D-net_admin" + local rc + + vm_ssh "init_ns" -- "${cmd}" python3 /root/ynl/cli.py --no-schema \ + --spec /root/ynl/vsock.yaml --do dev-netns-set &>/dev/null + rc=3D$? + + if [[ "${rc}" -eq 0 ]]; then + log_host "assign unexpectedly succeeded without CAP_NET_ADMIN" + return "${KSFT_FAIL}" + fi + + return "${KSFT_PASS}" +} + +test_ns_guest_assign_g2h_netns_unpriv_user_ns_fails() { + local unpriv_uid=3D65534 + local unpriv + local rc + + unpriv=3D"setpriv --reuid=3D${unpriv_uid} --regid=3D${unpriv_uid}" + unpriv=3D"${unpriv} --clear-groups" + + if ! vm_ssh "init_ns" -- "${unpriv} unshare -U true"; then + log_host "unprivileged user namespaces unavailable, skipping" + return "${KSFT_SKIP}" + fi + + vm_ssh "init_ns" -- "${unpriv} unshare -Urn" \ + python3 /root/ynl/cli.py --no-schema \ + --spec /root/ynl/vsock.yaml --do dev-netns-set &>/dev/null + rc=3D$? + + if [[ "${rc}" -eq 0 ]]; then + log_host "assign unexpectedly succeeded for unprivileged user" + return "${KSFT_FAIL}" + fi + + return "${KSFT_PASS}" +} + shared_vm_test() { local tname =20 --=20 2.53.0-Meta