diff options
author | Andreas Kling <kling@serenityos.org> | 2021-11-21 12:24:32 +0100 |
---|---|---|
committer | Andreas Kling <kling@serenityos.org> | 2021-11-21 20:22:48 +0100 |
commit | f2c3a41a8f8dab3ccd46b91f52a351a9a855879c (patch) | |
tree | 77fe50edcb6521dff4a40af73231adb214923631 | |
parent | b820ae2828379f1b34ee8106256c5f10c243077b (diff) | |
download | serenity-f2c3a41a8f8dab3ccd46b91f52a351a9a855879c.zip |
Kernel: Make UserOrKernelBuffer::for_user_buffer() return ErrorOr<T>
This simplifies EFAULT propagation with TRY(). :^)
-rw-r--r-- | Kernel/Coredump.cpp | 12 | ||||
-rw-r--r-- | Kernel/Syscalls/get_dir_entries.cpp | 6 | ||||
-rw-r--r-- | Kernel/Syscalls/getrandom.cpp | 6 | ||||
-rw-r--r-- | Kernel/Syscalls/read.cpp | 18 | ||||
-rw-r--r-- | Kernel/Syscalls/socket.cpp | 12 | ||||
-rw-r--r-- | Kernel/Syscalls/write.cpp | 12 | ||||
-rw-r--r-- | Kernel/UserOrKernelBuffer.h | 8 |
7 files changed, 27 insertions, 47 deletions
diff --git a/Kernel/Coredump.cpp b/Kernel/Coredump.cpp index 529d4e3e61..7d94784be2 100644 --- a/Kernel/Coredump.cpp +++ b/Kernel/Coredump.cpp @@ -182,16 +182,14 @@ ErrorOr<void> Coredump::write_regions() auto* page = region->physical_page(i); uint8_t zero_buffer[PAGE_SIZE] = {}; - Optional<UserOrKernelBuffer> src_buffer; - - if (page) { - src_buffer = UserOrKernelBuffer::for_user_buffer(reinterpret_cast<uint8_t*>((region->vaddr().as_ptr() + (i * PAGE_SIZE))), PAGE_SIZE); - } else { + auto src_buffer = [&]() -> ErrorOr<UserOrKernelBuffer> { + if (page) + return UserOrKernelBuffer::for_user_buffer(reinterpret_cast<uint8_t*>((region->vaddr().as_ptr() + (i * PAGE_SIZE))), PAGE_SIZE); // If the current page is not backed by a physical page, we zero it in the coredump file. // TODO: Do we want to include the contents of pages that have not been faulted-in in the coredump? // (A page may not be backed by a physical page because it has never been faulted in when the process ran). - src_buffer = UserOrKernelBuffer::for_kernel_buffer(zero_buffer); - } + return UserOrKernelBuffer::for_kernel_buffer(zero_buffer); + }(); TRY(m_description->write(src_buffer.value(), PAGE_SIZE)); } } diff --git a/Kernel/Syscalls/get_dir_entries.cpp b/Kernel/Syscalls/get_dir_entries.cpp index 604ab58af1..a3dfd40c91 100644 --- a/Kernel/Syscalls/get_dir_entries.cpp +++ b/Kernel/Syscalls/get_dir_entries.cpp @@ -16,10 +16,8 @@ ErrorOr<FlatPtr> Process::sys$get_dir_entries(int fd, Userspace<void*> user_buff if (user_size > NumericLimits<ssize_t>::max()) return EINVAL; auto description = TRY(fds().open_file_description(fd)); - auto buffer = UserOrKernelBuffer::for_user_buffer(user_buffer, static_cast<size_t>(user_size)); - if (!buffer.has_value()) - return EFAULT; - auto count = TRY(description->get_dir_entries(buffer.value(), user_size)); + auto buffer = TRY(UserOrKernelBuffer::for_user_buffer(user_buffer, static_cast<size_t>(user_size))); + auto count = TRY(description->get_dir_entries(buffer, user_size)); return count; } diff --git a/Kernel/Syscalls/getrandom.cpp b/Kernel/Syscalls/getrandom.cpp index 21e9efb848..ee1e6d4913 100644 --- a/Kernel/Syscalls/getrandom.cpp +++ b/Kernel/Syscalls/getrandom.cpp @@ -20,11 +20,9 @@ ErrorOr<FlatPtr> Process::sys$getrandom(Userspace<void*> buffer, size_t buffer_s if (buffer_size > NumericLimits<ssize_t>::max()) return EINVAL; - auto data_buffer = UserOrKernelBuffer::for_user_buffer(buffer, buffer_size); - if (!data_buffer.has_value()) - return EFAULT; + auto data_buffer = TRY(UserOrKernelBuffer::for_user_buffer(buffer, buffer_size)); - return TRY(data_buffer.value().write_buffered<1024>(buffer_size, [&](Bytes bytes) { + return TRY(data_buffer.write_buffered<1024>(buffer_size, [&](Bytes bytes) { get_good_random_bytes(bytes); return bytes.size(); })); diff --git a/Kernel/Syscalls/read.cpp b/Kernel/Syscalls/read.cpp index a001285925..2de85e5bbf 100644 --- a/Kernel/Syscalls/read.cpp +++ b/Kernel/Syscalls/read.cpp @@ -63,10 +63,8 @@ ErrorOr<FlatPtr> Process::sys$readv(int fd, Userspace<const struct iovec*> iov, int nread = 0; for (auto& vec : vecs) { TRY(check_blocked_read(description)); - auto buffer = UserOrKernelBuffer::for_user_buffer((u8*)vec.iov_base, vec.iov_len); - if (!buffer.has_value()) - return EFAULT; - auto nread_here = TRY(description->read(buffer.value(), vec.iov_len)); + auto buffer = TRY(UserOrKernelBuffer::for_user_buffer((u8*)vec.iov_base, vec.iov_len)); + auto nread_here = TRY(description->read(buffer, vec.iov_len)); nread += nread_here; } @@ -84,10 +82,8 @@ ErrorOr<FlatPtr> Process::sys$read(int fd, Userspace<u8*> buffer, size_t size) dbgln_if(IO_DEBUG, "sys$read({}, {}, {})", fd, buffer.ptr(), size); auto description = TRY(open_readable_file_description(fds(), fd)); TRY(check_blocked_read(description)); - auto user_buffer = UserOrKernelBuffer::for_user_buffer(buffer, size); - if (!user_buffer.has_value()) - return EFAULT; - return TRY(description->read(user_buffer.value(), size)); + auto user_buffer = TRY(UserOrKernelBuffer::for_user_buffer(buffer, size)); + return TRY(description->read(user_buffer, size)); } ErrorOr<FlatPtr> Process::sys$pread(int fd, Userspace<u8*> buffer, size_t size, Userspace<off_t*> userspace_offset) @@ -107,10 +103,8 @@ ErrorOr<FlatPtr> Process::sys$pread(int fd, Userspace<u8*> buffer, size_t size, if (!description->file().is_seekable()) return EINVAL; TRY(check_blocked_read(description)); - auto user_buffer = UserOrKernelBuffer::for_user_buffer(buffer, size); - if (!user_buffer.has_value()) - return EFAULT; - return TRY(description->read(user_buffer.value(), offset, size)); + auto user_buffer = TRY(UserOrKernelBuffer::for_user_buffer(buffer, size)); + return TRY(description->read(user_buffer, offset, size)); } } diff --git a/Kernel/Syscalls/socket.cpp b/Kernel/Syscalls/socket.cpp index 74a2a1bf96..5f0a40a43d 100644 --- a/Kernel/Syscalls/socket.cpp +++ b/Kernel/Syscalls/socket.cpp @@ -182,10 +182,8 @@ ErrorOr<FlatPtr> Process::sys$sendmsg(int sockfd, Userspace<const struct msghdr* auto& socket = *description->socket(); if (socket.is_shut_down_for_writing()) return EPIPE; - auto data_buffer = UserOrKernelBuffer::for_user_buffer((u8*)iovs[0].iov_base, iovs[0].iov_len); - if (!data_buffer.has_value()) - return EFAULT; - auto bytes_sent = TRY(socket.sendto(*description, data_buffer.value(), iovs[0].iov_len, flags, user_addr, addr_length)); + auto data_buffer = TRY(UserOrKernelBuffer::for_user_buffer((u8*)iovs[0].iov_base, iovs[0].iov_len)); + auto bytes_sent = TRY(socket.sendto(*description, data_buffer, iovs[0].iov_len, flags, user_addr, addr_length)); return bytes_sent; } @@ -218,11 +216,9 @@ ErrorOr<FlatPtr> Process::sys$recvmsg(int sockfd, Userspace<struct msghdr*> user if (flags & MSG_DONTWAIT) description->set_blocking(false); - auto data_buffer = UserOrKernelBuffer::for_user_buffer((u8*)iovs[0].iov_base, iovs[0].iov_len); - if (!data_buffer.has_value()) - return EFAULT; + auto data_buffer = TRY(UserOrKernelBuffer::for_user_buffer((u8*)iovs[0].iov_base, iovs[0].iov_len)); Time timestamp {}; - auto result = socket.recvfrom(*description, data_buffer.value(), iovs[0].iov_len, flags, user_addr, user_addr_length, timestamp); + auto result = socket.recvfrom(*description, data_buffer, iovs[0].iov_len, flags, user_addr, user_addr_length, timestamp); if (flags & MSG_DONTWAIT) description->set_blocking(original_blocking); diff --git a/Kernel/Syscalls/write.cpp b/Kernel/Syscalls/write.cpp index 09d4c40cfb..d056df3b6b 100644 --- a/Kernel/Syscalls/write.cpp +++ b/Kernel/Syscalls/write.cpp @@ -38,10 +38,8 @@ ErrorOr<FlatPtr> Process::sys$writev(int fd, Userspace<const struct iovec*> iov, int nwritten = 0; for (auto& vec : vecs) { - auto buffer = UserOrKernelBuffer::for_user_buffer((u8*)vec.iov_base, vec.iov_len); - if (!buffer.has_value()) - return EFAULT; - auto result = do_write(*description, buffer.value(), vec.iov_len); + auto buffer = TRY(UserOrKernelBuffer::for_user_buffer((u8*)vec.iov_base, vec.iov_len)); + auto result = do_write(*description, buffer, vec.iov_len); if (result.is_error()) { if (nwritten == 0) return result.release_error(); @@ -104,10 +102,8 @@ ErrorOr<FlatPtr> Process::sys$write(int fd, Userspace<const u8*> data, size_t si if (!description->is_writable()) return EBADF; - auto buffer = UserOrKernelBuffer::for_user_buffer(data, static_cast<size_t>(size)); - if (!buffer.has_value()) - return EFAULT; - return do_write(*description, buffer.value(), size); + auto buffer = TRY(UserOrKernelBuffer::for_user_buffer(data, static_cast<size_t>(size))); + return do_write(*description, buffer, size); } } diff --git a/Kernel/UserOrKernelBuffer.h b/Kernel/UserOrKernelBuffer.h index 11ffaf8dac..bebd512f3f 100644 --- a/Kernel/UserOrKernelBuffer.h +++ b/Kernel/UserOrKernelBuffer.h @@ -26,18 +26,18 @@ public: return UserOrKernelBuffer(kernel_buffer); } - static Optional<UserOrKernelBuffer> for_user_buffer(u8* user_buffer, size_t size) + static ErrorOr<UserOrKernelBuffer> for_user_buffer(u8* user_buffer, size_t size) { if (user_buffer && !Memory::is_user_range(VirtualAddress(user_buffer), size)) - return {}; + return Error::from_errno(EFAULT); return UserOrKernelBuffer(user_buffer); } template<typename UserspaceType> - static Optional<UserOrKernelBuffer> for_user_buffer(UserspaceType userspace, size_t size) + static ErrorOr<UserOrKernelBuffer> for_user_buffer(UserspaceType userspace, size_t size) { if (!Memory::is_user_range(VirtualAddress(userspace.unsafe_userspace_ptr()), size)) - return {}; + return Error::from_errno(EFAULT); return UserOrKernelBuffer(const_cast<u8*>((const u8*)userspace.unsafe_userspace_ptr())); } |