Hi Stefano, I like option 1 the most, as it is the most straightforward way to fix the issue. I am including the patch below. This fixes the clamping mismatch, but as you pointed out, it won't solve the root problem regarding the issue to arbitrarily set a maximum buffer value.
Since VSOCK uses a unified buffer size rather than separating read and write buffers like the core stack, introducing a vsock-specific sysctl (e.g., net.vmw_vsock.buffer_max_size) seems the cleanest approach to me. I was also considering net.core.wmem_max/rmem_max, but mapping to those feels less natural. If you agree with the vsock-specific sysctl, or have a different suggestion, let me know and I will send a follow-up patch for that. Thanks. Best, Norbert -- >8 -- From f5d160167c862c7f2ad6e6a1d4181d01997b683a Mon Sep 17 00:00:00 2001 From: Norbert Szetei <[email protected]> Date: Mon, 6 Apr 2026 19:52:52 +0200 Subject: [PATCH] vsock: fix buffer size clamping order In vsock_update_buffer_size(), the buffer size was being clamped to the maximum first, and then to the minimum. If a user sets a minimum buffer size larger than the maximum, the minimum check overrides the maximum check, inverting the constraint. This breaks the intended socket memory boundaries by allowing the vsk->buffer_size to grow beyond the configured vsk->buffer_max_size. Fix this by checking the minimum first, and then the maximum. This ensures the buffer size never exceeds the buffer_max_size. Signed-off-by: Norbert Szetei <[email protected]> --- net/vmw_vsock/af_vsock.c | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/net/vmw_vsock/af_vsock.c b/net/vmw_vsock/af_vsock.c index d912ed2f012a..08f4dfb9782c 100644 --- a/net/vmw_vsock/af_vsock.c +++ b/net/vmw_vsock/af_vsock.c @@ -1951,12 +1951,12 @@ static void vsock_update_buffer_size(struct vsock_sock *vsk, const struct vsock_transport *transport, u64 val) { - if (val > vsk->buffer_max_size) - val = vsk->buffer_max_size; - if (val < vsk->buffer_min_size) val = vsk->buffer_min_size; + if (val > vsk->buffer_max_size) + val = vsk->buffer_max_size; + if (val != vsk->buffer_size && transport && transport->notify_buffer_size) transport->notify_buffer_size(vsk, &val); -- 2.53.0 > On Mar 31, 2026, at 14:37, Stefano Garzarella <[email protected]> wrote: > > On Tue, Mar 24, 2026 at 06:28:12PM +0100, Norbert Szetei wrote: >> Hello, >> >> we have discovered a bug in AF_VSOCK where an unprivileged user can bypass >> socket >> memory constraints. This leads to refcount_t saturation and OOM. While >> refcount_t prevents a true UAF by saturating, the resulting state triggers >> kernel warnings and kernel panic, depending on the setup. >> >> In vsock_connectible_setsockopt(), the SO_VM_SOCKETS_BUFFER_MIN_SIZE and >> SO_VM_SOCKETS_BUFFER_MAX_SIZE options are used to update the buffer's minimum >> and maximum values independently. >> >> The vsock_update_buffer_size() function clamps the buffer size to the maximum >> first, then the minimum: >> >> // >> https://github.com/torvalds/linux/blob/c369299895a591d96745d6492d4888259b004a9e/net/vmw_vsock/af_vsock.c#L1950 >> if (val > vsk->buffer_max_size) >> val = vsk->buffer_max_size; >> >> if (val < vsk->buffer_min_size) >> val = vsk->buffer_min_size; >> >> vsk->buffer_size = val; >> >> By setting buffer_min_size to a large value, the second clamp overrides the >> first, forcing vsk->buffer_size to exceed the intended maximum. The transport >> layer then uses this value, allowing unbounded SKB allocation that saturates >> the >> 32-bit sk_wmem_alloc refcount. >> >> The fix should ensure that SO_VM_SOCKETS_BUFFER_MIN_SIZE cannot be used to >> set a >> value higher than the current buffer_max_size. Conversely, >> SO_VM_SOCKETS_BUFFER_MAX_SIZE should not be allowed to be set lower than the >> current buffer_min_size. > > Okay, but that wouldn't change much. As long as the user sets the maximum to > match the minimum you set in the POC, it behaves exactly the same way, right? > > Maybe we should add a sysctl to set a global upper bound, but this is another > problem, I agree that we should improve the kernel behavior around min/max. > I see 3 options: > > 1. Just invert the checks, fist check for min, then for max. > > 2. Simply adjust the min and max values so that they make sense. For example, > if the minimum value being set is greater than the maximum, the kernel could > adjust the maximum to the same value. However, this would not change the > behavior of your POC. > > 3. Force the minimum to be less than or equal to the maximum. This, however, > would require a certain order when setting the minimum and maximum, > especially relative to the default. For example, if you increase the minimum > beyond the default maximum, you must adjust the maximum first; conversely, if > you want to set the maximum below the default minimum, you must adjust the > minimum first. > > I'm more into 1 or 2. 3 IMO is too much. > > Do you want to send a patch? > > Thanks, > Stefano

