Linux Documentation
 help / color / mirror / Atom feed
From: netdev-bot+sashiko@kernel.org
To: bobbyeshleman@gmail.com
Cc: sgarzare@redhat.com, davem@davemloft.net, edumazet@google.com,
	kuba@kernel.org, pabeni@redhat.com, horms@kernel.org,
	corbet@lwn.net, skhan@linuxfoundation.org, stefanha@redhat.com,
	mst@redhat.com, jasowangio@gmail.com, xuanzhuo@linux.alibaba.com,
	eperezma@redhat.com, shuah@kernel.org, rdunlap@infradead.org,
	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, bobbyeshleman@meta.com
Subject: Re: [PATCH net-next 6/6] selftests/vsock: test the assign ioctl privilege checks
Date: Sun, 06 Sep 2026 17:04:06 +0000	[thread overview]
Message-ID: <178871424602.219967.12071178745366323858@kernel.org> (raw)
In-Reply-To: <20260902-vsock-guest-ns-v1-6-9995383e9a8b@meta.com>

Thank you for your contribution! Sashiko AI review found 3 potential
issue(s) to consider:

Critical: 0 · High: 0 · Medium: 2 · Low: 1

- [Medium] test_ns_guest_assign_g2h_netns_unpriv_user_ns_fails()
  (tools/testing/selftests/vsock/vmtest.sh:1835-1863) runs the helper as…
- [Medium] Both new tests equate a remote command exit status of 1 with
  'the kernel returned -EPERM from IOCTL_VM_SOCKETS_ASSIGN_G2H_NETNS'.
- [Low] Both new shared-VM tests (vmtest.sh:1820-1833 and 1835-1863) are
  added to USE_SHARED_VM but omit the `vm_reset_g2h` teardown that every…

--

selftests/vsock: test the assign ioctl privilege checks

This adds two vmtest.sh cases around IOCTL_VM_SOCKETS_ASSIGN_G2H_NETNS on
/dev/vsock: one drops CAP_NET_ADMIN via setpriv, the other runs the helper
as an unprivileged uid inside a new user plus net namespace.  Both expect
the helper to exit with the ioctl's errno, and CONFIG_USER_NS is added to
the config.

No Link: tags are present in the commit header.

> diff --git a/tools/testing/selftests/vsock/vmtest.sh b/tools/testing/selftests/vsock/vmtest.sh
> index 53591fa07f1a..efb94d17d997 100755
> --- a/tools/testing/selftests/vsock/vmtest.sh
> +++ b/tools/testing/selftests/vsock/vmtest.sh
> @@ -28,6 +28,7 @@ readonly WAIT_PERIOD=3
>  readonly WAIT_PERIOD_MAX=60
>  readonly WAIT_QEMU=5
>  readonly PIDFILE_TEMPLATE=/tmp/vsock_vmtest_XXXX.pid
> +readonly EPERM=1
>  declare -A PIDFILES

[ ... ]

> @@ -333,7 +344,8 @@ check_args() {
>  }
>  
>  check_deps() {
> -	for dep in vng ${QEMU} busybox pkill ssh ss socat nsenter unshare; do
> +	for dep in vng ${QEMU} busybox pkill ssh ss socat nsenter unshare \
> +		setpriv; do
>  		if [[ ! -x $(command -v "${dep}") ]]; then
>  			echo -e "skip:    dependency ${dep} not found!\n"
>  			exit "${KSFT_SKIP}"

[ ... ]

> @@ -1805,6 +1817,51 @@ test_ns_guest_assign_g2h_netns_reset_on_ns_delete_ok() {
>  	return "${KSFT_PASS}"
>  }
>  
> +test_ns_guest_assign_g2h_netns_no_cap_net_admin_fails() {
> +	local cmd="unshare -n setpriv --bounding-set=-net_admin"
> +	local rc
> +
> +	vm_ssh "init_ns" -- "${cmd}" ./vsock_assign_g2h_netns &>/dev/null
> +	rc=$?
> +
> +	if [[ "${rc}" -ne "${EPERM}" ]]; then
> +		log_host "expected EPERM (${EPERM}) without CAP_NET_ADMIN, got ${rc}"
> +		return "${KSFT_FAIL}"
> +	fi
> +
> +	return "${KSFT_PASS}"
> +}

[Severity: Medium]
Can this test pass without ever issuing the ioctl?

The helper turns errno into its own exit status:

tools/testing/selftests/vsock/vsock_assign_g2h_netns.c:main() {
	ret = ioctl(fd, IOCTL_VM_SOCKETS_ASSIGN_G2H_NETNS);
	if (ret < 0) {
		ret = errno;
	...
	return ret;
}

so "the ioctl returned -EPERM" is encoded as exit status 1, which is also
the generic EXIT_FAILURE of the two wrappers that are prepended here.  If
util-linux unshare cannot create the network namespace, or setpriv was
built without libcap-ng and cannot handle --bounding-set=-net_admin, the
wrapper exits 1 before exec'ing the helper, rc is 1, and the test returns
KSFT_PASS with vsock_dev_do_ioctl() never reached.

The &>/dev/null redirection discards the wrapper's own error message, so
that outcome is silent.

check_deps() only verifies that the setpriv binary exists, not that
--bounding-set is supported, so an unsupported setpriv becomes a pass
rather than a skip.

The same conflation applies to the second test below: the pre-flight probe
runs only "unshare -U true", while the command actually executed is
"${unpriv} unshare -Urn ${helper}".  A failure of the -r or -n part, or of
setpriv --reuid/--regid/--clear-groups, also exits 1 and is read as the
ioctl's EPERM.

Would it be better for the helper to report a distinct sentinel exit code
(or print a machine-checkable marker) for the ioctl result, so that the
kernel's capable(CAP_NET_ADMIN) check in vsock_dev_do_ioctl() cannot be
weakened without these tests noticing?

> +
> +test_ns_guest_assign_g2h_netns_unpriv_user_ns_fails() {
> +	local helper=/tmp/vsock_assign_g2h_netns
> +	local unpriv_uid=65534
> +	local unpriv
> +	local rc
> +
> +	unpriv="setpriv --reuid=${unpriv_uid} --regid=${unpriv_uid}"
> +	unpriv="${unpriv} --clear-groups"
> +
> +	if ! vm_ssh "init_ns" -- "${unpriv} unshare -U true"; then
> +		log_host "unprivileged user namespaces unavailable, skipping"
> +		return "${KSFT_SKIP}"
> +	fi
> +
> +	# The home shared with the guest is root-only, so place the helper where
> +	# an unprivileged user can execute it.
> +	vm_ssh "init_ns" -- \
> +		"cp ./vsock_assign_g2h_netns ${helper} && chmod 755 ${helper}"
> +
> +	vm_ssh "init_ns" -- "${unpriv} unshare -Urn ${helper}" &>/dev/null
> +	rc=$?
> +
> +	if [[ "${rc}" -ne "${EPERM}" ]]; then
> +		log_host "expected EPERM (${EPERM}) for an unprivileged user, got ${rc}"
> +		return "${KSFT_FAIL}"
> +	fi

[Severity: Medium]
Can uid 65534 open /dev/vsock in this guest at all?

The node is created from a miscdevice with no .mode:

net/vmw_vsock/af_vsock.c
static struct miscdevice vsock_device = {
	.name		= "vsock",
	.fops		= &vsock_device_ops,
};

misc_devnode() only overrides the mode when c->mode is non-zero, and
devtmpfs_create_node() then applies mode 0600 with uid/gid
GLOBAL_ROOT_UID/GLOBAL_ROOT_GID.  In the bare virtme-ng guest this script
boots there is no udev rule loosening it, so /dev/vsock is 0600 root:root.

With unshare -Urn only kuid 65534 is mapped, so the inode's kuid 0 is
unmapped in the new user namespace and capable_wrt_inode_uidgid() cannot
grant CAP_DAC_OVERRIDE.  open("/dev/vsock", O_RDONLY) then fails with
EACCES and the helper does:

tools/testing/selftests/vsock/vsock_assign_g2h_netns.c:main() {
	fd = open("/dev/vsock", O_RDONLY);
	if (fd < 0) {
		fprintf(stderr, "open /dev/vsock: %s\n", strerror(errno));
		return -1;
	}

which is exit status 255, so this rc check reports "expected EPERM (1) for
an unprivileged user, got 255" and returns KSFT_FAIL even though the
kernel behaved as intended.  The stderr message explaining why is dropped
by &>/dev/null.

Would it make sense to test whether the unprivileged uid can open
/dev/vsock first and return KSFT_SKIP if it cannot, so that an
inaccessible device node is distinguished from a refusal by the
CAP_NET_ADMIN check?

> +
> +	return "${KSFT_PASS}"
> +}
> +

[Severity: Low]
Both new tests are listed in USE_SHARED_VM but neither calls vm_reset_g2h,
while every other g2h-assign test does so on both the success and failure
paths, for example test_ns_guest_assign_g2h_netns_connect_to_host_ok(),
..._init_ns_connect_fails(), ..._host_connect_ok() and
..._reset_on_ns_delete_ok().

If the capable(CAP_NET_ADMIN) gate in vsock_dev_do_ioctl() is ever
weakened, the assign succeeds inside the throwaway unshare -n or
unshare -Urn namespace and these tests return KSFT_FAIL with the guest's
vsock device still owned by a dying namespace.

The neighbouring test already documents that the hand-back is not
immediate:

	# 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.

Could the following shared-VM tests then run while the device is still
unavailable, turning one real failure into a series of spurious ones?
Should these two tests call vm_reset_g2h before returning, like the others?

>  shared_vm_test() {
>  	local tname
>

-- 
Sashiko AI review · https://netdev-ai.bots.linux.dev/sashiko/#/patchset/20260902-vsock-guest-ns-v1-0-9995383e9a8b%40meta.com

  reply	other threads:[~2026-09-06 17:04 UTC|newest]

Thread overview: 16+ messages / expand[flat|nested]  mbox.gz  Atom feed  top
2026-09-02 23:00 [PATCH net-next 0/6] vsock: assign the guest vsock device to a network namespace Bobby Eshleman
2026-09-02 23:00 ` [PATCH net-next 1/6] vsock: constify the transport in vsock_for_each_connected_socket() Bobby Eshleman
2026-09-02 23:00 ` [PATCH net-next 2/6] vsock: add IOCTL_VM_SOCKETS_ASSIGN_G2H_NETNS Bobby Eshleman
2026-09-02 23:35   ` Randy Dunlap
2026-09-02 23:58     ` Bobby Eshleman
2026-09-06 17:03   ` netdev-bot+sashiko
2026-09-02 23:00 ` [PATCH net-next 3/6] vsock/virtio: support guest device network namespace Bobby Eshleman
2026-09-06 17:04   ` netdev-bot+sashiko
2026-09-02 23:00 ` [PATCH net-next 4/6] selftests/vsock: add a helper to assign the g2h device to a netns Bobby Eshleman
2026-09-06 17:04   ` netdev-bot+sashiko
2026-09-02 23:00 ` [PATCH net-next 5/6] selftests/vsock: test the guest vsock device network namespace Bobby Eshleman
2026-09-06 17:04   ` netdev-bot+sashiko
2026-09-02 23:00 ` [PATCH net-next 6/6] selftests/vsock: test the assign ioctl privilege checks Bobby Eshleman
2026-09-06 17:04   ` netdev-bot+sashiko [this message]
2026-09-04  8:55 ` [PATCH net-next 0/6] vsock: assign the guest vsock device to a network namespace Stefano Garzarella
2026-09-04 17:30   ` Bobby Eshleman

Reply instructions:

You may reply publicly to this message via plain-text email
using any one of the following methods:

* Save the following mbox file, import it into your mail client,
  and reply-to-all from there: mbox

  Avoid top-posting and favor interleaved quoting:
  https://en.wikipedia.org/wiki/Posting_style#Interleaved_style

* Reply using the --to, --cc, and --in-reply-to
  switches of git-send-email(1):

  git send-email \
    --in-reply-to=178871424602.219967.12071178745366323858@kernel.org \
    --to=netdev-bot+sashiko@kernel.org \
    --cc=bobbyeshleman@gmail.com \
    --cc=bobbyeshleman@meta.com \
    --cc=corbet@lwn.net \
    --cc=davem@davemloft.net \
    --cc=edumazet@google.com \
    --cc=eperezma@redhat.com \
    --cc=horms@kernel.org \
    --cc=jasowangio@gmail.com \
    --cc=jlinbox@meta.com \
    --cc=kuba@kernel.org \
    --cc=kvm@vger.kernel.org \
    --cc=linux-doc@vger.kernel.org \
    --cc=linux-kernel@vger.kernel.org \
    --cc=linux-kselftest@vger.kernel.org \
    --cc=mst@redhat.com \
    --cc=netdev@vger.kernel.org \
    --cc=pabeni@redhat.com \
    --cc=rdunlap@infradead.org \
    --cc=sargun@sargun.me \
    --cc=sgarzare@redhat.com \
    --cc=shuah@kernel.org \
    --cc=skhan@linuxfoundation.org \
    --cc=stefanha@redhat.com \
    --cc=virtualization@lists.linux.dev \
    --cc=xuanzhuo@linux.alibaba.com \
    /path/to/YOUR_REPLY

  https://kernel.org/pub/software/scm/git/docs/git-send-email.html

* If your mail client supports setting the In-Reply-To header
  via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line before the message body.
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox