diff --git a/Kernel/Net/IPv4Socket.cpp b/Kernel/Net/IPv4Socket.cpp index f38d3371f6..80c4d44c03 100644 --- a/Kernel/Net/IPv4Socket.cpp +++ b/Kernel/Net/IPv4Socket.cpp @@ -428,19 +428,23 @@ String IPv4Socket::absolute_path(const FileDescription&) const return builder.to_string(); } -KResult IPv4Socket::setsockopt(int level, int option, const void* value, socklen_t value_size) +KResult IPv4Socket::setsockopt(int level, int option, const void* user_value, socklen_t user_value_size) { if (level != IPPROTO_IP) - return Socket::setsockopt(level, option, value, value_size); + return Socket::setsockopt(level, option, user_value, user_value_size); switch (option) { - case IP_TTL: - if (value_size < sizeof(int)) + case IP_TTL: { + if (user_value_size < sizeof(int)) return KResult(-EINVAL); - if (*(const int*)value < 0 || *(const int*)value > 255) + int value; + if (!Process::current()->validate_read_and_copy_typed(&value, (const int*)user_value)) + return KResult(-EFAULT); + if (value < 0 || value > 255) return KResult(-EINVAL); - m_ttl = (u8) * (const int*)value; + m_ttl = value; return KSuccess; + } default: return KResult(-ENOPROTOOPT); } diff --git a/Kernel/Net/Socket.cpp b/Kernel/Net/Socket.cpp index 99c17d066a..22c2022fb9 100644 --- a/Kernel/Net/Socket.cpp +++ b/Kernel/Net/Socket.cpp @@ -101,24 +101,26 @@ KResult Socket::queue_connection_from(NonnullRefPtr peer) return KSuccess; } -KResult Socket::setsockopt(int level, int option, const void* value, socklen_t value_size) +KResult Socket::setsockopt(int level, int option, const void* user_value, socklen_t user_value_size) { ASSERT(level == SOL_SOCKET); switch (option) { case SO_SNDTIMEO: - if (value_size != sizeof(timeval)) + if (user_value_size != sizeof(timeval)) return KResult(-EINVAL); - m_send_timeout = *(const timeval*)value; + copy_from_user(&m_send_timeout, (const timeval*)user_value); return KSuccess; case SO_RCVTIMEO: - if (value_size != sizeof(timeval)) + if (user_value_size != sizeof(timeval)) return KResult(-EINVAL); - m_receive_timeout = *(const timeval*)value; + copy_from_user(&m_receive_timeout, (const timeval*)user_value); return KSuccess; case SO_BINDTODEVICE: { - if (value_size != IFNAMSIZ) + if (user_value_size != IFNAMSIZ) return KResult(-EINVAL); - StringView ifname { (const char*)value }; + auto ifname = Process::current()->validate_and_copy_string_from_user((const char*)user_value, user_value_size); + if (ifname.is_null()) + return KResult(-EFAULT); auto device = NetworkAdapter::lookup_by_name(ifname); if (!device) return KResult(-ENODEV); diff --git a/Kernel/Syscalls/socket.cpp b/Kernel/Syscalls/socket.cpp index 9204abcfc9..c8eb20ff85 100644 --- a/Kernel/Syscalls/socket.cpp +++ b/Kernel/Syscalls/socket.cpp @@ -317,29 +317,21 @@ int Process::sys$getsockopt(const Syscall::SC_getsockopt_params* params) return socket.getsockopt(*description, level, option, value, value_size); } -int Process::sys$setsockopt(const Syscall::SC_setsockopt_params* params) +int Process::sys$setsockopt(const Syscall::SC_setsockopt_params* user_params) { - if (!validate_read_typed(params)) + Syscall::SC_setsockopt_params params; + if (!validate_read_and_copy_typed(¶ms, user_params)) return -EFAULT; - - SmapDisabler disabler; - - int sockfd = params->sockfd; - int level = params->level; - int option = params->option; - const void* value = params->value; - socklen_t value_size = params->value_size; - - if (!validate_read(value, value_size)) + if (!validate_read(params.value, params.value_size)) return -EFAULT; - auto description = file_description(sockfd); + auto description = file_description(params.sockfd); if (!description) return -EBADF; if (!description->is_socket()) return -ENOTSOCK; auto& socket = *description->socket(); REQUIRE_PROMISE_FOR_SOCKET_DOMAIN(socket.domain()); - return socket.setsockopt(level, option, value, value_size); + return socket.setsockopt(params.level, params.option, params.value, params.value_size); } }