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



Reply via email to