1
Fork 0
mirror of https://github.com/RGBCube/serenity synced 2025-05-31 09:48:11 +00:00

Kernel: Use Userspace<T> for the recvfrom syscall, and Socket implementation

This fixes a bunch of unchecked kernel reads and writes, seems like they
would might exploitable :). Write of sockaddr_in size to any address you
please...
This commit is contained in:
Brian Gianforcaro 2020-08-18 00:25:23 -07:00 committed by Andreas Kling
parent 9f9b05ba0f
commit 8e97de2df9
9 changed files with 43 additions and 30 deletions

View file

@ -218,7 +218,7 @@ ssize_t Process::sys$sendto(Userspace<const Syscall::SC_sendto_params*> user_par
return result.value();
}
ssize_t Process::sys$recvfrom(const Syscall::SC_recvfrom_params* user_params)
ssize_t Process::sys$recvfrom(Userspace<const Syscall::SC_recvfrom_params*> user_params)
{
REQUIRE_PROMISE(stdio);
@ -227,18 +227,21 @@ ssize_t Process::sys$recvfrom(const Syscall::SC_recvfrom_params* user_params)
return -EFAULT;
int flags = params.flags;
sockaddr* addr = params.addr;
socklen_t* addr_length = params.addr_length;
Userspace<sockaddr*> user_addr = params.addr;
Userspace<socklen_t*> user_addr_length = params.addr_length;
SmapDisabler disabler;
if (!validate(params.buffer))
return -EFAULT;
if (addr_length) {
if (!validate_write_typed(addr_length))
if (user_addr_length) {
socklen_t addr_length;
if (!validate_read_and_copy_typed(&addr_length, user_addr_length))
return -EFAULT;
if (!validate_write(addr, *addr_length))
if (!validate_write_typed(user_addr_length))
return -EFAULT;
} else if (addr) {
if (!validate_write(user_addr, addr_length))
return -EFAULT;
} else if (user_addr) {
return -EINVAL;
}
auto description = file_description(params.sockfd);
@ -255,7 +258,7 @@ ssize_t Process::sys$recvfrom(const Syscall::SC_recvfrom_params* user_params)
if (flags & MSG_DONTWAIT)
description->set_blocking(false);
auto result = socket.recvfrom(*description, params.buffer.data, params.buffer.size, flags, addr, addr_length);
auto result = socket.recvfrom(*description, params.buffer.data, params.buffer.size, flags, user_addr, user_addr_length);
if (flags & MSG_DONTWAIT)
description->set_blocking(original_blocking);