[PATCH net v1] vsock: validate buffer min/max size in setsockopt
Rongguang Wei <[email protected]>
| Newsgroups | dev.linux.lists.virtualization,org.kernel.vger.netdev |
|---|---|
| Message-ID | <[email protected]> |
From: Rongguang Wei <[email protected]> SO_VM_SOCKETS_BUFFER_MIN_SIZE and SO_VM_SOCKETS_BUFFER_MAX_SIZE do not cross-validate against each other, allowing userspace to set buffer_min_size > buffer_max_size. When min > max, buffer_size is silently clamped to an incorrect value. For example, setting min=512KB then max=128 results in buffer_size=128 despite the user requesting much larger buffers via SO_VM_SOCKETS_BUFFER_SIZE. Reproduced with a test program: setsockopt(fd, AF_VSOCK, SO_VM_SOCKETS_BUFFER_MIN_SIZE, 512 * 1024, sizeof(int)); setsockopt(fd, AF_VSOCK, SO_VM_SOCKETS_BUFFER_MAX_SIZE, 128, sizeof(int)); // User asked for 1MB but got 128 bytes silently setsockopt(fd, AF_VSOCK, SO_VM_SOCKETS_BUFFER_SIZE, 1024 * 1024, sizeof(int)); After that use getsockopt to get the buffer_size = 128 and buffer_min_size = 524288, buffer_max_size = 128. The buffer_min_size > buffer_max_size and the kernel accepted contradictory values without error. Add value check to fix this issue. Return -EINVAL to userspace when setting MAX_SIZE to a value smaller than the current MIN_SIZE or setting MIN_SIZE to a value larger than the current MAX_SIZE. Fixes: b9f2b0ffde0c ("vsock: handle buffer_size sockopts in the core") Signed-off-by: Rongguang Wei <[email protected]> --- net/vmw_vsock/af_vsock.c | 8 ++++++++ 1 file changed, 8 insertions(+) diff --git a/net/vmw_vsock/af_vsock.c b/net/vmw_vsock/af_vsock.c index a33b2a2d381d..5faa30ee8745 100644 --- a/net/vmw_vsock/af_vsock.c +++ b/net/vmw_vsock/af_vsock.c @@ -2050,12 +2050,20 @@ static int vsock_connectible_setsockopt(struct socket *sock, case SO_VM_SOCKETS_BUFFER_MAX_SIZE: COPY_IN(val); + if (val < vsk->buffer_min_size) { + err = -EINVAL; + goto exit; + } vsk->buffer_max_size = val; vsock_update_buffer_size(vsk, transport, vsk->buffer_size); break; case SO_VM_SOCKETS_BUFFER_MIN_SIZE: COPY_IN(val); + if (val > vsk->buffer_max_size) { + err = -EINVAL; + goto exit; + } vsk->buffer_min_size = val; vsock_update_buffer_size(vsk, transport, vsk->buffer_size); break; -- 2.25.1 No virus found Checked by Hillstone Network AntiVirus