Selaa lähdekoodia

Kernel: Make UserOrKernelBuffer::for_user_buffer() return ErrorOr<T>

This simplifies EFAULT propagation with TRY(). :^)
Andreas Kling 3 vuotta sitten
vanhempi
commit
f2c3a41a8f

+ 5 - 7
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));
         }
     }

+ 2 - 4
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;
 }
 

+ 2 - 4
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();
     }));

+ 6 - 12
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));
 }
 
 }

+ 4 - 8
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);
 

+ 4 - 8
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);
 }
 
 }

+ 4 - 4
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()));
     }