From: netdev-bot+sashiko@kernel.org
To: qwe.aldo@gmail.com
Cc: sgarzare@redhat.com, virtualization@lists.linux.dev,
netdev@vger.kernel.org, linux-kernel@vger.kernel.org,
stable@vger.kernel.org, kuba@kernel.org
Subject: Re: [PATCH] vsock: preserve child namespace mode on an empty write
Date: Thu, 17 Sep 2026 14:20:06 +0000 [thread overview]
Message-ID: <178965480627.22033.2840574060294474673@kernel.org> (raw)
In-Reply-To: <20260915111417.2726515-1-qwe.aldo@gmail.com>
Thank you for your contribution! Sashiko AI review found 1 potential
issue(s) to consider:
Critical: 0 · High: 1 · Medium: 0 (1) · Low: 0
- [High] Incomplete fix: a zero-length write to
/proc/sys/net/vsock/child_ns_mode still consumes the write-once child-…
Pre-existing issues:
- [Medium] Non-atomic publication in vsock_net_set_child_mode()
(include/net/af_vsock.h:289-302): child_ns_mode_locked is published by…
--
vsock: preserve child namespace mode on an empty write
This initializes new_mode in vsock_net_child_mode_string() from the current
child mode, so the caller no longer reads an uninitialized enum when
__vsock_net_mode_string() returns success for a zero-length write.
> diff --git a/net/vmw_vsock/af_vsock.c b/net/vmw_vsock/af_vsock.c
> index f840498b58afb..9f89f199478b9 100644
> --- a/net/vmw_vsock/af_vsock.c
> +++ b/net/vmw_vsock/af_vsock.c
> @@ -2888,6 +2888,7 @@ static int vsock_net_child_mode_string(const struct ctl_table *table, int write,
> int ret;
>
> net = container_of(table->data, struct net, vsock.child_ns_mode);
> + new_mode = vsock_net_child_mode(net);
>
> ret = __vsock_net_mode_string(table, write, buffer, lenp, ppos,
> vsock_net_child_mode(net), &new_mode);
[Severity: High]
The changelog says "Initialize new_mode from the current child mode so that
an empty write is a no-op." Is the empty write really a no-op after this
change?
A zero-length write still reaches the handler with write == 1 and
*lenp == 0. fs/read_write.c:vfs_write() has no count == 0 early return
(rw_verify_area() only rejects negative counts), and
fs/proc/proc_sysctl.c:proc_sys_call_handler() does not short-circuit
either:
if (write) {
error = -EFAULT;
if (!copy_from_iter_full(kbuf, count, iter))
goto out_free_buf;
kbuf[count] = '\0';
}
...
error = table->proc_handler(table, write, kbuf, &count, &iocb->ki_pos);
copy_from_iter_full(kbuf, 0, iter) returns true, so
vsock_net_child_mode_string() is entered with *lenp == 0.
__vsock_net_mode_string() then returns 0 without parsing anything:
if (!table->data || !table->maxlen || !*lenp) {
*lenp = 0;
return 0;
}
Since that return value is indistinguishable from "a mode was parsed",
vsock_net_child_mode_string() falls into its write block anyway:
if (write) {
...
if (!vsock_net_set_child_mode(net, new_mode))
return -EBUSY;
}
so vsock_net_set_child_mode() is still called, now with the seeded current
mode rather than a stack value.
Does that still consume the write-once latch? In
include/net/af_vsock.h:vsock_net_set_child_mode():
int new_locked = mode + 1;
int old_locked = 0; /* unlocked */
if (try_cmpxchg(&net->vsock.child_ns_mode_locked,
&old_locked, new_locked)) {
WRITE_ONCE(net->vsock.child_ns_mode, mode);
return true;
}
On a fresh namespace vsock_net_init() leaves child_ns_mode_locked at 0, so
the cmpxchg succeeds and the mode is latched permanently.
Would this sequence then break a later legitimate lockdown on a global-mode
namespace?
write(fd, "", 0); /* returns 0, latches GLOBAL+1 */
echo local > .../child_ns_mode /* cmpxchg fails, -EBUSY */
Documentation/admin-guide/sysctl/net.rst describes the behaviour as:
The first write to ``child_ns_mode`` locks its value. Subsequent writes of
the same value succeed, but writing a different value returns ``-EBUSY``.
which ties the lock and the -EBUSY to writing a mode value, not to a write
that supplies no value.
Would it be more in line with the changelog to skip the write handling
entirely when nothing was parsed, for example an early
"if (write && !*lenp) return 0;" in vsock_net_child_mode_string(), or having
__vsock_net_mode_string() report "no value parsed" distinctly from success,
instead of re-applying the current mode through the cmpxchg?
[Severity: Medium]
This is a pre-existing issue and not introduced by this patch, but while
looking at vsock_net_set_child_mode() in include/net/af_vsock.h: is the
publication of the lock and of the mode value atomic with respect to
namespace creation?
if (try_cmpxchg(&net->vsock.child_ns_mode_locked,
&old_locked, new_locked)) {
WRITE_ONCE(net->vsock.child_ns_mode, mode);
return true;
}
return old_locked == new_locked;
The lock becomes observable before the child_ns_mode store, and a second
writer of the same mode returns success from the last line without waiting
for that store:
CPU0 (writes "local" on a global-mode netns)
try_cmpxchg() succeeds, child_ns_mode_locked = LOCAL+1
/* preempted here, before WRITE_ONCE(child_ns_mode, LOCAL) */
CPU1 (writes "local")
try_cmpxchg() fails, old_locked == LOCAL+1 == new_locked
return true; /* sysctl write reports success */
CPU2 (creates a netns after CPU1's write returned)
net/vmw_vsock/af_vsock.c:vsock_net_init()
net->vsock.mode = vsock_net_child_mode(current->nsproxy->net_ns);
net->vsock.child_ns_mode = net->vsock.mode;
Can the new namespace read VSOCK_NET_MODE_GLOBAL here and permanently
inherit the more permissive mode even though userspace was told the "local"
lockdown was committed?
A barrier does not seem sufficient, since the reader has already observed
the lock publication that precedes the value store. Would publishing the
mode and its locked state together help, for example deriving child_ns_mode
from child_ns_mode_locked, or adding an in-progress state that the second
writer waits on?
--
Sashiko AI review · https://netdev-ai.bots.linux.dev/sashiko/#/patchset/20260915111417.2726515-1-qwe.aldo%40gmail.com
prev parent reply other threads:[~2026-09-17 14:20 UTC|newest]
Thread overview: 11+ messages / expand[flat|nested] mbox.gz Atom feed top
2026-09-15 11:14 Aldo Ariel Panzardo
2026-09-15 14:15 ` [PATCH v2] vsock: ignore empty child namespace mode writes Aldo Ariel Panzardo
2026-09-15 16:32 ` Luigi Leonardi
2026-09-15 16:57 ` Stefano Garzarella
2026-09-15 16:50 ` Stefano Garzarella
2026-09-15 17:29 ` Aldo Ariel Panzardo
2026-09-15 17:30 ` [PATCH v3] " Aldo Ariel Panzardo
2026-09-16 15:38 ` Stefano Garzarella
2026-09-16 16:53 ` Bobby Eshleman
2026-09-18 2:10 ` patchwork-bot+netdevbpf
2026-09-17 14:20 ` netdev-bot+sashiko [this message]
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=178965480627.22033.2840574060294474673@kernel.org \
--to=netdev-bot+sashiko@kernel.org \
--cc=kuba@kernel.org \
--cc=linux-kernel@vger.kernel.org \
--cc=netdev@vger.kernel.org \
--cc=qwe.aldo@gmail.com \
--cc=sgarzare@redhat.com \
--cc=stable@vger.kernel.org \
--cc=virtualization@lists.linux.dev \
/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
all inboxes | Powered by JetHome®