From nobody Mon Jun 8 05:25:47 2026 Received: from mail-pl1-f170.google.com (mail-pl1-f170.google.com [209.85.214.170]) (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 B367E360EDE for ; Mon, 1 Jun 2026 19:24:38 +0000 (UTC) Authentication-Results: smtp.subspace.kernel.org; arc=none smtp.client-ip=209.85.214.170 ARC-Seal: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1780341881; cv=none; b=B7/ZQ16ZPTxDupMQKiS0qPl934GU5bmSKqL/Pp3g+OphrV9PZlhxAiPnizx3ewE5dVu64xcyy2AbkDU2PRiyJQSUItIpw1I5C2i+BqZUCRQJ5oq1o9PmZ7IAviPoav7OhYMlrhJVOkbhKJKM9zhgHrwYLu3JDUV+RJxjtim9OMk= ARC-Message-Signature: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1780341881; c=relaxed/simple; bh=rkHcjsPkRR9nNSHxR46h2y9fTpo1dvARrrbdvhIHj/M=; h=From:Date:Subject:MIME-Version:Content-Type:Message-Id:References: In-Reply-To:To:Cc; b=O3Jx5UrO9QQ8bkgGByTll2ZL7jHrv9da0SiuASyLSEph1dlIjPyefdjyHYHc1TWe6SGq/KHR+sjlLndt9FJYToVy5OiE1oOkmi4qESCoLQ9DAu90s5wkba9f767AU9NyGen+rl4lGGRHggJt4W2gYErq7B3mgE9jox5SSS6tSag= 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=Ky3hS9Aq; arc=none smtp.client-ip=209.85.214.170 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="Ky3hS9Aq" Received: by mail-pl1-f170.google.com with SMTP id d9443c01a7336-2c0c3315c5dso17666315ad.3 for ; Mon, 01 Jun 2026 12:24:38 -0700 (PDT) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=gmail.com; s=20251104; t=1780341878; x=1780946678; darn=vger.kernel.org; h=cc:to:in-reply-to:references:message-id:content-transfer-encoding :mime-version:subject:date:from:from:to:cc:subject:date:message-id :reply-to; bh=p8Jk1ivLmwr3VP3ike29F6VRWUYvoG1CiSF1zOqSE6U=; b=Ky3hS9AqHXRSJRKrQavLc3UCZYwr7npEDXG78lJeKbVx8lKsMxgYDvOwjHHukeehgo atSxmGiMrF71OcGGX32O6CAIlV9eo5Yk+lbACPC70YvKqcO3Rqdvhh3oKoaeYUmu7jbE V4Q6AEMfpp9ac0lN46yEntowvNO9NM9rJJGIY75VWjNn6lvjI+RtKQIE5wOfMOzkhegh HPxQN6/+KLkA/ABBiPEecPTnDGsaMRsJZMlJtwCr+pM8LiXTjD1xdXBECB+++LiwBpbA neFlcoSwXK/0hcPuoY9BZJDKUSoXW/g1T9/wiBECs4LbnlqW3MF0Qd30SYZ2XoQOOx8P SL6g== X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20251104; t=1780341878; x=1780946678; h=cc:to:in-reply-to:references:message-id:content-transfer-encoding :mime-version:subject:date:from:x-gm-gg:x-gm-message-state:from:to :cc:subject:date:message-id:reply-to; bh=p8Jk1ivLmwr3VP3ike29F6VRWUYvoG1CiSF1zOqSE6U=; b=p8NG0CU/9emRR+C4tDZZbe8VZroWwmR2WDpaJKQoP4tD/BTVlVUeB4m4MyfkROaOsT U46WW4RncwLwY7kZwEWGSIolj6Wy4/nVPwdcEo6WvlyB6eBeNIm+sbECUNhwMhnbf2kx 8VgA7SdfNo6AGMFazeSmy4oSNpZXmcBa/b2ljJMPvu8vzhwiXOLBXl4mBLLHoRxpdxDy Y45xG3VGHCjTwp8GRYao+H81BKV2OVApeQLtqHHwM3QGfVX9NO0+KkL9vAdm7DR126HM bI9YM50A/JfzRhUDeimin8FVYMS6ZPPgyQ6T75FIiYYM6ihXL6AlFMvH9eLUaU9xoLD5 JSKg== X-Forwarded-Encrypted: i=1; AFNElJ9O5m4wZGBodCm7NCbsWTeQ/AYyrn2l7azZzUVWU5/aTfBEynUuoKMbTG6pSYkpY6Sb0uXquE9dWYufMyo=@vger.kernel.org X-Gm-Message-State: AOJu0Yz3Rb8QBX0S3I3ZwPBBTFZVIOapOAxWey+gsMHmfoBhFe5tOr9H Q0x5SonhTCwLlHlRN66yuS0EnJMoEkS5IE44pDKEBpmzK9SB5t7OodLe X-Gm-Gg: Acq92OFDSX631StdhDX6OQ8/+JgO7DTlT67WLbfE6Wq6e9mkR75k05qncxE7LQf8NIx NmyJOISxd3K8dhhIfXnRMCbMw+n9pBCWgeeyK+mBbqch25X7bgllkxMAtbi8vNEqFMkyf7PyCfd xfOGx7dbBPbguLcBzEThcZkAMkaJnNx1xQeR5G1vmie85vwTxtZCxEvg61jXOBBfSq3pGUjcKP8 Ft70d1rHcyACtqkyW9viERfGK2hRt6a+jK+dxeNO/vkKmVqVsAbZR7eF2daPfzYL8r0I29AvDXZ RqmQ4AWJDOXSnowTkKdLSLQMMulLnB/liv6Za0Qy31ztqsdHM8zGv9DyeiNkSs5x/sV1oiApL48 WEgdfeyoYSmREKXIgndshKz1UO/By8RcgDA2JtHe/Me614cw4yRQuNp6KMXNQ06Bgn1ovCviJ/z 2X9NPYJC26TGqfvonYk6cpOSXZzemUuQ== X-Received: by 2002:a17:903:8c8:b0:2bc:eea4:83c3 with SMTP id d9443c01a7336-2bf368334b0mr136497405ad.25.1780341877857; Mon, 01 Jun 2026 12:24:37 -0700 (PDT) Received: from localhost ([2a03:2880:ff:41::]) by smtp.gmail.com with ESMTPSA id d9443c01a7336-2bf23a2dbfbsm113520295ad.37.2026.06.01.12.24.37 (version=TLS1_3 cipher=TLS_AES_256_GCM_SHA384 bits=256/256); Mon, 01 Jun 2026 12:24:37 -0700 (PDT) From: Bobby Eshleman Date: Mon, 01 Jun 2026 12:24:27 -0700 Subject: [PATCH net-next 1/2] net: devmem: allow bind-rx from non-init user namespaces 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: <20260601-nl-prov-v1-1-9bc57d6ca3f3@meta.com> References: <20260601-nl-prov-v1-0-9bc57d6ca3f3@meta.com> In-Reply-To: <20260601-nl-prov-v1-0-9bc57d6ca3f3@meta.com> To: Donald Hunter , Jakub Kicinski , "David S. Miller" , Eric Dumazet , Paolo Abeni , Simon Horman , Andrew Lunn , Shuah Khan Cc: netdev@vger.kernel.org, linux-kernel@vger.kernel.org, linux-kselftest@vger.kernel.org, Stanislav Fomichev , Mina Almasry , Bobby Eshleman X-Mailer: b4 0.14.3 From: Bobby Eshleman NETDEV_CMD_BIND_RX is currently GENL_ADMIN_PERM, which checks CAP_NET_ADMIN against init userns. With recent container/netkit/ns support for devmem, other userns/netns use cases come online and require bind-rx to allow CAP_NET_ADMIN in non-init user ns as well. Switch the flag to GENL_UNS_ADMIN_PERM to allow bind-rx for CAP_NET_ADMIN in the netns's owning userns as well. Signed-off-by: Bobby Eshleman --- Documentation/netlink/specs/netdev.yaml | 2 +- net/core/netdev-genl-gen.c | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/Documentation/netlink/specs/netdev.yaml b/Documentation/netlin= k/specs/netdev.yaml index a1f4c5a561e9..49862b666d7d 100644 --- a/Documentation/netlink/specs/netdev.yaml +++ b/Documentation/netlink/specs/netdev.yaml @@ -798,7 +798,7 @@ operations: name: bind-rx doc: Bind dmabuf to netdev attribute-set: dmabuf - flags: [admin-perm] + flags: [uns-admin-perm] do: request: attributes: diff --git a/net/core/netdev-genl-gen.c b/net/core/netdev-genl-gen.c index c7e138bfe345..d18c89b5a6c7 100644 --- a/net/core/netdev-genl-gen.c +++ b/net/core/netdev-genl-gen.c @@ -220,7 +220,7 @@ static const struct genl_split_ops netdev_nl_ops[] =3D { .doit =3D netdev_nl_bind_rx_doit, .policy =3D netdev_bind_rx_nl_policy, .maxattr =3D NETDEV_A_DMABUF_FD, - .flags =3D GENL_ADMIN_PERM | GENL_CMD_CAP_DO, + .flags =3D GENL_UNS_ADMIN_PERM | GENL_CMD_CAP_DO, }, { .cmd =3D NETDEV_CMD_NAPI_SET, --=20 2.53.0-Meta From nobody Mon Jun 8 05:25:47 2026 Received: from mail-pg1-f175.google.com (mail-pg1-f175.google.com [209.85.215.175]) (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 B8D0E37DAA6 for ; Mon, 1 Jun 2026 19:24:39 +0000 (UTC) Authentication-Results: smtp.subspace.kernel.org; arc=none smtp.client-ip=209.85.215.175 ARC-Seal: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1780341884; cv=none; b=rerfOshEHH8Ly2yZpJYQadNpk24NUiUWRibyxhOJrsB1i8fBK7KgHcsxtjembNY+9JVLzPSiiaY2nbgXF+T6p8gtKRiFCXXeLs/YaQgOUgN6uAmX0+34ip/d8TlGzX++/smKaWSeDWrDx+nMC3tsYkHuhYPvpIPPTUuodZlRMvw= ARC-Message-Signature: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1780341884; c=relaxed/simple; bh=jVuw5EjU5tCYizHznvHPTOEU3be/b9VcUMLV9hcnLs4=; h=From:Date:Subject:MIME-Version:Content-Type:Message-Id:References: In-Reply-To:To:Cc; b=hbkXOoiOQN5HfdPqbjkle1EABPLOZJMHFxjzHwRnS9ZiIIfuR5FjCU7UG2xPQ6R43VjrbYlF4yI841VOTYECJ0KwGdnQENcphQVpSlB5Vtz4oZLfGhpImcoZHnw8LWqQwE3ioMROudop5kpin6XbZthuxnN+8Neuv1zNtO0fGP8= 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=IAPixNMg; arc=none smtp.client-ip=209.85.215.175 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="IAPixNMg" Received: by mail-pg1-f175.google.com with SMTP id 41be03b00d2f7-c85825bbc4fso1636463a12.2 for ; Mon, 01 Jun 2026 12:24:39 -0700 (PDT) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=gmail.com; s=20251104; t=1780341879; x=1780946679; darn=vger.kernel.org; h=cc:to:in-reply-to:references:message-id:content-transfer-encoding :mime-version:subject:date:from:from:to:cc:subject:date:message-id :reply-to; bh=w6oyn/opTXc3qNaiYrGm87ZPTedwK1fmyCVPQB5WlRQ=; b=IAPixNMgkSUK696qSg1AavZ62Hnqy47hBSiAgSxwDb2C7kJ1pMUPZwKmONmcd2IHOL kcXckF2jtafQbJJlpe1hWQ+7ntuW5kRUTRz7oAX3hLAzP1jt7QgXoIQ+VInnLUF5PNG/ GPhw8UXNzx8lGkoOWXl1V9zEfKL93fa2arLWoy4PAqx2R6Whdl1/Q2xlErJKQJQewk9k 2y7h10DcTJLVTyGXIS+51/Cd+BgguGF/8Cb4QTMt1LRblytVoC455JEu7d2p/SNLrB9n 0KIwLSc7FL/RntvOHzu2ZfpOiIKb8RQawMKh0NwK6sGI4NgPfv8yhicUb2KLEjvUT/iy G4JA== X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20251104; t=1780341879; x=1780946679; h=cc:to:in-reply-to:references:message-id:content-transfer-encoding :mime-version:subject:date:from:x-gm-gg:x-gm-message-state:from:to :cc:subject:date:message-id:reply-to; bh=w6oyn/opTXc3qNaiYrGm87ZPTedwK1fmyCVPQB5WlRQ=; b=lE+zqFAZcB9xUPjVO9X3ucnyKwIBA3sa2gSV+uSyQr8u+zPmGEEDxTWqis6dy1JL70 qV3GSj8CGUUEQemwWDTF2/2P4GTbCKeFsMoynIET+vdIl0B2sY/1UFsv7rPgoUjFch3C 3jJPQv+mj+LteW740EGiZdqazDTPY8EbFEeaUkiqSb45OLz6YNcel87bfHvlFi9otU8x V+FTIn1CL4VMbqqm1lrbPn4r+GFb6TDr/383l9FDJpiY8z2X3wem8zsbIj2ypfIyyqOo JrZBoxDzV7v3QhEwvJ+OrIRYfyrMpB2GA67qDeGL9RzDETDONKADj0luBfe3/PP+ehj9 i8TA== X-Forwarded-Encrypted: i=1; AFNElJ/y+Wirps+QolTcqGdiobFkOFMMaJgPQO+6LpzqyPswhXKOsYBsZdlE6y2flF+LmbeTJRIg+4xeA4I2W4w=@vger.kernel.org X-Gm-Message-State: AOJu0YwBp1u0gHE2q5CfHwaTxnodw5zpM1byqKgfPZp4ym7LsHhzZSFi 9/wZS30RrmCV3cgiBbSxAYd4/TXcfdgr9OOBeW8tuSg+Fkyc7SEaTM8N X-Gm-Gg: Acq92OFoEF5bshq8f3s0ZvTx4hfre06Fuh9wpNYOKY4zOoMC4iaohIAOc6ORESYMe0Y Iy3rWf4wXMK6N+goSOO1P5grAHw9I94/d25RL3hu9I74dJsM8oCShQOetfWWXf1H5suHYI8C+Jh jRCIvV6V3Hcz59DJL4SlWhIpNLWM8QwJntiro3qBIkwWBJaGJQgs9TDADKCFJL+3fc0HWYjHuRx 1nlkJViy6SZM8KQNEIG5WMOaCao0NiRQdrpdsY/3HvRpnnzkqGluGCD345LeqnuUO1Pa76gvYTt pob3hTYkDLxv3rzZ03pa3yctf8ZkD8sLBbTPMBHnmmd0+tLrLyK0cWVSZo7dH9/2Lw0qpUd2ve6 wo/6ZqukHJpcGIIhFQR5ZfqYcjibtC9jkhkQOOfZo4yUygOEzdB1bvDiq7t/iLv/prBTkwLdlRu li+6Yf6btcaSEVoUSxI/ZrfE4Nqw01QQ== X-Received: by 2002:a05:6a20:4386:b0:398:8870:b58f with SMTP id adf61e73a8af0-3b427fb8528mr13017558637.14.1780341878840; Mon, 01 Jun 2026 12:24:38 -0700 (PDT) Received: from localhost ([2a03:2880:ff:4d::]) by smtp.gmail.com with ESMTPSA id 41be03b00d2f7-c857fb0b31dsm8997113a12.32.2026.06.01.12.24.38 (version=TLS1_3 cipher=TLS_AES_256_GCM_SHA384 bits=256/256); Mon, 01 Jun 2026 12:24:38 -0700 (PDT) From: Bobby Eshleman Date: Mon, 01 Jun 2026 12:24:28 -0700 Subject: [PATCH net-next 2/2] selftests: drv-net: add userns devmem RX test 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: <20260601-nl-prov-v1-2-9bc57d6ca3f3@meta.com> References: <20260601-nl-prov-v1-0-9bc57d6ca3f3@meta.com> In-Reply-To: <20260601-nl-prov-v1-0-9bc57d6ca3f3@meta.com> To: Donald Hunter , Jakub Kicinski , "David S. Miller" , Eric Dumazet , Paolo Abeni , Simon Horman , Andrew Lunn , Shuah Khan Cc: netdev@vger.kernel.org, linux-kernel@vger.kernel.org, linux-kselftest@vger.kernel.org, Stanislav Fomichev , Mina Almasry , Bobby Eshleman X-Mailer: b4 0.14.3 From: Bobby Eshleman Add userns_devmem.py, which mirrors nk_devmem.py but places the netkit guest in a netns whose owning user_ns is non-init. ncdevmem is ran there via nsenter so the bind-rx call is issued with creds that hold CAP_NET_ADMIN only in the child user_ns. Without the preceding GENL_UNS_ADMIN_PERM patch the test fails at bind-rx with EPERM, but with the patch the transfer completes and tests pass. Signed-off-by: Bobby Eshleman --- tools/testing/selftests/drivers/net/hw/Makefile | 1 + tools/testing/selftests/drivers/net/hw/config | 1 + .../selftests/drivers/net/hw/lib/py/__init__.py | 4 +- .../selftests/drivers/net/hw/userns_devmem.py | 48 +++++++++++++ tools/testing/selftests/drivers/net/lib/py/env.py | 8 ++- tools/testing/selftests/net/lib/py/__init__.py | 4 +- tools/testing/selftests/net/lib/py/netns.py | 79 ++++++++++++++++++= ++++ tools/testing/selftests/net/lib/py/utils.py | 7 +- 8 files changed, 144 insertions(+), 8 deletions(-) diff --git a/tools/testing/selftests/drivers/net/hw/Makefile b/tools/testin= g/selftests/drivers/net/hw/Makefile index c7a1206880ea..fd0535a96d84 100644 --- a/tools/testing/selftests/drivers/net/hw/Makefile +++ b/tools/testing/selftests/drivers/net/hw/Makefile @@ -47,6 +47,7 @@ TEST_PROGS =3D \ rss_input_xfrm.py \ toeplitz.py \ tso.py \ + userns_devmem.py \ uso.py \ xdp_metadata.py \ xsk_reconfig.py \ diff --git a/tools/testing/selftests/drivers/net/hw/config b/tools/testing/= selftests/drivers/net/hw/config index 8c132ace2b8d..3da6d3e39960 100644 --- a/tools/testing/selftests/drivers/net/hw/config +++ b/tools/testing/selftests/drivers/net/hw/config @@ -17,5 +17,6 @@ CONFIG_NET_IPGRE_DEMUX=3Dy CONFIG_NETKIT=3Dy CONFIG_NET_SCH_INGRESS=3Dy CONFIG_UDMABUF=3Dy +CONFIG_USER_NS=3Dy CONFIG_VXLAN=3Dy CONFIG_XFRM_USER=3Dy diff --git a/tools/testing/selftests/drivers/net/hw/lib/py/__init__.py b/to= ols/testing/selftests/drivers/net/hw/lib/py/__init__.py index 84a4dab6c649..8a58cb17cc06 100644 --- a/tools/testing/selftests/drivers/net/hw/lib/py/__init__.py +++ b/tools/testing/selftests/drivers/net/hw/lib/py/__init__.py @@ -18,7 +18,7 @@ try: sys.path.append(KSFT_DIR.as_posix()) =20 # Import one by one to avoid pylint false positives - from net.lib.py import NetNS, NetNSEnter, NetdevSimDev + from net.lib.py import NetNS, NetNSEnter, NetdevSimDev, UserNetNS from net.lib.py import EthtoolFamily, NetdevFamily, NetshaperFamily, \ NlError, RtnlFamily, DevlinkFamily, PSPFamily, Netlink from net.lib.py import CmdExitFailure @@ -34,7 +34,7 @@ try: from drivers.net.lib.py import GenerateTraffic, Remote, Iperf3Runner from drivers.net.lib.py import NetDrvEnv, NetDrvEpEnv, NetDrvContEnv =20 - __all__ =3D ["NetNS", "NetNSEnter", "NetdevSimDev", + __all__ =3D ["NetNS", "NetNSEnter", "NetdevSimDev", "UserNetNS", "EthtoolFamily", "NetdevFamily", "NetshaperFamily", "NlError", "RtnlFamily", "DevlinkFamily", "PSPFamily", "Net= link", "CmdExitFailure", diff --git a/tools/testing/selftests/drivers/net/hw/userns_devmem.py b/tool= s/testing/selftests/drivers/net/hw/userns_devmem.py new file mode 100755 index 000000000000..f824cc9ed3c6 --- /dev/null +++ b/tools/testing/selftests/drivers/net/hw/userns_devmem.py @@ -0,0 +1,48 @@ +#!/usr/bin/env python3 +# SPDX-License-Identifier: GPL-2.0 +""" +Devmem tests for non-init userns. +""" + +import os + +from devmem_lib import run_rx, run_rx_hds, run_tx, run_tx_chunks, setup_te= st +from lib.py import NetDrvContEnv, ksft_disruptive, ksft_exit, ksft_run + + +@ksft_disruptive +def check_userns_rx(cfg) -> None: + """Run the devmem RX test through non-init userns netkit.""" + run_rx(cfg) + + +@ksft_disruptive +def check_userns_tx(cfg) -> None: + """Run the devmem TX test through non-init userns netkit.""" + run_tx(cfg) + + +@ksft_disruptive +def check_userns_tx_chunks(cfg) -> None: + """Run the devmem TX chunking test through non-init userns netkit.""" + run_tx_chunks(cfg) + + +def check_userns_rx_hds(cfg) -> None: + """Run the HDS test through non-init userns netkit.""" + run_rx_hds(cfg) + + +def main() -> None: + with NetDrvContEnv(__file__, userns=3DTrue, rxqueues=3D2, + primary_rx_redirect=3DTrue) as cfg: + setup_test(cfg, + os.path.join(os.path.dirname(os.path.abspath(__file__)), + "ncdevmem")) + ksft_run([check_userns_rx, check_userns_tx, check_userns_tx_chunks, + check_userns_rx_hds], args=3D(cfg,)) + ksft_exit() + + +if __name__ =3D=3D "__main__": + main() diff --git a/tools/testing/selftests/drivers/net/lib/py/env.py b/tools/test= ing/selftests/drivers/net/lib/py/env.py index ef317aef3a0a..2cc78b8a2152 100644 --- a/tools/testing/selftests/drivers/net/lib/py/env.py +++ b/tools/testing/selftests/drivers/net/lib/py/env.py @@ -9,7 +9,7 @@ from pathlib import Path from lib.py import KsftSkipEx, KsftXfailEx from lib.py import ksft_setup, wait_file from lib.py import cmd, ethtool, ip, CmdExitFailure -from lib.py import NetNS, NetdevSimDev +from lib.py import NetNS, NetdevSimDev, UserNetNS from .remote import Remote from . import bpftool, RtnlFamily, Netlink =20 @@ -337,8 +337,10 @@ class NetDrvContEnv(NetDrvEpEnv): +---------------+ """ =20 - def __init__(self, src_path, rxqueues=3D1, primary_rx_redirect=3DFalse= , **kwargs): + def __init__(self, src_path, rxqueues=3D1, primary_rx_redirect=3DFalse, + userns=3DFalse, **kwargs): self.netns =3D None + self._userns =3D userns self._nk_host_ifname =3D None self.nk_guest_ifname =3D None self._tc_clsact_added =3D False @@ -463,7 +465,7 @@ class NetDrvContEnv(NetDrvEpEnv): with open(ra_path, "w", encoding=3D"utf-8") as f: f.write("2") =20 - self.netns =3D NetNS() + self.netns =3D UserNetNS() if self._userns else NetNS() cmd("ip netns attach init 1") self._init_ns_attached =3D True ip("netns set init 0", ns=3Dself.netns) diff --git a/tools/testing/selftests/net/lib/py/__init__.py b/tools/testing= /selftests/net/lib/py/__init__.py index 64a8c1ed4950..e58bdbdc58ee 100644 --- a/tools/testing/selftests/net/lib/py/__init__.py +++ b/tools/testing/selftests/net/lib/py/__init__.py @@ -10,7 +10,7 @@ from .ksft import KsftFailEx, KsftSkipEx, KsftXfailEx, ks= ft_pr, ksft_eq, \ ksft_ge, ksft_gt, ksft_lt, ksft_raises, ksft_busy_wait, \ ktap_result, ksft_disruptive, ksft_setup, ksft_run, ksft_exit, \ ksft_variants, KsftNamedVariant -from .netns import NetNS, NetNSEnter +from .netns import NetNS, NetNSEnter, UserNetNS from .nsim import NetdevSim, NetdevSimDev from .utils import CmdExitFailure, fd_read_timeout, cmd, bkg, defer, \ bpftool, ip, ethtool, bpftrace, rand_port, rand_ports, wait_port_liste= n, \ @@ -26,7 +26,7 @@ __all__ =3D ["KSRC", "ksft_is", "ksft_ge", "ksft_gt", "ksft_lt", "ksft_raises", "ksft_busy_wait", "ktap_result", "ksft_disruptive", "ksft_setup= ", "ksft_run", "ksft_exit", "ksft_variants", "KsftNamedVariant", - "NetNS", "NetNSEnter", + "NetNS", "NetNSEnter", "UserNetNS", "CmdExitFailure", "fd_read_timeout", "cmd", "bkg", "defer", "bpftool", "ip", "ethtool", "bpftrace", "rand_port", "rand_port= s", "wait_port_listen", "wait_file", "tool", "tc", diff --git a/tools/testing/selftests/net/lib/py/netns.py b/tools/testing/se= lftests/net/lib/py/netns.py index 8e9317044eef..965f5802bef2 100644 --- a/tools/testing/selftests/net/lib/py/netns.py +++ b/tools/testing/selftests/net/lib/py/netns.py @@ -2,8 +2,12 @@ =20 from .utils import ip import ctypes +import os import random import string +import subprocess +import time +from pathlib import Path =20 libc =3D ctypes.cdll.LoadLibrary('libc.so.6') =20 @@ -34,6 +38,81 @@ class NetNS: return f"NetNS({self.name})" =20 =20 +class UserNetNS: + """Network namespace owned by a non-init user namespace.""" + + def __init__(self): + self.name =3D ''.join( + random.choice(string.ascii_lowercase) for _ in range(8)) + self.user_ns_path =3D f"/run/userns/{self.name}" + self.net_ns_path =3D f"/run/netns/{self.name}" + self._user_mounted =3D False + self._net_mounted =3D False + self._unshare =3D None + + os.makedirs("/run/userns", exist_ok=3DTrue) + os.makedirs("/run/netns", exist_ok=3DTrue) + + Path(self.user_ns_path).touch() + Path(self.net_ns_path).touch() + + self._unshare =3D subprocess.Popen( + ["unshare", "--user", "--net", "--map-root-user", + "sleep", "infinity"]) + + try: + pid =3D self._unshare.pid + init_user =3D os.readlink("/proc/self/ns/user") + for _ in range(200): + try: + if os.readlink(f"/proc/{pid}/ns/user") !=3D init_user: + break + except OSError: + pass + time.sleep(0.01) + else: + raise RuntimeError("unshare child did not create userns") + + subprocess.run(["mount", "--bind", f"/proc/{pid}/ns/user", + self.user_ns_path], check=3DTrue) + self._user_mounted =3D True + subprocess.run(["mount", "--bind", f"/proc/{pid}/ns/net", + self.net_ns_path], check=3DTrue) + self._net_mounted =3D True + except (OSError, RuntimeError, subprocess.CalledProcessError): + self._unshare.kill() + self._unshare.wait() + raise + + def __del__(self): + if self._net_mounted: + subprocess.run(["umount", self.net_ns_path], check=3DFalse) + self._net_mounted =3D False + if self._user_mounted: + subprocess.run(["umount", self.user_ns_path], check=3DFalse) + self._user_mounted =3D False + if self._unshare and self._unshare.poll() is None: + self._unshare.kill() + self._unshare.wait() + for path in (self.net_ns_path, self.user_ns_path): + try: + os.unlink(path) + except OSError: + pass + + def __enter__(self): + return self + + def __exit__(self, ex_type, ex_value, ex_tb): + self.__del__() + + def __str__(self): + return self.name + + def __repr__(self): + return f"UserNetNS({self.name})" + + class NetNSEnter: def __init__(self, ns_name): self.ns_path =3D f"/run/netns/{ns_name}" diff --git a/tools/testing/selftests/net/lib/py/utils.py b/tools/testing/se= lftests/net/lib/py/utils.py index be9408a77168..87eae79d01c1 100644 --- a/tools/testing/selftests/net/lib/py/utils.py +++ b/tools/testing/selftests/net/lib/py/utils.py @@ -47,7 +47,12 @@ class cmd: background=3DFalse, host=3DNone, timeout=3D5, ksft_ready= =3DNone, ksft_wait=3DNone): if ns: - comm =3D f'ip netns exec {ns} ' + comm + if hasattr(ns, 'user_ns_path'): + comm =3D (f'nsenter --user=3D{ns.user_ns_path} ' + f'--net=3D{ns.net_ns_path} --setuid=3D0 --setgid= =3D0 -- ' + + comm) + else: + comm =3D f'ip netns exec {ns} ' + comm =20 self.stdout =3D None self.stderr =3D None --=20 2.53.0-Meta