summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorAndreas Kling <kling@serenityos.org>2021-11-21 12:24:32 +0100
committerAndreas Kling <kling@serenityos.org>2021-11-21 20:22:48 +0100
commitf2c3a41a8f8dab3ccd46b91f52a351a9a855879c (patch)
tree77fe50edcb6521dff4a40af73231adb214923631
parentb820ae2828379f1b34ee8106256c5f10c243077b (diff)
downloadserenity-f2c3a41a8f8dab3ccd46b91f52a351a9a855879c.zip
Kernel: Make UserOrKernelBuffer::for_user_buffer() return ErrorOr<T>
This simplifies EFAULT propagation with TRY(). :^)
-rw-r--r--Kernel/Coredump.cpp12
-rw-r--r--Kernel/Syscalls/get_dir_entries.cpp6
-rw-r--r--Kernel/Syscalls/getrandom.cpp6
-rw-r--r--Kernel/Syscalls/read.cpp18
-rw-r--r--Kernel/Syscalls/socket.cpp12
-rw-r--r--Kernel/Syscalls/write.cpp12
-rw-r--r--Kernel/UserOrKernelBuffer.h8
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()));
}