mirror of
				https://github.com/RGBCube/serenity
				synced 2025-10-31 04:12:43 +00:00 
			
		
		
		
	Kernel: Make UserOrKernelBuffer::for_user_buffer() return ErrorOr<T>
This simplifies EFAULT propagation with TRY(). :^)
This commit is contained in:
		
							parent
							
								
									b820ae2828
								
							
						
					
					
						commit
						f2c3a41a8f
					
				
					 7 changed files with 27 additions and 47 deletions
				
			
		|  | @ -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)); | ||||
|         } | ||||
|     } | ||||
|  |  | |||
|  | @ -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; | ||||
| } | ||||
| 
 | ||||
|  |  | |||
|  | @ -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(); | ||||
|     })); | ||||
|  |  | |||
|  | @ -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)); | ||||
| } | ||||
| 
 | ||||
| } | ||||
|  |  | |||
|  | @ -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); | ||||
| 
 | ||||
|  |  | |||
|  | @ -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); | ||||
| } | ||||
| 
 | ||||
| } | ||||
|  |  | |||
|  | @ -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())); | ||||
|     } | ||||
| 
 | ||||
|  |  | |||
		Loading…
	
	Add table
		Add a link
		
	
		Reference in a new issue
	
	 Andreas Kling
						Andreas Kling