Hi, v2: fix indentation/whitespace issues in the previous patch.
-- >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 Apr 6, 2026, at 20:41, Norbert Szetei <[email protected]> wrote: > > 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 > >

